From 64b5566083a802728c304d0caf8d0034c63e8d47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Wed, 7 Oct 2020 21:22:36 +0300 Subject: [PATCH] core: fix setHead cornercase where the threshold root has state --- core/blockchain.go | 33 ++-- core/blockchain_repair_test.go | 319 ++++++++++++++++++++++++++------ core/blockchain_sethead_test.go | 319 ++++++++++++++++++++++++++------ 3 files changed, 544 insertions(+), 127 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index fb780fcf5285..1a058a4ff75d 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -360,19 +360,18 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par } // Load any existing snapshot, regenerating it if loading failed if bc.cacheConfig.SnapshotLimit > 0 { - var ( - recovery bool - flag = rawdb.ReadSnapshotRecoveryNumber(bc.db) - ) - // The persisted snapshot recovery height is higher than - // current chain head. At least it means the snapshot disk - // layer is higher than current head. Enable the snapshot - // recovery mode. - if flag != nil && *flag > bc.CurrentBlock().NumberU64() { - recovery = true - log.Info("Enable snapshot recovery", "chainhead", bc.CurrentBlock().NumberU64(), "disklayer", *flag) + // If the chain was rewound past the snapshot persistent layer (causing + // a recovery block number to be persisted to disk), check if we're still + // in recovery mode and in that case, don't invalidate the snapshot on a + // head mismatch. + var recover bool + + head := bc.CurrentBlock() + if layer := rawdb.ReadSnapshotRecoveryNumber(bc.db); layer != nil && *layer > head.NumberU64() { + log.Warn("Enabling snapshot recovery", "chainhead", head.NumberU64(), "diskbase", *layer) + recover = true } - bc.snaps = snapshot.New(bc.db, bc.stateCache.TrieDB(), bc.cacheConfig.SnapshotLimit, bc.CurrentBlock().Root(), !bc.cacheConfig.SnapshotWait, recovery) + bc.snaps = snapshot.New(bc.db, bc.stateCache.TrieDB(), bc.cacheConfig.SnapshotLimit, head.Root(), !bc.cacheConfig.SnapshotWait, recover) } // Take ownership of this particular state go bc.update() @@ -517,11 +516,11 @@ func (bc *BlockChain) SetHeadBeyondRoot(head uint64, root common.Hash) (uint64, beyondRoot := (root == common.Hash{}) // Flag whether we're beyond the requested root (no root, always true) for { + // If a root threshold was requested but not yet crossed, check + if root != (common.Hash{}) && !beyondRoot && newHeadBlock.Root() == root { + beyondRoot, rootNumber = true, newHeadBlock.NumberU64() + } if _, err := state.New(newHeadBlock.Root(), bc.stateCache, bc.snaps); err != nil { - // If a root threshold was requested but not yet crossed, check - if root != (common.Hash{}) && !beyondRoot && newHeadBlock.Root() == root { - beyondRoot, rootNumber = true, newHeadBlock.NumberU64() - } log.Trace("Block state missing, rewinding further", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash()) if pivot == nil || newHeadBlock.NumberU64() > *pivot { newHeadBlock = bc.GetBlock(newHeadBlock.ParentHash(), newHeadBlock.NumberU64()-1) @@ -535,7 +534,7 @@ func (bc *BlockChain) SetHeadBeyondRoot(head uint64, root common.Hash) (uint64, log.Debug("Rewound to block with state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash()) break } - log.Debug("Skip the block with state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash()) + log.Debug("Skipping block with thershold state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash(), "root", newHeadBlock.Root()) newHeadBlock = bc.GetBlock(newHeadBlock.ParentHash(), newHeadBlock.NumberU64()-1) // Keep rewinding } } diff --git a/core/blockchain_repair_test.go b/core/blockchain_repair_test.go index 7ab2e9652e44..b5cd232a9c4f 100644 --- a/core/blockchain_repair_test.go +++ b/core/blockchain_repair_test.go @@ -39,7 +39,10 @@ import ( // committed to disk and then the process crashed. In this case we expect the full // chain to be rolled back to the committed block, but the chain data itself left // in the database for replaying. -func TestShortRepair(t *testing.T) { +func TestShortRepair(t *testing.T) { testShortRepair(t, false) } +func TestShortRepairWithSnapshots(t *testing.T) { testShortRepair(t, true) } + +func testShortRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // @@ -69,14 +72,17 @@ func TestShortRepair(t *testing.T) { expHeadHeader: 8, expHeadFastBlock: 8, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a short canonical chain where the fast sync pivot point was // already committed, after which the process crashed. In this case we expect the full // chain to be rolled back to the committed block, but the chain data itself left in // the database for replaying. -func TestShortFastSyncedRepair(t *testing.T) { +func TestShortFastSyncedRepair(t *testing.T) { testShortFastSyncedRepair(t, false) } +func TestShortFastSyncedRepairWithSnapshots(t *testing.T) { testShortFastSyncedRepair(t, true) } + +func testShortFastSyncedRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // @@ -106,14 +112,17 @@ func TestShortFastSyncedRepair(t *testing.T) { expHeadHeader: 8, expHeadFastBlock: 8, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a short canonical chain where the fast sync pivot point was // not yet committed, but the process crashed. In this case we expect the chain to // detect that it was fast syncing and not delete anything, since we can just pick // up directly where we left off. -func TestShortFastSyncingRepair(t *testing.T) { +func TestShortFastSyncingRepair(t *testing.T) { testShortFastSyncingRepair(t, false) } +func TestShortFastSyncingRepairWithSnapshots(t *testing.T) { testShortFastSyncingRepair(t, true) } + +func testShortFastSyncingRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // @@ -143,7 +152,7 @@ func TestShortFastSyncingRepair(t *testing.T) { expHeadHeader: 8, expHeadFastBlock: 8, expHeadBlock: 0, - }) + }, snapshots) } // Tests a recovery for a short canonical chain and a shorter side chain, where a @@ -151,7 +160,10 @@ func TestShortFastSyncingRepair(t *testing.T) { // test scenario the side chain is below the committed block. In this case we expect // the canonical chain to be rolled back to the committed block, but the chain data // itself left in the database for replaying. -func TestShortOldForkedRepair(t *testing.T) { +func TestShortOldForkedRepair(t *testing.T) { testShortOldForkedRepair(t, false) } +func TestShortOldForkedRepairWithSnapshots(t *testing.T) { testShortOldForkedRepair(t, true) } + +func testShortOldForkedRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // └->S1->S2->S3 @@ -183,7 +195,7 @@ func TestShortOldForkedRepair(t *testing.T) { expHeadHeader: 8, expHeadFastBlock: 8, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a short canonical chain and a shorter side chain, where @@ -192,6 +204,13 @@ func TestShortOldForkedRepair(t *testing.T) { // this case we expect the canonical chain to be rolled back to the committed block, // but the chain data itself left in the database for replaying. func TestShortOldForkedFastSyncedRepair(t *testing.T) { + testShortOldForkedFastSyncedRepair(t, false) +} +func TestShortOldForkedFastSyncedRepairWithSnapshots(t *testing.T) { + testShortOldForkedFastSyncedRepair(t, true) +} + +func testShortOldForkedFastSyncedRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // └->S1->S2->S3 @@ -223,7 +242,7 @@ func TestShortOldForkedFastSyncedRepair(t *testing.T) { expHeadHeader: 8, expHeadFastBlock: 8, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a short canonical chain and a shorter side chain, where @@ -232,6 +251,13 @@ func TestShortOldForkedFastSyncedRepair(t *testing.T) { // the chain to detect that it was fast syncing and not delete anything, since we // can just pick up directly where we left off. func TestShortOldForkedFastSyncingRepair(t *testing.T) { + testShortOldForkedFastSyncingRepair(t, false) +} +func TestShortOldForkedFastSyncingRepairWithSnapshots(t *testing.T) { + testShortOldForkedFastSyncingRepair(t, true) +} + +func testShortOldForkedFastSyncingRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // └->S1->S2->S3 @@ -263,7 +289,7 @@ func TestShortOldForkedFastSyncingRepair(t *testing.T) { expHeadHeader: 8, expHeadFastBlock: 8, expHeadBlock: 0, - }) + }, snapshots) } // Tests a recovery for a short canonical chain and a shorter side chain, where a @@ -271,7 +297,10 @@ func TestShortOldForkedFastSyncingRepair(t *testing.T) { // test scenario the side chain reaches above the committed block. In this case we // expect the canonical chain to be rolled back to the committed block, but the // chain data itself left in the database for replaying. -func TestShortNewlyForkedRepair(t *testing.T) { +func TestShortNewlyForkedRepair(t *testing.T) { testShortNewlyForkedRepair(t, false) } +func TestShortNewlyForkedRepairWithSnapshots(t *testing.T) { testShortNewlyForkedRepair(t, true) } + +func testShortNewlyForkedRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // └->S1->S2->S3->S4->S5->S6 @@ -303,7 +332,7 @@ func TestShortNewlyForkedRepair(t *testing.T) { expHeadHeader: 8, expHeadFastBlock: 8, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a short canonical chain and a shorter side chain, where @@ -312,6 +341,13 @@ func TestShortNewlyForkedRepair(t *testing.T) { // In this case we expect the canonical chain to be rolled back to the committed // block, but the chain data itself left in the database for replaying. func TestShortNewlyForkedFastSyncedRepair(t *testing.T) { + testShortNewlyForkedFastSyncedRepair(t, false) +} +func TestShortNewlyForkedFastSyncedRepairWithSnapshots(t *testing.T) { + testShortNewlyForkedFastSyncedRepair(t, true) +} + +func testShortNewlyForkedFastSyncedRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // └->S1->S2->S3->S4->S5->S6 @@ -343,7 +379,7 @@ func TestShortNewlyForkedFastSyncedRepair(t *testing.T) { expHeadHeader: 8, expHeadFastBlock: 8, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a short canonical chain and a shorter side chain, where @@ -352,6 +388,13 @@ func TestShortNewlyForkedFastSyncedRepair(t *testing.T) { // case we expect the chain to detect that it was fast syncing and not delete // anything, since we can just pick up directly where we left off. func TestShortNewlyForkedFastSyncingRepair(t *testing.T) { + testShortNewlyForkedFastSyncingRepair(t, false) +} +func TestShortNewlyForkedFastSyncingRepairWithSnapshots(t *testing.T) { + testShortNewlyForkedFastSyncingRepair(t, true) +} + +func testShortNewlyForkedFastSyncingRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // └->S1->S2->S3->S4->S5->S6 @@ -383,14 +426,17 @@ func TestShortNewlyForkedFastSyncingRepair(t *testing.T) { expHeadHeader: 8, expHeadFastBlock: 8, expHeadBlock: 0, - }) + }, snapshots) } // Tests a recovery for a short canonical chain and a longer side chain, where a // recent block was already committed to disk and then the process crashed. In this // case we expect the canonical chain to be rolled back to the committed block, but // the chain data itself left in the database for replaying. -func TestShortReorgedRepair(t *testing.T) { +func TestShortReorgedRepair(t *testing.T) { testShortReorgedRepair(t, false) } +func TestShortReorgedRepairWithSnapshots(t *testing.T) { testShortReorgedRepair(t, true) } + +func testShortReorgedRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 @@ -422,7 +468,7 @@ func TestShortReorgedRepair(t *testing.T) { expHeadHeader: 8, expHeadFastBlock: 8, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a short canonical chain and a longer side chain, where @@ -430,6 +476,13 @@ func TestShortReorgedRepair(t *testing.T) { // crashed. In this case we expect the canonical chain to be rolled back to the // committed block, but the chain data itself left in the database for replaying. func TestShortReorgedFastSyncedRepair(t *testing.T) { + testShortReorgedFastSyncedRepair(t, false) +} +func TestShortReorgedFastSyncedRepairWithSnapshots(t *testing.T) { + testShortReorgedFastSyncedRepair(t, true) +} + +func testShortReorgedFastSyncedRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 @@ -461,7 +514,7 @@ func TestShortReorgedFastSyncedRepair(t *testing.T) { expHeadHeader: 8, expHeadFastBlock: 8, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a short canonical chain and a longer side chain, where @@ -469,6 +522,13 @@ func TestShortReorgedFastSyncedRepair(t *testing.T) { // this case we expect the chain to detect that it was fast syncing and not delete // anything, since we can just pick up directly where we left off. func TestShortReorgedFastSyncingRepair(t *testing.T) { + testShortReorgedFastSyncingRepair(t, false) +} +func TestShortReorgedFastSyncingRepairWithSnapshots(t *testing.T) { + testShortReorgedFastSyncingRepair(t, true) +} + +func testShortReorgedFastSyncingRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 @@ -500,14 +560,17 @@ func TestShortReorgedFastSyncingRepair(t *testing.T) { expHeadHeader: 8, expHeadFastBlock: 8, expHeadBlock: 0, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks where a recent // block - newer than the ancient limit - was already committed to disk and then // the process crashed. In this case we expect the chain to be rolled back to the // committed block, with everything afterwads kept as fast sync data. -func TestLongShallowRepair(t *testing.T) { +func TestLongShallowRepair(t *testing.T) { testLongShallowRepair(t, false) } +func TestLongShallowRepairWithSnapshots(t *testing.T) { testLongShallowRepair(t, true) } + +func testLongShallowRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // @@ -542,14 +605,17 @@ func TestLongShallowRepair(t *testing.T) { expHeadHeader: 18, expHeadFastBlock: 18, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks where a recent // block - older than the ancient limit - was already committed to disk and then // the process crashed. In this case we expect the chain to be rolled back to the // committed block, with everything afterwads deleted. -func TestLongDeepRepair(t *testing.T) { +func TestLongDeepRepair(t *testing.T) { testLongDeepRepair(t, false) } +func TestLongDeepRepairWithSnapshots(t *testing.T) { testLongDeepRepair(t, true) } + +func testLongDeepRepair(t *testing.T, snapshots bool) { // Chain: // 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) // @@ -583,7 +649,7 @@ func TestLongDeepRepair(t *testing.T) { expHeadHeader: 4, expHeadFastBlock: 4, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks where the fast @@ -591,6 +657,13 @@ func TestLongDeepRepair(t *testing.T) { // which the process crashed. In this case we expect the chain to be rolled back // to the committed block, with everything afterwads kept as fast sync data. func TestLongFastSyncedShallowRepair(t *testing.T) { + testLongFastSyncedShallowRepair(t, false) +} +func TestLongFastSyncedShallowRepairWithSnapshots(t *testing.T) { + testLongFastSyncedShallowRepair(t, true) +} + +func testLongFastSyncedShallowRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // @@ -625,14 +698,17 @@ func TestLongFastSyncedShallowRepair(t *testing.T) { expHeadHeader: 18, expHeadFastBlock: 18, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks where the fast // sync pivot point - older than the ancient limit - was already committed, after // which the process crashed. In this case we expect the chain to be rolled back // to the committed block, with everything afterwads deleted. -func TestLongFastSyncedDeepRepair(t *testing.T) { +func TestLongFastSyncedDeepRepair(t *testing.T) { testLongFastSyncedDeepRepair(t, false) } +func TestLongFastSyncedDeepRepairWithSnapshots(t *testing.T) { testLongFastSyncedDeepRepair(t, true) } + +func testLongFastSyncedDeepRepair(t *testing.T, snapshots bool) { // Chain: // 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) // @@ -666,7 +742,7 @@ func TestLongFastSyncedDeepRepair(t *testing.T) { expHeadHeader: 4, expHeadFastBlock: 4, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks where the fast @@ -675,6 +751,13 @@ func TestLongFastSyncedDeepRepair(t *testing.T) { // syncing and not delete anything, since we can just pick up directly where we // left off. func TestLongFastSyncingShallowRepair(t *testing.T) { + testLongFastSyncingShallowRepair(t, false) +} +func TestLongFastSyncingShallowRepairWithSnapshots(t *testing.T) { + testLongFastSyncingShallowRepair(t, true) +} + +func testLongFastSyncingShallowRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // @@ -709,7 +792,7 @@ func TestLongFastSyncingShallowRepair(t *testing.T) { expHeadHeader: 18, expHeadFastBlock: 18, expHeadBlock: 0, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks where the fast @@ -717,7 +800,10 @@ func TestLongFastSyncingShallowRepair(t *testing.T) { // process crashed. In this case we expect the chain to detect that it was fast // syncing and not delete anything, since we can just pick up directly where we // left off. -func TestLongFastSyncingDeepRepair(t *testing.T) { +func TestLongFastSyncingDeepRepair(t *testing.T) { testLongFastSyncingDeepRepair(t, false) } +func TestLongFastSyncingDeepRepairWithSnapshots(t *testing.T) { testLongFastSyncingDeepRepair(t, true) } + +func testLongFastSyncingDeepRepair(t *testing.T, snapshots bool) { // Chain: // 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) // @@ -752,7 +838,7 @@ func TestLongFastSyncingDeepRepair(t *testing.T) { expHeadHeader: 24, expHeadFastBlock: 24, expHeadBlock: 0, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a shorter @@ -762,6 +848,13 @@ func TestLongFastSyncingDeepRepair(t *testing.T) { // rolled back to the committed block, with everything afterwads kept as fast // sync data; the side chain completely nuked by the freezer. func TestLongOldForkedShallowRepair(t *testing.T) { + testLongOldForkedShallowRepair(t, false) +} +func TestLongOldForkedShallowRepairWithSnapshots(t *testing.T) { + testLongOldForkedShallowRepair(t, true) +} + +func testLongOldForkedShallowRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->S1->S2->S3 @@ -797,7 +890,7 @@ func TestLongOldForkedShallowRepair(t *testing.T) { expHeadHeader: 18, expHeadFastBlock: 18, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a shorter @@ -806,7 +899,10 @@ func TestLongOldForkedShallowRepair(t *testing.T) { // chain is below the committed block. In this case we expect the canonical chain // to be rolled back to the committed block, with everything afterwads deleted; // the side chain completely nuked by the freezer. -func TestLongOldForkedDeepRepair(t *testing.T) { +func TestLongOldForkedDeepRepair(t *testing.T) { testLongOldForkedDeepRepair(t, false) } +func TestLongOldForkedDeepRepairWithSnapshots(t *testing.T) { testLongOldForkedDeepRepair(t, true) } + +func testLongOldForkedDeepRepair(t *testing.T, snapshots bool) { // Chain: // 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) // └->S1->S2->S3 @@ -841,7 +937,7 @@ func TestLongOldForkedDeepRepair(t *testing.T) { expHeadHeader: 4, expHeadFastBlock: 4, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a shorter @@ -851,6 +947,13 @@ func TestLongOldForkedDeepRepair(t *testing.T) { // to be rolled back to the committed block, with everything afterwads kept as // fast sync data; the side chain completely nuked by the freezer. func TestLongOldForkedFastSyncedShallowRepair(t *testing.T) { + testLongOldForkedFastSyncedShallowRepair(t, false) +} +func TestLongOldForkedFastSyncedShallowRepairWithSnapshots(t *testing.T) { + testLongOldForkedFastSyncedShallowRepair(t, true) +} + +func testLongOldForkedFastSyncedShallowRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->S1->S2->S3 @@ -886,7 +989,7 @@ func TestLongOldForkedFastSyncedShallowRepair(t *testing.T) { expHeadHeader: 18, expHeadFastBlock: 18, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a shorter @@ -896,6 +999,13 @@ func TestLongOldForkedFastSyncedShallowRepair(t *testing.T) { // chain to be rolled back to the committed block, with everything afterwads deleted; // the side chain completely nuked by the freezer. func TestLongOldForkedFastSyncedDeepRepair(t *testing.T) { + testLongOldForkedFastSyncedDeepRepair(t, false) +} +func TestLongOldForkedFastSyncedDeepRepairWithSnapshots(t *testing.T) { + testLongOldForkedFastSyncedDeepRepair(t, true) +} + +func testLongOldForkedFastSyncedDeepRepair(t *testing.T, snapshots bool) { // Chain: // 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) // └->S1->S2->S3 @@ -930,7 +1040,7 @@ func TestLongOldForkedFastSyncedDeepRepair(t *testing.T) { expHeadHeader: 4, expHeadFastBlock: 4, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a shorter @@ -940,6 +1050,13 @@ func TestLongOldForkedFastSyncedDeepRepair(t *testing.T) { // that it was fast syncing and not delete anything. The side chain is completely // nuked by the freezer. func TestLongOldForkedFastSyncingShallowRepair(t *testing.T) { + testLongOldForkedFastSyncingShallowRepair(t, false) +} +func TestLongOldForkedFastSyncingShallowRepairWithSnapshots(t *testing.T) { + testLongOldForkedFastSyncingShallowRepair(t, true) +} + +func testLongOldForkedFastSyncingShallowRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->S1->S2->S3 @@ -975,7 +1092,7 @@ func TestLongOldForkedFastSyncingShallowRepair(t *testing.T) { expHeadHeader: 18, expHeadFastBlock: 18, expHeadBlock: 0, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a shorter @@ -985,6 +1102,13 @@ func TestLongOldForkedFastSyncingShallowRepair(t *testing.T) { // that it was fast syncing and not delete anything. The side chain is completely // nuked by the freezer. func TestLongOldForkedFastSyncingDeepRepair(t *testing.T) { + testLongOldForkedFastSyncingDeepRepair(t, false) +} +func TestLongOldForkedFastSyncingDeepRepairWithSnapshots(t *testing.T) { + testLongOldForkedFastSyncingDeepRepair(t, true) +} + +func testLongOldForkedFastSyncingDeepRepair(t *testing.T, snapshots bool) { // Chain: // 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) // └->S1->S2->S3 @@ -1020,7 +1144,7 @@ func TestLongOldForkedFastSyncingDeepRepair(t *testing.T) { expHeadHeader: 24, expHeadFastBlock: 24, expHeadBlock: 0, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a shorter @@ -1030,6 +1154,13 @@ func TestLongOldForkedFastSyncingDeepRepair(t *testing.T) { // rolled back to the committed block, with everything afterwads kept as fast // sync data; the side chain completely nuked by the freezer. func TestLongNewerForkedShallowRepair(t *testing.T) { + testLongNewerForkedShallowRepair(t, false) +} +func TestLongNewerForkedShallowRepairWithSnapshots(t *testing.T) { + testLongNewerForkedShallowRepair(t, true) +} + +func testLongNewerForkedShallowRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 @@ -1065,7 +1196,7 @@ func TestLongNewerForkedShallowRepair(t *testing.T) { expHeadHeader: 18, expHeadFastBlock: 18, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a shorter @@ -1074,7 +1205,10 @@ func TestLongNewerForkedShallowRepair(t *testing.T) { // chain is above the committed block. In this case we expect the canonical chain // to be rolled back to the committed block, with everything afterwads deleted; // the side chain completely nuked by the freezer. -func TestLongNewerForkedDeepRepair(t *testing.T) { +func TestLongNewerForkedDeepRepair(t *testing.T) { testLongNewerForkedDeepRepair(t, false) } +func TestLongNewerForkedDeepRepairWithSnapshots(t *testing.T) { testLongNewerForkedDeepRepair(t, true) } + +func testLongNewerForkedDeepRepair(t *testing.T, snapshots bool) { // Chain: // 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) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 @@ -1109,7 +1243,7 @@ func TestLongNewerForkedDeepRepair(t *testing.T) { expHeadHeader: 4, expHeadFastBlock: 4, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a shorter @@ -1119,6 +1253,13 @@ func TestLongNewerForkedDeepRepair(t *testing.T) { // to be rolled back to the committed block, with everything afterwads kept as fast // sync data; the side chain completely nuked by the freezer. func TestLongNewerForkedFastSyncedShallowRepair(t *testing.T) { + testLongNewerForkedFastSyncedShallowRepair(t, false) +} +func TestLongNewerForkedFastSyncedShallowRepairWithSnapshots(t *testing.T) { + testLongNewerForkedFastSyncedShallowRepair(t, true) +} + +func testLongNewerForkedFastSyncedShallowRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 @@ -1154,7 +1295,7 @@ func TestLongNewerForkedFastSyncedShallowRepair(t *testing.T) { expHeadHeader: 18, expHeadFastBlock: 18, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a shorter @@ -1164,6 +1305,13 @@ func TestLongNewerForkedFastSyncedShallowRepair(t *testing.T) { // chain to be rolled back to the committed block, with everything afterwads deleted; // the side chain completely nuked by the freezer. func TestLongNewerForkedFastSyncedDeepRepair(t *testing.T) { + testLongNewerForkedFastSyncedDeepRepair(t, false) +} +func TestLongNewerForkedFastSyncedDeepRepairWithSnapshots(t *testing.T) { + testLongNewerForkedFastSyncedDeepRepair(t, true) +} + +func testLongNewerForkedFastSyncedDeepRepair(t *testing.T, snapshots bool) { // Chain: // 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) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 @@ -1198,7 +1346,7 @@ func TestLongNewerForkedFastSyncedDeepRepair(t *testing.T) { expHeadHeader: 4, expHeadFastBlock: 4, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a shorter @@ -1208,6 +1356,13 @@ func TestLongNewerForkedFastSyncedDeepRepair(t *testing.T) { // that it was fast syncing and not delete anything. The side chain is completely // nuked by the freezer. func TestLongNewerForkedFastSyncingShallowRepair(t *testing.T) { + testLongNewerForkedFastSyncingShallowRepair(t, false) +} +func TestLongNewerForkedFastSyncingShallowRepairWithSnapshots(t *testing.T) { + testLongNewerForkedFastSyncingShallowRepair(t, true) +} + +func testLongNewerForkedFastSyncingShallowRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 @@ -1243,7 +1398,7 @@ func TestLongNewerForkedFastSyncingShallowRepair(t *testing.T) { expHeadHeader: 18, expHeadFastBlock: 18, expHeadBlock: 0, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a shorter @@ -1253,6 +1408,13 @@ func TestLongNewerForkedFastSyncingShallowRepair(t *testing.T) { // that it was fast syncing and not delete anything. The side chain is completely // nuked by the freezer. func TestLongNewerForkedFastSyncingDeepRepair(t *testing.T) { + testLongNewerForkedFastSyncingDeepRepair(t, false) +} +func TestLongNewerForkedFastSyncingDeepRepairWithSnapshots(t *testing.T) { + testLongNewerForkedFastSyncingDeepRepair(t, true) +} + +func testLongNewerForkedFastSyncingDeepRepair(t *testing.T, snapshots bool) { // Chain: // 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) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 @@ -1288,7 +1450,7 @@ func TestLongNewerForkedFastSyncingDeepRepair(t *testing.T) { expHeadHeader: 24, expHeadFastBlock: 24, expHeadBlock: 0, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a longer side @@ -1296,7 +1458,10 @@ func TestLongNewerForkedFastSyncingDeepRepair(t *testing.T) { // to disk and then the process crashed. In this case we expect the chain to be // rolled back to the committed block, with everything afterwads kept as fast sync // data. The side chain completely nuked by the freezer. -func TestLongReorgedShallowRepair(t *testing.T) { +func TestLongReorgedShallowRepair(t *testing.T) { testLongReorgedShallowRepair(t, false) } +func TestLongReorgedShallowRepairWithSnapshots(t *testing.T) { testLongReorgedShallowRepair(t, true) } + +func testLongReorgedShallowRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->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 @@ -1332,7 +1497,7 @@ func TestLongReorgedShallowRepair(t *testing.T) { expHeadHeader: 18, expHeadFastBlock: 18, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a longer side @@ -1340,7 +1505,10 @@ func TestLongReorgedShallowRepair(t *testing.T) { // to disk and then the process crashed. In this case we expect the canonical chains // to be rolled back to the committed block, with everything afterwads deleted. The // side chain completely nuked by the freezer. -func TestLongReorgedDeepRepair(t *testing.T) { +func TestLongReorgedDeepRepair(t *testing.T) { testLongReorgedDeepRepair(t, false) } +func TestLongReorgedDeepRepairWithSnapshots(t *testing.T) { testLongReorgedDeepRepair(t, true) } + +func testLongReorgedDeepRepair(t *testing.T, snapshots bool) { // Chain: // 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) // └->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 @@ -1375,7 +1543,7 @@ func TestLongReorgedDeepRepair(t *testing.T) { expHeadHeader: 4, expHeadFastBlock: 4, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a longer @@ -1385,6 +1553,13 @@ func TestLongReorgedDeepRepair(t *testing.T) { // afterwads kept as fast sync data. The side chain completely nuked by the // freezer. func TestLongReorgedFastSyncedShallowRepair(t *testing.T) { + testLongReorgedFastSyncedShallowRepair(t, false) +} +func TestLongReorgedFastSyncedShallowRepairWithSnapshots(t *testing.T) { + testLongReorgedFastSyncedShallowRepair(t, true) +} + +func testLongReorgedFastSyncedShallowRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->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 @@ -1420,7 +1595,7 @@ func TestLongReorgedFastSyncedShallowRepair(t *testing.T) { expHeadHeader: 18, expHeadFastBlock: 18, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a longer @@ -1429,6 +1604,13 @@ func TestLongReorgedFastSyncedShallowRepair(t *testing.T) { // expect the canonical chains to be rolled back to the committed block, with // everything afterwads deleted. The side chain completely nuked by the freezer. func TestLongReorgedFastSyncedDeepRepair(t *testing.T) { + testLongReorgedFastSyncedDeepRepair(t, false) +} +func TestLongReorgedFastSyncedDeepRepairWithSnapshots(t *testing.T) { + testLongReorgedFastSyncedDeepRepair(t, true) +} + +func testLongReorgedFastSyncedDeepRepair(t *testing.T, snapshots bool) { // Chain: // 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) // └->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 @@ -1463,7 +1645,7 @@ func TestLongReorgedFastSyncedDeepRepair(t *testing.T) { expHeadHeader: 4, expHeadFastBlock: 4, expHeadBlock: 4, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a longer @@ -1472,6 +1654,13 @@ func TestLongReorgedFastSyncedDeepRepair(t *testing.T) { // chain to detect that it was fast syncing and not delete anything, since we // can just pick up directly where we left off. func TestLongReorgedFastSyncingShallowRepair(t *testing.T) { + testLongReorgedFastSyncingShallowRepair(t, false) +} +func TestLongReorgedFastSyncingShallowRepairWithSnapshots(t *testing.T) { + testLongReorgedFastSyncingShallowRepair(t, true) +} + +func testLongReorgedFastSyncingShallowRepair(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->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 @@ -1507,7 +1696,7 @@ func TestLongReorgedFastSyncingShallowRepair(t *testing.T) { expHeadHeader: 18, expHeadFastBlock: 18, expHeadBlock: 0, - }) + }, snapshots) } // Tests a recovery for a long canonical chain with frozen blocks and a longer @@ -1516,6 +1705,13 @@ func TestLongReorgedFastSyncingShallowRepair(t *testing.T) { // chain to detect that it was fast syncing and not delete anything, since we // can just pick up directly where we left off. func TestLongReorgedFastSyncingDeepRepair(t *testing.T) { + testLongReorgedFastSyncingDeepRepair(t, false) +} +func TestLongReorgedFastSyncingDeepRepairWithSnapshots(t *testing.T) { + testLongReorgedFastSyncingDeepRepair(t, true) +} + +func testLongReorgedFastSyncingDeepRepair(t *testing.T, snapshots bool) { // Chain: // 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) // └->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 @@ -1551,12 +1747,12 @@ func TestLongReorgedFastSyncingDeepRepair(t *testing.T) { expHeadHeader: 24, expHeadFastBlock: 24, expHeadBlock: 0, - }) + }, snapshots) } -func testRepair(t *testing.T, tt *rewindTest) { +func testRepair(t *testing.T, tt *rewindTest, snapshots bool) { // It's hard to follow the test case, visualize the input - // log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) + //log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) // fmt.Println(tt.dump(true)) // Create a temporary persistent database @@ -1574,16 +1770,20 @@ func testRepair(t *testing.T, tt *rewindTest) { // Initialize a fresh chain var ( - genesis = new(Genesis).MustCommit(db) - engine = ethash.NewFullFaker() - cacheConfig = &CacheConfig{ + genesis = new(Genesis).MustCommit(db) + engine = ethash.NewFullFaker() + config = &CacheConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 0, // Disable snapshot + SnapshotLimit: 0, // Disable snapshot by default } ) - chain, err := NewBlockChain(db, cacheConfig, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) + if snapshots { + config.SnapshotLimit = 256 + config.SnapshotWait = true + } + chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to create chain: %v", err) } @@ -1606,6 +1806,11 @@ func testRepair(t *testing.T, tt *rewindTest) { } if tt.commitBlock > 0 { chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil) + if snapshots { + if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { + t.Fatalf("Failed to flatten snapshots: %v", err) + } + } } if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil { t.Fatalf("Failed to import canonical chain tail: %v", err) diff --git a/core/blockchain_sethead_test.go b/core/blockchain_sethead_test.go index e4f81c9c9daf..45c4073eb4ce 100644 --- a/core/blockchain_sethead_test.go +++ b/core/blockchain_sethead_test.go @@ -151,7 +151,10 @@ func (tt *rewindTest) dump(crash bool) string { // chain to be rolled back to the committed block. Everything above the sethead // point should be deleted. In between the committed block and the requested head // the data can remain as "fast sync" data to avoid redownloading it. -func TestShortSetHead(t *testing.T) { +func TestShortSetHead(t *testing.T) { testShortSetHead(t, false) } +func TestShortSetHeadWithSnapshots(t *testing.T) { testShortSetHead(t, true) } + +func testShortSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // @@ -182,7 +185,7 @@ func TestShortSetHead(t *testing.T) { expHeadHeader: 7, expHeadFastBlock: 7, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a short canonical chain where the fast sync pivot point was @@ -191,7 +194,10 @@ func TestShortSetHead(t *testing.T) { // Everything above the sethead point should be deleted. In between the committed // block and the requested head the data can remain as "fast sync" data to avoid // redownloading it. -func TestShortFastSyncedSetHead(t *testing.T) { +func TestShortFastSyncedSetHead(t *testing.T) { testShortFastSyncedSetHead(t, false) } +func TestShortFastSyncedSetHeadWithSnapshots(t *testing.T) { testShortFastSyncedSetHead(t, true) } + +func testShortFastSyncedSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // @@ -222,7 +228,7 @@ func TestShortFastSyncedSetHead(t *testing.T) { expHeadHeader: 7, expHeadFastBlock: 7, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a short canonical chain where the fast sync pivot point was @@ -230,7 +236,10 @@ func TestShortFastSyncedSetHead(t *testing.T) { // detect that it was fast syncing and delete everything from the new head, since // we can just pick up fast syncing from there. The head full block should be set // to the genesis. -func TestShortFastSyncingSetHead(t *testing.T) { +func TestShortFastSyncingSetHead(t *testing.T) { testShortFastSyncingSetHead(t, false) } +func TestShortFastSyncingSetHeadWithSnapshots(t *testing.T) { testShortFastSyncingSetHead(t, true) } + +func testShortFastSyncingSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // @@ -261,7 +270,7 @@ func TestShortFastSyncingSetHead(t *testing.T) { expHeadHeader: 7, expHeadFastBlock: 7, expHeadBlock: 0, - }) + }, snapshots) } // Tests a sethead for a short canonical chain and a shorter side chain, where a @@ -271,7 +280,10 @@ func TestShortFastSyncingSetHead(t *testing.T) { // above the sethead point should be deleted. In between the committed block and // the requested head the data can remain as "fast sync" data to avoid redownloading // it. The side chain should be left alone as it was shorter. -func TestShortOldForkedSetHead(t *testing.T) { +func TestShortOldForkedSetHead(t *testing.T) { testShortOldForkedSetHead(t, false) } +func TestShortOldForkedSetHeadWithSnapshots(t *testing.T) { testShortOldForkedSetHead(t, true) } + +func testShortOldForkedSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // └->S1->S2->S3 @@ -304,7 +316,7 @@ func TestShortOldForkedSetHead(t *testing.T) { expHeadHeader: 7, expHeadFastBlock: 7, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a short canonical chain and a shorter side chain, where @@ -315,6 +327,13 @@ func TestShortOldForkedSetHead(t *testing.T) { // committed block and the requested head the data can remain as "fast sync" data // to avoid redownloading it. The side chain should be left alone as it was shorter. func TestShortOldForkedFastSyncedSetHead(t *testing.T) { + testShortOldForkedFastSyncedSetHead(t, false) +} +func TestShortOldForkedFastSyncedSetHeadWithSnapshots(t *testing.T) { + testShortOldForkedFastSyncedSetHead(t, true) +} + +func testShortOldForkedFastSyncedSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // └->S1->S2->S3 @@ -347,7 +366,7 @@ func TestShortOldForkedFastSyncedSetHead(t *testing.T) { expHeadHeader: 7, expHeadFastBlock: 7, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a short canonical chain and a shorter side chain, where @@ -357,6 +376,13 @@ func TestShortOldForkedFastSyncedSetHead(t *testing.T) { // head, since we can just pick up fast syncing from there. The head full block // should be set to the genesis. func TestShortOldForkedFastSyncingSetHead(t *testing.T) { + testShortOldForkedFastSyncingSetHead(t, false) +} +func TestShortOldForkedFastSyncingSetHeadWithSnapshots(t *testing.T) { + testShortOldForkedFastSyncingSetHead(t, true) +} + +func testShortOldForkedFastSyncingSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // └->S1->S2->S3 @@ -389,7 +415,7 @@ func TestShortOldForkedFastSyncingSetHead(t *testing.T) { expHeadHeader: 7, expHeadFastBlock: 7, expHeadBlock: 0, - }) + }, snapshots) } // Tests a sethead for a short canonical chain and a shorter side chain, where a @@ -403,7 +429,10 @@ func TestShortOldForkedFastSyncingSetHead(t *testing.T) { // The side chain could be left to be if the fork point was before the new head // we are deleting to, but it would be exceedingly hard to detect that case and // properly handle it, so we'll trade extra work in exchange for simpler code. -func TestShortNewlyForkedSetHead(t *testing.T) { +func TestShortNewlyForkedSetHead(t *testing.T) { testShortNewlyForkedSetHead(t, false) } +func TestShortNewlyForkedSetHeadWithSnapshots(t *testing.T) { testShortNewlyForkedSetHead(t, true) } + +func testShortNewlyForkedSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 (HEAD) // └->S1->S2->S3->S4->S5->S6->S7->S8 @@ -436,7 +465,7 @@ func TestShortNewlyForkedSetHead(t *testing.T) { expHeadHeader: 7, expHeadFastBlock: 7, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a short canonical chain and a shorter side chain, where @@ -450,6 +479,13 @@ func TestShortNewlyForkedSetHead(t *testing.T) { // we are deleting to, but it would be exceedingly hard to detect that case and // properly handle it, so we'll trade extra work in exchange for simpler code. func TestShortNewlyForkedFastSyncedSetHead(t *testing.T) { + testShortNewlyForkedFastSyncedSetHead(t, false) +} +func TestShortNewlyForkedFastSyncedSetHeadWithSnapshots(t *testing.T) { + testShortNewlyForkedFastSyncedSetHead(t, true) +} + +func testShortNewlyForkedFastSyncedSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 (HEAD) // └->S1->S2->S3->S4->S5->S6->S7->S8 @@ -482,7 +518,7 @@ func TestShortNewlyForkedFastSyncedSetHead(t *testing.T) { expHeadHeader: 7, expHeadFastBlock: 7, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a short canonical chain and a shorter side chain, where @@ -496,6 +532,13 @@ func TestShortNewlyForkedFastSyncedSetHead(t *testing.T) { // we are deleting to, but it would be exceedingly hard to detect that case and // properly handle it, so we'll trade extra work in exchange for simpler code. func TestShortNewlyForkedFastSyncingSetHead(t *testing.T) { + testShortNewlyForkedFastSyncingSetHead(t, false) +} +func TestShortNewlyForkedFastSyncingSetHeadWithSnapshots(t *testing.T) { + testShortNewlyForkedFastSyncingSetHead(t, true) +} + +func testShortNewlyForkedFastSyncingSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 (HEAD) // └->S1->S2->S3->S4->S5->S6->S7->S8 @@ -528,7 +571,7 @@ func TestShortNewlyForkedFastSyncingSetHead(t *testing.T) { expHeadHeader: 7, expHeadFastBlock: 7, expHeadBlock: 0, - }) + }, snapshots) } // Tests a sethead for a short canonical chain and a longer side chain, where a @@ -541,7 +584,10 @@ func TestShortNewlyForkedFastSyncingSetHead(t *testing.T) { // The side chain could be left to be if the fork point was before the new head // we are deleting to, but it would be exceedingly hard to detect that case and // properly handle it, so we'll trade extra work in exchange for simpler code. -func TestShortReorgedSetHead(t *testing.T) { +func TestShortReorgedSetHead(t *testing.T) { testShortReorgedSetHead(t, false) } +func TestShortReorgedSetHeadWithSnapshots(t *testing.T) { testShortReorgedSetHead(t, true) } + +func testShortReorgedSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 @@ -574,7 +620,7 @@ func TestShortReorgedSetHead(t *testing.T) { expHeadHeader: 7, expHeadFastBlock: 7, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a short canonical chain and a longer side chain, where @@ -589,6 +635,13 @@ func TestShortReorgedSetHead(t *testing.T) { // we are deleting to, but it would be exceedingly hard to detect that case and // properly handle it, so we'll trade extra work in exchange for simpler code. func TestShortReorgedFastSyncedSetHead(t *testing.T) { + testShortReorgedFastSyncedSetHead(t, false) +} +func TestShortReorgedFastSyncedSetHeadWithSnapshots(t *testing.T) { + testShortReorgedFastSyncedSetHead(t, true) +} + +func testShortReorgedFastSyncedSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 @@ -621,7 +674,7 @@ func TestShortReorgedFastSyncedSetHead(t *testing.T) { expHeadHeader: 7, expHeadFastBlock: 7, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a short canonical chain and a longer side chain, where @@ -634,6 +687,13 @@ func TestShortReorgedFastSyncedSetHead(t *testing.T) { // we are deleting to, but it would be exceedingly hard to detect that case and // properly handle it, so we'll trade extra work in exchange for simpler code. func TestShortReorgedFastSyncingSetHead(t *testing.T) { + testShortReorgedFastSyncingSetHead(t, false) +} +func TestShortReorgedFastSyncingSetHeadWithSnapshots(t *testing.T) { + testShortReorgedFastSyncingSetHead(t, true) +} + +func testShortReorgedFastSyncingSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 @@ -666,7 +726,7 @@ func TestShortReorgedFastSyncingSetHead(t *testing.T) { expHeadHeader: 7, expHeadFastBlock: 7, expHeadBlock: 0, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks where a recent @@ -675,7 +735,10 @@ func TestShortReorgedFastSyncingSetHead(t *testing.T) { // to the committed block. Everything above the sethead point should be deleted. // In between the committed block and the requested head the data can remain as // "fast sync" data to avoid redownloading it. -func TestLongShallowSetHead(t *testing.T) { +func TestLongShallowSetHead(t *testing.T) { testLongShallowSetHead(t, false) } +func TestLongShallowSetHeadWithSnapshots(t *testing.T) { testLongShallowSetHead(t, true) } + +func testLongShallowSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // @@ -711,7 +774,7 @@ func TestLongShallowSetHead(t *testing.T) { expHeadHeader: 6, expHeadFastBlock: 6, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks where a recent @@ -719,7 +782,10 @@ func TestLongShallowSetHead(t *testing.T) { // sethead was called. In this case we expect the full chain to be rolled back // to the committed block. Since the ancient limit was underflown, everything // needs to be deleted onwards to avoid creating a gap. -func TestLongDeepSetHead(t *testing.T) { +func TestLongDeepSetHead(t *testing.T) { testLongDeepSetHead(t, false) } +func TestLongDeepSetHeadWithSnapshots(t *testing.T) { testLongDeepSetHead(t, true) } + +func testLongDeepSetHead(t *testing.T, snapshots bool) { // Chain: // 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) // @@ -754,7 +820,7 @@ func TestLongDeepSetHead(t *testing.T) { expHeadHeader: 4, expHeadFastBlock: 4, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks where the fast @@ -764,6 +830,13 @@ func TestLongDeepSetHead(t *testing.T) { // deleted. In between the committed block and the requested head the data can // remain as "fast sync" data to avoid redownloading it. func TestLongFastSyncedShallowSetHead(t *testing.T) { + testLongFastSyncedShallowSetHead(t, false) +} +func TestLongFastSyncedShallowSetHeadWithSnapshots(t *testing.T) { + testLongFastSyncedShallowSetHead(t, true) +} + +func testLongFastSyncedShallowSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // @@ -799,7 +872,7 @@ func TestLongFastSyncedShallowSetHead(t *testing.T) { expHeadHeader: 6, expHeadFastBlock: 6, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks where the fast @@ -807,7 +880,10 @@ func TestLongFastSyncedShallowSetHead(t *testing.T) { // which sethead was called. In this case we expect the full chain to be rolled // back to the committed block. Since the ancient limit was underflown, everything // needs to be deleted onwards to avoid creating a gap. -func TestLongFastSyncedDeepSetHead(t *testing.T) { +func TestLongFastSyncedDeepSetHead(t *testing.T) { testLongFastSyncedDeepSetHead(t, false) } +func TestLongFastSyncedDeepSetHeadWithSnapshots(t *testing.T) { testLongFastSyncedDeepSetHead(t, true) } + +func testLongFastSyncedDeepSetHead(t *testing.T, snapshots bool) { // Chain: // 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) // @@ -842,7 +918,7 @@ func TestLongFastSyncedDeepSetHead(t *testing.T) { expHeadHeader: 4, expHeadFastBlock: 4, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks where the fast @@ -851,6 +927,13 @@ func TestLongFastSyncedDeepSetHead(t *testing.T) { // syncing and delete everything from the new head, since we can just pick up fast // syncing from there. func TestLongFastSyncingShallowSetHead(t *testing.T) { + testLongFastSyncingShallowSetHead(t, false) +} +func TestLongFastSyncingShallowSetHeadWithSnapshots(t *testing.T) { + testLongFastSyncingShallowSetHead(t, true) +} + +func testLongFastSyncingShallowSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // @@ -886,7 +969,7 @@ func TestLongFastSyncingShallowSetHead(t *testing.T) { expHeadHeader: 6, expHeadFastBlock: 6, expHeadBlock: 0, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks where the fast @@ -895,6 +978,13 @@ func TestLongFastSyncingShallowSetHead(t *testing.T) { // syncing and delete everything from the new head, since we can just pick up fast // syncing from there. func TestLongFastSyncingDeepSetHead(t *testing.T) { + testLongFastSyncingDeepSetHead(t, false) +} +func TestLongFastSyncingDeepSetHeadWithSnapshots(t *testing.T) { + testLongFastSyncingDeepSetHead(t, true) +} + +func testLongFastSyncingDeepSetHead(t *testing.T, snapshots bool) { // Chain: // 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) // @@ -929,7 +1019,7 @@ func TestLongFastSyncingDeepSetHead(t *testing.T) { expHeadHeader: 6, expHeadFastBlock: 6, expHeadBlock: 0, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a shorter side @@ -940,6 +1030,13 @@ func TestLongFastSyncingDeepSetHead(t *testing.T) { // can remain as "fast sync" data to avoid redownloading it. The side chain is nuked // by the freezer. func TestLongOldForkedShallowSetHead(t *testing.T) { + testLongOldForkedShallowSetHead(t, false) +} +func TestLongOldForkedShallowSetHeadWithSnapshots(t *testing.T) { + testLongOldForkedShallowSetHead(t, true) +} + +func testLongOldForkedShallowSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->S1->S2->S3 @@ -976,7 +1073,7 @@ func TestLongOldForkedShallowSetHead(t *testing.T) { expHeadHeader: 6, expHeadFastBlock: 6, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a shorter side @@ -985,7 +1082,10 @@ func TestLongOldForkedShallowSetHead(t *testing.T) { // chain to be rolled back to the committed block. Since the ancient limit was // underflown, everything needs to be deleted onwards to avoid creating a gap. The // side chain is nuked by the freezer. -func TestLongOldForkedDeepSetHead(t *testing.T) { +func TestLongOldForkedDeepSetHead(t *testing.T) { testLongOldForkedDeepSetHead(t, false) } +func TestLongOldForkedDeepSetHeadWithSnapshots(t *testing.T) { testLongOldForkedDeepSetHead(t, true) } + +func testLongOldForkedDeepSetHead(t *testing.T, snapshots bool) { // Chain: // 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) // └->S1->S2->S3 @@ -1021,7 +1121,7 @@ func TestLongOldForkedDeepSetHead(t *testing.T) { expHeadHeader: 4, expHeadFastBlock: 4, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a shorter @@ -1033,6 +1133,13 @@ func TestLongOldForkedDeepSetHead(t *testing.T) { // requested head the data can remain as "fast sync" data to avoid redownloading // it. The side chain is nuked by the freezer. func TestLongOldForkedFastSyncedShallowSetHead(t *testing.T) { + testLongOldForkedFastSyncedShallowSetHead(t, false) +} +func TestLongOldForkedFastSyncedShallowSetHeadWithSnapshots(t *testing.T) { + testLongOldForkedFastSyncedShallowSetHead(t, true) +} + +func testLongOldForkedFastSyncedShallowSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->S1->S2->S3 @@ -1069,7 +1176,7 @@ func TestLongOldForkedFastSyncedShallowSetHead(t *testing.T) { expHeadHeader: 6, expHeadFastBlock: 6, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a shorter @@ -1080,6 +1187,13 @@ func TestLongOldForkedFastSyncedShallowSetHead(t *testing.T) { // underflown, everything needs to be deleted onwards to avoid creating a gap. The // side chain is nuked by the freezer. func TestLongOldForkedFastSyncedDeepSetHead(t *testing.T) { + testLongOldForkedFastSyncedDeepSetHead(t, false) +} +func TestLongOldForkedFastSyncedDeepSetHeadWithSnapshots(t *testing.T) { + testLongOldForkedFastSyncedDeepSetHead(t, true) +} + +func testLongOldForkedFastSyncedDeepSetHead(t *testing.T, snapshots bool) { // Chain: // 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) // └->S1->S2->S3 @@ -1115,7 +1229,7 @@ func TestLongOldForkedFastSyncedDeepSetHead(t *testing.T) { expHeadHeader: 4, expHeadFastBlock: 4, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a shorter @@ -1126,6 +1240,13 @@ func TestLongOldForkedFastSyncedDeepSetHead(t *testing.T) { // just pick up fast syncing from there. The side chain is completely nuked by the // freezer. func TestLongOldForkedFastSyncingShallowSetHead(t *testing.T) { + testLongOldForkedFastSyncingShallowSetHead(t, false) +} +func TestLongOldForkedFastSyncingShallowSetHeadWithSnapshots(t *testing.T) { + testLongOldForkedFastSyncingShallowSetHead(t, true) +} + +func testLongOldForkedFastSyncingShallowSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->S1->S2->S3 @@ -1162,7 +1283,7 @@ func TestLongOldForkedFastSyncingShallowSetHead(t *testing.T) { expHeadHeader: 6, expHeadFastBlock: 6, expHeadBlock: 0, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a shorter @@ -1173,6 +1294,13 @@ func TestLongOldForkedFastSyncingShallowSetHead(t *testing.T) { // just pick up fast syncing from there. The side chain is completely nuked by the // freezer. func TestLongOldForkedFastSyncingDeepSetHead(t *testing.T) { + testLongOldForkedFastSyncingDeepSetHead(t, false) +} +func TestLongOldForkedFastSyncingDeepSetHeadWithSnapshots(t *testing.T) { + testLongOldForkedFastSyncingDeepSetHead(t, true) +} + +func testLongOldForkedFastSyncingDeepSetHead(t *testing.T, snapshots bool) { // Chain: // 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) // └->S1->S2->S3 @@ -1208,7 +1336,7 @@ func TestLongOldForkedFastSyncingDeepSetHead(t *testing.T) { expHeadHeader: 6, expHeadFastBlock: 6, expHeadBlock: 0, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a shorter @@ -1217,6 +1345,13 @@ func TestLongOldForkedFastSyncingDeepSetHead(t *testing.T) { // chain is above the committed block. In this case the freezer will delete the // sidechain since it's dangling, reverting to TestLongShallowSetHead. func TestLongNewerForkedShallowSetHead(t *testing.T) { + testLongNewerForkedShallowSetHead(t, false) +} +func TestLongNewerForkedShallowSetHeadWithSnapshots(t *testing.T) { + testLongNewerForkedShallowSetHead(t, true) +} + +func testLongNewerForkedShallowSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 @@ -1253,7 +1388,7 @@ func TestLongNewerForkedShallowSetHead(t *testing.T) { expHeadHeader: 6, expHeadFastBlock: 6, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a shorter @@ -1262,6 +1397,13 @@ func TestLongNewerForkedShallowSetHead(t *testing.T) { // chain is above the committed block. In this case the freezer will delete the // sidechain since it's dangling, reverting to TestLongDeepSetHead. func TestLongNewerForkedDeepSetHead(t *testing.T) { + testLongNewerForkedDeepSetHead(t, false) +} +func TestLongNewerForkedDeepSetHeadWithSnapshots(t *testing.T) { + testLongNewerForkedDeepSetHead(t, true) +} + +func testLongNewerForkedDeepSetHead(t *testing.T, snapshots bool) { // Chain: // 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) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 @@ -1297,7 +1439,7 @@ func TestLongNewerForkedDeepSetHead(t *testing.T) { expHeadHeader: 4, expHeadFastBlock: 4, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a shorter @@ -1306,6 +1448,13 @@ func TestLongNewerForkedDeepSetHead(t *testing.T) { // the side chain is above the committed block. In this case the freezer will delete // the sidechain since it's dangling, reverting to TestLongFastSyncedShallowSetHead. func TestLongNewerForkedFastSyncedShallowSetHead(t *testing.T) { + testLongNewerForkedFastSyncedShallowSetHead(t, false) +} +func TestLongNewerForkedFastSyncedShallowSetHeadWithSnapshots(t *testing.T) { + testLongNewerForkedFastSyncedShallowSetHead(t, true) +} + +func testLongNewerForkedFastSyncedShallowSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 @@ -1342,7 +1491,7 @@ func TestLongNewerForkedFastSyncedShallowSetHead(t *testing.T) { expHeadHeader: 6, expHeadFastBlock: 6, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a shorter @@ -1351,6 +1500,13 @@ func TestLongNewerForkedFastSyncedShallowSetHead(t *testing.T) { // the side chain is above the committed block. In this case the freezer will delete // the sidechain since it's dangling, reverting to TestLongFastSyncedDeepSetHead. func TestLongNewerForkedFastSyncedDeepSetHead(t *testing.T) { + testLongNewerForkedFastSyncedDeepSetHead(t, false) +} +func TestLongNewerForkedFastSyncedDeepSetHeadWithSnapshots(t *testing.T) { + testLongNewerForkedFastSyncedDeepSetHead(t, true) +} + +func testLongNewerForkedFastSyncedDeepSetHead(t *testing.T, snapshots bool) { // Chain: // 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) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 @@ -1386,7 +1542,7 @@ func TestLongNewerForkedFastSyncedDeepSetHead(t *testing.T) { expHeadHeader: 4, expHeadFastBlock: 4, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a shorter @@ -1395,6 +1551,13 @@ func TestLongNewerForkedFastSyncedDeepSetHead(t *testing.T) { // chain is above the committed block. In this case the freezer will delete the // sidechain since it's dangling, reverting to TestLongFastSyncinghallowSetHead. func TestLongNewerForkedFastSyncingShallowSetHead(t *testing.T) { + testLongNewerForkedFastSyncingShallowSetHead(t, false) +} +func TestLongNewerForkedFastSyncingShallowSetHeadWithSnapshots(t *testing.T) { + testLongNewerForkedFastSyncingShallowSetHead(t, true) +} + +func testLongNewerForkedFastSyncingShallowSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 @@ -1431,7 +1594,7 @@ func TestLongNewerForkedFastSyncingShallowSetHead(t *testing.T) { expHeadHeader: 6, expHeadFastBlock: 6, expHeadBlock: 0, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a shorter @@ -1440,6 +1603,13 @@ func TestLongNewerForkedFastSyncingShallowSetHead(t *testing.T) { // chain is above the committed block. In this case the freezer will delete the // sidechain since it's dangling, reverting to TestLongFastSyncingDeepSetHead. func TestLongNewerForkedFastSyncingDeepSetHead(t *testing.T) { + testLongNewerForkedFastSyncingDeepSetHead(t, false) +} +func TestLongNewerForkedFastSyncingDeepSetHeadWithSnapshots(t *testing.T) { + testLongNewerForkedFastSyncingDeepSetHead(t, true) +} + +func testLongNewerForkedFastSyncingDeepSetHead(t *testing.T, snapshots bool) { // Chain: // 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) // └->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 @@ -1475,14 +1645,17 @@ func TestLongNewerForkedFastSyncingDeepSetHead(t *testing.T) { expHeadHeader: 6, expHeadFastBlock: 6, expHeadBlock: 0, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a longer side // chain, where a recent block - newer than the ancient limit - was already committed // to disk and then sethead was called. In this case the freezer will delete the // sidechain since it's dangling, reverting to TestLongShallowSetHead. -func TestLongReorgedShallowSetHead(t *testing.T) { +func TestLongReorgedShallowSetHead(t *testing.T) { testLongReorgedShallowSetHead(t, false) } +func TestLongReorgedShallowSetHeadWithSnapshots(t *testing.T) { testLongReorgedShallowSetHead(t, true) } + +func testLongReorgedShallowSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->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 @@ -1519,14 +1692,17 @@ func TestLongReorgedShallowSetHead(t *testing.T) { expHeadHeader: 6, expHeadFastBlock: 6, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a longer side // chain, where a recent block - older than the ancient limit - was already committed // to disk and then sethead was called. In this case the freezer will delete the // sidechain since it's dangling, reverting to TestLongDeepSetHead. -func TestLongReorgedDeepSetHead(t *testing.T) { +func TestLongReorgedDeepSetHead(t *testing.T) { testLongReorgedDeepSetHead(t, false) } +func TestLongReorgedDeepSetHeadWithSnapshots(t *testing.T) { testLongReorgedDeepSetHead(t, true) } + +func testLongReorgedDeepSetHead(t *testing.T, snapshots bool) { // Chain: // 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) // └->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 @@ -1562,7 +1738,7 @@ func TestLongReorgedDeepSetHead(t *testing.T) { expHeadHeader: 4, expHeadFastBlock: 4, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a longer @@ -1571,6 +1747,13 @@ func TestLongReorgedDeepSetHead(t *testing.T) { // freezer will delete the sidechain since it's dangling, reverting to // TestLongFastSyncedShallowSetHead. func TestLongReorgedFastSyncedShallowSetHead(t *testing.T) { + testLongReorgedFastSyncedShallowSetHead(t, false) +} +func TestLongReorgedFastSyncedShallowSetHeadWithSnapshots(t *testing.T) { + testLongReorgedFastSyncedShallowSetHead(t, true) +} + +func testLongReorgedFastSyncedShallowSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->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 @@ -1607,7 +1790,7 @@ func TestLongReorgedFastSyncedShallowSetHead(t *testing.T) { expHeadHeader: 6, expHeadFastBlock: 6, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a longer @@ -1616,6 +1799,13 @@ func TestLongReorgedFastSyncedShallowSetHead(t *testing.T) { // freezer will delete the sidechain since it's dangling, reverting to // TestLongFastSyncedDeepSetHead. func TestLongReorgedFastSyncedDeepSetHead(t *testing.T) { + testLongReorgedFastSyncedDeepSetHead(t, false) +} +func TestLongReorgedFastSyncedDeepSetHeadWithSnapshots(t *testing.T) { + testLongReorgedFastSyncedDeepSetHead(t, true) +} + +func testLongReorgedFastSyncedDeepSetHead(t *testing.T, snapshots bool) { // Chain: // 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) // └->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 @@ -1651,7 +1841,7 @@ func TestLongReorgedFastSyncedDeepSetHead(t *testing.T) { expHeadHeader: 4, expHeadFastBlock: 4, expHeadBlock: 4, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a longer @@ -1661,6 +1851,13 @@ func TestLongReorgedFastSyncedDeepSetHead(t *testing.T) { // head, since we can just pick up fast syncing from there. The side chain is // completely nuked by the freezer. func TestLongReorgedFastSyncingShallowSetHead(t *testing.T) { + testLongReorgedFastSyncingShallowSetHead(t, false) +} +func TestLongReorgedFastSyncingShallowSetHeadWithSnapshots(t *testing.T) { + testLongReorgedFastSyncingShallowSetHead(t, true) +} + +func testLongReorgedFastSyncingShallowSetHead(t *testing.T, snapshots bool) { // Chain: // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) // └->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 @@ -1697,7 +1894,7 @@ func TestLongReorgedFastSyncingShallowSetHead(t *testing.T) { expHeadHeader: 6, expHeadFastBlock: 6, expHeadBlock: 0, - }) + }, snapshots) } // Tests a sethead for a long canonical chain with frozen blocks and a longer @@ -1707,6 +1904,13 @@ func TestLongReorgedFastSyncingShallowSetHead(t *testing.T) { // head, since we can just pick up fast syncing from there. The side chain is // completely nuked by the freezer. func TestLongReorgedFastSyncingDeepSetHead(t *testing.T) { + testLongReorgedFastSyncingDeepSetHead(t, false) +} +func TestLongReorgedFastSyncingDeepSetHeadWithSnapshots(t *testing.T) { + testLongReorgedFastSyncingDeepSetHead(t, true) +} + +func testLongReorgedFastSyncingDeepSetHead(t *testing.T, snapshots bool) { // Chain: // 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) // └->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 @@ -1742,10 +1946,10 @@ func TestLongReorgedFastSyncingDeepSetHead(t *testing.T) { expHeadHeader: 6, expHeadFastBlock: 6, expHeadBlock: 0, - }) + }, snapshots) } -func testSetHead(t *testing.T, tt *rewindTest) { +func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) { // It's hard to follow the test case, visualize the input // log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) // fmt.Println(tt.dump(false)) @@ -1765,16 +1969,20 @@ func testSetHead(t *testing.T, tt *rewindTest) { // Initialize a fresh chain var ( - genesis = new(Genesis).MustCommit(db) - engine = ethash.NewFullFaker() - cacheConfig = &CacheConfig{ + genesis = new(Genesis).MustCommit(db) + engine = ethash.NewFullFaker() + config = &CacheConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, SnapshotLimit: 0, // Disable snapshot } ) - chain, err := NewBlockChain(db, cacheConfig, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) + if snapshots { + config.SnapshotLimit = 256 + config.SnapshotWait = true + } + chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to create chain: %v", err) } @@ -1797,6 +2005,11 @@ func testSetHead(t *testing.T, tt *rewindTest) { } if tt.commitBlock > 0 { chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil) + if snapshots { + if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { + t.Fatalf("Failed to flatten snapshots: %v", err) + } + } } if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil { t.Fatalf("Failed to import canonical chain tail: %v", err)