github.com/theQRL/go-zond@v0.2.1/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  // TODO(now.youtrack.cloud/issue/TGZ-7)
    24  /*
    25  import (
    26  	"math/big"
    27  	"path"
    28  	"testing"
    29  	"time"
    30  
    31  	"github.com/theQRL/go-zond/common"
    32  	"github.com/theQRL/go-zond/consensus/beacon"
    33  	"github.com/theQRL/go-zond/core/rawdb"
    34  	"github.com/theQRL/go-zond/core/vm"
    35  	"github.com/theQRL/go-zond/params"
    36  )
    37  
    38  // Tests a recovery for a short canonical chain where a recent block was already
    39  // committed to disk and then the process crashed. In this case we expect the full
    40  // chain to be rolled back to the committed block, but the chain data itself left
    41  // in the database for replaying.
    42  // func TestShortRepair(t *testing.T) { testShortRepair(t, false) }
    43  
    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  		freezeThreshold:    16,
    67  		commitBlock:        4,
    68  		pivotBlock:         nil,
    69  		expCanonicalBlocks: 8,
    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  		freezeThreshold:    16,
   105  		commitBlock:        4,
   106  		pivotBlock:         uint64ptr(4),
   107  		expCanonicalBlocks: 8,
   108  		expFrozen:          0,
   109  		expHeadHeader:      8,
   110  		expHeadFastBlock:   8,
   111  		expHeadBlock:       4,
   112  	}, snapshots)
   113  }
   114  
   115  // Tests a recovery for a short canonical chain where the fast sync pivot point was
   116  // not yet committed, but the process crashed. In this case we expect the chain to
   117  // detect that it was fast syncing and not delete anything, since we can just pick
   118  // up directly where we left off.
   119  // func TestShortSnapSyncingRepair(t *testing.T)              { testShortSnapSyncingRepair(t, false) }
   120  // func TestShortSnapSyncingRepairWithSnapshots(t *testing.T) { testShortSnapSyncingRepair(t, true) }
   121  
   122  func testShortSnapSyncingRepair(t *testing.T, snapshots bool) {
   123  	// Chain:
   124  	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
   125  	//
   126  	// Frozen: none
   127  	// Commit: G
   128  	// Pivot : C4
   129  	//
   130  	// CRASH
   131  	//
   132  	// ------------------------------
   133  	//
   134  	// Expected in leveldb:
   135  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   136  	//
   137  	// Expected head header    : C8
   138  	// Expected head fast block: C8
   139  	// Expected head block     : G
   140  	testRepair(t, &rewindTest{
   141  		canonicalBlocks:    8,
   142  		freezeThreshold:    16,
   143  		commitBlock:        0,
   144  		pivotBlock:         uint64ptr(4),
   145  		expCanonicalBlocks: 8,
   146  		expFrozen:          0,
   147  		expHeadHeader:      8,
   148  		expHeadFastBlock:   8,
   149  		expHeadBlock:       0,
   150  	}, snapshots)
   151  }
   152  
   153  // Tests a recovery for a short canonical chain and a longer side chain, where a
   154  // recent block was already committed to disk and then the process crashed. In this
   155  // case we expect the canonical chain to be rolled back to the committed block, but
   156  // the chain data itself left in the database for replaying.
   157  // func TestShortReorgedRepair(t *testing.T)              { testShortReorgedRepair(t, false) }
   158  // func TestShortReorgedRepairWithSnapshots(t *testing.T) { testShortReorgedRepair(t, true) }
   159  
   160  func testShortReorgedRepair(t *testing.T, snapshots bool) {
   161  	// Chain:
   162  	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
   163  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10
   164  	//
   165  	// Frozen: none
   166  	// Commit: G, C4
   167  	// Pivot : none
   168  	//
   169  	// CRASH
   170  	//
   171  	// ------------------------------
   172  	//
   173  	// Expected in leveldb:
   174  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   175  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10
   176  	//
   177  	// Expected head header    : C8
   178  	// Expected head fast block: C8
   179  	// Expected head block     : C4
   180  	testRepair(t, &rewindTest{
   181  		canonicalBlocks:    8,
   182  		sidechainBlocks:    10,
   183  		freezeThreshold:    16,
   184  		commitBlock:        4,
   185  		pivotBlock:         nil,
   186  		expCanonicalBlocks: 8,
   187  		expSidechainBlocks: 10,
   188  		expFrozen:          0,
   189  		expHeadHeader:      8,
   190  		expHeadFastBlock:   8,
   191  		expHeadBlock:       4,
   192  	}, snapshots)
   193  }
   194  
   195  // Tests a recovery for a short canonical chain and a longer side chain, where
   196  // the fast sync pivot point was already committed to disk and then the process
   197  // crashed. In this case we expect the canonical chain to be rolled back to the
   198  // committed block, but the chain data itself left in the database for replaying.
   199  // func TestShortReorgedSnapSyncedRepair(t *testing.T) {
   200  // 	testShortReorgedSnapSyncedRepair(t, false)
   201  // }
   202  // func TestShortReorgedSnapSyncedRepairWithSnapshots(t *testing.T) {
   203  // 	testShortReorgedSnapSyncedRepair(t, true)
   204  // }
   205  
   206  func testShortReorgedSnapSyncedRepair(t *testing.T, snapshots bool) {
   207  	// Chain:
   208  	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
   209  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10
   210  	//
   211  	// Frozen: none
   212  	// Commit: G, C4
   213  	// Pivot : C4
   214  	//
   215  	// CRASH
   216  	//
   217  	// ------------------------------
   218  	//
   219  	// Expected in leveldb:
   220  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   221  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10
   222  	//
   223  	// Expected head header    : C8
   224  	// Expected head fast block: C8
   225  	// Expected head block     : C4
   226  	testRepair(t, &rewindTest{
   227  		canonicalBlocks:    8,
   228  		sidechainBlocks:    10,
   229  		freezeThreshold:    16,
   230  		commitBlock:        4,
   231  		pivotBlock:         uint64ptr(4),
   232  		expCanonicalBlocks: 8,
   233  		expSidechainBlocks: 10,
   234  		expFrozen:          0,
   235  		expHeadHeader:      8,
   236  		expHeadFastBlock:   8,
   237  		expHeadBlock:       4,
   238  	}, snapshots)
   239  }
   240  
   241  // Tests a recovery for a short canonical chain and a longer side chain, where
   242  // the fast sync pivot point was not yet committed, but the process crashed. In
   243  // this case we expect the chain to detect that it was fast syncing and not delete
   244  // anything, since we can just pick up directly where we left off.
   245  // func TestShortReorgedSnapSyncingRepair(t *testing.T) {
   246  // 	testShortReorgedSnapSyncingRepair(t, false)
   247  // }
   248  // func TestShortReorgedSnapSyncingRepairWithSnapshots(t *testing.T) {
   249  // 	testShortReorgedSnapSyncingRepair(t, true)
   250  // }
   251  
   252  func testShortReorgedSnapSyncingRepair(t *testing.T, snapshots bool) {
   253  	// Chain:
   254  	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
   255  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10
   256  	//
   257  	// Frozen: none
   258  	// Commit: G
   259  	// Pivot : C4
   260  	//
   261  	// CRASH
   262  	//
   263  	// ------------------------------
   264  	//
   265  	// Expected in leveldb:
   266  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   267  	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10
   268  	//
   269  	// Expected head header    : C8
   270  	// Expected head fast block: C8
   271  	// Expected head block     : G
   272  	testRepair(t, &rewindTest{
   273  		canonicalBlocks:    8,
   274  		sidechainBlocks:    10,
   275  		freezeThreshold:    16,
   276  		commitBlock:        0,
   277  		pivotBlock:         uint64ptr(4),
   278  		expCanonicalBlocks: 8,
   279  		expSidechainBlocks: 10,
   280  		expFrozen:          0,
   281  		expHeadHeader:      8,
   282  		expHeadFastBlock:   8,
   283  		expHeadBlock:       0,
   284  	}, snapshots)
   285  }
   286  
   287  // Tests a recovery for a long canonical chain with frozen blocks where a recent
   288  // block - newer than the ancient limit - was already committed to disk and then
   289  // the process crashed. In this case we expect the chain to be rolled back to the
   290  // committed block, with everything afterwards kept as fast sync data.
   291  // func TestLongShallowRepair(t *testing.T)              { testLongShallowRepair(t, false) }
   292  // func TestLongShallowRepairWithSnapshots(t *testing.T) { testLongShallowRepair(t, true) }
   293  
   294  func testLongShallowRepair(t *testing.T, snapshots bool) {
   295  	// Chain:
   296  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
   297  	//
   298  	// Frozen:
   299  	//   G->C1->C2
   300  	//
   301  	// Commit: G, C4
   302  	// Pivot : none
   303  	//
   304  	// CRASH
   305  	//
   306  	// ------------------------------
   307  	//
   308  	// Expected in freezer:
   309  	//   G->C1->C2
   310  	//
   311  	// Expected in leveldb:
   312  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
   313  	//
   314  	// Expected head header    : C18
   315  	// Expected head fast block: C18
   316  	// Expected head block     : C4
   317  	testRepair(t, &rewindTest{
   318  		canonicalBlocks:    18,
   319  		freezeThreshold:    16,
   320  		commitBlock:        4,
   321  		pivotBlock:         nil,
   322  		expCanonicalBlocks: 18,
   323  		expFrozen:          3,
   324  		expHeadHeader:      18,
   325  		expHeadFastBlock:   18,
   326  		expHeadBlock:       4,
   327  	}, snapshots)
   328  }
   329  
   330  // Tests a recovery for a long canonical chain with frozen blocks where a recent
   331  // block - older than the ancient limit - was already committed to disk and then
   332  // the process crashed. In this case we expect the chain to be rolled back to the
   333  // committed block, with everything afterwards deleted.
   334  // func TestLongDeepRepair(t *testing.T)              { testLongDeepRepair(t, false) }
   335  // func TestLongDeepRepairWithSnapshots(t *testing.T) { testLongDeepRepair(t, true) }
   336  
   337  func testLongDeepRepair(t *testing.T, snapshots bool) {
   338  	// Chain:
   339  	//   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)
   340  	//
   341  	// Frozen:
   342  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   343  	//
   344  	// Commit: G, C4
   345  	// Pivot : none
   346  	//
   347  	// CRASH
   348  	//
   349  	// ------------------------------
   350  	//
   351  	// Expected in freezer:
   352  	//   G->C1->C2->C3->C4
   353  	//
   354  	// Expected in leveldb: none
   355  	//
   356  	// Expected head header    : C4
   357  	// Expected head fast block: C4
   358  	// Expected head block     : C4
   359  	testRepair(t, &rewindTest{
   360  		canonicalBlocks:    24,
   361  		freezeThreshold:    16,
   362  		commitBlock:        4,
   363  		pivotBlock:         nil,
   364  		expCanonicalBlocks: 4,
   365  		expFrozen:          5,
   366  		expHeadHeader:      4,
   367  		expHeadFastBlock:   4,
   368  		expHeadBlock:       4,
   369  	}, snapshots)
   370  }
   371  
   372  // Tests a recovery for a long canonical chain with frozen blocks where the fast
   373  // sync pivot point - newer than the ancient limit - was already committed, after
   374  // which the process crashed. In this case we expect the chain to be rolled back
   375  // to the committed block, with everything afterwards kept as fast sync data.
   376  // func TestLongSnapSyncedShallowRepair(t *testing.T) {
   377  // 	testLongSnapSyncedShallowRepair(t, false)
   378  // }
   379  // func TestLongSnapSyncedShallowRepairWithSnapshots(t *testing.T) {
   380  // 	testLongSnapSyncedShallowRepair(t, true)
   381  // }
   382  
   383  func testLongSnapSyncedShallowRepair(t *testing.T, snapshots bool) {
   384  	// Chain:
   385  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
   386  	//
   387  	// Frozen:
   388  	//   G->C1->C2
   389  	//
   390  	// Commit: G, C4
   391  	// Pivot : C4
   392  	//
   393  	// CRASH
   394  	//
   395  	// ------------------------------
   396  	//
   397  	// Expected in freezer:
   398  	//   G->C1->C2
   399  	//
   400  	// Expected in leveldb:
   401  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
   402  	//
   403  	// Expected head header    : C18
   404  	// Expected head fast block: C18
   405  	// Expected head block     : C4
   406  	testRepair(t, &rewindTest{
   407  		canonicalBlocks:    18,
   408  		freezeThreshold:    16,
   409  		commitBlock:        4,
   410  		pivotBlock:         uint64ptr(4),
   411  		expCanonicalBlocks: 18,
   412  		expFrozen:          3,
   413  		expHeadHeader:      18,
   414  		expHeadFastBlock:   18,
   415  		expHeadBlock:       4,
   416  	}, snapshots)
   417  }
   418  
   419  // Tests a recovery for a long canonical chain with frozen blocks where the fast
   420  // sync pivot point - older than the ancient limit - was already committed, after
   421  // which the process crashed. In this case we expect the chain to be rolled back
   422  // to the committed block, with everything afterwards deleted.
   423  // func TestLongSnapSyncedDeepRepair(t *testing.T)              { testLongSnapSyncedDeepRepair(t, false) }
   424  // func TestLongSnapSyncedDeepRepairWithSnapshots(t *testing.T) { testLongSnapSyncedDeepRepair(t, true) }
   425  
   426  func testLongSnapSyncedDeepRepair(t *testing.T, snapshots bool) {
   427  	// Chain:
   428  	//   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)
   429  	//
   430  	// Frozen:
   431  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   432  	//
   433  	// Commit: G, C4
   434  	// Pivot : C4
   435  	//
   436  	// CRASH
   437  	//
   438  	// ------------------------------
   439  	//
   440  	// Expected in freezer:
   441  	//   G->C1->C2->C3->C4
   442  	//
   443  	// Expected in leveldb: none
   444  	//
   445  	// Expected head header    : C4
   446  	// Expected head fast block: C4
   447  	// Expected head block     : C4
   448  	testRepair(t, &rewindTest{
   449  		canonicalBlocks:    24,
   450  		freezeThreshold:    16,
   451  		commitBlock:        4,
   452  		pivotBlock:         uint64ptr(4),
   453  		expCanonicalBlocks: 4,
   454  		expFrozen:          5,
   455  		expHeadHeader:      4,
   456  		expHeadFastBlock:   4,
   457  		expHeadBlock:       4,
   458  	}, snapshots)
   459  }
   460  
   461  // Tests a recovery for a long canonical chain with frozen blocks where the fast
   462  // sync pivot point - older than the ancient limit - was not yet committed, but the
   463  // process crashed. In this case we expect the chain to detect that it was fast
   464  // syncing and not delete anything, since we can just pick up directly where we
   465  // left off.
   466  // func TestLongSnapSyncingShallowRepair(t *testing.T) {
   467  // 	testLongSnapSyncingShallowRepair(t, false)
   468  // }
   469  // func TestLongSnapSyncingShallowRepairWithSnapshots(t *testing.T) {
   470  // 	testLongSnapSyncingShallowRepair(t, true)
   471  // }
   472  
   473  func testLongSnapSyncingShallowRepair(t *testing.T, snapshots bool) {
   474  	// Chain:
   475  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
   476  	//
   477  	// Frozen:
   478  	//   G->C1->C2
   479  	//
   480  	// Commit: G
   481  	// Pivot : C4
   482  	//
   483  	// CRASH
   484  	//
   485  	// ------------------------------
   486  	//
   487  	// Expected in freezer:
   488  	//   G->C1->C2
   489  	//
   490  	// Expected in leveldb:
   491  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
   492  	//
   493  	// Expected head header    : C18
   494  	// Expected head fast block: C18
   495  	// Expected head block     : G
   496  	testRepair(t, &rewindTest{
   497  		canonicalBlocks:    18,
   498  		freezeThreshold:    16,
   499  		commitBlock:        0,
   500  		pivotBlock:         uint64ptr(4),
   501  		expCanonicalBlocks: 18,
   502  		expFrozen:          3,
   503  		expHeadHeader:      18,
   504  		expHeadFastBlock:   18,
   505  		expHeadBlock:       0,
   506  	}, snapshots)
   507  }
   508  
   509  // Tests a recovery for a long canonical chain with frozen blocks where the fast
   510  // sync pivot point - newer than the ancient limit - was not yet committed, but the
   511  // process crashed. In this case we expect the chain to detect that it was fast
   512  // syncing and not delete anything, since we can just pick up directly where we
   513  // left off.
   514  // func TestLongSnapSyncingDeepRepair(t *testing.T)              { testLongSnapSyncingDeepRepair(t, false) }
   515  // func TestLongSnapSyncingDeepRepairWithSnapshots(t *testing.T) { testLongSnapSyncingDeepRepair(t, true) }
   516  
   517  func testLongSnapSyncingDeepRepair(t *testing.T, snapshots bool) {
   518  	// Chain:
   519  	//   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)
   520  	//
   521  	// Frozen:
   522  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   523  	//
   524  	// Commit: G
   525  	// Pivot : C4
   526  	//
   527  	// CRASH
   528  	//
   529  	// ------------------------------
   530  	//
   531  	// Expected in freezer:
   532  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   533  	//
   534  	// Expected in leveldb:
   535  	//   C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24
   536  	//
   537  	// Expected head header    : C24
   538  	// Expected head fast block: C24
   539  	// Expected head block     : G
   540  	testRepair(t, &rewindTest{
   541  		canonicalBlocks:    24,
   542  		freezeThreshold:    16,
   543  		commitBlock:        0,
   544  		pivotBlock:         uint64ptr(4),
   545  		expCanonicalBlocks: 24,
   546  		expFrozen:          9,
   547  		expHeadHeader:      24,
   548  		expHeadFastBlock:   24,
   549  		expHeadBlock:       0,
   550  	}, snapshots)
   551  }
   552  
   553  // Tests a recovery for a long canonical chain with frozen blocks and a longer side
   554  // chain, where a recent block - newer than the ancient limit - was already committed
   555  // to disk and then the process crashed. In this case we expect the chain to be
   556  // rolled back to the committed block, with everything afterwards kept as fast sync
   557  // data. The side chain completely nuked by the freezer.
   558  // func TestLongReorgedShallowRepair(t *testing.T)              { testLongReorgedShallowRepair(t, false) }
   559  // func TestLongReorgedShallowRepairWithSnapshots(t *testing.T) { testLongReorgedShallowRepair(t, true) }
   560  
   561  func testLongReorgedShallowRepair(t *testing.T, snapshots bool) {
   562  	// Chain:
   563  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
   564  	//   └->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
   565  	//
   566  	// Frozen:
   567  	//   G->C1->C2
   568  	//
   569  	// Commit: G, C4
   570  	// Pivot : none
   571  	//
   572  	// CRASH
   573  	//
   574  	// ------------------------------
   575  	//
   576  	// Expected in freezer:
   577  	//   G->C1->C2
   578  	//
   579  	// Expected in leveldb:
   580  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
   581  	//
   582  	// Expected head header    : C18
   583  	// Expected head fast block: C18
   584  	// Expected head block     : C4
   585  	testRepair(t, &rewindTest{
   586  		canonicalBlocks:    18,
   587  		sidechainBlocks:    26,
   588  		freezeThreshold:    16,
   589  		commitBlock:        4,
   590  		pivotBlock:         nil,
   591  		expCanonicalBlocks: 18,
   592  		expSidechainBlocks: 0,
   593  		expFrozen:          3,
   594  		expHeadHeader:      18,
   595  		expHeadFastBlock:   18,
   596  		expHeadBlock:       4,
   597  	}, snapshots)
   598  }
   599  
   600  // Tests a recovery for a long canonical chain with frozen blocks and a longer side
   601  // chain, where a recent block - older than the ancient limit - was already committed
   602  // to disk and then the process crashed. In this case we expect the canonical chains
   603  // to be rolled back to the committed block, with everything afterwards deleted. The
   604  // side chain completely nuked by the freezer.
   605  // func TestLongReorgedDeepRepair(t *testing.T)              { testLongReorgedDeepRepair(t, false) }
   606  // func TestLongReorgedDeepRepairWithSnapshots(t *testing.T) { testLongReorgedDeepRepair(t, true) }
   607  
   608  func testLongReorgedDeepRepair(t *testing.T, snapshots bool) {
   609  	// Chain:
   610  	//   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)
   611  	//   └->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
   612  	//
   613  	// Frozen:
   614  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   615  	//
   616  	// Commit: G, C4
   617  	// Pivot : none
   618  	//
   619  	// CRASH
   620  	//
   621  	// ------------------------------
   622  	//
   623  	// Expected in freezer:
   624  	//   G->C1->C2->C3->C4
   625  	//
   626  	// Expected in leveldb: none
   627  	//
   628  	// Expected head header    : C4
   629  	// Expected head fast block: C4
   630  	// Expected head block     : C4
   631  	testRepair(t, &rewindTest{
   632  		canonicalBlocks:    24,
   633  		sidechainBlocks:    26,
   634  		freezeThreshold:    16,
   635  		commitBlock:        4,
   636  		pivotBlock:         nil,
   637  		expCanonicalBlocks: 4,
   638  		expSidechainBlocks: 0,
   639  		expFrozen:          5,
   640  		expHeadHeader:      4,
   641  		expHeadFastBlock:   4,
   642  		expHeadBlock:       4,
   643  	}, snapshots)
   644  }
   645  
   646  // Tests a recovery for a long canonical chain with frozen blocks and a longer
   647  // side chain, where the fast sync pivot point - newer than the ancient limit -
   648  // was already committed to disk and then the process crashed. In this case we
   649  // expect the chain to be rolled back to the committed block, with everything
   650  // afterwards kept as fast sync data. The side chain completely nuked by the
   651  // freezer.
   652  // func TestLongReorgedSnapSyncedShallowRepair(t *testing.T) {
   653  // 	testLongReorgedSnapSyncedShallowRepair(t, false)
   654  // }
   655  // func TestLongReorgedSnapSyncedShallowRepairWithSnapshots(t *testing.T) {
   656  // 	testLongReorgedSnapSyncedShallowRepair(t, true)
   657  // }
   658  
   659  func testLongReorgedSnapSyncedShallowRepair(t *testing.T, snapshots bool) {
   660  	// Chain:
   661  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
   662  	//   └->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
   663  	//
   664  	// Frozen:
   665  	//   G->C1->C2
   666  	//
   667  	// Commit: G, C4
   668  	// Pivot : C4
   669  	//
   670  	// CRASH
   671  	//
   672  	// ------------------------------
   673  	//
   674  	// Expected in freezer:
   675  	//   G->C1->C2
   676  	//
   677  	// Expected in leveldb:
   678  	//   C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18
   679  	//
   680  	// Expected head header    : C18
   681  	// Expected head fast block: C18
   682  	// Expected head block     : C4
   683  	testRepair(t, &rewindTest{
   684  		canonicalBlocks:    18,
   685  		sidechainBlocks:    26,
   686  		freezeThreshold:    16,
   687  		commitBlock:        4,
   688  		pivotBlock:         uint64ptr(4),
   689  		expCanonicalBlocks: 18,
   690  		expSidechainBlocks: 0,
   691  		expFrozen:          3,
   692  		expHeadHeader:      18,
   693  		expHeadFastBlock:   18,
   694  		expHeadBlock:       4,
   695  	}, snapshots)
   696  }
   697  
   698  // Tests a recovery for a long canonical chain with frozen blocks and a longer
   699  // side chain, where the fast sync pivot point - older than the ancient limit -
   700  // was already committed to disk and then the process crashed. In this case we
   701  // expect the canonical chains to be rolled back to the committed block, with
   702  // everything afterwards deleted. The side chain completely nuked by the freezer.
   703  // func TestLongReorgedSnapSyncedDeepRepair(t *testing.T) {
   704  // 	testLongReorgedSnapSyncedDeepRepair(t, false)
   705  // }
   706  // func TestLongReorgedSnapSyncedDeepRepairWithSnapshots(t *testing.T) {
   707  // 	testLongReorgedSnapSyncedDeepRepair(t, true)
   708  // }
   709  
   710  func testLongReorgedSnapSyncedDeepRepair(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  	//   └->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
   714  	//
   715  	// Frozen:
   716  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   717  	//
   718  	// Commit: G, C4
   719  	// Pivot : C4
   720  	//
   721  	// CRASH
   722  	//
   723  	// ------------------------------
   724  	//
   725  	// Expected in freezer:
   726  	//   G->C1->C2->C3->C4
   727  	//
   728  	// Expected in leveldb: none
   729  	//
   730  	// Expected head header    : C4
   731  	// Expected head fast block: C4
   732  	// Expected head block     : C4
   733  	testRepair(t, &rewindTest{
   734  		canonicalBlocks:    24,
   735  		sidechainBlocks:    26,
   736  		freezeThreshold:    16,
   737  		commitBlock:        4,
   738  		pivotBlock:         uint64ptr(4),
   739  		expCanonicalBlocks: 4,
   740  		expSidechainBlocks: 0,
   741  		expFrozen:          5,
   742  		expHeadHeader:      4,
   743  		expHeadFastBlock:   4,
   744  		expHeadBlock:       4,
   745  	}, snapshots)
   746  }
   747  
   748  // Tests a recovery for a long canonical chain with frozen blocks and a longer
   749  // side chain, where the fast sync pivot point - newer than the ancient limit -
   750  // was not yet committed, but the process crashed. In this case we expect the
   751  // chain to detect that it was fast syncing and not delete anything, since we
   752  // can just pick up directly where we left off.
   753  // func TestLongReorgedSnapSyncingShallowRepair(t *testing.T) {
   754  // 	testLongReorgedSnapSyncingShallowRepair(t, false)
   755  // }
   756  // func TestLongReorgedSnapSyncingShallowRepairWithSnapshots(t *testing.T) {
   757  // 	testLongReorgedSnapSyncingShallowRepair(t, true)
   758  // }
   759  
   760  func testLongReorgedSnapSyncingShallowRepair(t *testing.T, snapshots bool) {
   761  	// Chain:
   762  	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
   763  	//   └->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
   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:    26,
   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 and a longer
   800  // side chain, where the fast sync pivot point - older than the ancient limit -
   801  // was not yet committed, but the process crashed. In this case we expect the
   802  // chain to detect that it was fast syncing and not delete anything, since we
   803  // can just pick up directly where we left off.
   804  // func TestLongReorgedSnapSyncingDeepRepair(t *testing.T) {
   805  // 	testLongReorgedSnapSyncingDeepRepair(t, false)
   806  // }
   807  // func TestLongReorgedSnapSyncingDeepRepairWithSnapshots(t *testing.T) {
   808  // 	testLongReorgedSnapSyncingDeepRepair(t, true)
   809  // }
   810  
   811  func testLongReorgedSnapSyncingDeepRepair(t *testing.T, snapshots bool) {
   812  	// Chain:
   813  	//   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)
   814  	//   └->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
   815  	//
   816  	// Frozen:
   817  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   818  	//
   819  	// Commit: G
   820  	// Pivot : C4
   821  	//
   822  	// CRASH
   823  	//
   824  	// ------------------------------
   825  	//
   826  	// Expected in freezer:
   827  	//   G->C1->C2->C3->C4->C5->C6->C7->C8
   828  	//
   829  	// Expected in leveldb:
   830  	//   C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24
   831  	//
   832  	// Expected head header    : C24
   833  	// Expected head fast block: C24
   834  	// Expected head block     : G
   835  	testRepair(t, &rewindTest{
   836  		canonicalBlocks:    24,
   837  		sidechainBlocks:    26,
   838  		freezeThreshold:    16,
   839  		commitBlock:        0,
   840  		pivotBlock:         uint64ptr(4),
   841  		expCanonicalBlocks: 24,
   842  		expSidechainBlocks: 0,
   843  		expFrozen:          9,
   844  		expHeadHeader:      24,
   845  		expHeadFastBlock:   24,
   846  		expHeadBlock:       0,
   847  	}, snapshots)
   848  }
   849  
   850  func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
   851  	for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} {
   852  		testRepairWithScheme(t, tt, snapshots, scheme)
   853  	}
   854  }
   855  
   856  func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) {
   857  	// It's hard to follow the test case, visualize the input
   858  	//log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
   859  	// fmt.Println(tt.dump(true))
   860  
   861  	// Create a temporary persistent database
   862  	datadir := t.TempDir()
   863  	ancient := path.Join(datadir, "ancient")
   864  
   865  	db, err := rawdb.Open(rawdb.OpenOptions{
   866  		Directory:         datadir,
   867  		AncientsDirectory: ancient,
   868  		Ephemeral:         true,
   869  	})
   870  	if err != nil {
   871  		t.Fatalf("Failed to create persistent database: %v", err)
   872  	}
   873  	defer db.Close() // Might double close, should be fine
   874  
   875  	// Initialize a fresh chain
   876  	var (
   877  		gspec = &Genesis{
   878  			BaseFee: big.NewInt(params.InitialBaseFee),
   879  			Config:  params.AllBeaconProtocolChanges,
   880  		}
   881  		engine = beacon.NewFullFaker()
   882  		config = &CacheConfig{
   883  			TrieCleanLimit: 256,
   884  			TrieDirtyLimit: 256,
   885  			TrieTimeLimit:  5 * time.Minute,
   886  			SnapshotLimit:  0, // Disable snapshot by default
   887  			StateScheme:    scheme,
   888  		}
   889  	)
   890  	defer engine.Close()
   891  	if snapshots {
   892  		config.SnapshotLimit = 256
   893  		config.SnapshotWait = true
   894  	}
   895  	chain, err := NewBlockChain(db, config, gspec, engine, vm.Config{}, nil, nil)
   896  	if err != nil {
   897  		t.Fatalf("Failed to create chain: %v", err)
   898  	}
   899  	canonblocks, _ := GenerateChain(gspec.Config, gspec.ToBlock(), engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) {
   900  		b.SetCoinbase(common.Address{0x02})
   901  	})
   902  	if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil {
   903  		t.Fatalf("Failed to import canonical chain start: %v", err)
   904  	}
   905  	if tt.commitBlock > 0 {
   906  		if err := chain.triedb.Commit(canonblocks[tt.commitBlock-1].Root(), false); err != nil {
   907  			t.Fatalf("Failed to flush trie state: %v", err)
   908  		}
   909  		if snapshots {
   910  			if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil {
   911  				t.Fatalf("Failed to flatten snapshots: %v", err)
   912  			}
   913  		}
   914  	}
   915  	if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil {
   916  		t.Fatalf("Failed to import canonical chain tail: %v", err)
   917  	}
   918  	// Force run a freeze cycle
   919  	type freezer interface {
   920  		Freeze(threshold uint64) error
   921  		Ancients() (uint64, error)
   922  	}
   923  	db.(freezer).Freeze(tt.freezeThreshold)
   924  
   925  	// Set the simulated pivot block
   926  	if tt.pivotBlock != nil {
   927  		rawdb.WriteLastPivotNumber(db, *tt.pivotBlock)
   928  	}
   929  	// Pull the plug on the database, simulating a hard crash
   930  	chain.triedb.Close()
   931  	db.Close()
   932  	chain.stopWithoutSaving()
   933  
   934  	// Start a new blockchain back up and see where the repair leads us
   935  	db, err = rawdb.Open(rawdb.OpenOptions{
   936  		Directory:         datadir,
   937  		AncientsDirectory: ancient,
   938  		Ephemeral:         true,
   939  	})
   940  	if err != nil {
   941  		t.Fatalf("Failed to reopen persistent database: %v", err)
   942  	}
   943  	defer db.Close()
   944  
   945  	newChain, err := NewBlockChain(db, config, gspec, engine, vm.Config{}, nil, nil)
   946  	if err != nil {
   947  		t.Fatalf("Failed to recreate chain: %v", err)
   948  	}
   949  	defer newChain.Stop()
   950  
   951  	// Iterate over all the remaining blocks and ensure there are no gaps
   952  	verifyNoGaps(t, newChain, true, canonblocks)
   953  	verifyCutoff(t, newChain, true, canonblocks, tt.expCanonicalBlocks)
   954  
   955  	if head := newChain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader {
   956  		t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader)
   957  	}
   958  	if head := newChain.CurrentSnapBlock(); head.Number.Uint64() != tt.expHeadFastBlock {
   959  		t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, tt.expHeadFastBlock)
   960  	}
   961  	if head := newChain.CurrentBlock(); head.Number.Uint64() != tt.expHeadBlock {
   962  		t.Errorf("Head block mismatch: have %d, want %d", head.Number, tt.expHeadBlock)
   963  	}
   964  	if frozen, err := db.(freezer).Ancients(); err != nil {
   965  		t.Errorf("Failed to retrieve ancient count: %v\n", err)
   966  	} else if int(frozen) != tt.expFrozen {
   967  		t.Errorf("Frozen block count mismatch: have %d, want %d", frozen, tt.expFrozen)
   968  	}
   969  }
   970  
   971  // TestIssue23496 tests scenario described in https://github.com/theQRL/go-zond/pull/23496#issuecomment-926393893
   972  // Credits to @zzyalbert for finding the issue.
   973  //
   974  // Local chain owns these blocks:
   975  // G  B1  B2  B3  B4
   976  // B1: state committed
   977  // B2: snapshot disk layer
   978  // B3: state committed
   979  // B4: head block
   980  //
   981  // Crash happens without fully persisting snapshot and in-memory states,
   982  // chain rewinds itself to the B1 (skip B3 in order to recover snapshot)
   983  // In this case the snapshot layer of B3 is not created because of existent
   984  // state.
   985  // func TestIssue23496(t *testing.T) {
   986  // 	testIssue23496(t, rawdb.HashScheme)
   987  // 	testIssue23496(t, rawdb.PathScheme)
   988  // }
   989  
   990  func testIssue23496(t *testing.T, scheme string) {
   991  	// It's hard to follow the test case, visualize the input
   992  	//log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
   993  
   994  	// Create a temporary persistent database
   995  	datadir := t.TempDir()
   996  	ancient := path.Join(datadir, "ancient")
   997  
   998  	db, err := rawdb.Open(rawdb.OpenOptions{
   999  		Directory:         datadir,
  1000  		AncientsDirectory: ancient,
  1001  	})
  1002  	if err != nil {
  1003  		t.Fatalf("Failed to create persistent database: %v", err)
  1004  	}
  1005  	defer db.Close() // Might double close, should be fine
  1006  
  1007  	// Initialize a fresh chain
  1008  	var (
  1009  		gspec = &Genesis{
  1010  			Config:  params.TestChainConfig,
  1011  			BaseFee: big.NewInt(params.InitialBaseFee),
  1012  		}
  1013  		engine = beacon.NewFullFaker()
  1014  	)
  1015  	chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, engine, vm.Config{}, nil, nil)
  1016  	if err != nil {
  1017  		t.Fatalf("Failed to create chain: %v", err)
  1018  	}
  1019  	_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 4, func(i int, b *BlockGen) {
  1020  		b.SetCoinbase(common.Address{0x02})
  1021  	})
  1022  
  1023  	// Insert block B1 and commit the state into disk
  1024  	if _, err := chain.InsertChain(blocks[:1]); err != nil {
  1025  		t.Fatalf("Failed to import canonical chain start: %v", err)
  1026  	}
  1027  	chain.triedb.Commit(blocks[0].Root(), false)
  1028  
  1029  	// Insert block B2 and commit the snapshot into disk
  1030  	if _, err := chain.InsertChain(blocks[1:2]); err != nil {
  1031  		t.Fatalf("Failed to import canonical chain start: %v", err)
  1032  	}
  1033  	if err := chain.snaps.Cap(blocks[1].Root(), 0); err != nil {
  1034  		t.Fatalf("Failed to flatten snapshots: %v", err)
  1035  	}
  1036  
  1037  	// Insert block B3 and commit the state into disk
  1038  	if _, err := chain.InsertChain(blocks[2:3]); err != nil {
  1039  		t.Fatalf("Failed to import canonical chain start: %v", err)
  1040  	}
  1041  	chain.triedb.Commit(blocks[2].Root(), false)
  1042  
  1043  	// Insert the remaining blocks
  1044  	if _, err := chain.InsertChain(blocks[3:]); err != nil {
  1045  		t.Fatalf("Failed to import canonical chain tail: %v", err)
  1046  	}
  1047  
  1048  	// Pull the plug on the database, simulating a hard crash
  1049  	chain.triedb.Close()
  1050  	db.Close()
  1051  	chain.stopWithoutSaving()
  1052  
  1053  	// Start a new blockchain back up and see where the repair leads us
  1054  	db, err = rawdb.Open(rawdb.OpenOptions{
  1055  		Directory:         datadir,
  1056  		AncientsDirectory: ancient,
  1057  		Ephemeral:         true,
  1058  	})
  1059  	if err != nil {
  1060  		t.Fatalf("Failed to reopen persistent database: %v", err)
  1061  	}
  1062  	defer db.Close()
  1063  
  1064  	chain, err = NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, engine, vm.Config{}, nil, nil)
  1065  	if err != nil {
  1066  		t.Fatalf("Failed to recreate chain: %v", err)
  1067  	}
  1068  	defer chain.Stop()
  1069  
  1070  	if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) {
  1071  		t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4)
  1072  	}
  1073  	if head := chain.CurrentSnapBlock(); head.Number.Uint64() != uint64(4) {
  1074  		t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, uint64(4))
  1075  	}
  1076  	expHead := uint64(1)
  1077  	if scheme == rawdb.PathScheme {
  1078  		expHead = uint64(2)
  1079  	}
  1080  	if head := chain.CurrentBlock(); head.Number.Uint64() != expHead {
  1081  		t.Errorf("Head block mismatch: have %d, want %d", head.Number, expHead)
  1082  	}
  1083  
  1084  	// Reinsert B2-B4
  1085  	if _, err := chain.InsertChain(blocks[1:]); err != nil {
  1086  		t.Fatalf("Failed to import canonical chain tail: %v", err)
  1087  	}
  1088  	if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) {
  1089  		t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4)
  1090  	}
  1091  	if head := chain.CurrentSnapBlock(); head.Number.Uint64() != uint64(4) {
  1092  		t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, uint64(4))
  1093  	}
  1094  	if head := chain.CurrentBlock(); head.Number.Uint64() != uint64(4) {
  1095  		t.Errorf("Head block mismatch: have %d, want %d", head.Number, uint64(4))
  1096  	}
  1097  	if layer := chain.Snapshots().Snapshot(blocks[2].Root()); layer == nil {
  1098  		t.Error("Failed to regenerate the snapshot of known state")
  1099  	}
  1100  }
  1101  */