github.com/jimmyx0x/go-ethereum@v1.10.28/core/blockchain_repair_test.go (about)

     1  // Copyright 2020 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Tests that abnormal program termination (i.e.crash) and restart doesn't leave
    18  // the database in some strange state with gaps in the chain, nor with block data
    19  // dangling in the future.
    20  
    21  package core
    22  
    23  import (
    24  	"math/big"
    25  	"testing"
    26  	"time"
    27  
    28  	"github.com/ethereum/go-ethereum/common"
    29  	"github.com/ethereum/go-ethereum/consensus/ethash"
    30  	"github.com/ethereum/go-ethereum/core/rawdb"
    31  	"github.com/ethereum/go-ethereum/core/types"
    32  	"github.com/ethereum/go-ethereum/core/vm"
    33  	"github.com/ethereum/go-ethereum/params"
    34  )
    35  
    36  // Tests a recovery for a short canonical chain where a recent block was already
    37  // committed to disk and then the process crashed. In this case we expect the full
    38  // chain to be rolled back to the committed block, but the chain data itself left
    39  // in the database for replaying.
    40  func TestShortRepair(t *testing.T)              { testShortRepair(t, false) }
    41  func TestShortRepairWithSnapshots(t *testing.T) { testShortRepair(t, true) }
    42  
    43  func testShortRepair(t *testing.T, snapshots bool) {
    44  	// Chain:
    45  	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
    46  	//
    47  	// Frozen: none
    48  	// Commit: G, C4
    49  	// Pivot : none
    50  	//
    51  	// CRASH
    52  	//
    53  	// ------------------------------
    54  	//
    55  	// Expected in leveldb:
    56  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
    57  	//
    58  	// Expected head header    : C8
    59  	// Expected head fast block: C8
    60  	// Expected head block     : C4
    61  	testRepair(t, &rewindTest{
    62  		canonicalBlocks:    8,
    63  		sidechainBlocks:    0,
    64  		freezeThreshold:    16,
    65  		commitBlock:        4,
    66  		pivotBlock:         nil,
    67  		expCanonicalBlocks: 8,
    68  		expSidechainBlocks: 0,
    69  		expFrozen:          0,
    70  		expHeadHeader:      8,
    71  		expHeadFastBlock:   8,
    72  		expHeadBlock:       4,
    73  	}, snapshots)
    74  }
    75  
    76  // Tests a recovery for a short canonical chain where the fast sync pivot point was
    77  // already committed, after which the process crashed. In this case we expect the full
    78  // chain to be rolled back to the committed block, but the chain data itself left in
    79  // the database for replaying.
    80  func TestShortSnapSyncedRepair(t *testing.T)              { testShortSnapSyncedRepair(t, false) }
    81  func TestShortSnapSyncedRepairWithSnapshots(t *testing.T) { testShortSnapSyncedRepair(t, true) }
    82  
    83  func testShortSnapSyncedRepair(t *testing.T, snapshots bool) {
    84  	// Chain:
    85  	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
    86  	//
    87  	// Frozen: none
    88  	// Commit: G, C4
    89  	// Pivot : C4
    90  	//
    91  	// CRASH
    92  	//
    93  	// ------------------------------
    94  	//
    95  	// Expected in leveldb:
    96  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
    97  	//
    98  	// Expected head header    : C8
    99  	// Expected head fast block: C8
   100  	// Expected head block     : C4
   101  	testRepair(t, &rewindTest{
   102  		canonicalBlocks:    8,
   103  		sidechainBlocks:    0,
   104  		freezeThreshold:    16,
   105  		commitBlock:        4,
   106  		pivotBlock:         uint64ptr(4),
   107  		expCanonicalBlocks: 8,
   108  		expSidechainBlocks: 0,
   109  		expFrozen:          0,
   110  		expHeadHeader:      8,
   111  		expHeadFastBlock:   8,
   112  		expHeadBlock:       4,
   113  	}, snapshots)
   114  }
   115  
   116  // Tests a recovery for a short canonical chain where the fast sync pivot point was
   117  // not yet committed, but the process crashed. In this case we expect the chain to
   118  // detect that it was fast syncing and not delete anything, since we can just pick
   119  // up directly where we left off.
   120  func TestShortSnapSyncingRepair(t *testing.T)              { testShortSnapSyncingRepair(t, false) }
   121  func TestShortSnapSyncingRepairWithSnapshots(t *testing.T) { testShortSnapSyncingRepair(t, true) }
   122  
   123  func testShortSnapSyncingRepair(t *testing.T, snapshots bool) {
   124  	// Chain:
   125  	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
   126  	//
   127  	// Frozen: none
   128  	// Commit: G
   129  	// Pivot : C4
   130  	//
   131  	// CRASH
   132  	//
   133  	// ------------------------------
   134  	//
   135  	// Expected in leveldb:
   136  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   137  	//
   138  	// Expected head header    : C8
   139  	// Expected head fast block: C8
   140  	// Expected head block     : G
   141  	testRepair(t, &rewindTest{
   142  		canonicalBlocks:    8,
   143  		sidechainBlocks:    0,
   144  		freezeThreshold:    16,
   145  		commitBlock:        0,
   146  		pivotBlock:         uint64ptr(4),
   147  		expCanonicalBlocks: 8,
   148  		expSidechainBlocks: 0,
   149  		expFrozen:          0,
   150  		expHeadHeader:      8,
   151  		expHeadFastBlock:   8,
   152  		expHeadBlock:       0,
   153  	}, snapshots)
   154  }
   155  
   156  // Tests a recovery for a short canonical chain and a shorter side chain, where a
   157  // recent block was already committed to disk and then the process crashed. In this
   158  // test scenario the side chain is below the committed block. In this case we expect
   159  // the canonical chain to be rolled back to the committed block, but the chain data
   160  // itself left in the database for replaying.
   161  func TestShortOldForkedRepair(t *testing.T)              { testShortOldForkedRepair(t, false) }
   162  func TestShortOldForkedRepairWithSnapshots(t *testing.T) { testShortOldForkedRepair(t, true) }
   163  
   164  func testShortOldForkedRepair(t *testing.T, snapshots bool) {
   165  	// Chain:
   166  	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
   167  	//   └->S1->S2->S3
   168  	//
   169  	// Frozen: none
   170  	// Commit: G, C4
   171  	// Pivot : none
   172  	//
   173  	// CRASH
   174  	//
   175  	// ------------------------------
   176  	//
   177  	// Expected in leveldb:
   178  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   179  	//   └->S1->S2->S3
   180  	//
   181  	// Expected head header    : C8
   182  	// Expected head fast block: C8
   183  	// Expected head block     : C4
   184  	testRepair(t, &rewindTest{
   185  		canonicalBlocks:    8,
   186  		sidechainBlocks:    3,
   187  		freezeThreshold:    16,
   188  		commitBlock:        4,
   189  		pivotBlock:         nil,
   190  		expCanonicalBlocks: 8,
   191  		expSidechainBlocks: 3,
   192  		expFrozen:          0,
   193  		expHeadHeader:      8,
   194  		expHeadFastBlock:   8,
   195  		expHeadBlock:       4,
   196  	}, snapshots)
   197  }
   198  
   199  // Tests a recovery for a short canonical chain and a shorter side chain, where
   200  // the fast sync pivot point was already committed to disk and then the process
   201  // crashed. In this test scenario the side chain is below the committed block. In
   202  // this case we expect the canonical chain to be rolled back to the committed block,
   203  // but the chain data itself left in the database for replaying.
   204  func TestShortOldForkedSnapSyncedRepair(t *testing.T) {
   205  	testShortOldForkedSnapSyncedRepair(t, false)
   206  }
   207  func TestShortOldForkedSnapSyncedRepairWithSnapshots(t *testing.T) {
   208  	testShortOldForkedSnapSyncedRepair(t, true)
   209  }
   210  
   211  func testShortOldForkedSnapSyncedRepair(t *testing.T, snapshots bool) {
   212  	// Chain:
   213  	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
   214  	//   └->S1->S2->S3
   215  	//
   216  	// Frozen: none
   217  	// Commit: G, C4
   218  	// Pivot : C4
   219  	//
   220  	// CRASH
   221  	//
   222  	// ------------------------------
   223  	//
   224  	// Expected in leveldb:
   225  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   226  	//   └->S1->S2->S3
   227  	//
   228  	// Expected head header    : C8
   229  	// Expected head fast block: C8
   230  	// Expected head block     : C4
   231  	testRepair(t, &rewindTest{
   232  		canonicalBlocks:    8,
   233  		sidechainBlocks:    3,
   234  		freezeThreshold:    16,
   235  		commitBlock:        4,
   236  		pivotBlock:         uint64ptr(4),
   237  		expCanonicalBlocks: 8,
   238  		expSidechainBlocks: 3,
   239  		expFrozen:          0,
   240  		expHeadHeader:      8,
   241  		expHeadFastBlock:   8,
   242  		expHeadBlock:       4,
   243  	}, snapshots)
   244  }
   245  
   246  // Tests a recovery for a short canonical chain and a shorter side chain, where
   247  // the fast sync pivot point was not yet committed, but the process crashed. In this
   248  // test scenario the side chain is below the committed block. In this case we expect
   249  // the chain to detect that it was fast syncing and not delete anything, since we
   250  // can just pick up directly where we left off.
   251  func TestShortOldForkedSnapSyncingRepair(t *testing.T) {
   252  	testShortOldForkedSnapSyncingRepair(t, false)
   253  }
   254  func TestShortOldForkedSnapSyncingRepairWithSnapshots(t *testing.T) {
   255  	testShortOldForkedSnapSyncingRepair(t, true)
   256  }
   257  
   258  func testShortOldForkedSnapSyncingRepair(t *testing.T, snapshots bool) {
   259  	// Chain:
   260  	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
   261  	//   └->S1->S2->S3
   262  	//
   263  	// Frozen: none
   264  	// Commit: G
   265  	// Pivot : C4
   266  	//
   267  	// CRASH
   268  	//
   269  	// ------------------------------
   270  	//
   271  	// Expected in leveldb:
   272  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   273  	//   └->S1->S2->S3
   274  	//
   275  	// Expected head header    : C8
   276  	// Expected head fast block: C8
   277  	// Expected head block     : G
   278  	testRepair(t, &rewindTest{
   279  		canonicalBlocks:    8,
   280  		sidechainBlocks:    3,
   281  		freezeThreshold:    16,
   282  		commitBlock:        0,
   283  		pivotBlock:         uint64ptr(4),
   284  		expCanonicalBlocks: 8,
   285  		expSidechainBlocks: 3,
   286  		expFrozen:          0,
   287  		expHeadHeader:      8,
   288  		expHeadFastBlock:   8,
   289  		expHeadBlock:       0,
   290  	}, snapshots)
   291  }
   292  
   293  // Tests a recovery for a short canonical chain and a shorter side chain, where a
   294  // recent block was already committed to disk and then the process crashed. In this
   295  // test scenario the side chain reaches above the committed block. In this case we
   296  // expect the canonical chain to be rolled back to the committed block, but the
   297  // chain data itself left in the database for replaying.
   298  func TestShortNewlyForkedRepair(t *testing.T)              { testShortNewlyForkedRepair(t, false) }
   299  func TestShortNewlyForkedRepairWithSnapshots(t *testing.T) { testShortNewlyForkedRepair(t, true) }
   300  
   301  func testShortNewlyForkedRepair(t *testing.T, snapshots bool) {
   302  	// Chain:
   303  	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
   304  	//   └->S1->S2->S3->S4->S5->S6
   305  	//
   306  	// Frozen: none
   307  	// Commit: G, C4
   308  	// Pivot : none
   309  	//
   310  	// CRASH
   311  	//
   312  	// ------------------------------
   313  	//
   314  	// Expected in leveldb:
   315  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   316  	//   └->S1->S2->S3->S4->S5->S6
   317  	//
   318  	// Expected head header    : C8
   319  	// Expected head fast block: C8
   320  	// Expected head block     : C4
   321  	testRepair(t, &rewindTest{
   322  		canonicalBlocks:    8,
   323  		sidechainBlocks:    6,
   324  		freezeThreshold:    16,
   325  		commitBlock:        4,
   326  		pivotBlock:         nil,
   327  		expCanonicalBlocks: 8,
   328  		expSidechainBlocks: 6,
   329  		expFrozen:          0,
   330  		expHeadHeader:      8,
   331  		expHeadFastBlock:   8,
   332  		expHeadBlock:       4,
   333  	}, snapshots)
   334  }
   335  
   336  // Tests a recovery for a short canonical chain and a shorter side chain, where
   337  // the fast sync pivot point was already committed to disk and then the process
   338  // crashed. In this test scenario the side chain reaches above the committed block.
   339  // In this case we expect the canonical chain to be rolled back to the committed
   340  // block, but the chain data itself left in the database for replaying.
   341  func TestShortNewlyForkedSnapSyncedRepair(t *testing.T) {
   342  	testShortNewlyForkedSnapSyncedRepair(t, false)
   343  }
   344  func TestShortNewlyForkedSnapSyncedRepairWithSnapshots(t *testing.T) {
   345  	testShortNewlyForkedSnapSyncedRepair(t, true)
   346  }
   347  
   348  func testShortNewlyForkedSnapSyncedRepair(t *testing.T, snapshots bool) {
   349  	// Chain:
   350  	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
   351  	//   └->S1->S2->S3->S4->S5->S6
   352  	//
   353  	// Frozen: none
   354  	// Commit: G, C4
   355  	// Pivot : C4
   356  	//
   357  	// CRASH
   358  	//
   359  	// ------------------------------
   360  	//
   361  	// Expected in leveldb:
   362  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   363  	//   └->S1->S2->S3->S4->S5->S6
   364  	//
   365  	// Expected head header    : C8
   366  	// Expected head fast block: C8
   367  	// Expected head block     : C4
   368  	testRepair(t, &rewindTest{
   369  		canonicalBlocks:    8,
   370  		sidechainBlocks:    6,
   371  		freezeThreshold:    16,
   372  		commitBlock:        4,
   373  		pivotBlock:         uint64ptr(4),
   374  		expCanonicalBlocks: 8,
   375  		expSidechainBlocks: 6,
   376  		expFrozen:          0,
   377  		expHeadHeader:      8,
   378  		expHeadFastBlock:   8,
   379  		expHeadBlock:       4,
   380  	}, snapshots)
   381  }
   382  
   383  // Tests a recovery for a short canonical chain and a shorter side chain, where
   384  // the fast sync pivot point was not yet committed, but the process crashed. In
   385  // this test scenario the side chain reaches above the committed block. In this
   386  // case we expect the chain to detect that it was fast syncing and not delete
   387  // anything, since we can just pick up directly where we left off.
   388  func TestShortNewlyForkedSnapSyncingRepair(t *testing.T) {
   389  	testShortNewlyForkedSnapSyncingRepair(t, false)
   390  }
   391  func TestShortNewlyForkedSnapSyncingRepairWithSnapshots(t *testing.T) {
   392  	testShortNewlyForkedSnapSyncingRepair(t, true)
   393  }
   394  
   395  func testShortNewlyForkedSnapSyncingRepair(t *testing.T, snapshots bool) {
   396  	// Chain:
   397  	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
   398  	//   └->S1->S2->S3->S4->S5->S6
   399  	//
   400  	// Frozen: none
   401  	// Commit: G
   402  	// Pivot : C4
   403  	//
   404  	// CRASH
   405  	//
   406  	// ------------------------------
   407  	//
   408  	// Expected in leveldb:
   409  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   410  	//   └->S1->S2->S3->S4->S5->S6
   411  	//
   412  	// Expected head header    : C8
   413  	// Expected head fast block: C8
   414  	// Expected head block     : G
   415  	testRepair(t, &rewindTest{
   416  		canonicalBlocks:    8,
   417  		sidechainBlocks:    6,
   418  		freezeThreshold:    16,
   419  		commitBlock:        0,
   420  		pivotBlock:         uint64ptr(4),
   421  		expCanonicalBlocks: 8,
   422  		expSidechainBlocks: 6,
   423  		expFrozen:          0,
   424  		expHeadHeader:      8,
   425  		expHeadFastBlock:   8,
   426  		expHeadBlock:       0,
   427  	}, snapshots)
   428  }
   429  
   430  // Tests a recovery for a short canonical chain and a longer side chain, where a
   431  // recent block was already committed to disk and then the process crashed. In this
   432  // case we expect the canonical chain to be rolled back to the committed block, but
   433  // the chain data itself left in the database for replaying.
   434  func TestShortReorgedRepair(t *testing.T)              { testShortReorgedRepair(t, false) }
   435  func TestShortReorgedRepairWithSnapshots(t *testing.T) { testShortReorgedRepair(t, true) }
   436  
   437  func testShortReorgedRepair(t *testing.T, snapshots bool) {
   438  	// Chain:
   439  	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
   440  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10
   441  	//
   442  	// Frozen: none
   443  	// Commit: G, C4
   444  	// Pivot : none
   445  	//
   446  	// CRASH
   447  	//
   448  	// ------------------------------
   449  	//
   450  	// Expected in leveldb:
   451  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   452  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10
   453  	//
   454  	// Expected head header    : C8
   455  	// Expected head fast block: C8
   456  	// Expected head block     : C4
   457  	testRepair(t, &rewindTest{
   458  		canonicalBlocks:    8,
   459  		sidechainBlocks:    10,
   460  		freezeThreshold:    16,
   461  		commitBlock:        4,
   462  		pivotBlock:         nil,
   463  		expCanonicalBlocks: 8,
   464  		expSidechainBlocks: 10,
   465  		expFrozen:          0,
   466  		expHeadHeader:      8,
   467  		expHeadFastBlock:   8,
   468  		expHeadBlock:       4,
   469  	}, snapshots)
   470  }
   471  
   472  // Tests a recovery for a short canonical chain and a longer side chain, where
   473  // the fast sync pivot point was already committed to disk and then the process
   474  // crashed. In this case we expect the canonical chain to be rolled back to the
   475  // committed block, but the chain data itself left in the database for replaying.
   476  func TestShortReorgedSnapSyncedRepair(t *testing.T) {
   477  	testShortReorgedSnapSyncedRepair(t, false)
   478  }
   479  func TestShortReorgedSnapSyncedRepairWithSnapshots(t *testing.T) {
   480  	testShortReorgedSnapSyncedRepair(t, true)
   481  }
   482  
   483  func testShortReorgedSnapSyncedRepair(t *testing.T, snapshots bool) {
   484  	// Chain:
   485  	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
   486  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10
   487  	//
   488  	// Frozen: none
   489  	// Commit: G, C4
   490  	// Pivot : C4
   491  	//
   492  	// CRASH
   493  	//
   494  	// ------------------------------
   495  	//
   496  	// Expected in leveldb:
   497  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   498  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10
   499  	//
   500  	// Expected head header    : C8
   501  	// Expected head fast block: C8
   502  	// Expected head block     : C4
   503  	testRepair(t, &rewindTest{
   504  		canonicalBlocks:    8,
   505  		sidechainBlocks:    10,
   506  		freezeThreshold:    16,
   507  		commitBlock:        4,
   508  		pivotBlock:         uint64ptr(4),
   509  		expCanonicalBlocks: 8,
   510  		expSidechainBlocks: 10,
   511  		expFrozen:          0,
   512  		expHeadHeader:      8,
   513  		expHeadFastBlock:   8,
   514  		expHeadBlock:       4,
   515  	}, snapshots)
   516  }
   517  
   518  // Tests a recovery for a short canonical chain and a longer side chain, where
   519  // the fast sync pivot point was not yet committed, but the process crashed. In
   520  // this case we expect the chain to detect that it was fast syncing and not delete
   521  // anything, since we can just pick up directly where we left off.
   522  func TestShortReorgedSnapSyncingRepair(t *testing.T) {
   523  	testShortReorgedSnapSyncingRepair(t, false)
   524  }
   525  func TestShortReorgedSnapSyncingRepairWithSnapshots(t *testing.T) {
   526  	testShortReorgedSnapSyncingRepair(t, true)
   527  }
   528  
   529  func testShortReorgedSnapSyncingRepair(t *testing.T, snapshots bool) {
   530  	// Chain:
   531  	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
   532  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10
   533  	//
   534  	// Frozen: none
   535  	// Commit: G
   536  	// Pivot : C4
   537  	//
   538  	// CRASH
   539  	//
   540  	// ------------------------------
   541  	//
   542  	// Expected in leveldb:
   543  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   544  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10
   545  	//
   546  	// Expected head header    : C8
   547  	// Expected head fast block: C8
   548  	// Expected head block     : G
   549  	testRepair(t, &rewindTest{
   550  		canonicalBlocks:    8,
   551  		sidechainBlocks:    10,
   552  		freezeThreshold:    16,
   553  		commitBlock:        0,
   554  		pivotBlock:         uint64ptr(4),
   555  		expCanonicalBlocks: 8,
   556  		expSidechainBlocks: 10,
   557  		expFrozen:          0,
   558  		expHeadHeader:      8,
   559  		expHeadFastBlock:   8,
   560  		expHeadBlock:       0,
   561  	}, snapshots)
   562  }
   563  
   564  // Tests a recovery for a long canonical chain with frozen blocks where a recent
   565  // block - newer than the ancient limit - was already committed to disk and then
   566  // the process crashed. In this case we expect the chain to be rolled back to the
   567  // committed block, with everything afterwards kept as fast sync data.
   568  func TestLongShallowRepair(t *testing.T)              { testLongShallowRepair(t, false) }
   569  func TestLongShallowRepairWithSnapshots(t *testing.T) { testLongShallowRepair(t, true) }
   570  
   571  func testLongShallowRepair(t *testing.T, snapshots bool) {
   572  	// Chain:
   573  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
   574  	//
   575  	// Frozen:
   576  	//   G->C1->C2
   577  	//
   578  	// Commit: G, C4
   579  	// Pivot : none
   580  	//
   581  	// CRASH
   582  	//
   583  	// ------------------------------
   584  	//
   585  	// Expected in freezer:
   586  	//   G->C1->C2
   587  	//
   588  	// Expected in leveldb:
   589  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
   590  	//
   591  	// Expected head header    : C18
   592  	// Expected head fast block: C18
   593  	// Expected head block     : C4
   594  	testRepair(t, &rewindTest{
   595  		canonicalBlocks:    18,
   596  		sidechainBlocks:    0,
   597  		freezeThreshold:    16,
   598  		commitBlock:        4,
   599  		pivotBlock:         nil,
   600  		expCanonicalBlocks: 18,
   601  		expSidechainBlocks: 0,
   602  		expFrozen:          3,
   603  		expHeadHeader:      18,
   604  		expHeadFastBlock:   18,
   605  		expHeadBlock:       4,
   606  	}, snapshots)
   607  }
   608  
   609  // Tests a recovery for a long canonical chain with frozen blocks where a recent
   610  // block - older than the ancient limit - was already committed to disk and then
   611  // the process crashed. In this case we expect the chain to be rolled back to the
   612  // committed block, with everything afterwards deleted.
   613  func TestLongDeepRepair(t *testing.T)              { testLongDeepRepair(t, false) }
   614  func TestLongDeepRepairWithSnapshots(t *testing.T) { testLongDeepRepair(t, true) }
   615  
   616  func testLongDeepRepair(t *testing.T, snapshots bool) {
   617  	// Chain:
   618  	//   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)
   619  	//
   620  	// Frozen:
   621  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   622  	//
   623  	// Commit: G, C4
   624  	// Pivot : none
   625  	//
   626  	// CRASH
   627  	//
   628  	// ------------------------------
   629  	//
   630  	// Expected in freezer:
   631  	//   G->C1->C2->C3->C4
   632  	//
   633  	// Expected in leveldb: none
   634  	//
   635  	// Expected head header    : C4
   636  	// Expected head fast block: C4
   637  	// Expected head block     : C4
   638  	testRepair(t, &rewindTest{
   639  		canonicalBlocks:    24,
   640  		sidechainBlocks:    0,
   641  		freezeThreshold:    16,
   642  		commitBlock:        4,
   643  		pivotBlock:         nil,
   644  		expCanonicalBlocks: 4,
   645  		expSidechainBlocks: 0,
   646  		expFrozen:          5,
   647  		expHeadHeader:      4,
   648  		expHeadFastBlock:   4,
   649  		expHeadBlock:       4,
   650  	}, snapshots)
   651  }
   652  
   653  // Tests a recovery for a long canonical chain with frozen blocks where the fast
   654  // sync pivot point - newer than the ancient limit - was already committed, after
   655  // which the process crashed. In this case we expect the chain to be rolled back
   656  // to the committed block, with everything afterwards kept as fast sync data.
   657  func TestLongSnapSyncedShallowRepair(t *testing.T) {
   658  	testLongSnapSyncedShallowRepair(t, false)
   659  }
   660  func TestLongSnapSyncedShallowRepairWithSnapshots(t *testing.T) {
   661  	testLongSnapSyncedShallowRepair(t, true)
   662  }
   663  
   664  func testLongSnapSyncedShallowRepair(t *testing.T, snapshots bool) {
   665  	// Chain:
   666  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
   667  	//
   668  	// Frozen:
   669  	//   G->C1->C2
   670  	//
   671  	// Commit: G, C4
   672  	// Pivot : C4
   673  	//
   674  	// CRASH
   675  	//
   676  	// ------------------------------
   677  	//
   678  	// Expected in freezer:
   679  	//   G->C1->C2
   680  	//
   681  	// Expected in leveldb:
   682  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
   683  	//
   684  	// Expected head header    : C18
   685  	// Expected head fast block: C18
   686  	// Expected head block     : C4
   687  	testRepair(t, &rewindTest{
   688  		canonicalBlocks:    18,
   689  		sidechainBlocks:    0,
   690  		freezeThreshold:    16,
   691  		commitBlock:        4,
   692  		pivotBlock:         uint64ptr(4),
   693  		expCanonicalBlocks: 18,
   694  		expSidechainBlocks: 0,
   695  		expFrozen:          3,
   696  		expHeadHeader:      18,
   697  		expHeadFastBlock:   18,
   698  		expHeadBlock:       4,
   699  	}, snapshots)
   700  }
   701  
   702  // Tests a recovery for a long canonical chain with frozen blocks where the fast
   703  // sync pivot point - older than the ancient limit - was already committed, after
   704  // which the process crashed. In this case we expect the chain to be rolled back
   705  // to the committed block, with everything afterwards deleted.
   706  func TestLongSnapSyncedDeepRepair(t *testing.T)              { testLongSnapSyncedDeepRepair(t, false) }
   707  func TestLongSnapSyncedDeepRepairWithSnapshots(t *testing.T) { testLongSnapSyncedDeepRepair(t, true) }
   708  
   709  func testLongSnapSyncedDeepRepair(t *testing.T, snapshots bool) {
   710  	// Chain:
   711  	//   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)
   712  	//
   713  	// Frozen:
   714  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   715  	//
   716  	// Commit: G, C4
   717  	// Pivot : C4
   718  	//
   719  	// CRASH
   720  	//
   721  	// ------------------------------
   722  	//
   723  	// Expected in freezer:
   724  	//   G->C1->C2->C3->C4
   725  	//
   726  	// Expected in leveldb: none
   727  	//
   728  	// Expected head header    : C4
   729  	// Expected head fast block: C4
   730  	// Expected head block     : C4
   731  	testRepair(t, &rewindTest{
   732  		canonicalBlocks:    24,
   733  		sidechainBlocks:    0,
   734  		freezeThreshold:    16,
   735  		commitBlock:        4,
   736  		pivotBlock:         uint64ptr(4),
   737  		expCanonicalBlocks: 4,
   738  		expSidechainBlocks: 0,
   739  		expFrozen:          5,
   740  		expHeadHeader:      4,
   741  		expHeadFastBlock:   4,
   742  		expHeadBlock:       4,
   743  	}, snapshots)
   744  }
   745  
   746  // Tests a recovery for a long canonical chain with frozen blocks where the fast
   747  // sync pivot point - older than the ancient limit - was not yet committed, but the
   748  // process crashed. In this case we expect the chain to detect that it was fast
   749  // syncing and not delete anything, since we can just pick up directly where we
   750  // left off.
   751  func TestLongSnapSyncingShallowRepair(t *testing.T) {
   752  	testLongSnapSyncingShallowRepair(t, false)
   753  }
   754  func TestLongSnapSyncingShallowRepairWithSnapshots(t *testing.T) {
   755  	testLongSnapSyncingShallowRepair(t, true)
   756  }
   757  
   758  func testLongSnapSyncingShallowRepair(t *testing.T, snapshots bool) {
   759  	// Chain:
   760  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
   761  	//
   762  	// Frozen:
   763  	//   G->C1->C2
   764  	//
   765  	// Commit: G
   766  	// Pivot : C4
   767  	//
   768  	// CRASH
   769  	//
   770  	// ------------------------------
   771  	//
   772  	// Expected in freezer:
   773  	//   G->C1->C2
   774  	//
   775  	// Expected in leveldb:
   776  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
   777  	//
   778  	// Expected head header    : C18
   779  	// Expected head fast block: C18
   780  	// Expected head block     : G
   781  	testRepair(t, &rewindTest{
   782  		canonicalBlocks:    18,
   783  		sidechainBlocks:    0,
   784  		freezeThreshold:    16,
   785  		commitBlock:        0,
   786  		pivotBlock:         uint64ptr(4),
   787  		expCanonicalBlocks: 18,
   788  		expSidechainBlocks: 0,
   789  		expFrozen:          3,
   790  		expHeadHeader:      18,
   791  		expHeadFastBlock:   18,
   792  		expHeadBlock:       0,
   793  	}, snapshots)
   794  }
   795  
   796  // Tests a recovery for a long canonical chain with frozen blocks where the fast
   797  // sync pivot point - newer than the ancient limit - was not yet committed, but the
   798  // process crashed. In this case we expect the chain to detect that it was fast
   799  // syncing and not delete anything, since we can just pick up directly where we
   800  // left off.
   801  func TestLongSnapSyncingDeepRepair(t *testing.T)              { testLongSnapSyncingDeepRepair(t, false) }
   802  func TestLongSnapSyncingDeepRepairWithSnapshots(t *testing.T) { testLongSnapSyncingDeepRepair(t, true) }
   803  
   804  func testLongSnapSyncingDeepRepair(t *testing.T, snapshots bool) {
   805  	// Chain:
   806  	//   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)
   807  	//
   808  	// Frozen:
   809  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   810  	//
   811  	// Commit: G
   812  	// Pivot : C4
   813  	//
   814  	// CRASH
   815  	//
   816  	// ------------------------------
   817  	//
   818  	// Expected in freezer:
   819  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   820  	//
   821  	// Expected in leveldb:
   822  	//   C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24
   823  	//
   824  	// Expected head header    : C24
   825  	// Expected head fast block: C24
   826  	// Expected head block     : G
   827  	testRepair(t, &rewindTest{
   828  		canonicalBlocks:    24,
   829  		sidechainBlocks:    0,
   830  		freezeThreshold:    16,
   831  		commitBlock:        0,
   832  		pivotBlock:         uint64ptr(4),
   833  		expCanonicalBlocks: 24,
   834  		expSidechainBlocks: 0,
   835  		expFrozen:          9,
   836  		expHeadHeader:      24,
   837  		expHeadFastBlock:   24,
   838  		expHeadBlock:       0,
   839  	}, snapshots)
   840  }
   841  
   842  // Tests a recovery for a long canonical chain with frozen blocks and a shorter
   843  // side chain, where a recent block - newer than the ancient limit - was already
   844  // committed to disk and then the process crashed. In this test scenario the side
   845  // chain is below the committed block. In this case we expect the chain to be
   846  // rolled back to the committed block, with everything afterwards kept as fast
   847  // sync data; the side chain completely nuked by the freezer.
   848  func TestLongOldForkedShallowRepair(t *testing.T) {
   849  	testLongOldForkedShallowRepair(t, false)
   850  }
   851  func TestLongOldForkedShallowRepairWithSnapshots(t *testing.T) {
   852  	testLongOldForkedShallowRepair(t, true)
   853  }
   854  
   855  func testLongOldForkedShallowRepair(t *testing.T, snapshots bool) {
   856  	// Chain:
   857  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
   858  	//   └->S1->S2->S3
   859  	//
   860  	// Frozen:
   861  	//   G->C1->C2
   862  	//
   863  	// Commit: G, C4
   864  	// Pivot : none
   865  	//
   866  	// CRASH
   867  	//
   868  	// ------------------------------
   869  	//
   870  	// Expected in freezer:
   871  	//   G->C1->C2
   872  	//
   873  	// Expected in leveldb:
   874  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
   875  	//
   876  	// Expected head header    : C18
   877  	// Expected head fast block: C18
   878  	// Expected head block     : C4
   879  	testRepair(t, &rewindTest{
   880  		canonicalBlocks:    18,
   881  		sidechainBlocks:    3,
   882  		freezeThreshold:    16,
   883  		commitBlock:        4,
   884  		pivotBlock:         nil,
   885  		expCanonicalBlocks: 18,
   886  		expSidechainBlocks: 0,
   887  		expFrozen:          3,
   888  		expHeadHeader:      18,
   889  		expHeadFastBlock:   18,
   890  		expHeadBlock:       4,
   891  	}, snapshots)
   892  }
   893  
   894  // Tests a recovery for a long canonical chain with frozen blocks and a shorter
   895  // side chain, where a recent block - older than the ancient limit - was already
   896  // committed to disk and then the process crashed. In this test scenario the side
   897  // chain is below the committed block. In this case we expect the canonical chain
   898  // to be rolled back to the committed block, with everything afterwards deleted;
   899  // the side chain completely nuked by the freezer.
   900  func TestLongOldForkedDeepRepair(t *testing.T)              { testLongOldForkedDeepRepair(t, false) }
   901  func TestLongOldForkedDeepRepairWithSnapshots(t *testing.T) { testLongOldForkedDeepRepair(t, true) }
   902  
   903  func testLongOldForkedDeepRepair(t *testing.T, snapshots bool) {
   904  	// Chain:
   905  	//   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)
   906  	//   └->S1->S2->S3
   907  	//
   908  	// Frozen:
   909  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   910  	//
   911  	// Commit: G, C4
   912  	// Pivot : none
   913  	//
   914  	// CRASH
   915  	//
   916  	// ------------------------------
   917  	//
   918  	// Expected in freezer:
   919  	//   G->C1->C2->C3->C4
   920  	//
   921  	// Expected in leveldb: none
   922  	//
   923  	// Expected head header    : C4
   924  	// Expected head fast block: C4
   925  	// Expected head block     : C4
   926  	testRepair(t, &rewindTest{
   927  		canonicalBlocks:    24,
   928  		sidechainBlocks:    3,
   929  		freezeThreshold:    16,
   930  		commitBlock:        4,
   931  		pivotBlock:         nil,
   932  		expCanonicalBlocks: 4,
   933  		expSidechainBlocks: 0,
   934  		expFrozen:          5,
   935  		expHeadHeader:      4,
   936  		expHeadFastBlock:   4,
   937  		expHeadBlock:       4,
   938  	}, snapshots)
   939  }
   940  
   941  // Tests a recovery for a long canonical chain with frozen blocks and a shorter
   942  // side chain, where the fast sync pivot point - newer than the ancient limit -
   943  // was already committed to disk and then the process crashed. In this test scenario
   944  // the side chain is below the committed block. In this case we expect the chain
   945  // to be rolled back to the committed block, with everything afterwards kept as
   946  // fast sync data; the side chain completely nuked by the freezer.
   947  func TestLongOldForkedSnapSyncedShallowRepair(t *testing.T) {
   948  	testLongOldForkedSnapSyncedShallowRepair(t, false)
   949  }
   950  func TestLongOldForkedSnapSyncedShallowRepairWithSnapshots(t *testing.T) {
   951  	testLongOldForkedSnapSyncedShallowRepair(t, true)
   952  }
   953  
   954  func testLongOldForkedSnapSyncedShallowRepair(t *testing.T, snapshots bool) {
   955  	// Chain:
   956  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
   957  	//   └->S1->S2->S3
   958  	//
   959  	// Frozen:
   960  	//   G->C1->C2
   961  	//
   962  	// Commit: G, C4
   963  	// Pivot : C4
   964  	//
   965  	// CRASH
   966  	//
   967  	// ------------------------------
   968  	//
   969  	// Expected in freezer:
   970  	//   G->C1->C2
   971  	//
   972  	// Expected in leveldb:
   973  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
   974  	//
   975  	// Expected head header    : C18
   976  	// Expected head fast block: C18
   977  	// Expected head block     : C4
   978  	testRepair(t, &rewindTest{
   979  		canonicalBlocks:    18,
   980  		sidechainBlocks:    3,
   981  		freezeThreshold:    16,
   982  		commitBlock:        4,
   983  		pivotBlock:         uint64ptr(4),
   984  		expCanonicalBlocks: 18,
   985  		expSidechainBlocks: 0,
   986  		expFrozen:          3,
   987  		expHeadHeader:      18,
   988  		expHeadFastBlock:   18,
   989  		expHeadBlock:       4,
   990  	}, snapshots)
   991  }
   992  
   993  // Tests a recovery for a long canonical chain with frozen blocks and a shorter
   994  // side chain, where the fast sync pivot point - older than the ancient limit -
   995  // was already committed to disk and then the process crashed. In this test scenario
   996  // the side chain is below the committed block. In this case we expect the canonical
   997  // chain to be rolled back to the committed block, with everything afterwards deleted;
   998  // the side chain completely nuked by the freezer.
   999  func TestLongOldForkedSnapSyncedDeepRepair(t *testing.T) {
  1000  	testLongOldForkedSnapSyncedDeepRepair(t, false)
  1001  }
  1002  func TestLongOldForkedSnapSyncedDeepRepairWithSnapshots(t *testing.T) {
  1003  	testLongOldForkedSnapSyncedDeepRepair(t, true)
  1004  }
  1005  
  1006  func testLongOldForkedSnapSyncedDeepRepair(t *testing.T, snapshots bool) {
  1007  	// Chain:
  1008  	//   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)
  1009  	//   └->S1->S2->S3
  1010  	//
  1011  	// Frozen:
  1012  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
  1013  	//
  1014  	// Commit: G, C4
  1015  	// Pivot : C4
  1016  	//
  1017  	// CRASH
  1018  	//
  1019  	// ------------------------------
  1020  	//
  1021  	// Expected in freezer:
  1022  	//   G->C1->C2->C3->C4
  1023  	//
  1024  	// Expected in leveldb: none
  1025  	//
  1026  	// Expected head header    : C4
  1027  	// Expected head fast block: C4
  1028  	// Expected head block     : C4
  1029  	testRepair(t, &rewindTest{
  1030  		canonicalBlocks:    24,
  1031  		sidechainBlocks:    3,
  1032  		freezeThreshold:    16,
  1033  		commitBlock:        4,
  1034  		pivotBlock:         uint64ptr(4),
  1035  		expCanonicalBlocks: 4,
  1036  		expSidechainBlocks: 0,
  1037  		expFrozen:          5,
  1038  		expHeadHeader:      4,
  1039  		expHeadFastBlock:   4,
  1040  		expHeadBlock:       4,
  1041  	}, snapshots)
  1042  }
  1043  
  1044  // Tests a recovery for a long canonical chain with frozen blocks and a shorter
  1045  // side chain, where the fast sync pivot point - older than the ancient limit -
  1046  // was not yet committed, but the process crashed. In this test scenario the side
  1047  // chain is below the committed block. In this case we expect the chain to detect
  1048  // that it was fast syncing and not delete anything. The side chain is completely
  1049  // nuked by the freezer.
  1050  func TestLongOldForkedSnapSyncingShallowRepair(t *testing.T) {
  1051  	testLongOldForkedSnapSyncingShallowRepair(t, false)
  1052  }
  1053  func TestLongOldForkedSnapSyncingShallowRepairWithSnapshots(t *testing.T) {
  1054  	testLongOldForkedSnapSyncingShallowRepair(t, true)
  1055  }
  1056  
  1057  func testLongOldForkedSnapSyncingShallowRepair(t *testing.T, snapshots bool) {
  1058  	// Chain:
  1059  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
  1060  	//   └->S1->S2->S3
  1061  	//
  1062  	// Frozen:
  1063  	//   G->C1->C2
  1064  	//
  1065  	// Commit: G
  1066  	// Pivot : C4
  1067  	//
  1068  	// CRASH
  1069  	//
  1070  	// ------------------------------
  1071  	//
  1072  	// Expected in freezer:
  1073  	//   G->C1->C2
  1074  	//
  1075  	// Expected in leveldb:
  1076  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
  1077  	//
  1078  	// Expected head header    : C18
  1079  	// Expected head fast block: C18
  1080  	// Expected head block     : G
  1081  	testRepair(t, &rewindTest{
  1082  		canonicalBlocks:    18,
  1083  		sidechainBlocks:    3,
  1084  		freezeThreshold:    16,
  1085  		commitBlock:        0,
  1086  		pivotBlock:         uint64ptr(4),
  1087  		expCanonicalBlocks: 18,
  1088  		expSidechainBlocks: 0,
  1089  		expFrozen:          3,
  1090  		expHeadHeader:      18,
  1091  		expHeadFastBlock:   18,
  1092  		expHeadBlock:       0,
  1093  	}, snapshots)
  1094  }
  1095  
  1096  // Tests a recovery for a long canonical chain with frozen blocks and a shorter
  1097  // side chain, where the fast sync pivot point - older than the ancient limit -
  1098  // was not yet committed, but the process crashed. In this test scenario the side
  1099  // chain is below the committed block. In this case we expect the chain to detect
  1100  // that it was fast syncing and not delete anything. The side chain is completely
  1101  // nuked by the freezer.
  1102  func TestLongOldForkedSnapSyncingDeepRepair(t *testing.T) {
  1103  	testLongOldForkedSnapSyncingDeepRepair(t, false)
  1104  }
  1105  func TestLongOldForkedSnapSyncingDeepRepairWithSnapshots(t *testing.T) {
  1106  	testLongOldForkedSnapSyncingDeepRepair(t, true)
  1107  }
  1108  
  1109  func testLongOldForkedSnapSyncingDeepRepair(t *testing.T, snapshots bool) {
  1110  	// Chain:
  1111  	//   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)
  1112  	//   └->S1->S2->S3
  1113  	//
  1114  	// Frozen:
  1115  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
  1116  	//
  1117  	// Commit: G
  1118  	// Pivot : C4
  1119  	//
  1120  	// CRASH
  1121  	//
  1122  	// ------------------------------
  1123  	//
  1124  	// Expected in freezer:
  1125  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
  1126  	//
  1127  	// Expected in leveldb:
  1128  	//   C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24
  1129  	//
  1130  	// Expected head header    : C24
  1131  	// Expected head fast block: C24
  1132  	// Expected head block     : G
  1133  	testRepair(t, &rewindTest{
  1134  		canonicalBlocks:    24,
  1135  		sidechainBlocks:    3,
  1136  		freezeThreshold:    16,
  1137  		commitBlock:        0,
  1138  		pivotBlock:         uint64ptr(4),
  1139  		expCanonicalBlocks: 24,
  1140  		expSidechainBlocks: 0,
  1141  		expFrozen:          9,
  1142  		expHeadHeader:      24,
  1143  		expHeadFastBlock:   24,
  1144  		expHeadBlock:       0,
  1145  	}, snapshots)
  1146  }
  1147  
  1148  // Tests a recovery for a long canonical chain with frozen blocks and a shorter
  1149  // side chain, where a recent block - newer than the ancient limit - was already
  1150  // committed to disk and then the process crashed. In this test scenario the side
  1151  // chain is above the committed block. In this case we expect the chain to be
  1152  // rolled back to the committed block, with everything afterwards kept as fast
  1153  // sync data; the side chain completely nuked by the freezer.
  1154  func TestLongNewerForkedShallowRepair(t *testing.T) {
  1155  	testLongNewerForkedShallowRepair(t, false)
  1156  }
  1157  func TestLongNewerForkedShallowRepairWithSnapshots(t *testing.T) {
  1158  	testLongNewerForkedShallowRepair(t, true)
  1159  }
  1160  
  1161  func testLongNewerForkedShallowRepair(t *testing.T, snapshots bool) {
  1162  	// Chain:
  1163  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
  1164  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12
  1165  	//
  1166  	// Frozen:
  1167  	//   G->C1->C2
  1168  	//
  1169  	// Commit: G, C4
  1170  	// Pivot : none
  1171  	//
  1172  	// CRASH
  1173  	//
  1174  	// ------------------------------
  1175  	//
  1176  	// Expected in freezer:
  1177  	//   G->C1->C2
  1178  	//
  1179  	// Expected in leveldb:
  1180  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
  1181  	//
  1182  	// Expected head header    : C18
  1183  	// Expected head fast block: C18
  1184  	// Expected head block     : C4
  1185  	testRepair(t, &rewindTest{
  1186  		canonicalBlocks:    18,
  1187  		sidechainBlocks:    12,
  1188  		freezeThreshold:    16,
  1189  		commitBlock:        4,
  1190  		pivotBlock:         nil,
  1191  		expCanonicalBlocks: 18,
  1192  		expSidechainBlocks: 0,
  1193  		expFrozen:          3,
  1194  		expHeadHeader:      18,
  1195  		expHeadFastBlock:   18,
  1196  		expHeadBlock:       4,
  1197  	}, snapshots)
  1198  }
  1199  
  1200  // Tests a recovery for a long canonical chain with frozen blocks and a shorter
  1201  // side chain, where a recent block - older than the ancient limit - was already
  1202  // committed to disk and then the process crashed. In this test scenario the side
  1203  // chain is above the committed block. In this case we expect the canonical chain
  1204  // to be rolled back to the committed block, with everything afterwards deleted;
  1205  // the side chain completely nuked by the freezer.
  1206  func TestLongNewerForkedDeepRepair(t *testing.T)              { testLongNewerForkedDeepRepair(t, false) }
  1207  func TestLongNewerForkedDeepRepairWithSnapshots(t *testing.T) { testLongNewerForkedDeepRepair(t, true) }
  1208  
  1209  func testLongNewerForkedDeepRepair(t *testing.T, snapshots bool) {
  1210  	// Chain:
  1211  	//   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)
  1212  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12
  1213  	//
  1214  	// Frozen:
  1215  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
  1216  	//
  1217  	// Commit: G, C4
  1218  	// Pivot : none
  1219  	//
  1220  	// CRASH
  1221  	//
  1222  	// ------------------------------
  1223  	//
  1224  	// Expected in freezer:
  1225  	//   G->C1->C2->C3->C4
  1226  	//
  1227  	// Expected in leveldb: none
  1228  	//
  1229  	// Expected head header    : C4
  1230  	// Expected head fast block: C4
  1231  	// Expected head block     : C4
  1232  	testRepair(t, &rewindTest{
  1233  		canonicalBlocks:    24,
  1234  		sidechainBlocks:    12,
  1235  		freezeThreshold:    16,
  1236  		commitBlock:        4,
  1237  		pivotBlock:         nil,
  1238  		expCanonicalBlocks: 4,
  1239  		expSidechainBlocks: 0,
  1240  		expFrozen:          5,
  1241  		expHeadHeader:      4,
  1242  		expHeadFastBlock:   4,
  1243  		expHeadBlock:       4,
  1244  	}, snapshots)
  1245  }
  1246  
  1247  // Tests a recovery for a long canonical chain with frozen blocks and a shorter
  1248  // side chain, where the fast sync pivot point - newer than the ancient limit -
  1249  // was already committed to disk and then the process crashed. In this test scenario
  1250  // the side chain is above the committed block. In this case we expect the chain
  1251  // to be rolled back to the committed block, with everything afterwards kept as fast
  1252  // sync data; the side chain completely nuked by the freezer.
  1253  func TestLongNewerForkedSnapSyncedShallowRepair(t *testing.T) {
  1254  	testLongNewerForkedSnapSyncedShallowRepair(t, false)
  1255  }
  1256  func TestLongNewerForkedSnapSyncedShallowRepairWithSnapshots(t *testing.T) {
  1257  	testLongNewerForkedSnapSyncedShallowRepair(t, true)
  1258  }
  1259  
  1260  func testLongNewerForkedSnapSyncedShallowRepair(t *testing.T, snapshots bool) {
  1261  	// Chain:
  1262  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
  1263  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12
  1264  	//
  1265  	// Frozen:
  1266  	//   G->C1->C2
  1267  	//
  1268  	// Commit: G, C4
  1269  	// Pivot : C4
  1270  	//
  1271  	// CRASH
  1272  	//
  1273  	// ------------------------------
  1274  	//
  1275  	// Expected in freezer:
  1276  	//   G->C1->C2
  1277  	//
  1278  	// Expected in leveldb:
  1279  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
  1280  	//
  1281  	// Expected head header    : C18
  1282  	// Expected head fast block: C18
  1283  	// Expected head block     : C4
  1284  	testRepair(t, &rewindTest{
  1285  		canonicalBlocks:    18,
  1286  		sidechainBlocks:    12,
  1287  		freezeThreshold:    16,
  1288  		commitBlock:        4,
  1289  		pivotBlock:         uint64ptr(4),
  1290  		expCanonicalBlocks: 18,
  1291  		expSidechainBlocks: 0,
  1292  		expFrozen:          3,
  1293  		expHeadHeader:      18,
  1294  		expHeadFastBlock:   18,
  1295  		expHeadBlock:       4,
  1296  	}, snapshots)
  1297  }
  1298  
  1299  // Tests a recovery for a long canonical chain with frozen blocks and a shorter
  1300  // side chain, where the fast sync pivot point - older than the ancient limit -
  1301  // was already committed to disk and then the process crashed. In this test scenario
  1302  // the side chain is above the committed block. In this case we expect the canonical
  1303  // chain to be rolled back to the committed block, with everything afterwards deleted;
  1304  // the side chain completely nuked by the freezer.
  1305  func TestLongNewerForkedSnapSyncedDeepRepair(t *testing.T) {
  1306  	testLongNewerForkedSnapSyncedDeepRepair(t, false)
  1307  }
  1308  func TestLongNewerForkedSnapSyncedDeepRepairWithSnapshots(t *testing.T) {
  1309  	testLongNewerForkedSnapSyncedDeepRepair(t, true)
  1310  }
  1311  
  1312  func testLongNewerForkedSnapSyncedDeepRepair(t *testing.T, snapshots bool) {
  1313  	// Chain:
  1314  	//   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)
  1315  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12
  1316  	//
  1317  	// Frozen:
  1318  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
  1319  	//
  1320  	// Commit: G, C4
  1321  	// Pivot : C4
  1322  	//
  1323  	// CRASH
  1324  	//
  1325  	// ------------------------------
  1326  	//
  1327  	// Expected in freezer:
  1328  	//   G->C1->C2->C3->C4
  1329  	//
  1330  	// Expected in leveldb: none
  1331  	//
  1332  	// Expected head header    : C4
  1333  	// Expected head fast block: C4
  1334  	// Expected head block     : C4
  1335  	testRepair(t, &rewindTest{
  1336  		canonicalBlocks:    24,
  1337  		sidechainBlocks:    12,
  1338  		freezeThreshold:    16,
  1339  		commitBlock:        4,
  1340  		pivotBlock:         uint64ptr(4),
  1341  		expCanonicalBlocks: 4,
  1342  		expSidechainBlocks: 0,
  1343  		expFrozen:          5,
  1344  		expHeadHeader:      4,
  1345  		expHeadFastBlock:   4,
  1346  		expHeadBlock:       4,
  1347  	}, snapshots)
  1348  }
  1349  
  1350  // Tests a recovery for a long canonical chain with frozen blocks and a shorter
  1351  // side chain, where the fast sync pivot point - older than the ancient limit -
  1352  // was not yet committed, but the process crashed. In this test scenario the side
  1353  // chain is above the committed block. In this case we expect the chain to detect
  1354  // that it was fast syncing and not delete anything. The side chain is completely
  1355  // nuked by the freezer.
  1356  func TestLongNewerForkedSnapSyncingShallowRepair(t *testing.T) {
  1357  	testLongNewerForkedSnapSyncingShallowRepair(t, false)
  1358  }
  1359  func TestLongNewerForkedSnapSyncingShallowRepairWithSnapshots(t *testing.T) {
  1360  	testLongNewerForkedSnapSyncingShallowRepair(t, true)
  1361  }
  1362  
  1363  func testLongNewerForkedSnapSyncingShallowRepair(t *testing.T, snapshots bool) {
  1364  	// Chain:
  1365  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
  1366  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12
  1367  	//
  1368  	// Frozen:
  1369  	//   G->C1->C2
  1370  	//
  1371  	// Commit: G
  1372  	// Pivot : C4
  1373  	//
  1374  	// CRASH
  1375  	//
  1376  	// ------------------------------
  1377  	//
  1378  	// Expected in freezer:
  1379  	//   G->C1->C2
  1380  	//
  1381  	// Expected in leveldb:
  1382  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
  1383  	//
  1384  	// Expected head header    : C18
  1385  	// Expected head fast block: C18
  1386  	// Expected head block     : G
  1387  	testRepair(t, &rewindTest{
  1388  		canonicalBlocks:    18,
  1389  		sidechainBlocks:    12,
  1390  		freezeThreshold:    16,
  1391  		commitBlock:        0,
  1392  		pivotBlock:         uint64ptr(4),
  1393  		expCanonicalBlocks: 18,
  1394  		expSidechainBlocks: 0,
  1395  		expFrozen:          3,
  1396  		expHeadHeader:      18,
  1397  		expHeadFastBlock:   18,
  1398  		expHeadBlock:       0,
  1399  	}, snapshots)
  1400  }
  1401  
  1402  // Tests a recovery for a long canonical chain with frozen blocks and a shorter
  1403  // side chain, where the fast sync pivot point - older than the ancient limit -
  1404  // was not yet committed, but the process crashed. In this test scenario the side
  1405  // chain is above the committed block. In this case we expect the chain to detect
  1406  // that it was fast syncing and not delete anything. The side chain is completely
  1407  // nuked by the freezer.
  1408  func TestLongNewerForkedSnapSyncingDeepRepair(t *testing.T) {
  1409  	testLongNewerForkedSnapSyncingDeepRepair(t, false)
  1410  }
  1411  func TestLongNewerForkedSnapSyncingDeepRepairWithSnapshots(t *testing.T) {
  1412  	testLongNewerForkedSnapSyncingDeepRepair(t, true)
  1413  }
  1414  
  1415  func testLongNewerForkedSnapSyncingDeepRepair(t *testing.T, snapshots bool) {
  1416  	// Chain:
  1417  	//   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)
  1418  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12
  1419  	//
  1420  	// Frozen:
  1421  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
  1422  	//
  1423  	// Commit: G
  1424  	// Pivot : C4
  1425  	//
  1426  	// CRASH
  1427  	//
  1428  	// ------------------------------
  1429  	//
  1430  	// Expected in freezer:
  1431  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
  1432  	//
  1433  	// Expected in leveldb:
  1434  	//   C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24
  1435  	//
  1436  	// Expected head header    : C24
  1437  	// Expected head fast block: C24
  1438  	// Expected head block     : G
  1439  	testRepair(t, &rewindTest{
  1440  		canonicalBlocks:    24,
  1441  		sidechainBlocks:    12,
  1442  		freezeThreshold:    16,
  1443  		commitBlock:        0,
  1444  		pivotBlock:         uint64ptr(4),
  1445  		expCanonicalBlocks: 24,
  1446  		expSidechainBlocks: 0,
  1447  		expFrozen:          9,
  1448  		expHeadHeader:      24,
  1449  		expHeadFastBlock:   24,
  1450  		expHeadBlock:       0,
  1451  	}, snapshots)
  1452  }
  1453  
  1454  // Tests a recovery for a long canonical chain with frozen blocks and a longer side
  1455  // chain, where a recent block - newer than the ancient limit - was already committed
  1456  // to disk and then the process crashed. In this case we expect the chain to be
  1457  // rolled back to the committed block, with everything afterwards kept as fast sync
  1458  // data. The side chain completely nuked by the freezer.
  1459  func TestLongReorgedShallowRepair(t *testing.T)              { testLongReorgedShallowRepair(t, false) }
  1460  func TestLongReorgedShallowRepairWithSnapshots(t *testing.T) { testLongReorgedShallowRepair(t, true) }
  1461  
  1462  func testLongReorgedShallowRepair(t *testing.T, snapshots bool) {
  1463  	// Chain:
  1464  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
  1465  	//   └->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
  1466  	//
  1467  	// Frozen:
  1468  	//   G->C1->C2
  1469  	//
  1470  	// Commit: G, C4
  1471  	// Pivot : none
  1472  	//
  1473  	// CRASH
  1474  	//
  1475  	// ------------------------------
  1476  	//
  1477  	// Expected in freezer:
  1478  	//   G->C1->C2
  1479  	//
  1480  	// Expected in leveldb:
  1481  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
  1482  	//
  1483  	// Expected head header    : C18
  1484  	// Expected head fast block: C18
  1485  	// Expected head block     : C4
  1486  	testRepair(t, &rewindTest{
  1487  		canonicalBlocks:    18,
  1488  		sidechainBlocks:    26,
  1489  		freezeThreshold:    16,
  1490  		commitBlock:        4,
  1491  		pivotBlock:         nil,
  1492  		expCanonicalBlocks: 18,
  1493  		expSidechainBlocks: 0,
  1494  		expFrozen:          3,
  1495  		expHeadHeader:      18,
  1496  		expHeadFastBlock:   18,
  1497  		expHeadBlock:       4,
  1498  	}, snapshots)
  1499  }
  1500  
  1501  // Tests a recovery for a long canonical chain with frozen blocks and a longer side
  1502  // chain, where a recent block - older than the ancient limit - was already committed
  1503  // to disk and then the process crashed. In this case we expect the canonical chains
  1504  // to be rolled back to the committed block, with everything afterwards deleted. The
  1505  // side chain completely nuked by the freezer.
  1506  func TestLongReorgedDeepRepair(t *testing.T)              { testLongReorgedDeepRepair(t, false) }
  1507  func TestLongReorgedDeepRepairWithSnapshots(t *testing.T) { testLongReorgedDeepRepair(t, true) }
  1508  
  1509  func testLongReorgedDeepRepair(t *testing.T, snapshots bool) {
  1510  	// Chain:
  1511  	//   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)
  1512  	//   └->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
  1513  	//
  1514  	// Frozen:
  1515  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
  1516  	//
  1517  	// Commit: G, C4
  1518  	// Pivot : none
  1519  	//
  1520  	// CRASH
  1521  	//
  1522  	// ------------------------------
  1523  	//
  1524  	// Expected in freezer:
  1525  	//   G->C1->C2->C3->C4
  1526  	//
  1527  	// Expected in leveldb: none
  1528  	//
  1529  	// Expected head header    : C4
  1530  	// Expected head fast block: C4
  1531  	// Expected head block     : C4
  1532  	testRepair(t, &rewindTest{
  1533  		canonicalBlocks:    24,
  1534  		sidechainBlocks:    26,
  1535  		freezeThreshold:    16,
  1536  		commitBlock:        4,
  1537  		pivotBlock:         nil,
  1538  		expCanonicalBlocks: 4,
  1539  		expSidechainBlocks: 0,
  1540  		expFrozen:          5,
  1541  		expHeadHeader:      4,
  1542  		expHeadFastBlock:   4,
  1543  		expHeadBlock:       4,
  1544  	}, snapshots)
  1545  }
  1546  
  1547  // Tests a recovery for a long canonical chain with frozen blocks and a longer
  1548  // side chain, where the fast sync pivot point - newer than the ancient limit -
  1549  // was already committed to disk and then the process crashed. In this case we
  1550  // expect the chain to be rolled back to the committed block, with everything
  1551  // afterwards kept as fast sync data. The side chain completely nuked by the
  1552  // freezer.
  1553  func TestLongReorgedSnapSyncedShallowRepair(t *testing.T) {
  1554  	testLongReorgedSnapSyncedShallowRepair(t, false)
  1555  }
  1556  func TestLongReorgedSnapSyncedShallowRepairWithSnapshots(t *testing.T) {
  1557  	testLongReorgedSnapSyncedShallowRepair(t, true)
  1558  }
  1559  
  1560  func testLongReorgedSnapSyncedShallowRepair(t *testing.T, snapshots bool) {
  1561  	// Chain:
  1562  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
  1563  	//   └->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
  1564  	//
  1565  	// Frozen:
  1566  	//   G->C1->C2
  1567  	//
  1568  	// Commit: G, C4
  1569  	// Pivot : C4
  1570  	//
  1571  	// CRASH
  1572  	//
  1573  	// ------------------------------
  1574  	//
  1575  	// Expected in freezer:
  1576  	//   G->C1->C2
  1577  	//
  1578  	// Expected in leveldb:
  1579  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
  1580  	//
  1581  	// Expected head header    : C18
  1582  	// Expected head fast block: C18
  1583  	// Expected head block     : C4
  1584  	testRepair(t, &rewindTest{
  1585  		canonicalBlocks:    18,
  1586  		sidechainBlocks:    26,
  1587  		freezeThreshold:    16,
  1588  		commitBlock:        4,
  1589  		pivotBlock:         uint64ptr(4),
  1590  		expCanonicalBlocks: 18,
  1591  		expSidechainBlocks: 0,
  1592  		expFrozen:          3,
  1593  		expHeadHeader:      18,
  1594  		expHeadFastBlock:   18,
  1595  		expHeadBlock:       4,
  1596  	}, snapshots)
  1597  }
  1598  
  1599  // Tests a recovery for a long canonical chain with frozen blocks and a longer
  1600  // side chain, where the fast sync pivot point - older than the ancient limit -
  1601  // was already committed to disk and then the process crashed. In this case we
  1602  // expect the canonical chains to be rolled back to the committed block, with
  1603  // everything afterwards deleted. The side chain completely nuked by the freezer.
  1604  func TestLongReorgedSnapSyncedDeepRepair(t *testing.T) {
  1605  	testLongReorgedSnapSyncedDeepRepair(t, false)
  1606  }
  1607  func TestLongReorgedSnapSyncedDeepRepairWithSnapshots(t *testing.T) {
  1608  	testLongReorgedSnapSyncedDeepRepair(t, true)
  1609  }
  1610  
  1611  func testLongReorgedSnapSyncedDeepRepair(t *testing.T, snapshots bool) {
  1612  	// Chain:
  1613  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD)
  1614  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26
  1615  	//
  1616  	// Frozen:
  1617  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
  1618  	//
  1619  	// Commit: G, C4
  1620  	// Pivot : C4
  1621  	//
  1622  	// CRASH
  1623  	//
  1624  	// ------------------------------
  1625  	//
  1626  	// Expected in freezer:
  1627  	//   G->C1->C2->C3->C4
  1628  	//
  1629  	// Expected in leveldb: none
  1630  	//
  1631  	// Expected head header    : C4
  1632  	// Expected head fast block: C4
  1633  	// Expected head block     : C4
  1634  	testRepair(t, &rewindTest{
  1635  		canonicalBlocks:    24,
  1636  		sidechainBlocks:    26,
  1637  		freezeThreshold:    16,
  1638  		commitBlock:        4,
  1639  		pivotBlock:         uint64ptr(4),
  1640  		expCanonicalBlocks: 4,
  1641  		expSidechainBlocks: 0,
  1642  		expFrozen:          5,
  1643  		expHeadHeader:      4,
  1644  		expHeadFastBlock:   4,
  1645  		expHeadBlock:       4,
  1646  	}, snapshots)
  1647  }
  1648  
  1649  // Tests a recovery for a long canonical chain with frozen blocks and a longer
  1650  // side chain, where the fast sync pivot point - newer than the ancient limit -
  1651  // was not yet committed, but the process crashed. In this case we expect the
  1652  // chain to detect that it was fast syncing and not delete anything, since we
  1653  // can just pick up directly where we left off.
  1654  func TestLongReorgedSnapSyncingShallowRepair(t *testing.T) {
  1655  	testLongReorgedSnapSyncingShallowRepair(t, false)
  1656  }
  1657  func TestLongReorgedSnapSyncingShallowRepairWithSnapshots(t *testing.T) {
  1658  	testLongReorgedSnapSyncingShallowRepair(t, true)
  1659  }
  1660  
  1661  func testLongReorgedSnapSyncingShallowRepair(t *testing.T, snapshots bool) {
  1662  	// Chain:
  1663  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
  1664  	//   └->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
  1665  	//
  1666  	// Frozen:
  1667  	//   G->C1->C2
  1668  	//
  1669  	// Commit: G
  1670  	// Pivot : C4
  1671  	//
  1672  	// CRASH
  1673  	//
  1674  	// ------------------------------
  1675  	//
  1676  	// Expected in freezer:
  1677  	//   G->C1->C2
  1678  	//
  1679  	// Expected in leveldb:
  1680  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
  1681  	//
  1682  	// Expected head header    : C18
  1683  	// Expected head fast block: C18
  1684  	// Expected head block     : G
  1685  	testRepair(t, &rewindTest{
  1686  		canonicalBlocks:    18,
  1687  		sidechainBlocks:    26,
  1688  		freezeThreshold:    16,
  1689  		commitBlock:        0,
  1690  		pivotBlock:         uint64ptr(4),
  1691  		expCanonicalBlocks: 18,
  1692  		expSidechainBlocks: 0,
  1693  		expFrozen:          3,
  1694  		expHeadHeader:      18,
  1695  		expHeadFastBlock:   18,
  1696  		expHeadBlock:       0,
  1697  	}, snapshots)
  1698  }
  1699  
  1700  // Tests a recovery for a long canonical chain with frozen blocks and a longer
  1701  // side chain, where the fast sync pivot point - older than the ancient limit -
  1702  // was not yet committed, but the process crashed. In this case we expect the
  1703  // chain to detect that it was fast syncing and not delete anything, since we
  1704  // can just pick up directly where we left off.
  1705  func TestLongReorgedSnapSyncingDeepRepair(t *testing.T) {
  1706  	testLongReorgedSnapSyncingDeepRepair(t, false)
  1707  }
  1708  func TestLongReorgedSnapSyncingDeepRepairWithSnapshots(t *testing.T) {
  1709  	testLongReorgedSnapSyncingDeepRepair(t, true)
  1710  }
  1711  
  1712  func testLongReorgedSnapSyncingDeepRepair(t *testing.T, snapshots bool) {
  1713  	// Chain:
  1714  	//   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)
  1715  	//   └->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
  1716  	//
  1717  	// Frozen:
  1718  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
  1719  	//
  1720  	// Commit: G
  1721  	// Pivot : C4
  1722  	//
  1723  	// CRASH
  1724  	//
  1725  	// ------------------------------
  1726  	//
  1727  	// Expected in freezer:
  1728  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
  1729  	//
  1730  	// Expected in leveldb:
  1731  	//   C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24
  1732  	//
  1733  	// Expected head header    : C24
  1734  	// Expected head fast block: C24
  1735  	// Expected head block     : G
  1736  	testRepair(t, &rewindTest{
  1737  		canonicalBlocks:    24,
  1738  		sidechainBlocks:    26,
  1739  		freezeThreshold:    16,
  1740  		commitBlock:        0,
  1741  		pivotBlock:         uint64ptr(4),
  1742  		expCanonicalBlocks: 24,
  1743  		expSidechainBlocks: 0,
  1744  		expFrozen:          9,
  1745  		expHeadHeader:      24,
  1746  		expHeadFastBlock:   24,
  1747  		expHeadBlock:       0,
  1748  	}, snapshots)
  1749  }
  1750  
  1751  func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
  1752  	// It's hard to follow the test case, visualize the input
  1753  	//log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
  1754  	// fmt.Println(tt.dump(true))
  1755  
  1756  	// Create a temporary persistent database
  1757  	datadir := t.TempDir()
  1758  
  1759  	db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false)
  1760  	if err != nil {
  1761  		t.Fatalf("Failed to create persistent database: %v", err)
  1762  	}
  1763  	defer db.Close() // Might double close, should be fine
  1764  
  1765  	// Initialize a fresh chain
  1766  	var (
  1767  		gspec = &Genesis{
  1768  			BaseFee: big.NewInt(params.InitialBaseFee),
  1769  			Config:  params.AllEthashProtocolChanges,
  1770  		}
  1771  		engine = ethash.NewFullFaker()
  1772  		config = &CacheConfig{
  1773  			TrieCleanLimit: 256,
  1774  			TrieDirtyLimit: 256,
  1775  			TrieTimeLimit:  5 * time.Minute,
  1776  			SnapshotLimit:  0, // Disable snapshot by default
  1777  		}
  1778  	)
  1779  	defer engine.Close()
  1780  	if snapshots {
  1781  		config.SnapshotLimit = 256
  1782  		config.SnapshotWait = true
  1783  	}
  1784  	chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
  1785  	if err != nil {
  1786  		t.Fatalf("Failed to create chain: %v", err)
  1787  	}
  1788  	// If sidechain blocks are needed, make a light chain and import it
  1789  	var sideblocks types.Blocks
  1790  	if tt.sidechainBlocks > 0 {
  1791  		sideblocks, _ = GenerateChain(gspec.Config, gspec.ToBlock(), engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *BlockGen) {
  1792  			b.SetCoinbase(common.Address{0x01})
  1793  		})
  1794  		if _, err := chain.InsertChain(sideblocks); err != nil {
  1795  			t.Fatalf("Failed to import side chain: %v", err)
  1796  		}
  1797  	}
  1798  	canonblocks, _ := GenerateChain(gspec.Config, gspec.ToBlock(), engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) {
  1799  		b.SetCoinbase(common.Address{0x02})
  1800  		b.SetDifficulty(big.NewInt(1000000))
  1801  	})
  1802  	if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil {
  1803  		t.Fatalf("Failed to import canonical chain start: %v", err)
  1804  	}
  1805  	if tt.commitBlock > 0 {
  1806  		chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil)
  1807  		if snapshots {
  1808  			if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil {
  1809  				t.Fatalf("Failed to flatten snapshots: %v", err)
  1810  			}
  1811  		}
  1812  	}
  1813  	if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil {
  1814  		t.Fatalf("Failed to import canonical chain tail: %v", err)
  1815  	}
  1816  	// Force run a freeze cycle
  1817  	type freezer interface {
  1818  		Freeze(threshold uint64) error
  1819  		Ancients() (uint64, error)
  1820  	}
  1821  	db.(freezer).Freeze(tt.freezeThreshold)
  1822  
  1823  	// Set the simulated pivot block
  1824  	if tt.pivotBlock != nil {
  1825  		rawdb.WriteLastPivotNumber(db, *tt.pivotBlock)
  1826  	}
  1827  	// Pull the plug on the database, simulating a hard crash
  1828  	db.Close()
  1829  	chain.stopWithoutSaving()
  1830  
  1831  	// Start a new blockchain back up and see where the repair leads us
  1832  	db, err = rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false)
  1833  	if err != nil {
  1834  		t.Fatalf("Failed to reopen persistent database: %v", err)
  1835  	}
  1836  	defer db.Close()
  1837  
  1838  	newChain, err := NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil)
  1839  	if err != nil {
  1840  		t.Fatalf("Failed to recreate chain: %v", err)
  1841  	}
  1842  	defer newChain.Stop()
  1843  
  1844  	// Iterate over all the remaining blocks and ensure there are no gaps
  1845  	verifyNoGaps(t, newChain, true, canonblocks)
  1846  	verifyNoGaps(t, newChain, false, sideblocks)
  1847  	verifyCutoff(t, newChain, true, canonblocks, tt.expCanonicalBlocks)
  1848  	verifyCutoff(t, newChain, false, sideblocks, tt.expSidechainBlocks)
  1849  
  1850  	if head := newChain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader {
  1851  		t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader)
  1852  	}
  1853  	if head := newChain.CurrentFastBlock(); head.NumberU64() != tt.expHeadFastBlock {
  1854  		t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadFastBlock)
  1855  	}
  1856  	if head := newChain.CurrentBlock(); head.NumberU64() != tt.expHeadBlock {
  1857  		t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadBlock)
  1858  	}
  1859  	if frozen, err := db.(freezer).Ancients(); err != nil {
  1860  		t.Errorf("Failed to retrieve ancient count: %v\n", err)
  1861  	} else if int(frozen) != tt.expFrozen {
  1862  		t.Errorf("Frozen block count mismatch: have %d, want %d", frozen, tt.expFrozen)
  1863  	}
  1864  }
  1865  
  1866  // TestIssue23496 tests scenario described in https://github.com/ethereum/go-ethereum/pull/23496#issuecomment-926393893
  1867  // Credits to @zzyalbert for finding the issue.
  1868  //
  1869  // Local chain owns these blocks:
  1870  // G  B1  B2  B3  B4
  1871  // B1: state committed
  1872  // B2: snapshot disk layer
  1873  // B3: state committed
  1874  // B4: head block
  1875  //
  1876  // Crash happens without fully persisting snapshot and in-memory states,
  1877  // chain rewinds itself to the B1 (skip B3 in order to recover snapshot)
  1878  // In this case the snapshot layer of B3 is not created because of existent
  1879  // state.
  1880  func TestIssue23496(t *testing.T) {
  1881  	// It's hard to follow the test case, visualize the input
  1882  	//log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
  1883  
  1884  	// Create a temporary persistent database
  1885  	datadir := t.TempDir()
  1886  
  1887  	db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false)
  1888  	if err != nil {
  1889  		t.Fatalf("Failed to create persistent database: %v", err)
  1890  	}
  1891  	defer db.Close() // Might double close, should be fine
  1892  
  1893  	// Initialize a fresh chain
  1894  	var (
  1895  		gspec = &Genesis{
  1896  			Config:  params.TestChainConfig,
  1897  			BaseFee: big.NewInt(params.InitialBaseFee),
  1898  		}
  1899  		engine = ethash.NewFullFaker()
  1900  		config = &CacheConfig{
  1901  			TrieCleanLimit: 256,
  1902  			TrieDirtyLimit: 256,
  1903  			TrieTimeLimit:  5 * time.Minute,
  1904  			SnapshotLimit:  256,
  1905  			SnapshotWait:   true,
  1906  		}
  1907  	)
  1908  	chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
  1909  	if err != nil {
  1910  		t.Fatalf("Failed to create chain: %v", err)
  1911  	}
  1912  	_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 4, func(i int, b *BlockGen) {
  1913  		b.SetCoinbase(common.Address{0x02})
  1914  		b.SetDifficulty(big.NewInt(1000000))
  1915  	})
  1916  
  1917  	// Insert block B1 and commit the state into disk
  1918  	if _, err := chain.InsertChain(blocks[:1]); err != nil {
  1919  		t.Fatalf("Failed to import canonical chain start: %v", err)
  1920  	}
  1921  	chain.stateCache.TrieDB().Commit(blocks[0].Root(), true, nil)
  1922  
  1923  	// Insert block B2 and commit the snapshot into disk
  1924  	if _, err := chain.InsertChain(blocks[1:2]); err != nil {
  1925  		t.Fatalf("Failed to import canonical chain start: %v", err)
  1926  	}
  1927  	if err := chain.snaps.Cap(blocks[1].Root(), 0); err != nil {
  1928  		t.Fatalf("Failed to flatten snapshots: %v", err)
  1929  	}
  1930  
  1931  	// Insert block B3 and commit the state into disk
  1932  	if _, err := chain.InsertChain(blocks[2:3]); err != nil {
  1933  		t.Fatalf("Failed to import canonical chain start: %v", err)
  1934  	}
  1935  	chain.stateCache.TrieDB().Commit(blocks[2].Root(), true, nil)
  1936  
  1937  	// Insert the remaining blocks
  1938  	if _, err := chain.InsertChain(blocks[3:]); err != nil {
  1939  		t.Fatalf("Failed to import canonical chain tail: %v", err)
  1940  	}
  1941  
  1942  	// Pull the plug on the database, simulating a hard crash
  1943  	db.Close()
  1944  	chain.stopWithoutSaving()
  1945  
  1946  	// Start a new blockchain back up and see where the repair leads us
  1947  	db, err = rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false)
  1948  	if err != nil {
  1949  		t.Fatalf("Failed to reopen persistent database: %v", err)
  1950  	}
  1951  	defer db.Close()
  1952  
  1953  	chain, err = NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil)
  1954  	if err != nil {
  1955  		t.Fatalf("Failed to recreate chain: %v", err)
  1956  	}
  1957  	defer chain.Stop()
  1958  
  1959  	if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) {
  1960  		t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4)
  1961  	}
  1962  	if head := chain.CurrentFastBlock(); head.NumberU64() != uint64(4) {
  1963  		t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), uint64(4))
  1964  	}
  1965  	if head := chain.CurrentBlock(); head.NumberU64() != uint64(1) {
  1966  		t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), uint64(1))
  1967  	}
  1968  
  1969  	// Reinsert B2-B4
  1970  	if _, err := chain.InsertChain(blocks[1:]); err != nil {
  1971  		t.Fatalf("Failed to import canonical chain tail: %v", err)
  1972  	}
  1973  	if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) {
  1974  		t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4)
  1975  	}
  1976  	if head := chain.CurrentFastBlock(); head.NumberU64() != uint64(4) {
  1977  		t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), uint64(4))
  1978  	}
  1979  	if head := chain.CurrentBlock(); head.NumberU64() != uint64(4) {
  1980  		t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), uint64(4))
  1981  	}
  1982  	if layer := chain.Snapshots().Snapshot(blocks[2].Root()); layer == nil {
  1983  		t.Error("Failed to regenerate the snapshot of known state")
  1984  	}
  1985  }