github.com/nova-foundation/go-ethereum@v1.0.1/core/blockchain_sethead_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 setting the chain head backwards doesn't leave the database in some 18 // strange state with gaps in the chain, nor with block data dangling in the future. 19 20 package core 21 22 import ( 23 "fmt" 24 "math/big" 25 "strings" 26 "testing" 27 "time" 28 29 "github.com/Nova-foundation/go-ethereum/common" 30 "github.com/Nova-foundation/go-ethereum/consensus/ethash" 31 "github.com/Nova-foundation/go-ethereum/core/rawdb" 32 "github.com/Nova-foundation/go-ethereum/core/types" 33 "github.com/Nova-foundation/go-ethereum/core/vm" 34 "github.com/Nova-foundation/go-ethereum/params" 35 ) 36 37 // rewindTest is a test case for chain rollback upon user request. 38 type rewindTest struct { 39 canonicalBlocks int // Number of blocks to generate for the canonical chain (heavier) 40 sidechainBlocks int // Number of blocks to generate for the side chain (lighter) 41 freezeThreshold uint64 // Block number until which to move things into the freezer 42 commitBlock uint64 // Block number for which to commit the state to disk 43 pivotBlock *uint64 // Pivot block number in case of fast sync 44 45 setheadBlock uint64 // Block number to set head back to 46 expCanonicalBlocks int // Number of canonical blocks expected to remain in the database (excl. genesis) 47 expSidechainBlocks int // Number of sidechain blocks expected to remain in the database (excl. genesis) 48 expFrozen int // Number of canonical blocks expected to be in the freezer (incl. genesis) 49 expHeadHeader uint64 // Block number of the expected head header 50 expHeadFastBlock uint64 // Block number of the expected head fast sync block 51 expHeadBlock uint64 // Block number of the expected head full block 52 } 53 54 //nolint:unused 55 func (tt *rewindTest) dump(crash bool) string { 56 buffer := new(strings.Builder) 57 58 fmt.Fprint(buffer, "Chain:\n G") 59 for i := 0; i < tt.canonicalBlocks; i++ { 60 fmt.Fprintf(buffer, "->C%d", i+1) 61 } 62 fmt.Fprint(buffer, " (HEAD)\n") 63 if tt.sidechainBlocks > 0 { 64 fmt.Fprintf(buffer, " └") 65 for i := 0; i < tt.sidechainBlocks; i++ { 66 fmt.Fprintf(buffer, "->S%d", i+1) 67 } 68 fmt.Fprintf(buffer, "\n") 69 } 70 fmt.Fprintf(buffer, "\n") 71 72 if tt.canonicalBlocks > int(tt.freezeThreshold) { 73 fmt.Fprint(buffer, "Frozen:\n G") 74 for i := 0; i < tt.canonicalBlocks-int(tt.freezeThreshold); i++ { 75 fmt.Fprintf(buffer, "->C%d", i+1) 76 } 77 fmt.Fprintf(buffer, "\n\n") 78 } else { 79 fmt.Fprintf(buffer, "Frozen: none\n") 80 } 81 fmt.Fprintf(buffer, "Commit: G") 82 if tt.commitBlock > 0 { 83 fmt.Fprintf(buffer, ", C%d", tt.commitBlock) 84 } 85 fmt.Fprint(buffer, "\n") 86 87 if tt.pivotBlock == nil { 88 fmt.Fprintf(buffer, "Pivot : none\n") 89 } else { 90 fmt.Fprintf(buffer, "Pivot : C%d\n", *tt.pivotBlock) 91 } 92 if crash { 93 fmt.Fprintf(buffer, "\nCRASH\n\n") 94 } else { 95 fmt.Fprintf(buffer, "\nSetHead(%d)\n\n", tt.setheadBlock) 96 } 97 fmt.Fprintf(buffer, "------------------------------\n\n") 98 99 if tt.expFrozen > 0 { 100 fmt.Fprint(buffer, "Expected in freezer:\n G") 101 for i := 0; i < tt.expFrozen-1; i++ { 102 fmt.Fprintf(buffer, "->C%d", i+1) 103 } 104 fmt.Fprintf(buffer, "\n\n") 105 } 106 if tt.expFrozen > 0 { 107 if tt.expFrozen >= tt.expCanonicalBlocks { 108 fmt.Fprintf(buffer, "Expected in leveldb: none\n") 109 } else { 110 fmt.Fprintf(buffer, "Expected in leveldb:\n C%d)", tt.expFrozen-1) 111 for i := tt.expFrozen - 1; i < tt.expCanonicalBlocks; i++ { 112 fmt.Fprintf(buffer, "->C%d", i+1) 113 } 114 fmt.Fprint(buffer, "\n") 115 if tt.expSidechainBlocks > tt.expFrozen { 116 fmt.Fprintf(buffer, " └") 117 for i := tt.expFrozen - 1; i < tt.expSidechainBlocks; i++ { 118 fmt.Fprintf(buffer, "->S%d", i+1) 119 } 120 fmt.Fprintf(buffer, "\n") 121 } 122 } 123 } else { 124 fmt.Fprint(buffer, "Expected in leveldb:\n G") 125 for i := tt.expFrozen; i < tt.expCanonicalBlocks; i++ { 126 fmt.Fprintf(buffer, "->C%d", i+1) 127 } 128 fmt.Fprint(buffer, "\n") 129 if tt.expSidechainBlocks > tt.expFrozen { 130 fmt.Fprintf(buffer, " └") 131 for i := tt.expFrozen; i < tt.expSidechainBlocks; i++ { 132 fmt.Fprintf(buffer, "->S%d", i+1) 133 } 134 fmt.Fprintf(buffer, "\n") 135 } 136 } 137 fmt.Fprintf(buffer, "\n") 138 fmt.Fprintf(buffer, "Expected head header : C%d\n", tt.expHeadHeader) 139 fmt.Fprintf(buffer, "Expected head fast block: C%d\n", tt.expHeadFastBlock) 140 if tt.expHeadBlock == 0 { 141 fmt.Fprintf(buffer, "Expected head block : G\n") 142 } else { 143 fmt.Fprintf(buffer, "Expected head block : C%d\n", tt.expHeadBlock) 144 } 145 return buffer.String() 146 } 147 148 // Tests a sethead for a short canonical chain where a recent block was already 149 // committed to disk and then the sethead called. In this case we expect the full 150 // chain to be rolled back to the committed block. Everything above the sethead 151 // point should be deleted. In between the committed block and the requested head 152 // the data can remain as "fast sync" data to avoid redownloading it. 153 func TestShortSetHead(t *testing.T) { testShortSetHead(t, false) } 154 func TestShortSetHeadWithSnapshots(t *testing.T) { testShortSetHead(t, true) } 155 156 func testShortSetHead(t *testing.T, snapshots bool) { 157 // Chain: 158 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 159 // 160 // Frozen: none 161 // Commit: G, C4 162 // Pivot : none 163 // 164 // SetHead(7) 165 // 166 // ------------------------------ 167 // 168 // Expected in leveldb: 169 // G->C1->C2->C3->C4->C5->C6->C7 170 // 171 // Expected head header : C7 172 // Expected head fast block: C7 173 // Expected head block : C4 174 testSetHead(t, &rewindTest{ 175 canonicalBlocks: 8, 176 sidechainBlocks: 0, 177 freezeThreshold: 16, 178 commitBlock: 4, 179 pivotBlock: nil, 180 setheadBlock: 7, 181 expCanonicalBlocks: 7, 182 expSidechainBlocks: 0, 183 expFrozen: 0, 184 expHeadHeader: 7, 185 expHeadFastBlock: 7, 186 expHeadBlock: 4, 187 }, snapshots) 188 } 189 190 // Tests a sethead for a short canonical chain where the fast sync pivot point was 191 // already committed, after which sethead was called. In this case we expect the 192 // chain to behave like in full sync mode, rolling back to the committed block 193 // Everything above the sethead point should be deleted. In between the committed 194 // block and the requested head the data can remain as "fast sync" data to avoid 195 // redownloading it. 196 func TestShortSnapSyncedSetHead(t *testing.T) { testShortSnapSyncedSetHead(t, false) } 197 func TestShortSnapSyncedSetHeadWithSnapshots(t *testing.T) { testShortSnapSyncedSetHead(t, true) } 198 199 func testShortSnapSyncedSetHead(t *testing.T, snapshots bool) { 200 // Chain: 201 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 202 // 203 // Frozen: none 204 // Commit: G, C4 205 // Pivot : C4 206 // 207 // SetHead(7) 208 // 209 // ------------------------------ 210 // 211 // Expected in leveldb: 212 // G->C1->C2->C3->C4->C5->C6->C7 213 // 214 // Expected head header : C7 215 // Expected head fast block: C7 216 // Expected head block : C4 217 testSetHead(t, &rewindTest{ 218 canonicalBlocks: 8, 219 sidechainBlocks: 0, 220 freezeThreshold: 16, 221 commitBlock: 4, 222 pivotBlock: uint64ptr(4), 223 setheadBlock: 7, 224 expCanonicalBlocks: 7, 225 expSidechainBlocks: 0, 226 expFrozen: 0, 227 expHeadHeader: 7, 228 expHeadFastBlock: 7, 229 expHeadBlock: 4, 230 }, snapshots) 231 } 232 233 // Tests a sethead for a short canonical chain where the fast sync pivot point was 234 // not yet committed, but sethead was called. In this case we expect the chain to 235 // detect that it was fast syncing and delete everything from the new head, since 236 // we can just pick up fast syncing from there. The head full block should be set 237 // to the genesis. 238 func TestShortSnapSyncingSetHead(t *testing.T) { testShortSnapSyncingSetHead(t, false) } 239 func TestShortSnapSyncingSetHeadWithSnapshots(t *testing.T) { testShortSnapSyncingSetHead(t, true) } 240 241 func testShortSnapSyncingSetHead(t *testing.T, snapshots bool) { 242 // Chain: 243 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 244 // 245 // Frozen: none 246 // Commit: G 247 // Pivot : C4 248 // 249 // SetHead(7) 250 // 251 // ------------------------------ 252 // 253 // Expected in leveldb: 254 // G->C1->C2->C3->C4->C5->C6->C7 255 // 256 // Expected head header : C7 257 // Expected head fast block: C7 258 // Expected head block : G 259 testSetHead(t, &rewindTest{ 260 canonicalBlocks: 8, 261 sidechainBlocks: 0, 262 freezeThreshold: 16, 263 commitBlock: 0, 264 pivotBlock: uint64ptr(4), 265 setheadBlock: 7, 266 expCanonicalBlocks: 7, 267 expSidechainBlocks: 0, 268 expFrozen: 0, 269 expHeadHeader: 7, 270 expHeadFastBlock: 7, 271 expHeadBlock: 0, 272 }, snapshots) 273 } 274 275 // Tests a sethead for a short canonical chain and a shorter side chain, where a 276 // recent block was already committed to disk and then sethead was called. In this 277 // test scenario the side chain is below the committed block. In this case we expect 278 // the canonical full chain to be rolled back to the committed block. Everything 279 // above the sethead point should be deleted. In between the committed block and 280 // the requested head the data can remain as "fast sync" data to avoid redownloading 281 // it. The side chain should be left alone as it was shorter. 282 func TestShortOldForkedSetHead(t *testing.T) { testShortOldForkedSetHead(t, false) } 283 func TestShortOldForkedSetHeadWithSnapshots(t *testing.T) { testShortOldForkedSetHead(t, true) } 284 285 func testShortOldForkedSetHead(t *testing.T, snapshots bool) { 286 // Chain: 287 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 288 // └->S1->S2->S3 289 // 290 // Frozen: none 291 // Commit: G, C4 292 // Pivot : none 293 // 294 // SetHead(7) 295 // 296 // ------------------------------ 297 // 298 // Expected in leveldb: 299 // G->C1->C2->C3->C4->C5->C6->C7 300 // └->S1->S2->S3 301 // 302 // Expected head header : C7 303 // Expected head fast block: C7 304 // Expected head block : C4 305 testSetHead(t, &rewindTest{ 306 canonicalBlocks: 8, 307 sidechainBlocks: 3, 308 freezeThreshold: 16, 309 commitBlock: 4, 310 pivotBlock: nil, 311 setheadBlock: 7, 312 expCanonicalBlocks: 7, 313 expSidechainBlocks: 3, 314 expFrozen: 0, 315 expHeadHeader: 7, 316 expHeadFastBlock: 7, 317 expHeadBlock: 4, 318 }, snapshots) 319 } 320 321 // Tests a sethead for a short canonical chain and a shorter side chain, where 322 // the fast sync pivot point was already committed to disk and then sethead was 323 // called. In this test scenario the side chain is below the committed block. In 324 // this case we expect the canonical full chain to be rolled back to the committed 325 // block. Everything above the sethead point should be deleted. In between the 326 // committed block and the requested head the data can remain as "fast sync" data 327 // to avoid redownloading it. The side chain should be left alone as it was shorter. 328 func TestShortOldForkedSnapSyncedSetHead(t *testing.T) { 329 testShortOldForkedSnapSyncedSetHead(t, false) 330 } 331 func TestShortOldForkedSnapSyncedSetHeadWithSnapshots(t *testing.T) { 332 testShortOldForkedSnapSyncedSetHead(t, true) 333 } 334 335 func testShortOldForkedSnapSyncedSetHead(t *testing.T, snapshots bool) { 336 // Chain: 337 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 338 // └->S1->S2->S3 339 // 340 // Frozen: none 341 // Commit: G, C4 342 // Pivot : C4 343 // 344 // SetHead(7) 345 // 346 // ------------------------------ 347 // 348 // Expected in leveldb: 349 // G->C1->C2->C3->C4->C5->C6->C7 350 // └->S1->S2->S3 351 // 352 // Expected head header : C7 353 // Expected head fast block: C7 354 // Expected head block : C4 355 testSetHead(t, &rewindTest{ 356 canonicalBlocks: 8, 357 sidechainBlocks: 3, 358 freezeThreshold: 16, 359 commitBlock: 4, 360 pivotBlock: uint64ptr(4), 361 setheadBlock: 7, 362 expCanonicalBlocks: 7, 363 expSidechainBlocks: 3, 364 expFrozen: 0, 365 expHeadHeader: 7, 366 expHeadFastBlock: 7, 367 expHeadBlock: 4, 368 }, snapshots) 369 } 370 371 // Tests a sethead for a short canonical chain and a shorter side chain, where 372 // the fast sync pivot point was not yet committed, but sethead was called. In this 373 // test scenario the side chain is below the committed block. In this case we expect 374 // the chain to detect that it was fast syncing and delete everything from the new 375 // head, since we can just pick up fast syncing from there. The head full block 376 // should be set to the genesis. 377 func TestShortOldForkedSnapSyncingSetHead(t *testing.T) { 378 testShortOldForkedSnapSyncingSetHead(t, false) 379 } 380 func TestShortOldForkedSnapSyncingSetHeadWithSnapshots(t *testing.T) { 381 testShortOldForkedSnapSyncingSetHead(t, true) 382 } 383 384 func testShortOldForkedSnapSyncingSetHead(t *testing.T, snapshots bool) { 385 // Chain: 386 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 387 // └->S1->S2->S3 388 // 389 // Frozen: none 390 // Commit: G 391 // Pivot : C4 392 // 393 // SetHead(7) 394 // 395 // ------------------------------ 396 // 397 // Expected in leveldb: 398 // G->C1->C2->C3->C4->C5->C6->C7 399 // └->S1->S2->S3 400 // 401 // Expected head header : C7 402 // Expected head fast block: C7 403 // Expected head block : G 404 testSetHead(t, &rewindTest{ 405 canonicalBlocks: 8, 406 sidechainBlocks: 3, 407 freezeThreshold: 16, 408 commitBlock: 0, 409 pivotBlock: uint64ptr(4), 410 setheadBlock: 7, 411 expCanonicalBlocks: 7, 412 expSidechainBlocks: 3, 413 expFrozen: 0, 414 expHeadHeader: 7, 415 expHeadFastBlock: 7, 416 expHeadBlock: 0, 417 }, snapshots) 418 } 419 420 // Tests a sethead for a short canonical chain and a shorter side chain, where a 421 // recent block was already committed to disk and then sethead was called. In this 422 // test scenario the side chain reaches above the committed block. In this case we 423 // expect the canonical full chain to be rolled back to the committed block. All 424 // data above the sethead point should be deleted. In between the committed block 425 // and the requested head the data can remain as "fast sync" data to avoid having 426 // to redownload it. The side chain should be truncated to the head set. 427 // 428 // The side chain could be left to be if the fork point was before the new head 429 // we are deleting to, but it would be exceedingly hard to detect that case and 430 // properly handle it, so we'll trade extra work in exchange for simpler code. 431 func TestShortNewlyForkedSetHead(t *testing.T) { testShortNewlyForkedSetHead(t, false) } 432 func TestShortNewlyForkedSetHeadWithSnapshots(t *testing.T) { testShortNewlyForkedSetHead(t, true) } 433 434 func testShortNewlyForkedSetHead(t *testing.T, snapshots bool) { 435 // Chain: 436 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 (HEAD) 437 // └->S1->S2->S3->S4->S5->S6->S7->S8 438 // 439 // Frozen: none 440 // Commit: G, C4 441 // Pivot : none 442 // 443 // SetHead(7) 444 // 445 // ------------------------------ 446 // 447 // Expected in leveldb: 448 // G->C1->C2->C3->C4->C5->C6->C7 449 // └->S1->S2->S3->S4->S5->S6->S7 450 // 451 // Expected head header : C7 452 // Expected head fast block: C7 453 // Expected head block : C4 454 testSetHead(t, &rewindTest{ 455 canonicalBlocks: 10, 456 sidechainBlocks: 8, 457 freezeThreshold: 16, 458 commitBlock: 4, 459 pivotBlock: nil, 460 setheadBlock: 7, 461 expCanonicalBlocks: 7, 462 expSidechainBlocks: 7, 463 expFrozen: 0, 464 expHeadHeader: 7, 465 expHeadFastBlock: 7, 466 expHeadBlock: 4, 467 }, snapshots) 468 } 469 470 // Tests a sethead for a short canonical chain and a shorter side chain, where 471 // the fast sync pivot point was already committed to disk and then sethead was 472 // called. In this case we expect the canonical full chain to be rolled back to 473 // between the committed block and the requested head the data can remain as 474 // "fast sync" data to avoid having to redownload it. The side chain should be 475 // truncated to the head set. 476 // 477 // The side chain could be left to be if the fork point was before the new head 478 // we are deleting to, but it would be exceedingly hard to detect that case and 479 // properly handle it, so we'll trade extra work in exchange for simpler code. 480 func TestShortNewlyForkedSnapSyncedSetHead(t *testing.T) { 481 testShortNewlyForkedSnapSyncedSetHead(t, false) 482 } 483 func TestShortNewlyForkedSnapSyncedSetHeadWithSnapshots(t *testing.T) { 484 testShortNewlyForkedSnapSyncedSetHead(t, true) 485 } 486 487 func testShortNewlyForkedSnapSyncedSetHead(t *testing.T, snapshots bool) { 488 // Chain: 489 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 (HEAD) 490 // └->S1->S2->S3->S4->S5->S6->S7->S8 491 // 492 // Frozen: none 493 // Commit: G, C4 494 // Pivot : C4 495 // 496 // SetHead(7) 497 // 498 // ------------------------------ 499 // 500 // Expected in leveldb: 501 // G->C1->C2->C3->C4->C5->C6->C7 502 // └->S1->S2->S3->S4->S5->S6->S7 503 // 504 // Expected head header : C7 505 // Expected head fast block: C7 506 // Expected head block : C4 507 testSetHead(t, &rewindTest{ 508 canonicalBlocks: 10, 509 sidechainBlocks: 8, 510 freezeThreshold: 16, 511 commitBlock: 4, 512 pivotBlock: uint64ptr(4), 513 setheadBlock: 7, 514 expCanonicalBlocks: 7, 515 expSidechainBlocks: 7, 516 expFrozen: 0, 517 expHeadHeader: 7, 518 expHeadFastBlock: 7, 519 expHeadBlock: 4, 520 }, snapshots) 521 } 522 523 // Tests a sethead for a short canonical chain and a shorter side chain, where 524 // the fast sync pivot point was not yet committed, but sethead was called. In 525 // this test scenario the side chain reaches above the committed block. In this 526 // case we expect the chain to detect that it was fast syncing and delete 527 // everything from the new head, since we can just pick up fast syncing from 528 // there. 529 // 530 // The side chain could be left to be if the fork point was before the new head 531 // we are deleting to, but it would be exceedingly hard to detect that case and 532 // properly handle it, so we'll trade extra work in exchange for simpler code. 533 func TestShortNewlyForkedSnapSyncingSetHead(t *testing.T) { 534 testShortNewlyForkedSnapSyncingSetHead(t, false) 535 } 536 func TestShortNewlyForkedSnapSyncingSetHeadWithSnapshots(t *testing.T) { 537 testShortNewlyForkedSnapSyncingSetHead(t, true) 538 } 539 540 func testShortNewlyForkedSnapSyncingSetHead(t *testing.T, snapshots bool) { 541 // Chain: 542 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 (HEAD) 543 // └->S1->S2->S3->S4->S5->S6->S7->S8 544 // 545 // Frozen: none 546 // Commit: G 547 // Pivot : C4 548 // 549 // SetHead(7) 550 // 551 // ------------------------------ 552 // 553 // Expected in leveldb: 554 // G->C1->C2->C3->C4->C5->C6->C7 555 // └->S1->S2->S3->S4->S5->S6->S7 556 // 557 // Expected head header : C7 558 // Expected head fast block: C7 559 // Expected head block : G 560 testSetHead(t, &rewindTest{ 561 canonicalBlocks: 10, 562 sidechainBlocks: 8, 563 freezeThreshold: 16, 564 commitBlock: 0, 565 pivotBlock: uint64ptr(4), 566 setheadBlock: 7, 567 expCanonicalBlocks: 7, 568 expSidechainBlocks: 7, 569 expFrozen: 0, 570 expHeadHeader: 7, 571 expHeadFastBlock: 7, 572 expHeadBlock: 0, 573 }, snapshots) 574 } 575 576 // Tests a sethead for a short canonical chain and a longer side chain, where a 577 // recent block was already committed to disk and then sethead was called. In this 578 // case we expect the canonical full chain to be rolled back to the committed block. 579 // All data above the sethead point should be deleted. In between the committed 580 // block and the requested head the data can remain as "fast sync" data to avoid 581 // having to redownload it. The side chain should be truncated to the head set. 582 // 583 // The side chain could be left to be if the fork point was before the new head 584 // we are deleting to, but it would be exceedingly hard to detect that case and 585 // properly handle it, so we'll trade extra work in exchange for simpler code. 586 func TestShortReorgedSetHead(t *testing.T) { testShortReorgedSetHead(t, false) } 587 func TestShortReorgedSetHeadWithSnapshots(t *testing.T) { testShortReorgedSetHead(t, true) } 588 589 func testShortReorgedSetHead(t *testing.T, snapshots bool) { 590 // Chain: 591 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 592 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 593 // 594 // Frozen: none 595 // Commit: G, C4 596 // Pivot : none 597 // 598 // SetHead(7) 599 // 600 // ------------------------------ 601 // 602 // Expected in leveldb: 603 // G->C1->C2->C3->C4->C5->C6->C7 604 // └->S1->S2->S3->S4->S5->S6->S7 605 // 606 // Expected head header : C7 607 // Expected head fast block: C7 608 // Expected head block : C4 609 testSetHead(t, &rewindTest{ 610 canonicalBlocks: 8, 611 sidechainBlocks: 10, 612 freezeThreshold: 16, 613 commitBlock: 4, 614 pivotBlock: nil, 615 setheadBlock: 7, 616 expCanonicalBlocks: 7, 617 expSidechainBlocks: 7, 618 expFrozen: 0, 619 expHeadHeader: 7, 620 expHeadFastBlock: 7, 621 expHeadBlock: 4, 622 }, snapshots) 623 } 624 625 // Tests a sethead for a short canonical chain and a longer side chain, where 626 // the fast sync pivot point was already committed to disk and then sethead was 627 // called. In this case we expect the canonical full chain to be rolled back to 628 // the committed block. All data above the sethead point should be deleted. In 629 // between the committed block and the requested head the data can remain as 630 // "fast sync" data to avoid having to redownload it. The side chain should be 631 // truncated to the head set. 632 // 633 // The side chain could be left to be if the fork point was before the new head 634 // we are deleting to, but it would be exceedingly hard to detect that case and 635 // properly handle it, so we'll trade extra work in exchange for simpler code. 636 func TestShortReorgedSnapSyncedSetHead(t *testing.T) { 637 testShortReorgedSnapSyncedSetHead(t, false) 638 } 639 func TestShortReorgedSnapSyncedSetHeadWithSnapshots(t *testing.T) { 640 testShortReorgedSnapSyncedSetHead(t, true) 641 } 642 643 func testShortReorgedSnapSyncedSetHead(t *testing.T, snapshots bool) { 644 // Chain: 645 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 646 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 647 // 648 // Frozen: none 649 // Commit: G, C4 650 // Pivot : C4 651 // 652 // SetHead(7) 653 // 654 // ------------------------------ 655 // 656 // Expected in leveldb: 657 // G->C1->C2->C3->C4->C5->C6->C7 658 // └->S1->S2->S3->S4->S5->S6->S7 659 // 660 // Expected head header : C7 661 // Expected head fast block: C7 662 // Expected head block : C4 663 testSetHead(t, &rewindTest{ 664 canonicalBlocks: 8, 665 sidechainBlocks: 10, 666 freezeThreshold: 16, 667 commitBlock: 4, 668 pivotBlock: uint64ptr(4), 669 setheadBlock: 7, 670 expCanonicalBlocks: 7, 671 expSidechainBlocks: 7, 672 expFrozen: 0, 673 expHeadHeader: 7, 674 expHeadFastBlock: 7, 675 expHeadBlock: 4, 676 }, snapshots) 677 } 678 679 // Tests a sethead for a short canonical chain and a longer side chain, where 680 // the fast sync pivot point was not yet committed, but sethead was called. In 681 // this case we expect the chain to detect that it was fast syncing and delete 682 // everything from the new head, since we can just pick up fast syncing from 683 // there. 684 // 685 // The side chain could be left to be if the fork point was before the new head 686 // we are deleting to, but it would be exceedingly hard to detect that case and 687 // properly handle it, so we'll trade extra work in exchange for simpler code. 688 func TestShortReorgedSnapSyncingSetHead(t *testing.T) { 689 testShortReorgedSnapSyncingSetHead(t, false) 690 } 691 func TestShortReorgedSnapSyncingSetHeadWithSnapshots(t *testing.T) { 692 testShortReorgedSnapSyncingSetHead(t, true) 693 } 694 695 func testShortReorgedSnapSyncingSetHead(t *testing.T, snapshots bool) { 696 // Chain: 697 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 698 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 699 // 700 // Frozen: none 701 // Commit: G 702 // Pivot : C4 703 // 704 // SetHead(7) 705 // 706 // ------------------------------ 707 // 708 // Expected in leveldb: 709 // G->C1->C2->C3->C4->C5->C6->C7 710 // └->S1->S2->S3->S4->S5->S6->S7 711 // 712 // Expected head header : C7 713 // Expected head fast block: C7 714 // Expected head block : G 715 testSetHead(t, &rewindTest{ 716 canonicalBlocks: 8, 717 sidechainBlocks: 10, 718 freezeThreshold: 16, 719 commitBlock: 0, 720 pivotBlock: uint64ptr(4), 721 setheadBlock: 7, 722 expCanonicalBlocks: 7, 723 expSidechainBlocks: 7, 724 expFrozen: 0, 725 expHeadHeader: 7, 726 expHeadFastBlock: 7, 727 expHeadBlock: 0, 728 }, snapshots) 729 } 730 731 // Tests a sethead for a long canonical chain with frozen blocks where a recent 732 // block - newer than the ancient limit - was already committed to disk and then 733 // sethead was called. In this case we expect the full chain to be rolled back 734 // to the committed block. Everything above the sethead point should be deleted. 735 // In between the committed block and the requested head the data can remain as 736 // "fast sync" data to avoid redownloading it. 737 func TestLongShallowSetHead(t *testing.T) { testLongShallowSetHead(t, false) } 738 func TestLongShallowSetHeadWithSnapshots(t *testing.T) { testLongShallowSetHead(t, true) } 739 740 func testLongShallowSetHead(t *testing.T, snapshots bool) { 741 // Chain: 742 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 743 // 744 // Frozen: 745 // G->C1->C2 746 // 747 // Commit: G, C4 748 // Pivot : none 749 // 750 // SetHead(6) 751 // 752 // ------------------------------ 753 // 754 // Expected in freezer: 755 // G->C1->C2 756 // 757 // Expected in leveldb: 758 // C2)->C3->C4->C5->C6 759 // 760 // Expected head header : C6 761 // Expected head fast block: C6 762 // Expected head block : C4 763 testSetHead(t, &rewindTest{ 764 canonicalBlocks: 18, 765 sidechainBlocks: 0, 766 freezeThreshold: 16, 767 commitBlock: 4, 768 pivotBlock: nil, 769 setheadBlock: 6, 770 expCanonicalBlocks: 6, 771 expSidechainBlocks: 0, 772 expFrozen: 3, 773 expHeadHeader: 6, 774 expHeadFastBlock: 6, 775 expHeadBlock: 4, 776 }, snapshots) 777 } 778 779 // Tests a sethead for a long canonical chain with frozen blocks where a recent 780 // block - older than the ancient limit - was already committed to disk and then 781 // sethead was called. In this case we expect the full chain to be rolled back 782 // to the committed block. Since the ancient limit was underflown, everything 783 // needs to be deleted onwards to avoid creating a gap. 784 func TestLongDeepSetHead(t *testing.T) { testLongDeepSetHead(t, false) } 785 func TestLongDeepSetHeadWithSnapshots(t *testing.T) { testLongDeepSetHead(t, true) } 786 787 func testLongDeepSetHead(t *testing.T, snapshots bool) { 788 // Chain: 789 // 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) 790 // 791 // Frozen: 792 // G->C1->C2->C3->C4->C5->C6->C7->C8 793 // 794 // Commit: G, C4 795 // Pivot : none 796 // 797 // SetHead(6) 798 // 799 // ------------------------------ 800 // 801 // Expected in freezer: 802 // G->C1->C2->C3->C4 803 // 804 // Expected in leveldb: none 805 // 806 // Expected head header : C4 807 // Expected head fast block: C4 808 // Expected head block : C4 809 testSetHead(t, &rewindTest{ 810 canonicalBlocks: 24, 811 sidechainBlocks: 0, 812 freezeThreshold: 16, 813 commitBlock: 4, 814 pivotBlock: nil, 815 setheadBlock: 6, 816 expCanonicalBlocks: 4, 817 expSidechainBlocks: 0, 818 expFrozen: 5, 819 expHeadHeader: 4, 820 expHeadFastBlock: 4, 821 expHeadBlock: 4, 822 }, snapshots) 823 } 824 825 // Tests a sethead for a long canonical chain with frozen blocks where the fast 826 // sync pivot point - newer than the ancient limit - was already committed, after 827 // which sethead was called. In this case we expect the full chain to be rolled 828 // back to the committed block. Everything above the sethead point should be 829 // deleted. In between the committed block and the requested head the data can 830 // remain as "fast sync" data to avoid redownloading it. 831 func TestLongSnapSyncedShallowSetHead(t *testing.T) { 832 testLongSnapSyncedShallowSetHead(t, false) 833 } 834 func TestLongSnapSyncedShallowSetHeadWithSnapshots(t *testing.T) { 835 testLongSnapSyncedShallowSetHead(t, true) 836 } 837 838 func testLongSnapSyncedShallowSetHead(t *testing.T, snapshots bool) { 839 // Chain: 840 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 841 // 842 // Frozen: 843 // G->C1->C2 844 // 845 // Commit: G, C4 846 // Pivot : C4 847 // 848 // SetHead(6) 849 // 850 // ------------------------------ 851 // 852 // Expected in freezer: 853 // G->C1->C2 854 // 855 // Expected in leveldb: 856 // C2)->C3->C4->C5->C6 857 // 858 // Expected head header : C6 859 // Expected head fast block: C6 860 // Expected head block : C4 861 testSetHead(t, &rewindTest{ 862 canonicalBlocks: 18, 863 sidechainBlocks: 0, 864 freezeThreshold: 16, 865 commitBlock: 4, 866 pivotBlock: uint64ptr(4), 867 setheadBlock: 6, 868 expCanonicalBlocks: 6, 869 expSidechainBlocks: 0, 870 expFrozen: 3, 871 expHeadHeader: 6, 872 expHeadFastBlock: 6, 873 expHeadBlock: 4, 874 }, snapshots) 875 } 876 877 // Tests a sethead for a long canonical chain with frozen blocks where the fast 878 // sync pivot point - older than the ancient limit - was already committed, after 879 // which sethead was called. In this case we expect the full chain to be rolled 880 // back to the committed block. Since the ancient limit was underflown, everything 881 // needs to be deleted onwards to avoid creating a gap. 882 func TestLongSnapSyncedDeepSetHead(t *testing.T) { testLongSnapSyncedDeepSetHead(t, false) } 883 func TestLongSnapSyncedDeepSetHeadWithSnapshots(t *testing.T) { testLongSnapSyncedDeepSetHead(t, true) } 884 885 func testLongSnapSyncedDeepSetHead(t *testing.T, snapshots bool) { 886 // Chain: 887 // 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) 888 // 889 // Frozen: 890 // G->C1->C2->C3->C4->C5->C6->C7->C8 891 // 892 // Commit: G, C4 893 // Pivot : C4 894 // 895 // SetHead(6) 896 // 897 // ------------------------------ 898 // 899 // Expected in freezer: 900 // G->C1->C2->C3->C4 901 // 902 // Expected in leveldb: none 903 // 904 // Expected head header : C4 905 // Expected head fast block: C4 906 // Expected head block : C4 907 testSetHead(t, &rewindTest{ 908 canonicalBlocks: 24, 909 sidechainBlocks: 0, 910 freezeThreshold: 16, 911 commitBlock: 4, 912 pivotBlock: uint64ptr(4), 913 setheadBlock: 6, 914 expCanonicalBlocks: 4, 915 expSidechainBlocks: 0, 916 expFrozen: 5, 917 expHeadHeader: 4, 918 expHeadFastBlock: 4, 919 expHeadBlock: 4, 920 }, snapshots) 921 } 922 923 // Tests a sethead for a long canonical chain with frozen blocks where the fast 924 // sync pivot point - newer than the ancient limit - was not yet committed, but 925 // sethead was called. In this case we expect the chain to detect that it was fast 926 // syncing and delete everything from the new head, since we can just pick up fast 927 // syncing from there. 928 func TestLongSnapSyncingShallowSetHead(t *testing.T) { 929 testLongSnapSyncingShallowSetHead(t, false) 930 } 931 func TestLongSnapSyncingShallowSetHeadWithSnapshots(t *testing.T) { 932 testLongSnapSyncingShallowSetHead(t, true) 933 } 934 935 func testLongSnapSyncingShallowSetHead(t *testing.T, snapshots bool) { 936 // Chain: 937 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 938 // 939 // Frozen: 940 // G->C1->C2 941 // 942 // Commit: G 943 // Pivot : C4 944 // 945 // SetHead(6) 946 // 947 // ------------------------------ 948 // 949 // Expected in freezer: 950 // G->C1->C2 951 // 952 // Expected in leveldb: 953 // C2)->C3->C4->C5->C6 954 // 955 // Expected head header : C6 956 // Expected head fast block: C6 957 // Expected head block : G 958 testSetHead(t, &rewindTest{ 959 canonicalBlocks: 18, 960 sidechainBlocks: 0, 961 freezeThreshold: 16, 962 commitBlock: 0, 963 pivotBlock: uint64ptr(4), 964 setheadBlock: 6, 965 expCanonicalBlocks: 6, 966 expSidechainBlocks: 0, 967 expFrozen: 3, 968 expHeadHeader: 6, 969 expHeadFastBlock: 6, 970 expHeadBlock: 0, 971 }, snapshots) 972 } 973 974 // Tests a sethead for a long canonical chain with frozen blocks where the fast 975 // sync pivot point - older than the ancient limit - was not yet committed, but 976 // sethead was called. In this case we expect the chain to detect that it was fast 977 // syncing and delete everything from the new head, since we can just pick up fast 978 // syncing from there. 979 func TestLongSnapSyncingDeepSetHead(t *testing.T) { 980 testLongSnapSyncingDeepSetHead(t, false) 981 } 982 func TestLongSnapSyncingDeepSetHeadWithSnapshots(t *testing.T) { 983 testLongSnapSyncingDeepSetHead(t, true) 984 } 985 986 func testLongSnapSyncingDeepSetHead(t *testing.T, snapshots bool) { 987 // Chain: 988 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) 989 // 990 // Frozen: 991 // G->C1->C2->C3->C4->C5->C6->C7->C8 992 // 993 // Commit: G 994 // Pivot : C4 995 // 996 // SetHead(6) 997 // 998 // ------------------------------ 999 // 1000 // Expected in freezer: 1001 // G->C1->C2->C3->C4->C5->C6 1002 // 1003 // Expected in leveldb: none 1004 // 1005 // Expected head header : C6 1006 // Expected head fast block: C6 1007 // Expected head block : G 1008 testSetHead(t, &rewindTest{ 1009 canonicalBlocks: 24, 1010 sidechainBlocks: 0, 1011 freezeThreshold: 16, 1012 commitBlock: 0, 1013 pivotBlock: uint64ptr(4), 1014 setheadBlock: 6, 1015 expCanonicalBlocks: 6, 1016 expSidechainBlocks: 0, 1017 expFrozen: 7, 1018 expHeadHeader: 6, 1019 expHeadFastBlock: 6, 1020 expHeadBlock: 0, 1021 }, snapshots) 1022 } 1023 1024 // Tests a sethead for a long canonical chain with frozen blocks and a shorter side 1025 // chain, where a recent block - newer than the ancient limit - was already committed 1026 // to disk and then sethead was called. In this case we expect the canonical full 1027 // chain to be rolled back to the committed block. Everything above the sethead point 1028 // should be deleted. In between the committed block and the requested head the data 1029 // can remain as "fast sync" data to avoid redownloading it. The side chain is nuked 1030 // by the freezer. 1031 func TestLongOldForkedShallowSetHead(t *testing.T) { 1032 testLongOldForkedShallowSetHead(t, false) 1033 } 1034 func TestLongOldForkedShallowSetHeadWithSnapshots(t *testing.T) { 1035 testLongOldForkedShallowSetHead(t, true) 1036 } 1037 1038 func testLongOldForkedShallowSetHead(t *testing.T, snapshots bool) { 1039 // Chain: 1040 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1041 // └->S1->S2->S3 1042 // 1043 // Frozen: 1044 // G->C1->C2 1045 // 1046 // Commit: G, C4 1047 // Pivot : none 1048 // 1049 // SetHead(6) 1050 // 1051 // ------------------------------ 1052 // 1053 // Expected in freezer: 1054 // G->C1->C2 1055 // 1056 // Expected in leveldb: 1057 // C2)->C3->C4->C5->C6 1058 // 1059 // Expected head header : C6 1060 // Expected head fast block: C6 1061 // Expected head block : C4 1062 testSetHead(t, &rewindTest{ 1063 canonicalBlocks: 18, 1064 sidechainBlocks: 3, 1065 freezeThreshold: 16, 1066 commitBlock: 4, 1067 pivotBlock: nil, 1068 setheadBlock: 6, 1069 expCanonicalBlocks: 6, 1070 expSidechainBlocks: 0, 1071 expFrozen: 3, 1072 expHeadHeader: 6, 1073 expHeadFastBlock: 6, 1074 expHeadBlock: 4, 1075 }, snapshots) 1076 } 1077 1078 // Tests a sethead for a long canonical chain with frozen blocks and a shorter side 1079 // chain, where a recent block - older than the ancient limit - was already committed 1080 // to disk and then sethead was called. In this case we expect the canonical full 1081 // chain to be rolled back to the committed block. Since the ancient limit was 1082 // underflown, everything needs to be deleted onwards to avoid creating a gap. The 1083 // side chain is nuked by the freezer. 1084 func TestLongOldForkedDeepSetHead(t *testing.T) { testLongOldForkedDeepSetHead(t, false) } 1085 func TestLongOldForkedDeepSetHeadWithSnapshots(t *testing.T) { testLongOldForkedDeepSetHead(t, true) } 1086 1087 func testLongOldForkedDeepSetHead(t *testing.T, snapshots bool) { 1088 // Chain: 1089 // 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) 1090 // └->S1->S2->S3 1091 // 1092 // Frozen: 1093 // G->C1->C2->C3->C4->C5->C6->C7->C8 1094 // 1095 // Commit: G, C4 1096 // Pivot : none 1097 // 1098 // SetHead(6) 1099 // 1100 // ------------------------------ 1101 // 1102 // Expected in freezer: 1103 // G->C1->C2->C3->C4 1104 // 1105 // Expected in leveldb: none 1106 // 1107 // Expected head header : C4 1108 // Expected head fast block: C4 1109 // Expected head block : C4 1110 testSetHead(t, &rewindTest{ 1111 canonicalBlocks: 24, 1112 sidechainBlocks: 3, 1113 freezeThreshold: 16, 1114 commitBlock: 4, 1115 pivotBlock: nil, 1116 setheadBlock: 6, 1117 expCanonicalBlocks: 4, 1118 expSidechainBlocks: 0, 1119 expFrozen: 5, 1120 expHeadHeader: 4, 1121 expHeadFastBlock: 4, 1122 expHeadBlock: 4, 1123 }, snapshots) 1124 } 1125 1126 // Tests a sethead for a long canonical chain with frozen blocks and a shorter 1127 // side chain, where the fast sync pivot point - newer than the ancient limit - 1128 // was already committed to disk and then sethead was called. In this test scenario 1129 // the side chain is below the committed block. In this case we expect the canonical 1130 // full chain to be rolled back to the committed block. Everything above the 1131 // sethead point should be deleted. In between the committed block and the 1132 // requested head the data can remain as "fast sync" data to avoid redownloading 1133 // it. The side chain is nuked by the freezer. 1134 func TestLongOldForkedSnapSyncedShallowSetHead(t *testing.T) { 1135 testLongOldForkedSnapSyncedShallowSetHead(t, false) 1136 } 1137 func TestLongOldForkedSnapSyncedShallowSetHeadWithSnapshots(t *testing.T) { 1138 testLongOldForkedSnapSyncedShallowSetHead(t, true) 1139 } 1140 1141 func testLongOldForkedSnapSyncedShallowSetHead(t *testing.T, snapshots bool) { 1142 // Chain: 1143 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1144 // └->S1->S2->S3 1145 // 1146 // Frozen: 1147 // G->C1->C2 1148 // 1149 // Commit: G, C4 1150 // Pivot : C4 1151 // 1152 // SetHead(6) 1153 // 1154 // ------------------------------ 1155 // 1156 // Expected in freezer: 1157 // G->C1->C2 1158 // 1159 // Expected in leveldb: 1160 // C2)->C3->C4->C5->C6 1161 // 1162 // Expected head header : C6 1163 // Expected head fast block: C6 1164 // Expected head block : C4 1165 testSetHead(t, &rewindTest{ 1166 canonicalBlocks: 18, 1167 sidechainBlocks: 3, 1168 freezeThreshold: 16, 1169 commitBlock: 4, 1170 pivotBlock: uint64ptr(4), 1171 setheadBlock: 6, 1172 expCanonicalBlocks: 6, 1173 expSidechainBlocks: 0, 1174 expFrozen: 3, 1175 expHeadHeader: 6, 1176 expHeadFastBlock: 6, 1177 expHeadBlock: 4, 1178 }, snapshots) 1179 } 1180 1181 // Tests a sethead for a long canonical chain with frozen blocks and a shorter 1182 // side chain, where the fast sync pivot point - older than the ancient limit - 1183 // was already committed to disk and then sethead was called. In this test scenario 1184 // the side chain is below the committed block. In this case we expect the canonical 1185 // full chain to be rolled back to the committed block. Since the ancient limit was 1186 // underflown, everything needs to be deleted onwards to avoid creating a gap. The 1187 // side chain is nuked by the freezer. 1188 func TestLongOldForkedSnapSyncedDeepSetHead(t *testing.T) { 1189 testLongOldForkedSnapSyncedDeepSetHead(t, false) 1190 } 1191 func TestLongOldForkedSnapSyncedDeepSetHeadWithSnapshots(t *testing.T) { 1192 testLongOldForkedSnapSyncedDeepSetHead(t, true) 1193 } 1194 1195 func testLongOldForkedSnapSyncedDeepSetHead(t *testing.T, snapshots bool) { 1196 // Chain: 1197 // 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) 1198 // └->S1->S2->S3 1199 // 1200 // Frozen: 1201 // G->C1->C2->C3->C4->C5->C6->C7->C8 1202 // 1203 // Commit: G, C4 1204 // Pivot : C4 1205 // 1206 // SetHead(6) 1207 // 1208 // ------------------------------ 1209 // 1210 // Expected in freezer: 1211 // G->C1->C2->C3->C4->C5->C6 1212 // 1213 // Expected in leveldb: none 1214 // 1215 // Expected head header : C6 1216 // Expected head fast block: C6 1217 // Expected head block : C4 1218 testSetHead(t, &rewindTest{ 1219 canonicalBlocks: 24, 1220 sidechainBlocks: 3, 1221 freezeThreshold: 16, 1222 commitBlock: 4, 1223 pivotBlock: uint64ptr(4), 1224 setheadBlock: 6, 1225 expCanonicalBlocks: 4, 1226 expSidechainBlocks: 0, 1227 expFrozen: 5, 1228 expHeadHeader: 4, 1229 expHeadFastBlock: 4, 1230 expHeadBlock: 4, 1231 }, snapshots) 1232 } 1233 1234 // Tests a sethead for a long canonical chain with frozen blocks and a shorter 1235 // side chain, where the fast sync pivot point - newer than the ancient limit - 1236 // was not yet committed, but sethead was called. In this test scenario the side 1237 // chain is below the committed block. In this case we expect the chain to detect 1238 // that it was fast syncing and delete everything from the new head, since we can 1239 // just pick up fast syncing from there. The side chain is completely nuked by the 1240 // freezer. 1241 func TestLongOldForkedSnapSyncingShallowSetHead(t *testing.T) { 1242 testLongOldForkedSnapSyncingShallowSetHead(t, false) 1243 } 1244 func TestLongOldForkedSnapSyncingShallowSetHeadWithSnapshots(t *testing.T) { 1245 testLongOldForkedSnapSyncingShallowSetHead(t, true) 1246 } 1247 1248 func testLongOldForkedSnapSyncingShallowSetHead(t *testing.T, snapshots bool) { 1249 // Chain: 1250 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1251 // └->S1->S2->S3 1252 // 1253 // Frozen: 1254 // G->C1->C2 1255 // 1256 // Commit: G 1257 // Pivot : C4 1258 // 1259 // SetHead(6) 1260 // 1261 // ------------------------------ 1262 // 1263 // Expected in freezer: 1264 // G->C1->C2 1265 // 1266 // Expected in leveldb: 1267 // C2)->C3->C4->C5->C6 1268 // 1269 // Expected head header : C6 1270 // Expected head fast block: C6 1271 // Expected head block : G 1272 testSetHead(t, &rewindTest{ 1273 canonicalBlocks: 18, 1274 sidechainBlocks: 3, 1275 freezeThreshold: 16, 1276 commitBlock: 0, 1277 pivotBlock: uint64ptr(4), 1278 setheadBlock: 6, 1279 expCanonicalBlocks: 6, 1280 expSidechainBlocks: 0, 1281 expFrozen: 3, 1282 expHeadHeader: 6, 1283 expHeadFastBlock: 6, 1284 expHeadBlock: 0, 1285 }, snapshots) 1286 } 1287 1288 // Tests a sethead for a long canonical chain with frozen blocks and a shorter 1289 // side chain, where the fast sync pivot point - older than the ancient limit - 1290 // was not yet committed, but sethead was called. In this test scenario the side 1291 // chain is below the committed block. In this case we expect the chain to detect 1292 // that it was fast syncing and delete everything from the new head, since we can 1293 // just pick up fast syncing from there. The side chain is completely nuked by the 1294 // freezer. 1295 func TestLongOldForkedSnapSyncingDeepSetHead(t *testing.T) { 1296 testLongOldForkedSnapSyncingDeepSetHead(t, false) 1297 } 1298 func TestLongOldForkedSnapSyncingDeepSetHeadWithSnapshots(t *testing.T) { 1299 testLongOldForkedSnapSyncingDeepSetHead(t, true) 1300 } 1301 1302 func testLongOldForkedSnapSyncingDeepSetHead(t *testing.T, snapshots bool) { 1303 // Chain: 1304 // 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) 1305 // └->S1->S2->S3 1306 // 1307 // Frozen: 1308 // G->C1->C2->C3->C4->C5->C6->C7->C8 1309 // 1310 // Commit: G 1311 // Pivot : C4 1312 // 1313 // SetHead(6) 1314 // 1315 // ------------------------------ 1316 // 1317 // Expected in freezer: 1318 // G->C1->C2->C3->C4->C5->C6 1319 // 1320 // Expected in leveldb: none 1321 // 1322 // Expected head header : C6 1323 // Expected head fast block: C6 1324 // Expected head block : G 1325 testSetHead(t, &rewindTest{ 1326 canonicalBlocks: 24, 1327 sidechainBlocks: 3, 1328 freezeThreshold: 16, 1329 commitBlock: 0, 1330 pivotBlock: uint64ptr(4), 1331 setheadBlock: 6, 1332 expCanonicalBlocks: 6, 1333 expSidechainBlocks: 0, 1334 expFrozen: 7, 1335 expHeadHeader: 6, 1336 expHeadFastBlock: 6, 1337 expHeadBlock: 0, 1338 }, snapshots) 1339 } 1340 1341 // Tests a sethead for a long canonical chain with frozen blocks and a shorter 1342 // side chain, where a recent block - newer than the ancient limit - was already 1343 // committed to disk and then sethead was called. In this test scenario the side 1344 // chain is above the committed block. In this case the freezer will delete the 1345 // sidechain since it's dangling, reverting to TestLongShallowSetHead. 1346 func TestLongNewerForkedShallowSetHead(t *testing.T) { 1347 testLongNewerForkedShallowSetHead(t, false) 1348 } 1349 func TestLongNewerForkedShallowSetHeadWithSnapshots(t *testing.T) { 1350 testLongNewerForkedShallowSetHead(t, true) 1351 } 1352 1353 func testLongNewerForkedShallowSetHead(t *testing.T, snapshots bool) { 1354 // Chain: 1355 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1356 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1357 // 1358 // Frozen: 1359 // G->C1->C2 1360 // 1361 // Commit: G, C4 1362 // Pivot : none 1363 // 1364 // SetHead(6) 1365 // 1366 // ------------------------------ 1367 // 1368 // Expected in freezer: 1369 // G->C1->C2 1370 // 1371 // Expected in leveldb: 1372 // C2)->C3->C4->C5->C6 1373 // 1374 // Expected head header : C6 1375 // Expected head fast block: C6 1376 // Expected head block : C4 1377 testSetHead(t, &rewindTest{ 1378 canonicalBlocks: 18, 1379 sidechainBlocks: 12, 1380 freezeThreshold: 16, 1381 commitBlock: 4, 1382 pivotBlock: nil, 1383 setheadBlock: 6, 1384 expCanonicalBlocks: 6, 1385 expSidechainBlocks: 0, 1386 expFrozen: 3, 1387 expHeadHeader: 6, 1388 expHeadFastBlock: 6, 1389 expHeadBlock: 4, 1390 }, snapshots) 1391 } 1392 1393 // Tests a sethead for a long canonical chain with frozen blocks and a shorter 1394 // side chain, where a recent block - older than the ancient limit - was already 1395 // committed to disk and then sethead was called. In this test scenario the side 1396 // chain is above the committed block. In this case the freezer will delete the 1397 // sidechain since it's dangling, reverting to TestLongDeepSetHead. 1398 func TestLongNewerForkedDeepSetHead(t *testing.T) { 1399 testLongNewerForkedDeepSetHead(t, false) 1400 } 1401 func TestLongNewerForkedDeepSetHeadWithSnapshots(t *testing.T) { 1402 testLongNewerForkedDeepSetHead(t, true) 1403 } 1404 1405 func testLongNewerForkedDeepSetHead(t *testing.T, snapshots bool) { 1406 // Chain: 1407 // 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) 1408 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1409 // 1410 // Frozen: 1411 // G->C1->C2->C3->C4->C5->C6->C7->C8 1412 // 1413 // Commit: G, C4 1414 // Pivot : none 1415 // 1416 // SetHead(6) 1417 // 1418 // ------------------------------ 1419 // 1420 // Expected in freezer: 1421 // G->C1->C2->C3->C4 1422 // 1423 // Expected in leveldb: none 1424 // 1425 // Expected head header : C4 1426 // Expected head fast block: C4 1427 // Expected head block : C4 1428 testSetHead(t, &rewindTest{ 1429 canonicalBlocks: 24, 1430 sidechainBlocks: 12, 1431 freezeThreshold: 16, 1432 commitBlock: 4, 1433 pivotBlock: nil, 1434 setheadBlock: 6, 1435 expCanonicalBlocks: 4, 1436 expSidechainBlocks: 0, 1437 expFrozen: 5, 1438 expHeadHeader: 4, 1439 expHeadFastBlock: 4, 1440 expHeadBlock: 4, 1441 }, snapshots) 1442 } 1443 1444 // Tests a sethead for a long canonical chain with frozen blocks and a shorter 1445 // side chain, where the fast sync pivot point - newer than the ancient limit - 1446 // was already committed to disk and then sethead was called. In this test scenario 1447 // the side chain is above the committed block. In this case the freezer will delete 1448 // the sidechain since it's dangling, reverting to TestLongSnapSyncedShallowSetHead. 1449 func TestLongNewerForkedSnapSyncedShallowSetHead(t *testing.T) { 1450 testLongNewerForkedSnapSyncedShallowSetHead(t, false) 1451 } 1452 func TestLongNewerForkedSnapSyncedShallowSetHeadWithSnapshots(t *testing.T) { 1453 testLongNewerForkedSnapSyncedShallowSetHead(t, true) 1454 } 1455 1456 func testLongNewerForkedSnapSyncedShallowSetHead(t *testing.T, snapshots bool) { 1457 // Chain: 1458 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1459 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1460 // 1461 // Frozen: 1462 // G->C1->C2 1463 // 1464 // Commit: G, C4 1465 // Pivot : C4 1466 // 1467 // SetHead(6) 1468 // 1469 // ------------------------------ 1470 // 1471 // Expected in freezer: 1472 // G->C1->C2 1473 // 1474 // Expected in leveldb: 1475 // C2)->C3->C4->C5->C6 1476 // 1477 // Expected head header : C6 1478 // Expected head fast block: C6 1479 // Expected head block : C4 1480 testSetHead(t, &rewindTest{ 1481 canonicalBlocks: 18, 1482 sidechainBlocks: 12, 1483 freezeThreshold: 16, 1484 commitBlock: 4, 1485 pivotBlock: uint64ptr(4), 1486 setheadBlock: 6, 1487 expCanonicalBlocks: 6, 1488 expSidechainBlocks: 0, 1489 expFrozen: 3, 1490 expHeadHeader: 6, 1491 expHeadFastBlock: 6, 1492 expHeadBlock: 4, 1493 }, snapshots) 1494 } 1495 1496 // Tests a sethead for a long canonical chain with frozen blocks and a shorter 1497 // side chain, where the fast sync pivot point - older than the ancient limit - 1498 // was already committed to disk and then sethead was called. In this test scenario 1499 // the side chain is above the committed block. In this case the freezer will delete 1500 // the sidechain since it's dangling, reverting to TestLongSnapSyncedDeepSetHead. 1501 func TestLongNewerForkedSnapSyncedDeepSetHead(t *testing.T) { 1502 testLongNewerForkedSnapSyncedDeepSetHead(t, false) 1503 } 1504 func TestLongNewerForkedSnapSyncedDeepSetHeadWithSnapshots(t *testing.T) { 1505 testLongNewerForkedSnapSyncedDeepSetHead(t, true) 1506 } 1507 1508 func testLongNewerForkedSnapSyncedDeepSetHead(t *testing.T, snapshots bool) { 1509 // Chain: 1510 // 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) 1511 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1512 // 1513 // Frozen: 1514 // G->C1->C2->C3->C4->C5->C6->C7->C8 1515 // 1516 // Commit: G, C4 1517 // Pivot : C4 1518 // 1519 // SetHead(6) 1520 // 1521 // ------------------------------ 1522 // 1523 // Expected in freezer: 1524 // G->C1->C2->C3->C4 1525 // 1526 // Expected in leveldb: none 1527 // 1528 // Expected head header : C4 1529 // Expected head fast block: C4 1530 // Expected head block : C 1531 testSetHead(t, &rewindTest{ 1532 canonicalBlocks: 24, 1533 sidechainBlocks: 12, 1534 freezeThreshold: 16, 1535 commitBlock: 4, 1536 pivotBlock: uint64ptr(4), 1537 setheadBlock: 6, 1538 expCanonicalBlocks: 4, 1539 expSidechainBlocks: 0, 1540 expFrozen: 5, 1541 expHeadHeader: 4, 1542 expHeadFastBlock: 4, 1543 expHeadBlock: 4, 1544 }, snapshots) 1545 } 1546 1547 // Tests a sethead for a long canonical chain with frozen blocks and a shorter 1548 // side chain, where the fast sync pivot point - newer than the ancient limit - 1549 // was not yet committed, but sethead was called. In this test scenario the side 1550 // chain is above the committed block. In this case the freezer will delete the 1551 // sidechain since it's dangling, reverting to TestLongSnapSyncinghallowSetHead. 1552 func TestLongNewerForkedSnapSyncingShallowSetHead(t *testing.T) { 1553 testLongNewerForkedSnapSyncingShallowSetHead(t, false) 1554 } 1555 func TestLongNewerForkedSnapSyncingShallowSetHeadWithSnapshots(t *testing.T) { 1556 testLongNewerForkedSnapSyncingShallowSetHead(t, true) 1557 } 1558 1559 func testLongNewerForkedSnapSyncingShallowSetHead(t *testing.T, snapshots bool) { 1560 // Chain: 1561 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1562 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1563 // 1564 // Frozen: 1565 // G->C1->C2 1566 // 1567 // Commit: G 1568 // Pivot : C4 1569 // 1570 // SetHead(6) 1571 // 1572 // ------------------------------ 1573 // 1574 // Expected in freezer: 1575 // G->C1->C2 1576 // 1577 // Expected in leveldb: 1578 // C2)->C3->C4->C5->C6 1579 // 1580 // Expected head header : C6 1581 // Expected head fast block: C6 1582 // Expected head block : G 1583 testSetHead(t, &rewindTest{ 1584 canonicalBlocks: 18, 1585 sidechainBlocks: 12, 1586 freezeThreshold: 16, 1587 commitBlock: 0, 1588 pivotBlock: uint64ptr(4), 1589 setheadBlock: 6, 1590 expCanonicalBlocks: 6, 1591 expSidechainBlocks: 0, 1592 expFrozen: 3, 1593 expHeadHeader: 6, 1594 expHeadFastBlock: 6, 1595 expHeadBlock: 0, 1596 }, snapshots) 1597 } 1598 1599 // Tests a sethead for a long canonical chain with frozen blocks and a shorter 1600 // side chain, where the fast sync pivot point - older than the ancient limit - 1601 // was not yet committed, but sethead was called. In this test scenario the side 1602 // chain is above the committed block. In this case the freezer will delete the 1603 // sidechain since it's dangling, reverting to TestLongSnapSyncingDeepSetHead. 1604 func TestLongNewerForkedSnapSyncingDeepSetHead(t *testing.T) { 1605 testLongNewerForkedSnapSyncingDeepSetHead(t, false) 1606 } 1607 func TestLongNewerForkedSnapSyncingDeepSetHeadWithSnapshots(t *testing.T) { 1608 testLongNewerForkedSnapSyncingDeepSetHead(t, true) 1609 } 1610 1611 func testLongNewerForkedSnapSyncingDeepSetHead(t *testing.T, snapshots bool) { 1612 // Chain: 1613 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) 1614 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 1615 // 1616 // Frozen: 1617 // G->C1->C2->C3->C4->C5->C6->C7->C8 1618 // 1619 // Commit: G 1620 // Pivot : C4 1621 // 1622 // SetHead(6) 1623 // 1624 // ------------------------------ 1625 // 1626 // Expected in freezer: 1627 // G->C1->C2->C3->C4->C5->C6 1628 // 1629 // Expected in leveldb: none 1630 // 1631 // Expected head header : C6 1632 // Expected head fast block: C6 1633 // Expected head block : G 1634 testSetHead(t, &rewindTest{ 1635 canonicalBlocks: 24, 1636 sidechainBlocks: 12, 1637 freezeThreshold: 16, 1638 commitBlock: 0, 1639 pivotBlock: uint64ptr(4), 1640 setheadBlock: 6, 1641 expCanonicalBlocks: 6, 1642 expSidechainBlocks: 0, 1643 expFrozen: 7, 1644 expHeadHeader: 6, 1645 expHeadFastBlock: 6, 1646 expHeadBlock: 0, 1647 }, snapshots) 1648 } 1649 1650 // Tests a sethead for a long canonical chain with frozen blocks and a longer side 1651 // chain, where a recent block - newer than the ancient limit - was already committed 1652 // to disk and then sethead was called. In this case the freezer will delete the 1653 // sidechain since it's dangling, reverting to TestLongShallowSetHead. 1654 func TestLongReorgedShallowSetHead(t *testing.T) { testLongReorgedShallowSetHead(t, false) } 1655 func TestLongReorgedShallowSetHeadWithSnapshots(t *testing.T) { testLongReorgedShallowSetHead(t, true) } 1656 1657 func testLongReorgedShallowSetHead(t *testing.T, snapshots bool) { 1658 // Chain: 1659 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1660 // └->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 1661 // 1662 // Frozen: 1663 // G->C1->C2 1664 // 1665 // Commit: G, C4 1666 // Pivot : none 1667 // 1668 // SetHead(6) 1669 // 1670 // ------------------------------ 1671 // 1672 // Expected in freezer: 1673 // G->C1->C2 1674 // 1675 // Expected in leveldb: 1676 // C2)->C3->C4->C5->C6 1677 // 1678 // Expected head header : C6 1679 // Expected head fast block: C6 1680 // Expected head block : C4 1681 testSetHead(t, &rewindTest{ 1682 canonicalBlocks: 18, 1683 sidechainBlocks: 26, 1684 freezeThreshold: 16, 1685 commitBlock: 4, 1686 pivotBlock: nil, 1687 setheadBlock: 6, 1688 expCanonicalBlocks: 6, 1689 expSidechainBlocks: 0, 1690 expFrozen: 3, 1691 expHeadHeader: 6, 1692 expHeadFastBlock: 6, 1693 expHeadBlock: 4, 1694 }, snapshots) 1695 } 1696 1697 // Tests a sethead for a long canonical chain with frozen blocks and a longer side 1698 // chain, where a recent block - older than the ancient limit - was already committed 1699 // to disk and then sethead was called. In this case the freezer will delete the 1700 // sidechain since it's dangling, reverting to TestLongDeepSetHead. 1701 func TestLongReorgedDeepSetHead(t *testing.T) { testLongReorgedDeepSetHead(t, false) } 1702 func TestLongReorgedDeepSetHeadWithSnapshots(t *testing.T) { testLongReorgedDeepSetHead(t, true) } 1703 1704 func testLongReorgedDeepSetHead(t *testing.T, snapshots bool) { 1705 // Chain: 1706 // 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) 1707 // └->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 1708 // 1709 // Frozen: 1710 // G->C1->C2->C3->C4->C5->C6->C7->C8 1711 // 1712 // Commit: G, C4 1713 // Pivot : none 1714 // 1715 // SetHead(6) 1716 // 1717 // ------------------------------ 1718 // 1719 // Expected in freezer: 1720 // G->C1->C2->C3->C4 1721 // 1722 // Expected in leveldb: none 1723 // 1724 // Expected head header : C4 1725 // Expected head fast block: C4 1726 // Expected head block : C4 1727 testSetHead(t, &rewindTest{ 1728 canonicalBlocks: 24, 1729 sidechainBlocks: 26, 1730 freezeThreshold: 16, 1731 commitBlock: 4, 1732 pivotBlock: nil, 1733 setheadBlock: 6, 1734 expCanonicalBlocks: 4, 1735 expSidechainBlocks: 0, 1736 expFrozen: 5, 1737 expHeadHeader: 4, 1738 expHeadFastBlock: 4, 1739 expHeadBlock: 4, 1740 }, snapshots) 1741 } 1742 1743 // Tests a sethead for a long canonical chain with frozen blocks and a longer 1744 // side chain, where the fast sync pivot point - newer than the ancient limit - 1745 // was already committed to disk and then sethead was called. In this case the 1746 // freezer will delete the sidechain since it's dangling, reverting to 1747 // TestLongSnapSyncedShallowSetHead. 1748 func TestLongReorgedSnapSyncedShallowSetHead(t *testing.T) { 1749 testLongReorgedSnapSyncedShallowSetHead(t, false) 1750 } 1751 func TestLongReorgedSnapSyncedShallowSetHeadWithSnapshots(t *testing.T) { 1752 testLongReorgedSnapSyncedShallowSetHead(t, true) 1753 } 1754 1755 func testLongReorgedSnapSyncedShallowSetHead(t *testing.T, snapshots bool) { 1756 // Chain: 1757 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1758 // └->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 1759 // 1760 // Frozen: 1761 // G->C1->C2 1762 // 1763 // Commit: G, C4 1764 // Pivot : C4 1765 // 1766 // SetHead(6) 1767 // 1768 // ------------------------------ 1769 // 1770 // Expected in freezer: 1771 // G->C1->C2 1772 // 1773 // Expected in leveldb: 1774 // C2)->C3->C4->C5->C6 1775 // 1776 // Expected head header : C6 1777 // Expected head fast block: C6 1778 // Expected head block : C4 1779 testSetHead(t, &rewindTest{ 1780 canonicalBlocks: 18, 1781 sidechainBlocks: 26, 1782 freezeThreshold: 16, 1783 commitBlock: 4, 1784 pivotBlock: uint64ptr(4), 1785 setheadBlock: 6, 1786 expCanonicalBlocks: 6, 1787 expSidechainBlocks: 0, 1788 expFrozen: 3, 1789 expHeadHeader: 6, 1790 expHeadFastBlock: 6, 1791 expHeadBlock: 4, 1792 }, snapshots) 1793 } 1794 1795 // Tests a sethead for a long canonical chain with frozen blocks and a longer 1796 // side chain, where the fast sync pivot point - older than the ancient limit - 1797 // was already committed to disk and then sethead was called. In this case the 1798 // freezer will delete the sidechain since it's dangling, reverting to 1799 // TestLongSnapSyncedDeepSetHead. 1800 func TestLongReorgedSnapSyncedDeepSetHead(t *testing.T) { 1801 testLongReorgedSnapSyncedDeepSetHead(t, false) 1802 } 1803 func TestLongReorgedSnapSyncedDeepSetHeadWithSnapshots(t *testing.T) { 1804 testLongReorgedSnapSyncedDeepSetHead(t, true) 1805 } 1806 1807 func testLongReorgedSnapSyncedDeepSetHead(t *testing.T, snapshots bool) { 1808 // Chain: 1809 // 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) 1810 // └->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 1811 // 1812 // Frozen: 1813 // G->C1->C2->C3->C4->C5->C6->C7->C8 1814 // 1815 // Commit: G, C4 1816 // Pivot : C4 1817 // 1818 // SetHead(6) 1819 // 1820 // ------------------------------ 1821 // 1822 // Expected in freezer: 1823 // G->C1->C2->C3->C4 1824 // 1825 // Expected in leveldb: none 1826 // 1827 // Expected head header : C4 1828 // Expected head fast block: C4 1829 // Expected head block : C4 1830 testSetHead(t, &rewindTest{ 1831 canonicalBlocks: 24, 1832 sidechainBlocks: 26, 1833 freezeThreshold: 16, 1834 commitBlock: 4, 1835 pivotBlock: uint64ptr(4), 1836 setheadBlock: 6, 1837 expCanonicalBlocks: 4, 1838 expSidechainBlocks: 0, 1839 expFrozen: 5, 1840 expHeadHeader: 4, 1841 expHeadFastBlock: 4, 1842 expHeadBlock: 4, 1843 }, snapshots) 1844 } 1845 1846 // Tests a sethead for a long canonical chain with frozen blocks and a longer 1847 // side chain, where the fast sync pivot point - newer than the ancient limit - 1848 // was not yet committed, but sethead was called. In this case we expect the 1849 // chain to detect that it was fast syncing and delete everything from the new 1850 // head, since we can just pick up fast syncing from there. The side chain is 1851 // completely nuked by the freezer. 1852 func TestLongReorgedSnapSyncingShallowSetHead(t *testing.T) { 1853 testLongReorgedSnapSyncingShallowSetHead(t, false) 1854 } 1855 func TestLongReorgedSnapSyncingShallowSetHeadWithSnapshots(t *testing.T) { 1856 testLongReorgedSnapSyncingShallowSetHead(t, true) 1857 } 1858 1859 func testLongReorgedSnapSyncingShallowSetHead(t *testing.T, snapshots bool) { 1860 // Chain: 1861 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 1862 // └->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 1863 // 1864 // Frozen: 1865 // G->C1->C2 1866 // 1867 // Commit: G 1868 // Pivot : C4 1869 // 1870 // SetHead(6) 1871 // 1872 // ------------------------------ 1873 // 1874 // Expected in freezer: 1875 // G->C1->C2 1876 // 1877 // Expected in leveldb: 1878 // C2)->C3->C4->C5->C6 1879 // 1880 // Expected head header : C6 1881 // Expected head fast block: C6 1882 // Expected head block : G 1883 testSetHead(t, &rewindTest{ 1884 canonicalBlocks: 18, 1885 sidechainBlocks: 26, 1886 freezeThreshold: 16, 1887 commitBlock: 0, 1888 pivotBlock: uint64ptr(4), 1889 setheadBlock: 6, 1890 expCanonicalBlocks: 6, 1891 expSidechainBlocks: 0, 1892 expFrozen: 3, 1893 expHeadHeader: 6, 1894 expHeadFastBlock: 6, 1895 expHeadBlock: 0, 1896 }, snapshots) 1897 } 1898 1899 // Tests a sethead for a long canonical chain with frozen blocks and a longer 1900 // side chain, where the fast sync pivot point - older than the ancient limit - 1901 // was not yet committed, but sethead was called. In this case we expect the 1902 // chain to detect that it was fast syncing and delete everything from the new 1903 // head, since we can just pick up fast syncing from there. The side chain is 1904 // completely nuked by the freezer. 1905 func TestLongReorgedSnapSyncingDeepSetHead(t *testing.T) { 1906 testLongReorgedSnapSyncingDeepSetHead(t, false) 1907 } 1908 func TestLongReorgedSnapSyncingDeepSetHeadWithSnapshots(t *testing.T) { 1909 testLongReorgedSnapSyncingDeepSetHead(t, true) 1910 } 1911 1912 func testLongReorgedSnapSyncingDeepSetHead(t *testing.T, snapshots bool) { 1913 // Chain: 1914 // 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) 1915 // └->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 1916 // 1917 // Frozen: 1918 // G->C1->C2->C3->C4->C5->C6->C7->C8 1919 // 1920 // Commit: G 1921 // Pivot : C4 1922 // 1923 // SetHead(6) 1924 // 1925 // ------------------------------ 1926 // 1927 // Expected in freezer: 1928 // G->C1->C2->C3->C4->C5->C6 1929 // 1930 // Expected in leveldb: none 1931 // 1932 // Expected head header : C6 1933 // Expected head fast block: C6 1934 // Expected head block : G 1935 testSetHead(t, &rewindTest{ 1936 canonicalBlocks: 24, 1937 sidechainBlocks: 26, 1938 freezeThreshold: 16, 1939 commitBlock: 0, 1940 pivotBlock: uint64ptr(4), 1941 setheadBlock: 6, 1942 expCanonicalBlocks: 6, 1943 expSidechainBlocks: 0, 1944 expFrozen: 7, 1945 expHeadHeader: 6, 1946 expHeadFastBlock: 6, 1947 expHeadBlock: 0, 1948 }, snapshots) 1949 } 1950 1951 func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) { 1952 // It's hard to follow the test case, visualize the input 1953 // log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) 1954 // fmt.Println(tt.dump(false)) 1955 1956 // Create a temporary persistent database 1957 datadir := t.TempDir() 1958 1959 db, err := rawdb.Open(rawdb.OpenOptions{ 1960 Directory: datadir, 1961 AncientsDirectory: datadir, 1962 }) 1963 if err != nil { 1964 t.Fatalf("Failed to create persistent database: %v", err) 1965 } 1966 defer db.Close() 1967 1968 // Initialize a fresh chain 1969 var ( 1970 gspec = &Genesis{ 1971 BaseFee: big.NewInt(params.InitialBaseFee), 1972 Config: params.AllEthashProtocolChanges, 1973 } 1974 engine = ethash.NewFullFaker() 1975 config = &CacheConfig{ 1976 TrieCleanLimit: 256, 1977 TrieDirtyLimit: 256, 1978 TrieTimeLimit: 5 * time.Minute, 1979 SnapshotLimit: 0, // Disable snapshot 1980 } 1981 ) 1982 if snapshots { 1983 config.SnapshotLimit = 256 1984 config.SnapshotWait = true 1985 } 1986 chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil) 1987 if err != nil { 1988 t.Fatalf("Failed to create chain: %v", err) 1989 } 1990 defer chain.Stop() 1991 1992 // If sidechain blocks are needed, make a light chain and import it 1993 var sideblocks types.Blocks 1994 if tt.sidechainBlocks > 0 { 1995 sideblocks, _ = GenerateChain(gspec.Config, gspec.ToBlock(), engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *BlockGen) { 1996 b.SetCoinbase(common.Address{0x01}) 1997 }) 1998 if _, err := chain.InsertChain(sideblocks); err != nil { 1999 t.Fatalf("Failed to import side chain: %v", err) 2000 } 2001 } 2002 canonblocks, _ := GenerateChain(gspec.Config, gspec.ToBlock(), engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) { 2003 b.SetCoinbase(common.Address{0x02}) 2004 b.SetDifficulty(big.NewInt(1000000)) 2005 }) 2006 if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil { 2007 t.Fatalf("Failed to import canonical chain start: %v", err) 2008 } 2009 if tt.commitBlock > 0 { 2010 chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), false) 2011 if snapshots { 2012 if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { 2013 t.Fatalf("Failed to flatten snapshots: %v", err) 2014 } 2015 } 2016 } 2017 if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil { 2018 t.Fatalf("Failed to import canonical chain tail: %v", err) 2019 } 2020 // Manually dereference anything not committed to not have to work with 128+ tries 2021 for _, block := range sideblocks { 2022 chain.stateCache.TrieDB().Dereference(block.Root()) 2023 } 2024 for _, block := range canonblocks { 2025 chain.stateCache.TrieDB().Dereference(block.Root()) 2026 } 2027 // Force run a freeze cycle 2028 type freezer interface { 2029 Freeze(threshold uint64) error 2030 Ancients() (uint64, error) 2031 } 2032 db.(freezer).Freeze(tt.freezeThreshold) 2033 2034 // Set the simulated pivot block 2035 if tt.pivotBlock != nil { 2036 rawdb.WriteLastPivotNumber(db, *tt.pivotBlock) 2037 } 2038 // Set the head of the chain back to the requested number 2039 chain.SetHead(tt.setheadBlock) 2040 2041 // Iterate over all the remaining blocks and ensure there are no gaps 2042 verifyNoGaps(t, chain, true, canonblocks) 2043 verifyNoGaps(t, chain, false, sideblocks) 2044 verifyCutoff(t, chain, true, canonblocks, tt.expCanonicalBlocks) 2045 verifyCutoff(t, chain, false, sideblocks, tt.expSidechainBlocks) 2046 2047 if head := chain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader { 2048 t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader) 2049 } 2050 if head := chain.CurrentSnapBlock(); head.Number.Uint64() != tt.expHeadFastBlock { 2051 t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, tt.expHeadFastBlock) 2052 } 2053 if head := chain.CurrentBlock(); head.Number.Uint64() != tt.expHeadBlock { 2054 t.Errorf("Head block mismatch: have %d, want %d", head.Number, tt.expHeadBlock) 2055 } 2056 if frozen, err := db.(freezer).Ancients(); err != nil { 2057 t.Errorf("Failed to retrieve ancient count: %v\n", err) 2058 } else if int(frozen) != tt.expFrozen { 2059 t.Errorf("Frozen block count mismatch: have %d, want %d", frozen, tt.expFrozen) 2060 } 2061 } 2062 2063 // verifyNoGaps checks that there are no gaps after the initial set of blocks in 2064 // the database and errors if found. 2065 func verifyNoGaps(t *testing.T, chain *BlockChain, canonical bool, inserted types.Blocks) { 2066 t.Helper() 2067 2068 var end uint64 2069 for i := uint64(0); i <= uint64(len(inserted)); i++ { 2070 header := chain.GetHeaderByNumber(i) 2071 if header == nil && end == 0 { 2072 end = i 2073 } 2074 if header != nil && end > 0 { 2075 if canonical { 2076 t.Errorf("Canonical header gap between #%d-#%d", end, i-1) 2077 } else { 2078 t.Errorf("Sidechain header gap between #%d-#%d", end, i-1) 2079 } 2080 end = 0 // Reset for further gap detection 2081 } 2082 } 2083 end = 0 2084 for i := uint64(0); i <= uint64(len(inserted)); i++ { 2085 block := chain.GetBlockByNumber(i) 2086 if block == nil && end == 0 { 2087 end = i 2088 } 2089 if block != nil && end > 0 { 2090 if canonical { 2091 t.Errorf("Canonical block gap between #%d-#%d", end, i-1) 2092 } else { 2093 t.Errorf("Sidechain block gap between #%d-#%d", end, i-1) 2094 } 2095 end = 0 // Reset for further gap detection 2096 } 2097 } 2098 end = 0 2099 for i := uint64(1); i <= uint64(len(inserted)); i++ { 2100 receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()) 2101 if receipts == nil && end == 0 { 2102 end = i 2103 } 2104 if receipts != nil && end > 0 { 2105 if canonical { 2106 t.Errorf("Canonical receipt gap between #%d-#%d", end, i-1) 2107 } else { 2108 t.Errorf("Sidechain receipt gap between #%d-#%d", end, i-1) 2109 } 2110 end = 0 // Reset for further gap detection 2111 } 2112 } 2113 } 2114 2115 // verifyCutoff checks that there are no chain data available in the chain after 2116 // the specified limit, but that it is available before. 2117 func verifyCutoff(t *testing.T, chain *BlockChain, canonical bool, inserted types.Blocks, head int) { 2118 t.Helper() 2119 2120 for i := 1; i <= len(inserted); i++ { 2121 if i <= head { 2122 if header := chain.GetHeader(inserted[i-1].Hash(), uint64(i)); header == nil { 2123 if canonical { 2124 t.Errorf("Canonical header #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 2125 } else { 2126 t.Errorf("Sidechain header #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 2127 } 2128 } 2129 if block := chain.GetBlock(inserted[i-1].Hash(), uint64(i)); block == nil { 2130 if canonical { 2131 t.Errorf("Canonical block #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 2132 } else { 2133 t.Errorf("Sidechain block #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 2134 } 2135 } 2136 if receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()); receipts == nil { 2137 if canonical { 2138 t.Errorf("Canonical receipts #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 2139 } else { 2140 t.Errorf("Sidechain receipts #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 2141 } 2142 } 2143 } else { 2144 if header := chain.GetHeader(inserted[i-1].Hash(), uint64(i)); header != nil { 2145 if canonical { 2146 t.Errorf("Canonical header #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 2147 } else { 2148 t.Errorf("Sidechain header #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 2149 } 2150 } 2151 if block := chain.GetBlock(inserted[i-1].Hash(), uint64(i)); block != nil { 2152 if canonical { 2153 t.Errorf("Canonical block #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 2154 } else { 2155 t.Errorf("Sidechain block #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 2156 } 2157 } 2158 if receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()); receipts != nil { 2159 if canonical { 2160 t.Errorf("Canonical receipts #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 2161 } else { 2162 t.Errorf("Sidechain receipts #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 2163 } 2164 } 2165 } 2166 } 2167 } 2168 2169 // uint64ptr is a weird helper to allow 1-line constant pointer creation. 2170 func uint64ptr(n uint64) *uint64 { 2171 return &n 2172 }