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