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  */