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 setting the chain head backwards doesn't leave the database in some
18// strange state with gaps in the chain, nor with block data dangling in the future.
19
20package core
21
22import (
23	"fmt"
24	"io/ioutil"
25	"math/big"
26	"os"
27	"strings"
28	"testing"
29	"time"
30
31	"github.com/ethereum/go-ethereum/common"
32	"github.com/ethereum/go-ethereum/consensus/ethash"
33	"github.com/ethereum/go-ethereum/core/rawdb"
34	"github.com/ethereum/go-ethereum/core/types"
35	"github.com/ethereum/go-ethereum/core/vm"
36	"github.com/ethereum/go-ethereum/params"
37)
38
39// rewindTest is a test case for chain rollback upon user request.
40type rewindTest struct {
41	canonicalBlocks int     // Number of blocks to generate for the canonical chain (heavier)
42	sidechainBlocks int     // Number of blocks to generate for the side chain (lighter)
43	freezeThreshold uint64  // Block number until which to move things into the freezer
44	commitBlock     uint64  // Block number for which to commit the state to disk
45	pivotBlock      *uint64 // Pivot block number in case of fast sync
46
47	setheadBlock       uint64 // Block number to set head back to
48	expCanonicalBlocks int    // Number of canonical blocks expected to remain in the database (excl. genesis)
49	expSidechainBlocks int    // Number of sidechain blocks expected to remain in the database (excl. genesis)
50	expFrozen          int    // Number of canonical blocks expected to be in the freezer (incl. genesis)
51	expHeadHeader      uint64 // Block number of the expected head header
52	expHeadFastBlock   uint64 // Block number of the expected head fast sync block
53	expHeadBlock       uint64 // Block number of the expected head full block
54}
55
56func (tt *rewindTest) dump(crash bool) string {
57	buffer := new(strings.Builder)
58
59	fmt.Fprint(buffer, "Chain:\n  G")
60	for i := 0; i < tt.canonicalBlocks; i++ {
61		fmt.Fprintf(buffer, "->C%d", i+1)
62	}
63	fmt.Fprint(buffer, " (HEAD)\n")
64	if tt.sidechainBlocks > 0 {
65		fmt.Fprintf(buffer, "  └")
66		for i := 0; i < tt.sidechainBlocks; i++ {
67			fmt.Fprintf(buffer, "->S%d", i+1)
68		}
69		fmt.Fprintf(buffer, "\n")
70	}
71	fmt.Fprintf(buffer, "\n")
72
73	if tt.canonicalBlocks > int(tt.freezeThreshold) {
74		fmt.Fprint(buffer, "Frozen:\n  G")
75		for i := 0; i < tt.canonicalBlocks-int(tt.freezeThreshold); i++ {
76			fmt.Fprintf(buffer, "->C%d", i+1)
77		}
78		fmt.Fprintf(buffer, "\n\n")
79	} else {
80		fmt.Fprintf(buffer, "Frozen: none\n")
81	}
82	fmt.Fprintf(buffer, "Commit: G")
83	if tt.commitBlock > 0 {
84		fmt.Fprintf(buffer, ", C%d", tt.commitBlock)
85	}
86	fmt.Fprint(buffer, "\n")
87
88	if tt.pivotBlock == nil {
89		fmt.Fprintf(buffer, "Pivot : none\n")
90	} else {
91		fmt.Fprintf(buffer, "Pivot : C%d\n", *tt.pivotBlock)
92	}
93	if crash {
94		fmt.Fprintf(buffer, "\nCRASH\n\n")
95	} else {
96		fmt.Fprintf(buffer, "\nSetHead(%d)\n\n", tt.setheadBlock)
97	}
98	fmt.Fprintf(buffer, "------------------------------\n\n")
99
100	if tt.expFrozen > 0 {
101		fmt.Fprint(buffer, "Expected in freezer:\n  G")
102		for i := 0; i < tt.expFrozen-1; i++ {
103			fmt.Fprintf(buffer, "->C%d", i+1)
104		}
105		fmt.Fprintf(buffer, "\n\n")
106	}
107	if tt.expFrozen > 0 {
108		if tt.expFrozen >= tt.expCanonicalBlocks {
109			fmt.Fprintf(buffer, "Expected in leveldb: none\n")
110		} else {
111			fmt.Fprintf(buffer, "Expected in leveldb:\n  C%d)", tt.expFrozen-1)
112			for i := tt.expFrozen - 1; i < tt.expCanonicalBlocks; i++ {
113				fmt.Fprintf(buffer, "->C%d", i+1)
114			}
115			fmt.Fprint(buffer, "\n")
116			if tt.expSidechainBlocks > tt.expFrozen {
117				fmt.Fprintf(buffer, "  └")
118				for i := tt.expFrozen - 1; i < tt.expSidechainBlocks; i++ {
119					fmt.Fprintf(buffer, "->S%d", i+1)
120				}
121				fmt.Fprintf(buffer, "\n")
122			}
123		}
124	} else {
125		fmt.Fprint(buffer, "Expected in leveldb:\n  G")
126		for i := tt.expFrozen; i < tt.expCanonicalBlocks; i++ {
127			fmt.Fprintf(buffer, "->C%d", i+1)
128		}
129		fmt.Fprint(buffer, "\n")
130		if tt.expSidechainBlocks > tt.expFrozen {
131			fmt.Fprintf(buffer, "  └")
132			for i := tt.expFrozen; i < tt.expSidechainBlocks; i++ {
133				fmt.Fprintf(buffer, "->S%d", i+1)
134			}
135			fmt.Fprintf(buffer, "\n")
136		}
137	}
138	fmt.Fprintf(buffer, "\n")
139	fmt.Fprintf(buffer, "Expected head header    : C%d\n", tt.expHeadHeader)
140	fmt.Fprintf(buffer, "Expected head fast block: C%d\n", tt.expHeadFastBlock)
141	if tt.expHeadBlock == 0 {
142		fmt.Fprintf(buffer, "Expected head block     : G\n")
143	} else {
144		fmt.Fprintf(buffer, "Expected head block     : C%d\n", tt.expHeadBlock)
145	}
146	return buffer.String()
147}
148
149// Tests a sethead for a short canonical chain where a recent block was already
150// committed to disk and then the sethead called. In this case we expect the full
151// chain to be rolled back to the committed block. Everything above the sethead
152// point should be deleted. In between the committed block and the requested head
153// the data can remain as "fast sync" data to avoid redownloading it.
154func TestShortSetHead(t *testing.T)              { testShortSetHead(t, false) }
155func TestShortSetHeadWithSnapshots(t *testing.T) { testShortSetHead(t, true) }
156
157func testShortSetHead(t *testing.T, snapshots bool) {
158	// Chain:
159	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
160	//
161	// Frozen: none
162	// Commit: G, C4
163	// Pivot : none
164	//
165	// SetHead(7)
166	//
167	// ------------------------------
168	//
169	// Expected in leveldb:
170	//   G->C1->C2->C3->C4->C5->C6->C7
171	//
172	// Expected head header    : C7
173	// Expected head fast block: C7
174	// Expected head block     : C4
175	testSetHead(t, &rewindTest{
176		canonicalBlocks:    8,
177		sidechainBlocks:    0,
178		freezeThreshold:    16,
179		commitBlock:        4,
180		pivotBlock:         nil,
181		setheadBlock:       7,
182		expCanonicalBlocks: 7,
183		expSidechainBlocks: 0,
184		expFrozen:          0,
185		expHeadHeader:      7,
186		expHeadFastBlock:   7,
187		expHeadBlock:       4,
188	}, snapshots)
189}
190
191// Tests a sethead for a short canonical chain where the fast sync pivot point was
192// already committed, after which sethead was called. In this case we expect the
193// chain to behave like in full sync mode, rolling back to the committed block
194// Everything above the sethead point should be deleted. In between the committed
195// block and the requested head the data can remain as "fast sync" data to avoid
196// redownloading it.
197func TestShortSnapSyncedSetHead(t *testing.T)              { testShortSnapSyncedSetHead(t, false) }
198func TestShortSnapSyncedSetHeadWithSnapshots(t *testing.T) { testShortSnapSyncedSetHead(t, true) }
199
200func testShortSnapSyncedSetHead(t *testing.T, snapshots bool) {
201	// Chain:
202	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
203	//
204	// Frozen: none
205	// Commit: G, C4
206	// Pivot : C4
207	//
208	// SetHead(7)
209	//
210	// ------------------------------
211	//
212	// Expected in leveldb:
213	//   G->C1->C2->C3->C4->C5->C6->C7
214	//
215	// Expected head header    : C7
216	// Expected head fast block: C7
217	// Expected head block     : C4
218	testSetHead(t, &rewindTest{
219		canonicalBlocks:    8,
220		sidechainBlocks:    0,
221		freezeThreshold:    16,
222		commitBlock:        4,
223		pivotBlock:         uint64ptr(4),
224		setheadBlock:       7,
225		expCanonicalBlocks: 7,
226		expSidechainBlocks: 0,
227		expFrozen:          0,
228		expHeadHeader:      7,
229		expHeadFastBlock:   7,
230		expHeadBlock:       4,
231	}, snapshots)
232}
233
234// Tests a sethead for a short canonical chain where the fast sync pivot point was
235// not yet committed, but sethead was called. In this case we expect the chain to
236// detect that it was fast syncing and delete everything from the new head, since
237// we can just pick up fast syncing from there. The head full block should be set
238// to the genesis.
239func TestShortSnapSyncingSetHead(t *testing.T)              { testShortSnapSyncingSetHead(t, false) }
240func TestShortSnapSyncingSetHeadWithSnapshots(t *testing.T) { testShortSnapSyncingSetHead(t, true) }
241
242func testShortSnapSyncingSetHead(t *testing.T, snapshots bool) {
243	// Chain:
244	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
245	//
246	// Frozen: none
247	// Commit: G
248	// Pivot : C4
249	//
250	// SetHead(7)
251	//
252	// ------------------------------
253	//
254	// Expected in leveldb:
255	//   G->C1->C2->C3->C4->C5->C6->C7
256	//
257	// Expected head header    : C7
258	// Expected head fast block: C7
259	// Expected head block     : G
260	testSetHead(t, &rewindTest{
261		canonicalBlocks:    8,
262		sidechainBlocks:    0,
263		freezeThreshold:    16,
264		commitBlock:        0,
265		pivotBlock:         uint64ptr(4),
266		setheadBlock:       7,
267		expCanonicalBlocks: 7,
268		expSidechainBlocks: 0,
269		expFrozen:          0,
270		expHeadHeader:      7,
271		expHeadFastBlock:   7,
272		expHeadBlock:       0,
273	}, snapshots)
274}
275
276// Tests a sethead for a short canonical chain and a shorter side chain, where a
277// recent block was already committed to disk and then sethead was called. In this
278// test scenario the side chain is below the committed block. In this case we expect
279// the canonical full chain to be rolled back to the committed block. Everything
280// above the sethead point should be deleted. In between the committed block and
281// the requested head the data can remain as "fast sync" data to avoid redownloading
282// it. The side chain should be left alone as it was shorter.
283func TestShortOldForkedSetHead(t *testing.T)              { testShortOldForkedSetHead(t, false) }
284func TestShortOldForkedSetHeadWithSnapshots(t *testing.T) { testShortOldForkedSetHead(t, true) }
285
286func testShortOldForkedSetHead(t *testing.T, snapshots bool) {
287	// Chain:
288	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
289	//   └->S1->S2->S3
290	//
291	// Frozen: none
292	// Commit: G, C4
293	// Pivot : none
294	//
295	// SetHead(7)
296	//
297	// ------------------------------
298	//
299	// Expected in leveldb:
300	//   G->C1->C2->C3->C4->C5->C6->C7
301	//   └->S1->S2->S3
302	//
303	// Expected head header    : C7
304	// Expected head fast block: C7
305	// Expected head block     : C4
306	testSetHead(t, &rewindTest{
307		canonicalBlocks:    8,
308		sidechainBlocks:    3,
309		freezeThreshold:    16,
310		commitBlock:        4,
311		pivotBlock:         nil,
312		setheadBlock:       7,
313		expCanonicalBlocks: 7,
314		expSidechainBlocks: 3,
315		expFrozen:          0,
316		expHeadHeader:      7,
317		expHeadFastBlock:   7,
318		expHeadBlock:       4,
319	}, snapshots)
320}
321
322// Tests a sethead for a short canonical chain and a shorter side chain, where
323// the fast sync pivot point was already committed to disk and then sethead was
324// called. In this test scenario the side chain is below the committed block. In
325// this case we expect the canonical full chain to be rolled back to the committed
326// block. Everything above the sethead point should be deleted. In between the
327// committed block and the requested head the data can remain as "fast sync" data
328// to avoid redownloading it. The side chain should be left alone as it was shorter.
329func TestShortOldForkedSnapSyncedSetHead(t *testing.T) {
330	testShortOldForkedSnapSyncedSetHead(t, false)
331}
332func TestShortOldForkedSnapSyncedSetHeadWithSnapshots(t *testing.T) {
333	testShortOldForkedSnapSyncedSetHead(t, true)
334}
335
336func testShortOldForkedSnapSyncedSetHead(t *testing.T, snapshots bool) {
337	// Chain:
338	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
339	//   └->S1->S2->S3
340	//
341	// Frozen: none
342	// Commit: G, C4
343	// Pivot : C4
344	//
345	// SetHead(7)
346	//
347	// ------------------------------
348	//
349	// Expected in leveldb:
350	//   G->C1->C2->C3->C4->C5->C6->C7
351	//   └->S1->S2->S3
352	//
353	// Expected head header    : C7
354	// Expected head fast block: C7
355	// Expected head block     : C4
356	testSetHead(t, &rewindTest{
357		canonicalBlocks:    8,
358		sidechainBlocks:    3,
359		freezeThreshold:    16,
360		commitBlock:        4,
361		pivotBlock:         uint64ptr(4),
362		setheadBlock:       7,
363		expCanonicalBlocks: 7,
364		expSidechainBlocks: 3,
365		expFrozen:          0,
366		expHeadHeader:      7,
367		expHeadFastBlock:   7,
368		expHeadBlock:       4,
369	}, snapshots)
370}
371
372// Tests a sethead for a short canonical chain and a shorter side chain, where
373// the fast sync pivot point was not yet committed, but sethead was called. In this
374// test scenario the side chain is below the committed block. In this case we expect
375// the chain to detect that it was fast syncing and delete everything from the new
376// head, since we can just pick up fast syncing from there. The head full block
377// should be set to the genesis.
378func TestShortOldForkedSnapSyncingSetHead(t *testing.T) {
379	testShortOldForkedSnapSyncingSetHead(t, false)
380}
381func TestShortOldForkedSnapSyncingSetHeadWithSnapshots(t *testing.T) {
382	testShortOldForkedSnapSyncingSetHead(t, true)
383}
384
385func testShortOldForkedSnapSyncingSetHead(t *testing.T, snapshots bool) {
386	// Chain:
387	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
388	//   └->S1->S2->S3
389	//
390	// Frozen: none
391	// Commit: G
392	// Pivot : C4
393	//
394	// SetHead(7)
395	//
396	// ------------------------------
397	//
398	// Expected in leveldb:
399	//   G->C1->C2->C3->C4->C5->C6->C7
400	//   └->S1->S2->S3
401	//
402	// Expected head header    : C7
403	// Expected head fast block: C7
404	// Expected head block     : G
405	testSetHead(t, &rewindTest{
406		canonicalBlocks:    8,
407		sidechainBlocks:    3,
408		freezeThreshold:    16,
409		commitBlock:        0,
410		pivotBlock:         uint64ptr(4),
411		setheadBlock:       7,
412		expCanonicalBlocks: 7,
413		expSidechainBlocks: 3,
414		expFrozen:          0,
415		expHeadHeader:      7,
416		expHeadFastBlock:   7,
417		expHeadBlock:       0,
418	}, snapshots)
419}
420
421// Tests a sethead for a short canonical chain and a shorter side chain, where a
422// recent block was already committed to disk and then sethead was called. In this
423// test scenario the side chain reaches above the committed block. In this case we
424// expect the canonical full chain to be rolled back to the committed block. All
425// data above the sethead point should be deleted. In between the committed block
426// and the requested head the data can remain as "fast sync" data to avoid having
427// to redownload it. The side chain should be truncated to the head set.
428//
429// The side chain could be left to be if the fork point was before the new head
430// we are deleting to, but it would be exceedingly hard to detect that case and
431// properly handle it, so we'll trade extra work in exchange for simpler code.
432func TestShortNewlyForkedSetHead(t *testing.T)              { testShortNewlyForkedSetHead(t, false) }
433func TestShortNewlyForkedSetHeadWithSnapshots(t *testing.T) { testShortNewlyForkedSetHead(t, true) }
434
435func testShortNewlyForkedSetHead(t *testing.T, snapshots bool) {
436	// Chain:
437	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 (HEAD)
438	//   └->S1->S2->S3->S4->S5->S6->S7->S8
439	//
440	// Frozen: none
441	// Commit: G, C4
442	// Pivot : none
443	//
444	// SetHead(7)
445	//
446	// ------------------------------
447	//
448	// Expected in leveldb:
449	//   G->C1->C2->C3->C4->C5->C6->C7
450	//   └->S1->S2->S3->S4->S5->S6->S7
451	//
452	// Expected head header    : C7
453	// Expected head fast block: C7
454	// Expected head block     : C4
455	testSetHead(t, &rewindTest{
456		canonicalBlocks:    10,
457		sidechainBlocks:    8,
458		freezeThreshold:    16,
459		commitBlock:        4,
460		pivotBlock:         nil,
461		setheadBlock:       7,
462		expCanonicalBlocks: 7,
463		expSidechainBlocks: 7,
464		expFrozen:          0,
465		expHeadHeader:      7,
466		expHeadFastBlock:   7,
467		expHeadBlock:       4,
468	}, snapshots)
469}
470
471// Tests a sethead for a short canonical chain and a shorter side chain, where
472// the fast sync pivot point was already committed to disk and then sethead was
473// called. In this case we expect the canonical full chain to be rolled back to
474// between the committed block and the requested head the data can remain as
475// "fast sync" data to avoid having to redownload it. The side chain should be
476// truncated to the head set.
477//
478// The side chain could be left to be if the fork point was before the new head
479// we are deleting to, but it would be exceedingly hard to detect that case and
480// properly handle it, so we'll trade extra work in exchange for simpler code.
481func TestShortNewlyForkedSnapSyncedSetHead(t *testing.T) {
482	testShortNewlyForkedSnapSyncedSetHead(t, false)
483}
484func TestShortNewlyForkedSnapSyncedSetHeadWithSnapshots(t *testing.T) {
485	testShortNewlyForkedSnapSyncedSetHead(t, true)
486}
487
488func testShortNewlyForkedSnapSyncedSetHead(t *testing.T, snapshots bool) {
489	// Chain:
490	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 (HEAD)
491	//   └->S1->S2->S3->S4->S5->S6->S7->S8
492	//
493	// Frozen: none
494	// Commit: G, C4
495	// Pivot : C4
496	//
497	// SetHead(7)
498	//
499	// ------------------------------
500	//
501	// Expected in leveldb:
502	//   G->C1->C2->C3->C4->C5->C6->C7
503	//   └->S1->S2->S3->S4->S5->S6->S7
504	//
505	// Expected head header    : C7
506	// Expected head fast block: C7
507	// Expected head block     : C4
508	testSetHead(t, &rewindTest{
509		canonicalBlocks:    10,
510		sidechainBlocks:    8,
511		freezeThreshold:    16,
512		commitBlock:        4,
513		pivotBlock:         uint64ptr(4),
514		setheadBlock:       7,
515		expCanonicalBlocks: 7,
516		expSidechainBlocks: 7,
517		expFrozen:          0,
518		expHeadHeader:      7,
519		expHeadFastBlock:   7,
520		expHeadBlock:       4,
521	}, snapshots)
522}
523
524// Tests a sethead for a short canonical chain and a shorter side chain, where
525// the fast sync pivot point was not yet committed, but sethead was called. In
526// this test scenario the side chain reaches above the committed block. In this
527// case we expect the chain to detect that it was fast syncing and delete
528// everything from the new head, since we can just pick up fast syncing from
529// there.
530//
531// The side chain could be left to be if the fork point was before the new head
532// we are deleting to, but it would be exceedingly hard to detect that case and
533// properly handle it, so we'll trade extra work in exchange for simpler code.
534func TestShortNewlyForkedSnapSyncingSetHead(t *testing.T) {
535	testShortNewlyForkedSnapSyncingSetHead(t, false)
536}
537func TestShortNewlyForkedSnapSyncingSetHeadWithSnapshots(t *testing.T) {
538	testShortNewlyForkedSnapSyncingSetHead(t, true)
539}
540
541func testShortNewlyForkedSnapSyncingSetHead(t *testing.T, snapshots bool) {
542	// Chain:
543	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 (HEAD)
544	//   └->S1->S2->S3->S4->S5->S6->S7->S8
545	//
546	// Frozen: none
547	// Commit: G
548	// Pivot : C4
549	//
550	// SetHead(7)
551	//
552	// ------------------------------
553	//
554	// Expected in leveldb:
555	//   G->C1->C2->C3->C4->C5->C6->C7
556	//   └->S1->S2->S3->S4->S5->S6->S7
557	//
558	// Expected head header    : C7
559	// Expected head fast block: C7
560	// Expected head block     : G
561	testSetHead(t, &rewindTest{
562		canonicalBlocks:    10,
563		sidechainBlocks:    8,
564		freezeThreshold:    16,
565		commitBlock:        0,
566		pivotBlock:         uint64ptr(4),
567		setheadBlock:       7,
568		expCanonicalBlocks: 7,
569		expSidechainBlocks: 7,
570		expFrozen:          0,
571		expHeadHeader:      7,
572		expHeadFastBlock:   7,
573		expHeadBlock:       0,
574	}, snapshots)
575}
576
577// Tests a sethead for a short canonical chain and a longer side chain, where a
578// recent block was already committed to disk and then sethead was called. In this
579// case we expect the canonical full chain to be rolled back to the committed block.
580// All data above the sethead point should be deleted. In between the committed
581// block and the requested head the data can remain as "fast sync" data to avoid
582// having to redownload it. The side chain should be truncated to the head set.
583//
584// The side chain could be left to be if the fork point was before the new head
585// we are deleting to, but it would be exceedingly hard to detect that case and
586// properly handle it, so we'll trade extra work in exchange for simpler code.
587func TestShortReorgedSetHead(t *testing.T)              { testShortReorgedSetHead(t, false) }
588func TestShortReorgedSetHeadWithSnapshots(t *testing.T) { testShortReorgedSetHead(t, true) }
589
590func testShortReorgedSetHead(t *testing.T, snapshots bool) {
591	// Chain:
592	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
593	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10
594	//
595	// Frozen: none
596	// Commit: G, C4
597	// Pivot : none
598	//
599	// SetHead(7)
600	//
601	// ------------------------------
602	//
603	// Expected in leveldb:
604	//   G->C1->C2->C3->C4->C5->C6->C7
605	//   └->S1->S2->S3->S4->S5->S6->S7
606	//
607	// Expected head header    : C7
608	// Expected head fast block: C7
609	// Expected head block     : C4
610	testSetHead(t, &rewindTest{
611		canonicalBlocks:    8,
612		sidechainBlocks:    10,
613		freezeThreshold:    16,
614		commitBlock:        4,
615		pivotBlock:         nil,
616		setheadBlock:       7,
617		expCanonicalBlocks: 7,
618		expSidechainBlocks: 7,
619		expFrozen:          0,
620		expHeadHeader:      7,
621		expHeadFastBlock:   7,
622		expHeadBlock:       4,
623	}, snapshots)
624}
625
626// Tests a sethead for a short canonical chain and a longer side chain, where
627// the fast sync pivot point was already committed to disk and then sethead was
628// called. In this case we expect the canonical full chain to be rolled back to
629// the committed block. All data above the sethead point should be deleted. In
630// between the committed block and the requested head the data can remain as
631// "fast sync" data to avoid having to redownload it. The side chain should be
632// truncated to the head set.
633//
634// The side chain could be left to be if the fork point was before the new head
635// we are deleting to, but it would be exceedingly hard to detect that case and
636// properly handle it, so we'll trade extra work in exchange for simpler code.
637func TestShortReorgedSnapSyncedSetHead(t *testing.T) {
638	testShortReorgedSnapSyncedSetHead(t, false)
639}
640func TestShortReorgedSnapSyncedSetHeadWithSnapshots(t *testing.T) {
641	testShortReorgedSnapSyncedSetHead(t, true)
642}
643
644func testShortReorgedSnapSyncedSetHead(t *testing.T, snapshots bool) {
645	// Chain:
646	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
647	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10
648	//
649	// Frozen: none
650	// Commit: G, C4
651	// Pivot : C4
652	//
653	// SetHead(7)
654	//
655	// ------------------------------
656	//
657	// Expected in leveldb:
658	//   G->C1->C2->C3->C4->C5->C6->C7
659	//   └->S1->S2->S3->S4->S5->S6->S7
660	//
661	// Expected head header    : C7
662	// Expected head fast block: C7
663	// Expected head block     : C4
664	testSetHead(t, &rewindTest{
665		canonicalBlocks:    8,
666		sidechainBlocks:    10,
667		freezeThreshold:    16,
668		commitBlock:        4,
669		pivotBlock:         uint64ptr(4),
670		setheadBlock:       7,
671		expCanonicalBlocks: 7,
672		expSidechainBlocks: 7,
673		expFrozen:          0,
674		expHeadHeader:      7,
675		expHeadFastBlock:   7,
676		expHeadBlock:       4,
677	}, snapshots)
678}
679
680// Tests a sethead for a short canonical chain and a longer side chain, where
681// the fast sync pivot point was not yet committed, but sethead was called. In
682// this case we expect the chain to detect that it was fast syncing and delete
683// everything from the new head, since we can just pick up fast syncing from
684// there.
685//
686// The side chain could be left to be if the fork point was before the new head
687// we are deleting to, but it would be exceedingly hard to detect that case and
688// properly handle it, so we'll trade extra work in exchange for simpler code.
689func TestShortReorgedSnapSyncingSetHead(t *testing.T) {
690	testShortReorgedSnapSyncingSetHead(t, false)
691}
692func TestShortReorgedSnapSyncingSetHeadWithSnapshots(t *testing.T) {
693	testShortReorgedSnapSyncingSetHead(t, true)
694}
695
696func testShortReorgedSnapSyncingSetHead(t *testing.T, snapshots bool) {
697	// Chain:
698	//   G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD)
699	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10
700	//
701	// Frozen: none
702	// Commit: G
703	// Pivot : C4
704	//
705	// SetHead(7)
706	//
707	// ------------------------------
708	//
709	// Expected in leveldb:
710	//   G->C1->C2->C3->C4->C5->C6->C7
711	//   └->S1->S2->S3->S4->S5->S6->S7
712	//
713	// Expected head header    : C7
714	// Expected head fast block: C7
715	// Expected head block     : G
716	testSetHead(t, &rewindTest{
717		canonicalBlocks:    8,
718		sidechainBlocks:    10,
719		freezeThreshold:    16,
720		commitBlock:        0,
721		pivotBlock:         uint64ptr(4),
722		setheadBlock:       7,
723		expCanonicalBlocks: 7,
724		expSidechainBlocks: 7,
725		expFrozen:          0,
726		expHeadHeader:      7,
727		expHeadFastBlock:   7,
728		expHeadBlock:       0,
729	}, snapshots)
730}
731
732// Tests a sethead for a long canonical chain with frozen blocks where a recent
733// block - newer than the ancient limit - was already committed to disk and then
734// sethead was called. In this case we expect the full chain to be rolled back
735// to the committed block. Everything above the sethead point should be deleted.
736// In between the committed block and the requested head the data can remain as
737// "fast sync" data to avoid redownloading it.
738func TestLongShallowSetHead(t *testing.T)              { testLongShallowSetHead(t, false) }
739func TestLongShallowSetHeadWithSnapshots(t *testing.T) { testLongShallowSetHead(t, true) }
740
741func testLongShallowSetHead(t *testing.T, snapshots bool) {
742	// Chain:
743	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
744	//
745	// Frozen:
746	//   G->C1->C2
747	//
748	// Commit: G, C4
749	// Pivot : none
750	//
751	// SetHead(6)
752	//
753	// ------------------------------
754	//
755	// Expected in freezer:
756	//   G->C1->C2
757	//
758	// Expected in leveldb:
759	//   C2)->C3->C4->C5->C6
760	//
761	// Expected head header    : C6
762	// Expected head fast block: C6
763	// Expected head block     : C4
764	testSetHead(t, &rewindTest{
765		canonicalBlocks:    18,
766		sidechainBlocks:    0,
767		freezeThreshold:    16,
768		commitBlock:        4,
769		pivotBlock:         nil,
770		setheadBlock:       6,
771		expCanonicalBlocks: 6,
772		expSidechainBlocks: 0,
773		expFrozen:          3,
774		expHeadHeader:      6,
775		expHeadFastBlock:   6,
776		expHeadBlock:       4,
777	}, snapshots)
778}
779
780// Tests a sethead for a long canonical chain with frozen blocks where a recent
781// block - older than the ancient limit - was already committed to disk and then
782// sethead was called. In this case we expect the full chain to be rolled back
783// to the committed block. Since the ancient limit was underflown, everything
784// needs to be deleted onwards to avoid creating a gap.
785func TestLongDeepSetHead(t *testing.T)              { testLongDeepSetHead(t, false) }
786func TestLongDeepSetHeadWithSnapshots(t *testing.T) { testLongDeepSetHead(t, true) }
787
788func testLongDeepSetHead(t *testing.T, snapshots bool) {
789	// Chain:
790	//   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)
791	//
792	// Frozen:
793	//   G->C1->C2->C3->C4->C5->C6->C7->C8
794	//
795	// Commit: G, C4
796	// Pivot : none
797	//
798	// SetHead(6)
799	//
800	// ------------------------------
801	//
802	// Expected in freezer:
803	//   G->C1->C2->C3->C4
804	//
805	// Expected in leveldb: none
806	//
807	// Expected head header    : C4
808	// Expected head fast block: C4
809	// Expected head block     : C4
810	testSetHead(t, &rewindTest{
811		canonicalBlocks:    24,
812		sidechainBlocks:    0,
813		freezeThreshold:    16,
814		commitBlock:        4,
815		pivotBlock:         nil,
816		setheadBlock:       6,
817		expCanonicalBlocks: 4,
818		expSidechainBlocks: 0,
819		expFrozen:          5,
820		expHeadHeader:      4,
821		expHeadFastBlock:   4,
822		expHeadBlock:       4,
823	}, snapshots)
824}
825
826// Tests a sethead for a long canonical chain with frozen blocks where the fast
827// sync pivot point - newer than the ancient limit - was already committed, after
828// which sethead was called. In this case we expect the full chain to be rolled
829// back to the committed block. Everything above the sethead point should be
830// deleted. In between the committed block and the requested head the data can
831// remain as "fast sync" data to avoid redownloading it.
832func TestLongSnapSyncedShallowSetHead(t *testing.T) {
833	testLongSnapSyncedShallowSetHead(t, false)
834}
835func TestLongSnapSyncedShallowSetHeadWithSnapshots(t *testing.T) {
836	testLongSnapSyncedShallowSetHead(t, true)
837}
838
839func testLongSnapSyncedShallowSetHead(t *testing.T, snapshots bool) {
840	// Chain:
841	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
842	//
843	// Frozen:
844	//   G->C1->C2
845	//
846	// Commit: G, C4
847	// Pivot : C4
848	//
849	// SetHead(6)
850	//
851	// ------------------------------
852	//
853	// Expected in freezer:
854	//   G->C1->C2
855	//
856	// Expected in leveldb:
857	//   C2)->C3->C4->C5->C6
858	//
859	// Expected head header    : C6
860	// Expected head fast block: C6
861	// Expected head block     : C4
862	testSetHead(t, &rewindTest{
863		canonicalBlocks:    18,
864		sidechainBlocks:    0,
865		freezeThreshold:    16,
866		commitBlock:        4,
867		pivotBlock:         uint64ptr(4),
868		setheadBlock:       6,
869		expCanonicalBlocks: 6,
870		expSidechainBlocks: 0,
871		expFrozen:          3,
872		expHeadHeader:      6,
873		expHeadFastBlock:   6,
874		expHeadBlock:       4,
875	}, snapshots)
876}
877
878// Tests a sethead for a long canonical chain with frozen blocks where the fast
879// sync pivot point - older than the ancient limit - was already committed, after
880// which sethead was called. In this case we expect the full chain to be rolled
881// back to the committed block. Since the ancient limit was underflown, everything
882// needs to be deleted onwards to avoid creating a gap.
883func TestLongSnapSyncedDeepSetHead(t *testing.T)              { testLongSnapSyncedDeepSetHead(t, false) }
884func TestLongSnapSyncedDeepSetHeadWithSnapshots(t *testing.T) { testLongSnapSyncedDeepSetHead(t, true) }
885
886func testLongSnapSyncedDeepSetHead(t *testing.T, snapshots bool) {
887	// Chain:
888	//   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)
889	//
890	// Frozen:
891	//   G->C1->C2->C3->C4->C5->C6->C7->C8
892	//
893	// Commit: G, C4
894	// Pivot : C4
895	//
896	// SetHead(6)
897	//
898	// ------------------------------
899	//
900	// Expected in freezer:
901	//   G->C1->C2->C3->C4
902	//
903	// Expected in leveldb: none
904	//
905	// Expected head header    : C4
906	// Expected head fast block: C4
907	// Expected head block     : C4
908	testSetHead(t, &rewindTest{
909		canonicalBlocks:    24,
910		sidechainBlocks:    0,
911		freezeThreshold:    16,
912		commitBlock:        4,
913		pivotBlock:         uint64ptr(4),
914		setheadBlock:       6,
915		expCanonicalBlocks: 4,
916		expSidechainBlocks: 0,
917		expFrozen:          5,
918		expHeadHeader:      4,
919		expHeadFastBlock:   4,
920		expHeadBlock:       4,
921	}, snapshots)
922}
923
924// Tests a sethead for a long canonical chain with frozen blocks where the fast
925// sync pivot point - newer than the ancient limit - was not yet committed, but
926// sethead was called. In this case we expect the chain to detect that it was fast
927// syncing and delete everything from the new head, since we can just pick up fast
928// syncing from there.
929func TestLongSnapSyncingShallowSetHead(t *testing.T) {
930	testLongSnapSyncingShallowSetHead(t, false)
931}
932func TestLongSnapSyncingShallowSetHeadWithSnapshots(t *testing.T) {
933	testLongSnapSyncingShallowSetHead(t, true)
934}
935
936func testLongSnapSyncingShallowSetHead(t *testing.T, snapshots bool) {
937	// Chain:
938	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
939	//
940	// Frozen:
941	//   G->C1->C2
942	//
943	// Commit: G
944	// Pivot : C4
945	//
946	// SetHead(6)
947	//
948	// ------------------------------
949	//
950	// Expected in freezer:
951	//   G->C1->C2
952	//
953	// Expected in leveldb:
954	//   C2)->C3->C4->C5->C6
955	//
956	// Expected head header    : C6
957	// Expected head fast block: C6
958	// Expected head block     : G
959	testSetHead(t, &rewindTest{
960		canonicalBlocks:    18,
961		sidechainBlocks:    0,
962		freezeThreshold:    16,
963		commitBlock:        0,
964		pivotBlock:         uint64ptr(4),
965		setheadBlock:       6,
966		expCanonicalBlocks: 6,
967		expSidechainBlocks: 0,
968		expFrozen:          3,
969		expHeadHeader:      6,
970		expHeadFastBlock:   6,
971		expHeadBlock:       0,
972	}, snapshots)
973}
974
975// Tests a sethead for a long canonical chain with frozen blocks where the fast
976// sync pivot point - older than the ancient limit - was not yet committed, but
977// sethead was called. In this case we expect the chain to detect that it was fast
978// syncing and delete everything from the new head, since we can just pick up fast
979// syncing from there.
980func TestLongSnapSyncingDeepSetHead(t *testing.T) {
981	testLongSnapSyncingDeepSetHead(t, false)
982}
983func TestLongSnapSyncingDeepSetHeadWithSnapshots(t *testing.T) {
984	testLongSnapSyncingDeepSetHead(t, true)
985}
986
987func testLongSnapSyncingDeepSetHead(t *testing.T, snapshots bool) {
988	// Chain:
989	//   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)
990	//
991	// Frozen:
992	//   G->C1->C2->C3->C4->C5->C6->C7->C8
993	//
994	// Commit: G
995	// Pivot : C4
996	//
997	// SetHead(6)
998	//
999	// ------------------------------
1000	//
1001	// Expected in freezer:
1002	//   G->C1->C2->C3->C4->C5->C6
1003	//
1004	// Expected in leveldb: none
1005	//
1006	// Expected head header    : C6
1007	// Expected head fast block: C6
1008	// Expected head block     : G
1009	testSetHead(t, &rewindTest{
1010		canonicalBlocks:    24,
1011		sidechainBlocks:    0,
1012		freezeThreshold:    16,
1013		commitBlock:        0,
1014		pivotBlock:         uint64ptr(4),
1015		setheadBlock:       6,
1016		expCanonicalBlocks: 6,
1017		expSidechainBlocks: 0,
1018		expFrozen:          7,
1019		expHeadHeader:      6,
1020		expHeadFastBlock:   6,
1021		expHeadBlock:       0,
1022	}, snapshots)
1023}
1024
1025// Tests a sethead for a long canonical chain with frozen blocks and a shorter side
1026// chain, where a recent block - newer than the ancient limit - was already committed
1027// to disk and then sethead was called. In this case we expect the canonical full
1028// chain to be rolled back to the committed block. Everything above the sethead point
1029// should be deleted. In between the committed block and the requested head the data
1030// can remain as "fast sync" data to avoid redownloading it. The side chain is nuked
1031// by the freezer.
1032func TestLongOldForkedShallowSetHead(t *testing.T) {
1033	testLongOldForkedShallowSetHead(t, false)
1034}
1035func TestLongOldForkedShallowSetHeadWithSnapshots(t *testing.T) {
1036	testLongOldForkedShallowSetHead(t, true)
1037}
1038
1039func testLongOldForkedShallowSetHead(t *testing.T, snapshots bool) {
1040	// Chain:
1041	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
1042	//   └->S1->S2->S3
1043	//
1044	// Frozen:
1045	//   G->C1->C2
1046	//
1047	// Commit: G, C4
1048	// Pivot : none
1049	//
1050	// SetHead(6)
1051	//
1052	// ------------------------------
1053	//
1054	// Expected in freezer:
1055	//   G->C1->C2
1056	//
1057	// Expected in leveldb:
1058	//   C2)->C3->C4->C5->C6
1059	//
1060	// Expected head header    : C6
1061	// Expected head fast block: C6
1062	// Expected head block     : C4
1063	testSetHead(t, &rewindTest{
1064		canonicalBlocks:    18,
1065		sidechainBlocks:    3,
1066		freezeThreshold:    16,
1067		commitBlock:        4,
1068		pivotBlock:         nil,
1069		setheadBlock:       6,
1070		expCanonicalBlocks: 6,
1071		expSidechainBlocks: 0,
1072		expFrozen:          3,
1073		expHeadHeader:      6,
1074		expHeadFastBlock:   6,
1075		expHeadBlock:       4,
1076	}, snapshots)
1077}
1078
1079// Tests a sethead for a long canonical chain with frozen blocks and a shorter side
1080// chain, where a recent block - older than the ancient limit - was already committed
1081// to disk and then sethead was called. In this case we expect the canonical full
1082// chain to be rolled back to the committed block. Since the ancient limit was
1083// underflown, everything needs to be deleted onwards to avoid creating a gap. The
1084// side chain is nuked by the freezer.
1085func TestLongOldForkedDeepSetHead(t *testing.T)              { testLongOldForkedDeepSetHead(t, false) }
1086func TestLongOldForkedDeepSetHeadWithSnapshots(t *testing.T) { testLongOldForkedDeepSetHead(t, true) }
1087
1088func testLongOldForkedDeepSetHead(t *testing.T, snapshots bool) {
1089	// Chain:
1090	//   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)
1091	//   └->S1->S2->S3
1092	//
1093	// Frozen:
1094	//   G->C1->C2->C3->C4->C5->C6->C7->C8
1095	//
1096	// Commit: G, C4
1097	// Pivot : none
1098	//
1099	// SetHead(6)
1100	//
1101	// ------------------------------
1102	//
1103	// Expected in freezer:
1104	//   G->C1->C2->C3->C4
1105	//
1106	// Expected in leveldb: none
1107	//
1108	// Expected head header    : C4
1109	// Expected head fast block: C4
1110	// Expected head block     : C4
1111	testSetHead(t, &rewindTest{
1112		canonicalBlocks:    24,
1113		sidechainBlocks:    3,
1114		freezeThreshold:    16,
1115		commitBlock:        4,
1116		pivotBlock:         nil,
1117		setheadBlock:       6,
1118		expCanonicalBlocks: 4,
1119		expSidechainBlocks: 0,
1120		expFrozen:          5,
1121		expHeadHeader:      4,
1122		expHeadFastBlock:   4,
1123		expHeadBlock:       4,
1124	}, snapshots)
1125}
1126
1127// Tests a sethead for a long canonical chain with frozen blocks and a shorter
1128// side chain, where the fast sync pivot point - newer than the ancient limit -
1129// was already committed to disk and then sethead was called. In this test scenario
1130// the side chain is below the committed block. In this case we expect the canonical
1131// full chain to be rolled back to the committed block. Everything above the
1132// sethead point should be deleted. In between the committed block and the
1133// requested head the data can remain as "fast sync" data to avoid redownloading
1134// it. The side chain is nuked by the freezer.
1135func TestLongOldForkedSnapSyncedShallowSetHead(t *testing.T) {
1136	testLongOldForkedSnapSyncedShallowSetHead(t, false)
1137}
1138func TestLongOldForkedSnapSyncedShallowSetHeadWithSnapshots(t *testing.T) {
1139	testLongOldForkedSnapSyncedShallowSetHead(t, true)
1140}
1141
1142func testLongOldForkedSnapSyncedShallowSetHead(t *testing.T, snapshots bool) {
1143	// Chain:
1144	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
1145	//   └->S1->S2->S3
1146	//
1147	// Frozen:
1148	//   G->C1->C2
1149	//
1150	// Commit: G, C4
1151	// Pivot : C4
1152	//
1153	// SetHead(6)
1154	//
1155	// ------------------------------
1156	//
1157	// Expected in freezer:
1158	//   G->C1->C2
1159	//
1160	// Expected in leveldb:
1161	//   C2)->C3->C4->C5->C6
1162	//
1163	// Expected head header    : C6
1164	// Expected head fast block: C6
1165	// Expected head block     : C4
1166	testSetHead(t, &rewindTest{
1167		canonicalBlocks:    18,
1168		sidechainBlocks:    3,
1169		freezeThreshold:    16,
1170		commitBlock:        4,
1171		pivotBlock:         uint64ptr(4),
1172		setheadBlock:       6,
1173		expCanonicalBlocks: 6,
1174		expSidechainBlocks: 0,
1175		expFrozen:          3,
1176		expHeadHeader:      6,
1177		expHeadFastBlock:   6,
1178		expHeadBlock:       4,
1179	}, snapshots)
1180}
1181
1182// Tests a sethead for a long canonical chain with frozen blocks and a shorter
1183// side chain, where the fast sync pivot point - older than the ancient limit -
1184// was already committed to disk and then sethead was called. In this test scenario
1185// the side chain is below the committed block. In this case we expect the canonical
1186// full chain to be rolled back to the committed block. Since the ancient limit was
1187// underflown, everything needs to be deleted onwards to avoid creating a gap. The
1188// side chain is nuked by the freezer.
1189func TestLongOldForkedSnapSyncedDeepSetHead(t *testing.T) {
1190	testLongOldForkedSnapSyncedDeepSetHead(t, false)
1191}
1192func TestLongOldForkedSnapSyncedDeepSetHeadWithSnapshots(t *testing.T) {
1193	testLongOldForkedSnapSyncedDeepSetHead(t, true)
1194}
1195
1196func testLongOldForkedSnapSyncedDeepSetHead(t *testing.T, snapshots bool) {
1197	// Chain:
1198	//   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)
1199	//   └->S1->S2->S3
1200	//
1201	// Frozen:
1202	//   G->C1->C2->C3->C4->C5->C6->C7->C8
1203	//
1204	// Commit: G, C4
1205	// Pivot : C4
1206	//
1207	// SetHead(6)
1208	//
1209	// ------------------------------
1210	//
1211	// Expected in freezer:
1212	//   G->C1->C2->C3->C4->C5->C6
1213	//
1214	// Expected in leveldb: none
1215	//
1216	// Expected head header    : C6
1217	// Expected head fast block: C6
1218	// Expected head block     : C4
1219	testSetHead(t, &rewindTest{
1220		canonicalBlocks:    24,
1221		sidechainBlocks:    3,
1222		freezeThreshold:    16,
1223		commitBlock:        4,
1224		pivotBlock:         uint64ptr(4),
1225		setheadBlock:       6,
1226		expCanonicalBlocks: 4,
1227		expSidechainBlocks: 0,
1228		expFrozen:          5,
1229		expHeadHeader:      4,
1230		expHeadFastBlock:   4,
1231		expHeadBlock:       4,
1232	}, snapshots)
1233}
1234
1235// Tests a sethead for a long canonical chain with frozen blocks and a shorter
1236// side chain, where the fast sync pivot point - newer than the ancient limit -
1237// was not yet committed, but sethead was called. In this test scenario the side
1238// chain is below the committed block. In this case we expect the chain to detect
1239// that it was fast syncing and delete everything from the new head, since we can
1240// just pick up fast syncing from there. The side chain is completely nuked by the
1241// freezer.
1242func TestLongOldForkedSnapSyncingShallowSetHead(t *testing.T) {
1243	testLongOldForkedSnapSyncingShallowSetHead(t, false)
1244}
1245func TestLongOldForkedSnapSyncingShallowSetHeadWithSnapshots(t *testing.T) {
1246	testLongOldForkedSnapSyncingShallowSetHead(t, true)
1247}
1248
1249func testLongOldForkedSnapSyncingShallowSetHead(t *testing.T, snapshots bool) {
1250	// Chain:
1251	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
1252	//   └->S1->S2->S3
1253	//
1254	// Frozen:
1255	//   G->C1->C2
1256	//
1257	// Commit: G
1258	// Pivot : C4
1259	//
1260	// SetHead(6)
1261	//
1262	// ------------------------------
1263	//
1264	// Expected in freezer:
1265	//   G->C1->C2
1266	//
1267	// Expected in leveldb:
1268	//   C2)->C3->C4->C5->C6
1269	//
1270	// Expected head header    : C6
1271	// Expected head fast block: C6
1272	// Expected head block     : G
1273	testSetHead(t, &rewindTest{
1274		canonicalBlocks:    18,
1275		sidechainBlocks:    3,
1276		freezeThreshold:    16,
1277		commitBlock:        0,
1278		pivotBlock:         uint64ptr(4),
1279		setheadBlock:       6,
1280		expCanonicalBlocks: 6,
1281		expSidechainBlocks: 0,
1282		expFrozen:          3,
1283		expHeadHeader:      6,
1284		expHeadFastBlock:   6,
1285		expHeadBlock:       0,
1286	}, snapshots)
1287}
1288
1289// Tests a sethead for a long canonical chain with frozen blocks and a shorter
1290// side chain, where the fast sync pivot point - older than the ancient limit -
1291// was not yet committed, but sethead was called. In this test scenario the side
1292// chain is below the committed block. In this case we expect the chain to detect
1293// that it was fast syncing and delete everything from the new head, since we can
1294// just pick up fast syncing from there. The side chain is completely nuked by the
1295// freezer.
1296func TestLongOldForkedSnapSyncingDeepSetHead(t *testing.T) {
1297	testLongOldForkedSnapSyncingDeepSetHead(t, false)
1298}
1299func TestLongOldForkedSnapSyncingDeepSetHeadWithSnapshots(t *testing.T) {
1300	testLongOldForkedSnapSyncingDeepSetHead(t, true)
1301}
1302
1303func testLongOldForkedSnapSyncingDeepSetHead(t *testing.T, snapshots bool) {
1304	// Chain:
1305	//   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)
1306	//   └->S1->S2->S3
1307	//
1308	// Frozen:
1309	//   G->C1->C2->C3->C4->C5->C6->C7->C8
1310	//
1311	// Commit: G
1312	// Pivot : C4
1313	//
1314	// SetHead(6)
1315	//
1316	// ------------------------------
1317	//
1318	// Expected in freezer:
1319	//   G->C1->C2->C3->C4->C5->C6
1320	//
1321	// Expected in leveldb: none
1322	//
1323	// Expected head header    : C6
1324	// Expected head fast block: C6
1325	// Expected head block     : G
1326	testSetHead(t, &rewindTest{
1327		canonicalBlocks:    24,
1328		sidechainBlocks:    3,
1329		freezeThreshold:    16,
1330		commitBlock:        0,
1331		pivotBlock:         uint64ptr(4),
1332		setheadBlock:       6,
1333		expCanonicalBlocks: 6,
1334		expSidechainBlocks: 0,
1335		expFrozen:          7,
1336		expHeadHeader:      6,
1337		expHeadFastBlock:   6,
1338		expHeadBlock:       0,
1339	}, snapshots)
1340}
1341
1342// Tests a sethead for a long canonical chain with frozen blocks and a shorter
1343// side chain, where a recent block - newer than the ancient limit - was already
1344// committed to disk and then sethead was called. In this test scenario the side
1345// chain is above the committed block. In this case the freezer will delete the
1346// sidechain since it's dangling, reverting to TestLongShallowSetHead.
1347func TestLongNewerForkedShallowSetHead(t *testing.T) {
1348	testLongNewerForkedShallowSetHead(t, false)
1349}
1350func TestLongNewerForkedShallowSetHeadWithSnapshots(t *testing.T) {
1351	testLongNewerForkedShallowSetHead(t, true)
1352}
1353
1354func testLongNewerForkedShallowSetHead(t *testing.T, snapshots bool) {
1355	// Chain:
1356	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
1357	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12
1358	//
1359	// Frozen:
1360	//   G->C1->C2
1361	//
1362	// Commit: G, C4
1363	// Pivot : none
1364	//
1365	// SetHead(6)
1366	//
1367	// ------------------------------
1368	//
1369	// Expected in freezer:
1370	//   G->C1->C2
1371	//
1372	// Expected in leveldb:
1373	//   C2)->C3->C4->C5->C6
1374	//
1375	// Expected head header    : C6
1376	// Expected head fast block: C6
1377	// Expected head block     : C4
1378	testSetHead(t, &rewindTest{
1379		canonicalBlocks:    18,
1380		sidechainBlocks:    12,
1381		freezeThreshold:    16,
1382		commitBlock:        4,
1383		pivotBlock:         nil,
1384		setheadBlock:       6,
1385		expCanonicalBlocks: 6,
1386		expSidechainBlocks: 0,
1387		expFrozen:          3,
1388		expHeadHeader:      6,
1389		expHeadFastBlock:   6,
1390		expHeadBlock:       4,
1391	}, snapshots)
1392}
1393
1394// Tests a sethead for a long canonical chain with frozen blocks and a shorter
1395// side chain, where a recent block - older than the ancient limit - was already
1396// committed to disk and then sethead was called. In this test scenario the side
1397// chain is above the committed block. In this case the freezer will delete the
1398// sidechain since it's dangling, reverting to TestLongDeepSetHead.
1399func TestLongNewerForkedDeepSetHead(t *testing.T) {
1400	testLongNewerForkedDeepSetHead(t, false)
1401}
1402func TestLongNewerForkedDeepSetHeadWithSnapshots(t *testing.T) {
1403	testLongNewerForkedDeepSetHead(t, true)
1404}
1405
1406func testLongNewerForkedDeepSetHead(t *testing.T, snapshots bool) {
1407	// Chain:
1408	//   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)
1409	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12
1410	//
1411	// Frozen:
1412	//   G->C1->C2->C3->C4->C5->C6->C7->C8
1413	//
1414	// Commit: G, C4
1415	// Pivot : none
1416	//
1417	// SetHead(6)
1418	//
1419	// ------------------------------
1420	//
1421	// Expected in freezer:
1422	//   G->C1->C2->C3->C4
1423	//
1424	// Expected in leveldb: none
1425	//
1426	// Expected head header    : C4
1427	// Expected head fast block: C4
1428	// Expected head block     : C4
1429	testSetHead(t, &rewindTest{
1430		canonicalBlocks:    24,
1431		sidechainBlocks:    12,
1432		freezeThreshold:    16,
1433		commitBlock:        4,
1434		pivotBlock:         nil,
1435		setheadBlock:       6,
1436		expCanonicalBlocks: 4,
1437		expSidechainBlocks: 0,
1438		expFrozen:          5,
1439		expHeadHeader:      4,
1440		expHeadFastBlock:   4,
1441		expHeadBlock:       4,
1442	}, snapshots)
1443}
1444
1445// Tests a sethead for a long canonical chain with frozen blocks and a shorter
1446// side chain, where the fast sync pivot point - newer than the ancient limit -
1447// was already committed to disk and then sethead was called. In this test scenario
1448// the side chain is above the committed block. In this case the freezer will delete
1449// the sidechain since it's dangling, reverting to TestLongSnapSyncedShallowSetHead.
1450func TestLongNewerForkedSnapSyncedShallowSetHead(t *testing.T) {
1451	testLongNewerForkedSnapSyncedShallowSetHead(t, false)
1452}
1453func TestLongNewerForkedSnapSyncedShallowSetHeadWithSnapshots(t *testing.T) {
1454	testLongNewerForkedSnapSyncedShallowSetHead(t, true)
1455}
1456
1457func testLongNewerForkedSnapSyncedShallowSetHead(t *testing.T, snapshots bool) {
1458	// Chain:
1459	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
1460	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12
1461	//
1462	// Frozen:
1463	//   G->C1->C2
1464	//
1465	// Commit: G, C4
1466	// Pivot : C4
1467	//
1468	// SetHead(6)
1469	//
1470	// ------------------------------
1471	//
1472	// Expected in freezer:
1473	//   G->C1->C2
1474	//
1475	// Expected in leveldb:
1476	//   C2)->C3->C4->C5->C6
1477	//
1478	// Expected head header    : C6
1479	// Expected head fast block: C6
1480	// Expected head block     : C4
1481	testSetHead(t, &rewindTest{
1482		canonicalBlocks:    18,
1483		sidechainBlocks:    12,
1484		freezeThreshold:    16,
1485		commitBlock:        4,
1486		pivotBlock:         uint64ptr(4),
1487		setheadBlock:       6,
1488		expCanonicalBlocks: 6,
1489		expSidechainBlocks: 0,
1490		expFrozen:          3,
1491		expHeadHeader:      6,
1492		expHeadFastBlock:   6,
1493		expHeadBlock:       4,
1494	}, snapshots)
1495}
1496
1497// Tests a sethead for a long canonical chain with frozen blocks and a shorter
1498// side chain, where the fast sync pivot point - older than the ancient limit -
1499// was already committed to disk and then sethead was called. In this test scenario
1500// the side chain is above the committed block. In this case the freezer will delete
1501// the sidechain since it's dangling, reverting to TestLongSnapSyncedDeepSetHead.
1502func TestLongNewerForkedSnapSyncedDeepSetHead(t *testing.T) {
1503	testLongNewerForkedSnapSyncedDeepSetHead(t, false)
1504}
1505func TestLongNewerForkedSnapSyncedDeepSetHeadWithSnapshots(t *testing.T) {
1506	testLongNewerForkedSnapSyncedDeepSetHead(t, true)
1507}
1508
1509func testLongNewerForkedSnapSyncedDeepSetHead(t *testing.T, snapshots bool) {
1510	// Chain:
1511	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD)
1512	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12
1513	//
1514	// Frozen:
1515	//   G->C1->C2->C3->C4->C5->C6->C7->C8
1516	//
1517	// Commit: G, C4
1518	// Pivot : C4
1519	//
1520	// SetHead(6)
1521	//
1522	// ------------------------------
1523	//
1524	// Expected in freezer:
1525	//   G->C1->C2->C3->C4
1526	//
1527	// Expected in leveldb: none
1528	//
1529	// Expected head header    : C4
1530	// Expected head fast block: C4
1531	// Expected head block     : C
1532	testSetHead(t, &rewindTest{
1533		canonicalBlocks:    24,
1534		sidechainBlocks:    12,
1535		freezeThreshold:    16,
1536		commitBlock:        4,
1537		pivotBlock:         uint64ptr(4),
1538		setheadBlock:       6,
1539		expCanonicalBlocks: 4,
1540		expSidechainBlocks: 0,
1541		expFrozen:          5,
1542		expHeadHeader:      4,
1543		expHeadFastBlock:   4,
1544		expHeadBlock:       4,
1545	}, snapshots)
1546}
1547
1548// Tests a sethead for a long canonical chain with frozen blocks and a shorter
1549// side chain, where the fast sync pivot point - newer than the ancient limit -
1550// was not yet committed, but sethead was called. In this test scenario the side
1551// chain is above the committed block. In this case the freezer will delete the
1552// sidechain since it's dangling, reverting to TestLongSnapSyncinghallowSetHead.
1553func TestLongNewerForkedSnapSyncingShallowSetHead(t *testing.T) {
1554	testLongNewerForkedSnapSyncingShallowSetHead(t, false)
1555}
1556func TestLongNewerForkedSnapSyncingShallowSetHeadWithSnapshots(t *testing.T) {
1557	testLongNewerForkedSnapSyncingShallowSetHead(t, true)
1558}
1559
1560func testLongNewerForkedSnapSyncingShallowSetHead(t *testing.T, snapshots bool) {
1561	// Chain:
1562	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
1563	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12
1564	//
1565	// Frozen:
1566	//   G->C1->C2
1567	//
1568	// Commit: G
1569	// Pivot : C4
1570	//
1571	// SetHead(6)
1572	//
1573	// ------------------------------
1574	//
1575	// Expected in freezer:
1576	//   G->C1->C2
1577	//
1578	// Expected in leveldb:
1579	//   C2)->C3->C4->C5->C6
1580	//
1581	// Expected head header    : C6
1582	// Expected head fast block: C6
1583	// Expected head block     : G
1584	testSetHead(t, &rewindTest{
1585		canonicalBlocks:    18,
1586		sidechainBlocks:    12,
1587		freezeThreshold:    16,
1588		commitBlock:        0,
1589		pivotBlock:         uint64ptr(4),
1590		setheadBlock:       6,
1591		expCanonicalBlocks: 6,
1592		expSidechainBlocks: 0,
1593		expFrozen:          3,
1594		expHeadHeader:      6,
1595		expHeadFastBlock:   6,
1596		expHeadBlock:       0,
1597	}, snapshots)
1598}
1599
1600// Tests a sethead for a long canonical chain with frozen blocks and a shorter
1601// side chain, where the fast sync pivot point - older than the ancient limit -
1602// was not yet committed, but sethead was called. In this test scenario the side
1603// chain is above the committed block. In this case the freezer will delete the
1604// sidechain since it's dangling, reverting to TestLongSnapSyncingDeepSetHead.
1605func TestLongNewerForkedSnapSyncingDeepSetHead(t *testing.T) {
1606	testLongNewerForkedSnapSyncingDeepSetHead(t, false)
1607}
1608func TestLongNewerForkedSnapSyncingDeepSetHeadWithSnapshots(t *testing.T) {
1609	testLongNewerForkedSnapSyncingDeepSetHead(t, true)
1610}
1611
1612func testLongNewerForkedSnapSyncingDeepSetHead(t *testing.T, snapshots bool) {
1613	// Chain:
1614	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD)
1615	//   └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12
1616	//
1617	// Frozen:
1618	//   G->C1->C2->C3->C4->C5->C6->C7->C8
1619	//
1620	// Commit: G
1621	// Pivot : C4
1622	//
1623	// SetHead(6)
1624	//
1625	// ------------------------------
1626	//
1627	// Expected in freezer:
1628	//   G->C1->C2->C3->C4->C5->C6
1629	//
1630	// Expected in leveldb: none
1631	//
1632	// Expected head header    : C6
1633	// Expected head fast block: C6
1634	// Expected head block     : G
1635	testSetHead(t, &rewindTest{
1636		canonicalBlocks:    24,
1637		sidechainBlocks:    12,
1638		freezeThreshold:    16,
1639		commitBlock:        0,
1640		pivotBlock:         uint64ptr(4),
1641		setheadBlock:       6,
1642		expCanonicalBlocks: 6,
1643		expSidechainBlocks: 0,
1644		expFrozen:          7,
1645		expHeadHeader:      6,
1646		expHeadFastBlock:   6,
1647		expHeadBlock:       0,
1648	}, snapshots)
1649}
1650
1651// Tests a sethead for a long canonical chain with frozen blocks and a longer side
1652// chain, where a recent block - newer than the ancient limit - was already committed
1653// to disk and then sethead was called. In this case the freezer will delete the
1654// sidechain since it's dangling, reverting to TestLongShallowSetHead.
1655func TestLongReorgedShallowSetHead(t *testing.T)              { testLongReorgedShallowSetHead(t, false) }
1656func TestLongReorgedShallowSetHeadWithSnapshots(t *testing.T) { testLongReorgedShallowSetHead(t, true) }
1657
1658func testLongReorgedShallowSetHead(t *testing.T, snapshots bool) {
1659	// Chain:
1660	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
1661	//   └->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
1662	//
1663	// Frozen:
1664	//   G->C1->C2
1665	//
1666	// Commit: G, C4
1667	// Pivot : none
1668	//
1669	// SetHead(6)
1670	//
1671	// ------------------------------
1672	//
1673	// Expected in freezer:
1674	//   G->C1->C2
1675	//
1676	// Expected in leveldb:
1677	//   C2)->C3->C4->C5->C6
1678	//
1679	// Expected head header    : C6
1680	// Expected head fast block: C6
1681	// Expected head block     : C4
1682	testSetHead(t, &rewindTest{
1683		canonicalBlocks:    18,
1684		sidechainBlocks:    26,
1685		freezeThreshold:    16,
1686		commitBlock:        4,
1687		pivotBlock:         nil,
1688		setheadBlock:       6,
1689		expCanonicalBlocks: 6,
1690		expSidechainBlocks: 0,
1691		expFrozen:          3,
1692		expHeadHeader:      6,
1693		expHeadFastBlock:   6,
1694		expHeadBlock:       4,
1695	}, snapshots)
1696}
1697
1698// Tests a sethead for a long canonical chain with frozen blocks and a longer side
1699// chain, where a recent block - older than the ancient limit - was already committed
1700// to disk and then sethead was called. In this case the freezer will delete the
1701// sidechain since it's dangling, reverting to TestLongDeepSetHead.
1702func TestLongReorgedDeepSetHead(t *testing.T)              { testLongReorgedDeepSetHead(t, false) }
1703func TestLongReorgedDeepSetHeadWithSnapshots(t *testing.T) { testLongReorgedDeepSetHead(t, true) }
1704
1705func testLongReorgedDeepSetHead(t *testing.T, snapshots bool) {
1706	// Chain:
1707	//   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)
1708	//   └->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
1709	//
1710	// Frozen:
1711	//   G->C1->C2->C3->C4->C5->C6->C7->C8
1712	//
1713	// Commit: G, C4
1714	// Pivot : none
1715	//
1716	// SetHead(6)
1717	//
1718	// ------------------------------
1719	//
1720	// Expected in freezer:
1721	//   G->C1->C2->C3->C4
1722	//
1723	// Expected in leveldb: none
1724	//
1725	// Expected head header    : C4
1726	// Expected head fast block: C4
1727	// Expected head block     : C4
1728	testSetHead(t, &rewindTest{
1729		canonicalBlocks:    24,
1730		sidechainBlocks:    26,
1731		freezeThreshold:    16,
1732		commitBlock:        4,
1733		pivotBlock:         nil,
1734		setheadBlock:       6,
1735		expCanonicalBlocks: 4,
1736		expSidechainBlocks: 0,
1737		expFrozen:          5,
1738		expHeadHeader:      4,
1739		expHeadFastBlock:   4,
1740		expHeadBlock:       4,
1741	}, snapshots)
1742}
1743
1744// Tests a sethead for a long canonical chain with frozen blocks and a longer
1745// side chain, where the fast sync pivot point - newer than the ancient limit -
1746// was already committed to disk and then sethead was called. In this case the
1747// freezer will delete the sidechain since it's dangling, reverting to
1748// TestLongSnapSyncedShallowSetHead.
1749func TestLongReorgedSnapSyncedShallowSetHead(t *testing.T) {
1750	testLongReorgedSnapSyncedShallowSetHead(t, false)
1751}
1752func TestLongReorgedSnapSyncedShallowSetHeadWithSnapshots(t *testing.T) {
1753	testLongReorgedSnapSyncedShallowSetHead(t, true)
1754}
1755
1756func testLongReorgedSnapSyncedShallowSetHead(t *testing.T, snapshots bool) {
1757	// Chain:
1758	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
1759	//   └->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
1760	//
1761	// Frozen:
1762	//   G->C1->C2
1763	//
1764	// Commit: G, C4
1765	// Pivot : C4
1766	//
1767	// SetHead(6)
1768	//
1769	// ------------------------------
1770	//
1771	// Expected in freezer:
1772	//   G->C1->C2
1773	//
1774	// Expected in leveldb:
1775	//   C2)->C3->C4->C5->C6
1776	//
1777	// Expected head header    : C6
1778	// Expected head fast block: C6
1779	// Expected head block     : C4
1780	testSetHead(t, &rewindTest{
1781		canonicalBlocks:    18,
1782		sidechainBlocks:    26,
1783		freezeThreshold:    16,
1784		commitBlock:        4,
1785		pivotBlock:         uint64ptr(4),
1786		setheadBlock:       6,
1787		expCanonicalBlocks: 6,
1788		expSidechainBlocks: 0,
1789		expFrozen:          3,
1790		expHeadHeader:      6,
1791		expHeadFastBlock:   6,
1792		expHeadBlock:       4,
1793	}, snapshots)
1794}
1795
1796// Tests a sethead for a long canonical chain with frozen blocks and a longer
1797// side chain, where the fast sync pivot point - older than the ancient limit -
1798// was already committed to disk and then sethead was called. In this case the
1799// freezer will delete the sidechain since it's dangling, reverting to
1800// TestLongSnapSyncedDeepSetHead.
1801func TestLongReorgedSnapSyncedDeepSetHead(t *testing.T) {
1802	testLongReorgedSnapSyncedDeepSetHead(t, false)
1803}
1804func TestLongReorgedSnapSyncedDeepSetHeadWithSnapshots(t *testing.T) {
1805	testLongReorgedSnapSyncedDeepSetHead(t, true)
1806}
1807
1808func testLongReorgedSnapSyncedDeepSetHead(t *testing.T, snapshots bool) {
1809	// Chain:
1810	//   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)
1811	//   └->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
1812	//
1813	// Frozen:
1814	//   G->C1->C2->C3->C4->C5->C6->C7->C8
1815	//
1816	// Commit: G, C4
1817	// Pivot : C4
1818	//
1819	// SetHead(6)
1820	//
1821	// ------------------------------
1822	//
1823	// Expected in freezer:
1824	//   G->C1->C2->C3->C4
1825	//
1826	// Expected in leveldb: none
1827	//
1828	// Expected head header    : C4
1829	// Expected head fast block: C4
1830	// Expected head block     : C4
1831	testSetHead(t, &rewindTest{
1832		canonicalBlocks:    24,
1833		sidechainBlocks:    26,
1834		freezeThreshold:    16,
1835		commitBlock:        4,
1836		pivotBlock:         uint64ptr(4),
1837		setheadBlock:       6,
1838		expCanonicalBlocks: 4,
1839		expSidechainBlocks: 0,
1840		expFrozen:          5,
1841		expHeadHeader:      4,
1842		expHeadFastBlock:   4,
1843		expHeadBlock:       4,
1844	}, snapshots)
1845}
1846
1847// Tests a sethead for a long canonical chain with frozen blocks and a longer
1848// side chain, where the fast sync pivot point - newer than the ancient limit -
1849// was not yet committed, but sethead was called. In this case we expect the
1850// chain to detect that it was fast syncing and delete everything from the new
1851// head, since we can just pick up fast syncing from there. The side chain is
1852// completely nuked by the freezer.
1853func TestLongReorgedSnapSyncingShallowSetHead(t *testing.T) {
1854	testLongReorgedSnapSyncingShallowSetHead(t, false)
1855}
1856func TestLongReorgedSnapSyncingShallowSetHeadWithSnapshots(t *testing.T) {
1857	testLongReorgedSnapSyncingShallowSetHead(t, true)
1858}
1859
1860func testLongReorgedSnapSyncingShallowSetHead(t *testing.T, snapshots bool) {
1861	// Chain:
1862	//   G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD)
1863	//   └->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
1864	//
1865	// Frozen:
1866	//   G->C1->C2
1867	//
1868	// Commit: G
1869	// Pivot : C4
1870	//
1871	// SetHead(6)
1872	//
1873	// ------------------------------
1874	//
1875	// Expected in freezer:
1876	//   G->C1->C2
1877	//
1878	// Expected in leveldb:
1879	//   C2)->C3->C4->C5->C6
1880	//
1881	// Expected head header    : C6
1882	// Expected head fast block: C6
1883	// Expected head block     : G
1884	testSetHead(t, &rewindTest{
1885		canonicalBlocks:    18,
1886		sidechainBlocks:    26,
1887		freezeThreshold:    16,
1888		commitBlock:        0,
1889		pivotBlock:         uint64ptr(4),
1890		setheadBlock:       6,
1891		expCanonicalBlocks: 6,
1892		expSidechainBlocks: 0,
1893		expFrozen:          3,
1894		expHeadHeader:      6,
1895		expHeadFastBlock:   6,
1896		expHeadBlock:       0,
1897	}, snapshots)
1898}
1899
1900// Tests a sethead for a long canonical chain with frozen blocks and a longer
1901// side chain, where the fast sync pivot point - older than the ancient limit -
1902// was not yet committed, but sethead was called. In this case we expect the
1903// chain to detect that it was fast syncing and delete everything from the new
1904// head, since we can just pick up fast syncing from there. The side chain is
1905// completely nuked by the freezer.
1906func TestLongReorgedSnapSyncingDeepSetHead(t *testing.T) {
1907	testLongReorgedSnapSyncingDeepSetHead(t, false)
1908}
1909func TestLongReorgedSnapSyncingDeepSetHeadWithSnapshots(t *testing.T) {
1910	testLongReorgedSnapSyncingDeepSetHead(t, true)
1911}
1912
1913func testLongReorgedSnapSyncingDeepSetHead(t *testing.T, snapshots bool) {
1914	// Chain:
1915	//   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)
1916	//   └->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
1917	//
1918	// Frozen:
1919	//   G->C1->C2->C3->C4->C5->C6->C7->C8
1920	//
1921	// Commit: G
1922	// Pivot : C4
1923	//
1924	// SetHead(6)
1925	//
1926	// ------------------------------
1927	//
1928	// Expected in freezer:
1929	//   G->C1->C2->C3->C4->C5->C6
1930	//
1931	// Expected in leveldb: none
1932	//
1933	// Expected head header    : C6
1934	// Expected head fast block: C6
1935	// Expected head block     : G
1936	testSetHead(t, &rewindTest{
1937		canonicalBlocks:    24,
1938		sidechainBlocks:    26,
1939		freezeThreshold:    16,
1940		commitBlock:        0,
1941		pivotBlock:         uint64ptr(4),
1942		setheadBlock:       6,
1943		expCanonicalBlocks: 6,
1944		expSidechainBlocks: 0,
1945		expFrozen:          7,
1946		expHeadHeader:      6,
1947		expHeadFastBlock:   6,
1948		expHeadBlock:       0,
1949	}, snapshots)
1950}
1951
1952func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
1953	// It's hard to follow the test case, visualize the input
1954	// log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
1955	// fmt.Println(tt.dump(false))
1956
1957	// Create a temporary persistent database
1958	datadir, err := ioutil.TempDir("", "")
1959	if err != nil {
1960		t.Fatalf("Failed to create temporary datadir: %v", err)
1961	}
1962	os.RemoveAll(datadir)
1963
1964	db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false)
1965	if err != nil {
1966		t.Fatalf("Failed to create persistent database: %v", err)
1967	}
1968	defer db.Close()
1969
1970	// Initialize a fresh chain
1971	var (
1972		genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
1973		engine  = ethash.NewFullFaker()
1974		config  = &CacheConfig{
1975			TrieCleanLimit: 256,
1976			TrieDirtyLimit: 256,
1977			TrieTimeLimit:  5 * time.Minute,
1978			SnapshotLimit:  0, // Disable snapshot
1979		}
1980	)
1981	if snapshots {
1982		config.SnapshotLimit = 256
1983		config.SnapshotWait = true
1984	}
1985	chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil)
1986	if err != nil {
1987		t.Fatalf("Failed to create chain: %v", err)
1988	}
1989	// If sidechain blocks are needed, make a light chain and import it
1990	var sideblocks types.Blocks
1991	if tt.sidechainBlocks > 0 {
1992		sideblocks, _ = GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *BlockGen) {
1993			b.SetCoinbase(common.Address{0x01})
1994		})
1995		if _, err := chain.InsertChain(sideblocks); err != nil {
1996			t.Fatalf("Failed to import side chain: %v", err)
1997		}
1998	}
1999	canonblocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) {
2000		b.SetCoinbase(common.Address{0x02})
2001		b.SetDifficulty(big.NewInt(1000000))
2002	})
2003	if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil {
2004		t.Fatalf("Failed to import canonical chain start: %v", err)
2005	}
2006	if tt.commitBlock > 0 {
2007		chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil)
2008		if snapshots {
2009			if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil {
2010				t.Fatalf("Failed to flatten snapshots: %v", err)
2011			}
2012		}
2013	}
2014	if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil {
2015		t.Fatalf("Failed to import canonical chain tail: %v", err)
2016	}
2017	// Manually dereference anything not committed to not have to work with 128+ tries
2018	for _, block := range sideblocks {
2019		chain.stateCache.TrieDB().Dereference(block.Root())
2020	}
2021	for _, block := range canonblocks {
2022		chain.stateCache.TrieDB().Dereference(block.Root())
2023	}
2024	// Force run a freeze cycle
2025	type freezer interface {
2026		Freeze(threshold uint64) error
2027		Ancients() (uint64, error)
2028	}
2029	db.(freezer).Freeze(tt.freezeThreshold)
2030
2031	// Set the simulated pivot block
2032	if tt.pivotBlock != nil {
2033		rawdb.WriteLastPivotNumber(db, *tt.pivotBlock)
2034	}
2035	// Set the head of the chain back to the requested number
2036	chain.SetHead(tt.setheadBlock)
2037
2038	// Iterate over all the remaining blocks and ensure there are no gaps
2039	verifyNoGaps(t, chain, true, canonblocks)
2040	verifyNoGaps(t, chain, false, sideblocks)
2041	verifyCutoff(t, chain, true, canonblocks, tt.expCanonicalBlocks)
2042	verifyCutoff(t, chain, false, sideblocks, tt.expSidechainBlocks)
2043
2044	if head := chain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader {
2045		t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader)
2046	}
2047	if head := chain.CurrentFastBlock(); head.NumberU64() != tt.expHeadFastBlock {
2048		t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadFastBlock)
2049	}
2050	if head := chain.CurrentBlock(); head.NumberU64() != tt.expHeadBlock {
2051		t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadBlock)
2052	}
2053	if frozen, err := db.(freezer).Ancients(); err != nil {
2054		t.Errorf("Failed to retrieve ancient count: %v\n", err)
2055	} else if int(frozen) != tt.expFrozen {
2056		t.Errorf("Frozen block count mismatch: have %d, want %d", frozen, tt.expFrozen)
2057	}
2058}
2059
2060// verifyNoGaps checks that there are no gaps after the initial set of blocks in
2061// the database and errors if found.
2062func verifyNoGaps(t *testing.T, chain *BlockChain, canonical bool, inserted types.Blocks) {
2063	t.Helper()
2064
2065	var end uint64
2066	for i := uint64(0); i <= uint64(len(inserted)); i++ {
2067		header := chain.GetHeaderByNumber(i)
2068		if header == nil && end == 0 {
2069			end = i
2070		}
2071		if header != nil && end > 0 {
2072			if canonical {
2073				t.Errorf("Canonical header gap between #%d-#%d", end, i-1)
2074			} else {
2075				t.Errorf("Sidechain header gap between #%d-#%d", end, i-1)
2076			}
2077			end = 0 // Reset for further gap detection
2078		}
2079	}
2080	end = 0
2081	for i := uint64(0); i <= uint64(len(inserted)); i++ {
2082		block := chain.GetBlockByNumber(i)
2083		if block == nil && end == 0 {
2084			end = i
2085		}
2086		if block != nil && end > 0 {
2087			if canonical {
2088				t.Errorf("Canonical block gap between #%d-#%d", end, i-1)
2089			} else {
2090				t.Errorf("Sidechain block gap between #%d-#%d", end, i-1)
2091			}
2092			end = 0 // Reset for further gap detection
2093		}
2094	}
2095	end = 0
2096	for i := uint64(1); i <= uint64(len(inserted)); i++ {
2097		receipts := chain.GetReceiptsByHash(inserted[i-1].Hash())
2098		if receipts == nil && end == 0 {
2099			end = i
2100		}
2101		if receipts != nil && end > 0 {
2102			if canonical {
2103				t.Errorf("Canonical receipt gap between #%d-#%d", end, i-1)
2104			} else {
2105				t.Errorf("Sidechain receipt gap between #%d-#%d", end, i-1)
2106			}
2107			end = 0 // Reset for further gap detection
2108		}
2109	}
2110}
2111
2112// verifyCutoff checks that there are no chain data available in the chain after
2113// the specified limit, but that it is available before.
2114func verifyCutoff(t *testing.T, chain *BlockChain, canonical bool, inserted types.Blocks, head int) {
2115	t.Helper()
2116
2117	for i := 1; i <= len(inserted); i++ {
2118		if i <= head {
2119			if header := chain.GetHeader(inserted[i-1].Hash(), uint64(i)); header == nil {
2120				if canonical {
2121					t.Errorf("Canonical header   #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head)
2122				} else {
2123					t.Errorf("Sidechain header   #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head)
2124				}
2125			}
2126			if block := chain.GetBlock(inserted[i-1].Hash(), uint64(i)); block == nil {
2127				if canonical {
2128					t.Errorf("Canonical block    #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head)
2129				} else {
2130					t.Errorf("Sidechain block    #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head)
2131				}
2132			}
2133			if receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()); receipts == nil {
2134				if canonical {
2135					t.Errorf("Canonical receipts #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head)
2136				} else {
2137					t.Errorf("Sidechain receipts #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head)
2138				}
2139			}
2140		} else {
2141			if header := chain.GetHeader(inserted[i-1].Hash(), uint64(i)); header != nil {
2142				if canonical {
2143					t.Errorf("Canonical header   #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head)
2144				} else {
2145					t.Errorf("Sidechain header   #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head)
2146				}
2147			}
2148			if block := chain.GetBlock(inserted[i-1].Hash(), uint64(i)); block != nil {
2149				if canonical {
2150					t.Errorf("Canonical block    #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head)
2151				} else {
2152					t.Errorf("Sidechain block    #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head)
2153				}
2154			}
2155			if receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()); receipts != nil {
2156				if canonical {
2157					t.Errorf("Canonical receipts #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head)
2158				} else {
2159					t.Errorf("Sidechain receipts #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head)
2160				}
2161			}
2162		}
2163	}
2164}
2165
2166// uint64ptr is a weird helper to allow 1-line constant pointer creation.
2167func uint64ptr(n uint64) *uint64 {
2168	return &n
2169}
2170