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