github.com/core-coin/go-core/v2@v2.1.9/core/blockchain_repair_test.go (about)

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