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