github.com/theQRL/go-zond@v0.2.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/beacon" 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 // TODO(now.youtrack.cloud/issue/TGZ-10) 154 /* 155 // Tests a sethead for a short canonical chain where a recent block was already 156 // committed to disk and then the sethead called. In this case we expect the full 157 // chain to be rolled back to the committed block. Everything above the sethead 158 // point should be deleted. In between the committed block and the requested head 159 // the data can remain as "fast sync" data to avoid redownloading it. 160 func TestShortSetHead(t *testing.T) { testShortSetHead(t, false) } 161 162 func TestShortSetHeadWithSnapshots(t *testing.T) { testShortSetHead(t, true) } 163 164 func testShortSetHead(t *testing.T, snapshots bool) { 165 // Chain: 166 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 167 // 168 // Frozen: none 169 // Commit: G, C4 170 // Pivot : none 171 // 172 // SetHead(7) 173 // 174 // ------------------------------ 175 // 176 // Expected in leveldb: 177 // G->C1->C2->C3->C4->C5->C6->C7 178 // 179 // Expected head header : C7 180 // Expected head fast block: C7 181 // Expected head block : C4 182 testSetHead(t, &rewindTest{ 183 canonicalBlocks: 8, 184 sidechainBlocks: 0, 185 freezeThreshold: 16, 186 commitBlock: 4, 187 pivotBlock: nil, 188 setheadBlock: 7, 189 expCanonicalBlocks: 7, 190 expSidechainBlocks: 0, 191 expFrozen: 0, 192 expHeadHeader: 7, 193 expHeadFastBlock: 7, 194 expHeadBlock: 4, 195 }, snapshots) 196 } 197 198 // Tests a sethead for a short canonical chain where the fast sync pivot point was 199 // already committed, after which sethead was called. In this case we expect the 200 // chain to behave like in full sync mode, rolling back to the committed block 201 // Everything above the sethead point should be deleted. In between the committed 202 // block and the requested head the data can remain as "fast sync" data to avoid 203 // redownloading it. 204 func TestShortSnapSyncedSetHead(t *testing.T) { testShortSnapSyncedSetHead(t, false) } 205 206 func TestShortSnapSyncedSetHeadWithSnapshots(t *testing.T) { testShortSnapSyncedSetHead(t, true) } 207 208 func testShortSnapSyncedSetHead(t *testing.T, snapshots bool) { 209 // Chain: 210 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 211 // 212 // Frozen: none 213 // Commit: G, C4 214 // Pivot : C4 215 // 216 // SetHead(7) 217 // 218 // ------------------------------ 219 // 220 // Expected in leveldb: 221 // G->C1->C2->C3->C4->C5->C6->C7 222 // 223 // Expected head header : C7 224 // Expected head fast block: C7 225 // Expected head block : C4 226 testSetHead(t, &rewindTest{ 227 canonicalBlocks: 8, 228 freezeThreshold: 16, 229 // commitBlock: 4, 230 pivotBlock: uint64ptr(4), 231 setheadBlock: 7, 232 expCanonicalBlocks: 7, 233 expFrozen: 0, 234 expHeadHeader: 7, 235 expHeadFastBlock: 7, 236 // expHeadBlock: 4, 237 expHeadBlock: 7, 238 }, snapshots) 239 } 240 241 // Tests a sethead for a short canonical chain where the fast sync pivot point was 242 // not yet committed, but sethead was called. In this case we expect the chain to 243 // detect that it was fast syncing and delete everything from the new head, since 244 // we can just pick up fast syncing from there. The head full block should be set 245 // to the genesis. 246 func TestShortSnapSyncingSetHead(t *testing.T) { testShortSnapSyncingSetHead(t, false) } 247 248 func TestShortSnapSyncingSetHeadWithSnapshots(t *testing.T) { testShortSnapSyncingSetHead(t, true) } 249 250 func testShortSnapSyncingSetHead(t *testing.T, snapshots bool) { 251 // Chain: 252 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 253 // 254 // Frozen: none 255 // Commit: G 256 // Pivot : C4 257 // 258 // SetHead(7) 259 // 260 // ------------------------------ 261 // 262 // Expected in leveldb: 263 // G->C1->C2->C3->C4->C5->C6->C7 264 // 265 // Expected head header : C7 266 // Expected head fast block: C7 267 // Expected head block : G 268 testSetHead(t, &rewindTest{ 269 canonicalBlocks: 8, 270 freezeThreshold: 16, 271 commitBlock: 0, 272 pivotBlock: uint64ptr(4), 273 setheadBlock: 7, 274 expCanonicalBlocks: 7, 275 expFrozen: 0, 276 expHeadHeader: 7, 277 expHeadFastBlock: 7, 278 // expHeadBlock: 0, 279 expHeadBlock: 7, 280 }, snapshots) 281 } 282 283 // Tests a sethead for a short canonical chain and a longer side chain, where a 284 // recent block was already committed to disk and then sethead was called. In this 285 // case we expect the canonical full chain to be rolled back to the committed block. 286 // All data above the sethead point should be deleted. In between the committed 287 // block and the requested head the data can remain as "fast sync" data to avoid 288 // having to redownload it. The side chain should be truncated to the head set. 289 // 290 // The side chain could be left to be if the fork point was before the new head 291 // we are deleting to, but it would be exceedingly hard to detect that case and 292 // properly handle it, so we'll trade extra work in exchange for simpler code. 293 func TestShortReorgedSetHead(t *testing.T) { testShortReorgedSetHead(t, false) } 294 295 func TestShortReorgedSetHeadWithSnapshots(t *testing.T) { testShortReorgedSetHead(t, true) } 296 297 func testShortReorgedSetHead(t *testing.T, snapshots bool) { 298 // Chain: 299 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 300 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 301 // 302 // Frozen: none 303 // Commit: G, C4 304 // Pivot : none 305 // 306 // SetHead(7) 307 // 308 // ------------------------------ 309 // 310 // Expected in leveldb: 311 // G->C1->C2->C3->C4->C5->C6->C7 312 // └->S1->S2->S3->S4->S5->S6->S7 313 // 314 // Expected head header : C7 315 // Expected head fast block: C7 316 // Expected head block : C4 317 testSetHead(t, &rewindTest{ 318 canonicalBlocks: 8, 319 sidechainBlocks: 10, 320 freezeThreshold: 16, 321 commitBlock: 4, 322 pivotBlock: nil, 323 setheadBlock: 7, 324 expCanonicalBlocks: 7, 325 expSidechainBlocks: 7, 326 expFrozen: 0, 327 expHeadHeader: 7, 328 expHeadFastBlock: 7, 329 expHeadBlock: 4, 330 }, snapshots) 331 } 332 333 // Tests a sethead for a short canonical chain and a longer side chain, where 334 // the fast sync pivot point was already committed to disk and then sethead was 335 // called. In this case we expect the canonical full chain to be rolled back to 336 // the committed block. All data above the sethead point should be deleted. In 337 // between the committed block and the requested head the data can remain as 338 // "fast sync" data to avoid having to redownload it. The side chain should be 339 // truncated to the head set. 340 // 341 // The side chain could be left to be if the fork point was before the new head 342 // we are deleting to, but it would be exceedingly hard to detect that case and 343 // properly handle it, so we'll trade extra work in exchange for simpler code. 344 // func TestShortReorgedSnapSyncedSetHead(t *testing.T) { 345 // testShortReorgedSnapSyncedSetHead(t, false) 346 // } 347 // func TestShortReorgedSnapSyncedSetHeadWithSnapshots(t *testing.T) { 348 // testShortReorgedSnapSyncedSetHead(t, true) 349 // } 350 351 func testShortReorgedSnapSyncedSetHead(t *testing.T, snapshots bool) { 352 // Chain: 353 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 354 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 355 // 356 // Frozen: none 357 // Commit: G, C4 358 // Pivot : C4 359 // 360 // SetHead(7) 361 // 362 // ------------------------------ 363 // 364 // Expected in leveldb: 365 // G->C1->C2->C3->C4->C5->C6->C7 366 // └->S1->S2->S3->S4->S5->S6->S7 367 // 368 // Expected head header : C7 369 // Expected head fast block: C7 370 // Expected head block : C4 371 testSetHead(t, &rewindTest{ 372 canonicalBlocks: 8, 373 // sidechainBlocks: 10, 374 freezeThreshold: 16, 375 commitBlock: 4, 376 pivotBlock: uint64ptr(4), 377 setheadBlock: 7, 378 expCanonicalBlocks: 7, 379 // expSidechainBlocks: 7, 380 expFrozen: 0, 381 expHeadHeader: 7, 382 expHeadFastBlock: 7, 383 expHeadBlock: 4, 384 }, snapshots) 385 } 386 387 // Tests a sethead for a short canonical chain and a longer side chain, where 388 // the fast sync pivot point was not yet committed, but sethead was called. In 389 // this case we expect the chain to detect that it was fast syncing and delete 390 // everything from the new head, since we can just pick up fast syncing from 391 // there. 392 // 393 // The side chain could be left to be if the fork point was before the new head 394 // we are deleting to, but it would be exceedingly hard to detect that case and 395 // properly handle it, so we'll trade extra work in exchange for simpler code. 396 // func TestShortReorgedSnapSyncingSetHead(t *testing.T) { 397 // testShortReorgedSnapSyncingSetHead(t, false) 398 // } 399 // func TestShortReorgedSnapSyncingSetHeadWithSnapshots(t *testing.T) { 400 // testShortReorgedSnapSyncingSetHead(t, true) 401 // } 402 403 func testShortReorgedSnapSyncingSetHead(t *testing.T, snapshots bool) { 404 // Chain: 405 // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) 406 // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 407 // 408 // Frozen: none 409 // Commit: G 410 // Pivot : C4 411 // 412 // SetHead(7) 413 // 414 // ------------------------------ 415 // 416 // Expected in leveldb: 417 // G->C1->C2->C3->C4->C5->C6->C7 418 // └->S1->S2->S3->S4->S5->S6->S7 419 // 420 // Expected head header : C7 421 // Expected head fast block: C7 422 // Expected head block : G 423 testSetHead(t, &rewindTest{ 424 canonicalBlocks: 8, 425 // sidechainBlocks: 10, 426 freezeThreshold: 16, 427 commitBlock: 0, 428 pivotBlock: uint64ptr(4), 429 setheadBlock: 7, 430 expCanonicalBlocks: 7, 431 // expSidechainBlocks: 7, 432 expFrozen: 0, 433 expHeadHeader: 7, 434 expHeadFastBlock: 7, 435 expHeadBlock: 0, 436 }, snapshots) 437 } 438 439 // Tests a sethead for a long canonical chain with frozen blocks where a recent 440 // block - newer than the ancient limit - was already committed to disk and then 441 // sethead was called. In this case we expect the full chain to be rolled back 442 // to the committed block. Everything above the sethead point should be deleted. 443 // In between the committed block and the requested head the data can remain as 444 // "fast sync" data to avoid redownloading it. 445 // func TestLongShallowSetHead(t *testing.T) { testLongShallowSetHead(t, false) } 446 // func TestLongShallowSetHeadWithSnapshots(t *testing.T) { testLongShallowSetHead(t, true) } 447 448 func testLongShallowSetHead(t *testing.T, snapshots bool) { 449 // Chain: 450 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 451 // 452 // Frozen: 453 // G->C1->C2 454 // 455 // Commit: G, C4 456 // Pivot : none 457 // 458 // SetHead(6) 459 // 460 // ------------------------------ 461 // 462 // Expected in freezer: 463 // G->C1->C2 464 // 465 // Expected in leveldb: 466 // C2)->C3->C4->C5->C6 467 // 468 // Expected head header : C6 469 // Expected head fast block: C6 470 // Expected head block : C4 471 testSetHead(t, &rewindTest{ 472 canonicalBlocks: 18, 473 // sidechainBlocks: 0, 474 freezeThreshold: 16, 475 commitBlock: 4, 476 pivotBlock: nil, 477 setheadBlock: 6, 478 expCanonicalBlocks: 6, 479 // expSidechainBlocks: 0, 480 expFrozen: 3, 481 expHeadHeader: 6, 482 expHeadFastBlock: 6, 483 expHeadBlock: 4, 484 }, snapshots) 485 } 486 487 // Tests a sethead for a long canonical chain with frozen blocks where a recent 488 // block - older than the ancient limit - was already committed to disk and then 489 // sethead was called. In this case we expect the full chain to be rolled back 490 // to the committed block. Since the ancient limit was underflown, everything 491 // needs to be deleted onwards to avoid creating a gap. 492 // func TestLongDeepSetHead(t *testing.T) { testLongDeepSetHead(t, false) } 493 // func TestLongDeepSetHeadWithSnapshots(t *testing.T) { testLongDeepSetHead(t, true) } 494 495 func testLongDeepSetHead(t *testing.T, snapshots bool) { 496 // Chain: 497 // 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) 498 // 499 // Frozen: 500 // G->C1->C2->C3->C4->C5->C6->C7->C8 501 // 502 // Commit: G, C4 503 // Pivot : none 504 // 505 // SetHead(6) 506 // 507 // ------------------------------ 508 // 509 // Expected in freezer: 510 // G->C1->C2->C3->C4 511 // 512 // Expected in leveldb: none 513 // 514 // Expected head header : C4 515 // Expected head fast block: C4 516 // Expected head block : C4 517 testSetHead(t, &rewindTest{ 518 canonicalBlocks: 24, 519 // sidechainBlocks: 0, 520 freezeThreshold: 16, 521 commitBlock: 4, 522 pivotBlock: nil, 523 setheadBlock: 6, 524 expCanonicalBlocks: 4, 525 // expSidechainBlocks: 0, 526 expFrozen: 5, 527 expHeadHeader: 4, 528 expHeadFastBlock: 4, 529 expHeadBlock: 4, 530 }, snapshots) 531 } 532 533 // Tests a sethead for a long canonical chain with frozen blocks where the fast 534 // sync pivot point - newer than the ancient limit - was already committed, after 535 // which sethead was called. In this case we expect the full chain to be rolled 536 // back to the committed block. Everything above the sethead point should be 537 // deleted. In between the committed block and the requested head the data can 538 // remain as "fast sync" data to avoid redownloading it. 539 // func TestLongSnapSyncedShallowSetHead(t *testing.T) { 540 // testLongSnapSyncedShallowSetHead(t, false) 541 // } 542 // func TestLongSnapSyncedShallowSetHeadWithSnapshots(t *testing.T) { 543 // testLongSnapSyncedShallowSetHead(t, true) 544 // } 545 546 func testLongSnapSyncedShallowSetHead(t *testing.T, snapshots bool) { 547 // Chain: 548 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 549 // 550 // Frozen: 551 // G->C1->C2 552 // 553 // Commit: G, C4 554 // Pivot : C4 555 // 556 // SetHead(6) 557 // 558 // ------------------------------ 559 // 560 // Expected in freezer: 561 // G->C1->C2 562 // 563 // Expected in leveldb: 564 // C2)->C3->C4->C5->C6 565 // 566 // Expected head header : C6 567 // Expected head fast block: C6 568 // Expected head block : C4 569 testSetHead(t, &rewindTest{ 570 canonicalBlocks: 18, 571 // sidechainBlocks: 0, 572 freezeThreshold: 16, 573 commitBlock: 4, 574 pivotBlock: uint64ptr(4), 575 setheadBlock: 6, 576 expCanonicalBlocks: 6, 577 // expSidechainBlocks: 0, 578 expFrozen: 3, 579 expHeadHeader: 6, 580 expHeadFastBlock: 6, 581 expHeadBlock: 4, 582 }, snapshots) 583 } 584 585 // Tests a sethead for a long canonical chain with frozen blocks where the fast 586 // sync pivot point - older than the ancient limit - was already committed, after 587 // which sethead was called. In this case we expect the full chain to be rolled 588 // back to the committed block. Since the ancient limit was underflown, everything 589 // needs to be deleted onwards to avoid creating a gap. 590 // func TestLongSnapSyncedDeepSetHead(t *testing.T) { testLongSnapSyncedDeepSetHead(t, false) } 591 // func TestLongSnapSyncedDeepSetHeadWithSnapshots(t *testing.T) { testLongSnapSyncedDeepSetHead(t, true) } 592 593 func testLongSnapSyncedDeepSetHead(t *testing.T, snapshots bool) { 594 // Chain: 595 // 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) 596 // 597 // Frozen: 598 // G->C1->C2->C3->C4->C5->C6->C7->C8 599 // 600 // Commit: G, C4 601 // Pivot : C4 602 // 603 // SetHead(6) 604 // 605 // ------------------------------ 606 // 607 // Expected in freezer: 608 // G->C1->C2->C3->C4 609 // 610 // Expected in leveldb: none 611 // 612 // Expected head header : C4 613 // Expected head fast block: C4 614 // Expected head block : C4 615 testSetHead(t, &rewindTest{ 616 canonicalBlocks: 24, 617 // sidechainBlocks: 0, 618 freezeThreshold: 16, 619 commitBlock: 4, 620 pivotBlock: uint64ptr(4), 621 setheadBlock: 6, 622 expCanonicalBlocks: 4, 623 // expSidechainBlocks: 0, 624 expFrozen: 5, 625 expHeadHeader: 4, 626 expHeadFastBlock: 4, 627 expHeadBlock: 4, 628 }, snapshots) 629 } 630 631 // Tests a sethead for a long canonical chain with frozen blocks where the fast 632 // sync pivot point - newer than the ancient limit - was not yet committed, but 633 // sethead was called. In this case we expect the chain to detect that it was fast 634 // syncing and delete everything from the new head, since we can just pick up fast 635 // syncing from there. 636 // func TestLongSnapSyncingShallowSetHead(t *testing.T) { 637 // testLongSnapSyncingShallowSetHead(t, false) 638 // } 639 // func TestLongSnapSyncingShallowSetHeadWithSnapshots(t *testing.T) { 640 // testLongSnapSyncingShallowSetHead(t, true) 641 // } 642 643 func testLongSnapSyncingShallowSetHead(t *testing.T, snapshots bool) { 644 // Chain: 645 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 646 // 647 // Frozen: 648 // G->C1->C2 649 // 650 // Commit: G 651 // Pivot : C4 652 // 653 // SetHead(6) 654 // 655 // ------------------------------ 656 // 657 // Expected in freezer: 658 // G->C1->C2 659 // 660 // Expected in leveldb: 661 // C2)->C3->C4->C5->C6 662 // 663 // Expected head header : C6 664 // Expected head fast block: C6 665 // Expected head block : G 666 testSetHead(t, &rewindTest{ 667 canonicalBlocks: 18, 668 // sidechainBlocks: 0, 669 freezeThreshold: 16, 670 commitBlock: 0, 671 pivotBlock: uint64ptr(4), 672 setheadBlock: 6, 673 expCanonicalBlocks: 6, 674 // expSidechainBlocks: 0, 675 expFrozen: 3, 676 expHeadHeader: 6, 677 expHeadFastBlock: 6, 678 expHeadBlock: 0, 679 }, snapshots) 680 } 681 682 // Tests a sethead for a long canonical chain with frozen blocks where the fast 683 // sync pivot point - older than the ancient limit - was not yet committed, but 684 // sethead was called. In this case we expect the chain to detect that it was fast 685 // syncing and delete everything from the new head, since we can just pick up fast 686 // syncing from there. 687 // func TestLongSnapSyncingDeepSetHead(t *testing.T) { 688 // testLongSnapSyncingDeepSetHead(t, false) 689 // } 690 // func TestLongSnapSyncingDeepSetHeadWithSnapshots(t *testing.T) { 691 // testLongSnapSyncingDeepSetHead(t, true) 692 // } 693 694 func testLongSnapSyncingDeepSetHead(t *testing.T, snapshots bool) { 695 // Chain: 696 // 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) 697 // 698 // Frozen: 699 // G->C1->C2->C3->C4->C5->C6->C7->C8 700 // 701 // Commit: G 702 // Pivot : C4 703 // 704 // SetHead(6) 705 // 706 // ------------------------------ 707 // 708 // Expected in freezer: 709 // G->C1->C2->C3->C4->C5->C6 710 // 711 // Expected in leveldb: none 712 // 713 // Expected head header : C6 714 // Expected head fast block: C6 715 // Expected head block : G 716 testSetHead(t, &rewindTest{ 717 canonicalBlocks: 24, 718 // sidechainBlocks: 0, 719 freezeThreshold: 16, 720 commitBlock: 0, 721 pivotBlock: uint64ptr(4), 722 setheadBlock: 6, 723 expCanonicalBlocks: 6, 724 // expSidechainBlocks: 0, 725 expFrozen: 7, 726 expHeadHeader: 6, 727 expHeadFastBlock: 6, 728 expHeadBlock: 0, 729 }, snapshots) 730 } 731 732 // Tests a sethead for a long canonical chain with frozen blocks and a longer side 733 // chain, where a recent block - newer than the ancient limit - was already committed 734 // to disk and then sethead was called. In this case the freezer will delete the 735 // sidechain since it's dangling, reverting to TestLongShallowSetHead. 736 // func TestLongReorgedShallowSetHead(t *testing.T) { testLongReorgedShallowSetHead(t, false) } 737 // func TestLongReorgedShallowSetHeadWithSnapshots(t *testing.T) { testLongReorgedShallowSetHead(t, true) } 738 739 func testLongReorgedShallowSetHead(t *testing.T, snapshots bool) { 740 // Chain: 741 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 742 // └->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 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: 26, 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 and a longer side 780 // chain, where a recent block - older than the ancient limit - was already committed 781 // to disk and then sethead was called. In this case the freezer will delete the 782 // sidechain since it's dangling, reverting to TestLongDeepSetHead. 783 // func TestLongReorgedDeepSetHead(t *testing.T) { testLongReorgedDeepSetHead(t, false) } 784 // func TestLongReorgedDeepSetHeadWithSnapshots(t *testing.T) { testLongReorgedDeepSetHead(t, true) } 785 786 func testLongReorgedDeepSetHead(t *testing.T, snapshots bool) { 787 // Chain: 788 // 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) 789 // └->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 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: 26, 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 and a longer 826 // side chain, where the fast sync pivot point - newer than the ancient limit - 827 // was already committed to disk and then sethead was called. In this case the 828 // freezer will delete the sidechain since it's dangling, reverting to 829 // TestLongSnapSyncedShallowSetHead. 830 // func TestLongReorgedSnapSyncedShallowSetHead(t *testing.T) { 831 // testLongReorgedSnapSyncedShallowSetHead(t, false) 832 // } 833 // func TestLongReorgedSnapSyncedShallowSetHeadWithSnapshots(t *testing.T) { 834 // testLongReorgedSnapSyncedShallowSetHead(t, true) 835 // } 836 837 func testLongReorgedSnapSyncedShallowSetHead(t *testing.T, snapshots bool) { 838 // Chain: 839 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 840 // └->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 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: 26, 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 and a longer 878 // side chain, where the fast sync pivot point - older than the ancient limit - 879 // was already committed to disk and then sethead was called. In this case the 880 // freezer will delete the sidechain since it's dangling, reverting to 881 // TestLongSnapSyncedDeepSetHead. 882 // func TestLongReorgedSnapSyncedDeepSetHead(t *testing.T) { 883 // testLongReorgedSnapSyncedDeepSetHead(t, false) 884 // } 885 // func TestLongReorgedSnapSyncedDeepSetHeadWithSnapshots(t *testing.T) { 886 // testLongReorgedSnapSyncedDeepSetHead(t, true) 887 // } 888 889 func testLongReorgedSnapSyncedDeepSetHead(t *testing.T, snapshots bool) { 890 // Chain: 891 // 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) 892 // └->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 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: 26, 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 and a longer 929 // side chain, where the fast sync pivot point - newer than the ancient limit - 930 // was not yet committed, but sethead was called. In this case we expect the 931 // chain to detect that it was fast syncing and delete everything from the new 932 // head, since we can just pick up fast syncing from there. The side chain is 933 // completely nuked by the freezer. 934 // func TestLongReorgedSnapSyncingShallowSetHead(t *testing.T) { 935 // testLongReorgedSnapSyncingShallowSetHead(t, false) 936 // } 937 // func TestLongReorgedSnapSyncingShallowSetHeadWithSnapshots(t *testing.T) { 938 // testLongReorgedSnapSyncingShallowSetHead(t, true) 939 // } 940 941 func testLongReorgedSnapSyncingShallowSetHead(t *testing.T, snapshots bool) { 942 // Chain: 943 // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) 944 // └->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 945 // 946 // Frozen: 947 // G->C1->C2 948 // 949 // Commit: G 950 // Pivot : C4 951 // 952 // SetHead(6) 953 // 954 // ------------------------------ 955 // 956 // Expected in freezer: 957 // G->C1->C2 958 // 959 // Expected in leveldb: 960 // C2)->C3->C4->C5->C6 961 // 962 // Expected head header : C6 963 // Expected head fast block: C6 964 // Expected head block : G 965 testSetHead(t, &rewindTest{ 966 canonicalBlocks: 18, 967 // sidechainBlocks: 26, 968 freezeThreshold: 16, 969 commitBlock: 0, 970 pivotBlock: uint64ptr(4), 971 setheadBlock: 6, 972 expCanonicalBlocks: 6, 973 // expSidechainBlocks: 0, 974 expFrozen: 3, 975 expHeadHeader: 6, 976 expHeadFastBlock: 6, 977 expHeadBlock: 0, 978 }, snapshots) 979 } 980 981 // Tests a sethead for a long canonical chain with frozen blocks and a longer 982 // side chain, where the fast sync pivot point - older than the ancient limit - 983 // was not yet committed, but sethead was called. In this case we expect the 984 // chain to detect that it was fast syncing and delete everything from the new 985 // head, since we can just pick up fast syncing from there. The side chain is 986 // completely nuked by the freezer. 987 // func TestLongReorgedSnapSyncingDeepSetHead(t *testing.T) { 988 // testLongReorgedSnapSyncingDeepSetHead(t, false) 989 // } 990 // func TestLongReorgedSnapSyncingDeepSetHeadWithSnapshots(t *testing.T) { 991 // testLongReorgedSnapSyncingDeepSetHead(t, true) 992 // } 993 994 func testLongReorgedSnapSyncingDeepSetHead(t *testing.T, snapshots bool) { 995 // Chain: 996 // 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) 997 // └->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 998 // 999 // Frozen: 1000 // G->C1->C2->C3->C4->C5->C6->C7->C8 1001 // 1002 // Commit: G 1003 // Pivot : C4 1004 // 1005 // SetHead(6) 1006 // 1007 // ------------------------------ 1008 // 1009 // Expected in freezer: 1010 // G->C1->C2->C3->C4->C5->C6 1011 // 1012 // Expected in leveldb: none 1013 // 1014 // Expected head header : C6 1015 // Expected head fast block: C6 1016 // Expected head block : G 1017 testSetHead(t, &rewindTest{ 1018 canonicalBlocks: 24, 1019 // sidechainBlocks: 26, 1020 freezeThreshold: 16, 1021 commitBlock: 0, 1022 pivotBlock: uint64ptr(4), 1023 setheadBlock: 6, 1024 expCanonicalBlocks: 6, 1025 // expSidechainBlocks: 0, 1026 expFrozen: 7, 1027 expHeadHeader: 6, 1028 expHeadFastBlock: 6, 1029 expHeadBlock: 0, 1030 }, snapshots) 1031 } 1032 */ 1033 1034 func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) { 1035 for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { 1036 testSetHeadWithScheme(t, tt, snapshots, scheme) 1037 } 1038 } 1039 1040 func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) { 1041 // It's hard to follow the test case, visualize the input 1042 // log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) 1043 // fmt.Println(tt.dump(false)) 1044 1045 // Create a temporary persistent database 1046 datadir := t.TempDir() 1047 ancient := path.Join(datadir, "ancient") 1048 1049 db, err := rawdb.Open(rawdb.OpenOptions{ 1050 Directory: datadir, 1051 AncientsDirectory: ancient, 1052 Ephemeral: true, 1053 }) 1054 if err != nil { 1055 t.Fatalf("Failed to create persistent database: %v", err) 1056 } 1057 defer db.Close() 1058 1059 // Initialize a fresh chain 1060 var ( 1061 gspec = &Genesis{ 1062 BaseFee: big.NewInt(params.InitialBaseFee), 1063 Config: params.AllBeaconProtocolChanges, 1064 } 1065 engine = beacon.NewFullFaker() 1066 config = &CacheConfig{ 1067 TrieCleanLimit: 256, 1068 TrieDirtyLimit: 256, 1069 TrieTimeLimit: 5 * time.Minute, 1070 SnapshotLimit: 0, // Disable snapshot 1071 StateScheme: scheme, 1072 } 1073 ) 1074 if snapshots { 1075 config.SnapshotLimit = 256 1076 config.SnapshotWait = true 1077 } 1078 chain, err := NewBlockChain(db, config, gspec, engine, vm.Config{}, nil) 1079 if err != nil { 1080 t.Fatalf("Failed to create chain: %v", err) 1081 } 1082 defer chain.Stop() 1083 1084 // If sidechain blocks are needed, make a light chain and import it 1085 var sideblocks types.Blocks 1086 if tt.sidechainBlocks > 0 { 1087 sideblocks, _ = GenerateChain(gspec.Config, gspec.ToBlock(), engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *BlockGen) { 1088 b.SetCoinbase(common.Address{0x01}) 1089 }) 1090 if _, err := chain.InsertChain(sideblocks); err != nil { 1091 t.Fatalf("Failed to import side chain: %v", err) 1092 } 1093 } 1094 canonblocks, _ := GenerateChain(gspec.Config, gspec.ToBlock(), engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) { 1095 b.SetCoinbase(common.Address{0x02}) 1096 }) 1097 if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil { 1098 t.Fatalf("Failed to import canonical chain start: %v", err) 1099 } 1100 if tt.commitBlock > 0 { 1101 chain.triedb.Commit(canonblocks[tt.commitBlock-1].Root(), false) 1102 if snapshots { 1103 if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { 1104 t.Fatalf("Failed to flatten snapshots: %v", err) 1105 } 1106 } 1107 } 1108 if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil { 1109 t.Fatalf("Failed to import canonical chain tail: %v", err) 1110 } 1111 // Reopen the trie database without persisting in-memory dirty nodes. 1112 chain.triedb.Close() 1113 dbconfig := &trie.Config{} 1114 if scheme == rawdb.PathScheme { 1115 dbconfig.PathDB = pathdb.Defaults 1116 } else { 1117 dbconfig.HashDB = hashdb.Defaults 1118 } 1119 chain.triedb = trie.NewDatabase(chain.db, dbconfig) 1120 chain.stateCache = state.NewDatabaseWithNodeDB(chain.db, chain.triedb) 1121 1122 // Force run a freeze cycle 1123 type freezer interface { 1124 Freeze(threshold uint64) error 1125 Ancients() (uint64, error) 1126 } 1127 db.(freezer).Freeze(tt.freezeThreshold) 1128 1129 // Set the simulated pivot block 1130 if tt.pivotBlock != nil { 1131 rawdb.WriteLastPivotNumber(db, *tt.pivotBlock) 1132 } 1133 // Set the head of the chain back to the requested number 1134 chain.SetHead(tt.setheadBlock) 1135 1136 // Iterate over all the remaining blocks and ensure there are no gaps 1137 verifyNoGaps(t, chain, true, canonblocks) 1138 verifyNoGaps(t, chain, false, sideblocks) 1139 verifyCutoff(t, chain, true, canonblocks, tt.expCanonicalBlocks) 1140 verifyCutoff(t, chain, false, sideblocks, tt.expSidechainBlocks) 1141 1142 if head := chain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader { 1143 t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader) 1144 } 1145 if head := chain.CurrentSnapBlock(); head.Number.Uint64() != tt.expHeadFastBlock { 1146 t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, tt.expHeadFastBlock) 1147 } 1148 if head := chain.CurrentBlock(); head.Number.Uint64() != tt.expHeadBlock { 1149 t.Errorf("Head block mismatch: have %d, want %d", head.Number, tt.expHeadBlock) 1150 } 1151 if frozen, err := db.(freezer).Ancients(); err != nil { 1152 t.Errorf("Failed to retrieve ancient count: %v\n", err) 1153 } else if int(frozen) != tt.expFrozen { 1154 t.Errorf("Frozen block count mismatch: have %d, want %d", frozen, tt.expFrozen) 1155 } 1156 } 1157 1158 // verifyNoGaps checks that there are no gaps after the initial set of blocks in 1159 // the database and errors if found. 1160 func verifyNoGaps(t *testing.T, chain *BlockChain, canonical bool, inserted types.Blocks) { 1161 t.Helper() 1162 1163 var end uint64 1164 for i := uint64(0); i <= uint64(len(inserted)); i++ { 1165 header := chain.GetHeaderByNumber(i) 1166 if header == nil && end == 0 { 1167 end = i 1168 } 1169 if header != nil && end > 0 { 1170 if canonical { 1171 t.Errorf("Canonical header gap between #%d-#%d", end, i-1) 1172 } else { 1173 t.Errorf("Sidechain header gap between #%d-#%d", end, i-1) 1174 } 1175 end = 0 // Reset for further gap detection 1176 } 1177 } 1178 end = 0 1179 for i := uint64(0); i <= uint64(len(inserted)); i++ { 1180 block := chain.GetBlockByNumber(i) 1181 if block == nil && end == 0 { 1182 end = i 1183 } 1184 if block != nil && end > 0 { 1185 if canonical { 1186 t.Errorf("Canonical block gap between #%d-#%d", end, i-1) 1187 } else { 1188 t.Errorf("Sidechain block gap between #%d-#%d", end, i-1) 1189 } 1190 end = 0 // Reset for further gap detection 1191 } 1192 } 1193 end = 0 1194 for i := uint64(1); i <= uint64(len(inserted)); i++ { 1195 receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()) 1196 if receipts == nil && end == 0 { 1197 end = i 1198 } 1199 if receipts != nil && end > 0 { 1200 if canonical { 1201 t.Errorf("Canonical receipt gap between #%d-#%d", end, i-1) 1202 } else { 1203 t.Errorf("Sidechain receipt gap between #%d-#%d", end, i-1) 1204 } 1205 end = 0 // Reset for further gap detection 1206 } 1207 } 1208 } 1209 1210 // verifyCutoff checks that there are no chain data available in the chain after 1211 // the specified limit, but that it is available before. 1212 func verifyCutoff(t *testing.T, chain *BlockChain, canonical bool, inserted types.Blocks, head int) { 1213 t.Helper() 1214 1215 for i := 1; i <= len(inserted); i++ { 1216 if i <= head { 1217 if header := chain.GetHeader(inserted[i-1].Hash(), uint64(i)); header == nil { 1218 if canonical { 1219 t.Errorf("Canonical header #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 1220 } else { 1221 t.Errorf("Sidechain header #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 1222 } 1223 } 1224 if block := chain.GetBlock(inserted[i-1].Hash(), uint64(i)); block == nil { 1225 if canonical { 1226 t.Errorf("Canonical block #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 1227 } else { 1228 t.Errorf("Sidechain block #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 1229 } 1230 } 1231 if receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()); receipts == nil { 1232 if canonical { 1233 t.Errorf("Canonical receipts #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 1234 } else { 1235 t.Errorf("Sidechain receipts #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 1236 } 1237 } 1238 } else { 1239 if header := chain.GetHeader(inserted[i-1].Hash(), uint64(i)); header != nil { 1240 if canonical { 1241 t.Errorf("Canonical header #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 1242 } else { 1243 t.Errorf("Sidechain header #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 1244 } 1245 } 1246 if block := chain.GetBlock(inserted[i-1].Hash(), uint64(i)); block != nil { 1247 if canonical { 1248 t.Errorf("Canonical block #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 1249 } else { 1250 t.Errorf("Sidechain block #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 1251 } 1252 } 1253 if receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()); receipts != nil { 1254 if canonical { 1255 t.Errorf("Canonical receipts #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 1256 } else { 1257 t.Errorf("Sidechain receipts #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) 1258 } 1259 } 1260 } 1261 } 1262 } 1263 1264 /* 1265 // uint64ptr is a weird helper to allow 1-line constant pointer creation. 1266 func uint64ptr(n uint64) *uint64 { 1267 return &n 1268 } 1269 */