@@ -57,7 +57,7 @@ func TestCache_RestoreFromStore_EmptyChain(t *testing.T) {
5757 st := testMemStore (t )
5858
5959 c := NewCache (st , "hdr/" )
60- require .NoError (t , c .RestoreFromStore (context .Background ()))
60+ require .NoError (t , c .RestoreFromStore (context .Background (), 0 ))
6161
6262 assert .Equal (t , 0 , c .daIncludedLen (), "no entries expected on empty chain" )
6363 assert .Equal (t , uint64 (0 ), c .daHeight ())
@@ -75,7 +75,7 @@ func TestCache_RestoreFromStore_FullyFinalized(t *testing.T) {
7575 writeSnapshot (t , st , "hdr/" , nil )
7676
7777 c := NewCache (st , "hdr/" )
78- require .NoError (t , c .RestoreFromStore (ctx ))
78+ require .NoError (t , c .RestoreFromStore (ctx , 0 ))
7979
8080 assert .Equal (t , 0 , c .daIncludedLen (), "no in-flight entries expected" )
8181 assert .Equal (t , uint64 (0 ), c .daHeight (), "no in-flight entries means daHeight is 0" )
@@ -93,7 +93,7 @@ func TestCache_RestoreFromStore_InFlightWindow(t *testing.T) {
9393 })
9494
9595 c := NewCache (st , "hdr/" )
96- require .NoError (t , c .RestoreFromStore (ctx ))
96+ require .NoError (t , c .RestoreFromStore (ctx , 0 ))
9797
9898 assert .Equal (t , 2 , c .daIncludedLen (), "exactly the in-flight snapshot entries should be loaded" )
9999 assert .Equal (t , uint64 (14 ), c .daHeight (), "maxDAHeight should reflect the highest in-flight DA height" )
@@ -118,7 +118,7 @@ func TestCache_RestoreFromStore_SingleEntry(t *testing.T) {
118118 })
119119
120120 c := NewCache (st , "hdr/" )
121- require .NoError (t , c .RestoreFromStore (ctx ))
121+ require .NoError (t , c .RestoreFromStore (ctx , 0 ))
122122
123123 assert .Equal (t , 1 , c .daIncludedLen (), "one entry should be in-flight" )
124124 assert .Equal (t , uint64 (20 ), c .daHeight ())
@@ -131,7 +131,7 @@ func TestCache_RestoreFromStore_SingleEntry(t *testing.T) {
131131
132132func TestCache_RestoreFromStore_NilStore (t * testing.T ) {
133133 c := NewCache (nil , "" )
134- require .NoError (t , c .RestoreFromStore (context .Background ()))
134+ require .NoError (t , c .RestoreFromStore (context .Background (), 0 ))
135135 assert .Equal (t , 0 , c .daIncludedLen ())
136136}
137137
@@ -147,7 +147,7 @@ func TestCache_RestoreFromStore_PlaceholderOverwrittenByRealHash(t *testing.T) {
147147 })
148148
149149 c := NewCache (st , "hdr/" )
150- require .NoError (t , c .RestoreFromStore (ctx ))
150+ require .NoError (t , c .RestoreFromStore (ctx , 0 ))
151151
152152 assert .Equal (t , 1 , c .daIncludedLen (), "one placeholder for height 3" )
153153
@@ -176,7 +176,7 @@ func TestCache_RestoreFromStore_RoundTrip(t *testing.T) {
176176 require .NoError (t , c1 .SaveToStore (ctx ))
177177
178178 c2 := NewCache (st , "rt/" )
179- require .NoError (t , c2 .RestoreFromStore (ctx ))
179+ require .NoError (t , c2 .RestoreFromStore (ctx , 0 ))
180180
181181 assert .Equal (t , 2 , c2 .daIncludedLen (), "only non-deleted entries should be restored" )
182182 assert .Equal (t , uint64 (30 ), c2 .daHeight ())
@@ -189,6 +189,42 @@ func TestCache_RestoreFromStore_RoundTrip(t *testing.T) {
189189 assert .True (t , ok , "height 3 placeholder should exist" )
190190}
191191
192+ // TestCache_RestoreFromStore_SkipsFinalizedEntries verifies that snapshot
193+ // entries at or below the finalized height are not installed as placeholders
194+ // (a stale snapshot from a previous graceful shutdown can contain heights the
195+ // inclusion loop has already advanced past), while maxDAHeight still accounts
196+ // for them.
197+ func TestCache_RestoreFromStore_SkipsFinalizedEntries (t * testing.T ) {
198+ st := testMemStore (t )
199+ ctx := context .Background ()
200+
201+ writeSnapshot (t , st , "hdr/" , []snapshotEntry {
202+ {blockHeight : 3 , daHeight : 10 },
203+ {blockHeight : 4 , daHeight : 11 },
204+ {blockHeight : 5 , daHeight : 12 },
205+ })
206+
207+ c := NewCache (st , "hdr/" )
208+ require .NoError (t , c .RestoreFromStore (ctx , 4 ))
209+
210+ assert .Equal (t , 1 , c .daIncludedLen (), "only entries above the finalized height should be installed" )
211+ assert .Equal (t , uint64 (12 ), c .daHeight (), "maxDAHeight should include skipped entries" )
212+
213+ _ , ok := c .getDAIncludedByHeight (3 )
214+ assert .False (t , ok , "height 3 is finalized, must not be restored" )
215+ _ , ok = c .getDAIncludedByHeight (4 )
216+ assert .False (t , ok , "height 4 is finalized, must not be restored" )
217+ daH , ok := c .getDAIncludedByHeight (5 )
218+ require .True (t , ok , "height 5 is in-flight, must be restored" )
219+ assert .Equal (t , uint64 (12 ), daH )
220+
221+ // A fully-stale snapshot restores nothing but still seeds maxDAHeight.
222+ c2 := NewCache (st , "hdr/" )
223+ require .NoError (t , c2 .RestoreFromStore (ctx , 10 ))
224+ assert .Equal (t , 0 , c2 .daIncludedLen (), "all entries finalized, nothing restored" )
225+ assert .Equal (t , uint64 (12 ), c2 .daHeight ())
226+ }
227+
192228// ---------------------------------------------------------------------------
193229// Basic operations
194230// ---------------------------------------------------------------------------
@@ -306,7 +342,7 @@ func TestCache_NoPlaceholderLeakAfterRefire(t *testing.T) {
306342 require .NoError (t , c1 .SaveToStore (ctx ))
307343
308344 c2 := NewCache (st , "pfx/" )
309- require .NoError (t , c2 .RestoreFromStore (ctx ))
345+ require .NoError (t , c2 .RestoreFromStore (ctx , 0 ))
310346
311347 placeholder := HeightPlaceholderKey ("pfx/" , 3 )
312348 _ , placeholderPresent := c2 .getDAIncluded (placeholder )
@@ -344,7 +380,7 @@ func TestCache_RestartIdempotent(t *testing.T) {
344380
345381 for restart := 1 ; restart <= 3 ; restart ++ {
346382 cR := NewCache (st , "pfx/" )
347- require .NoError (t , cR .RestoreFromStore (ctx ), "restart %d: RestoreFromStore" , restart )
383+ require .NoError (t , cR .RestoreFromStore (ctx , 0 ), "restart %d: RestoreFromStore" , restart )
348384
349385 assert .Equal (t , 1 , cR .daIncludedLen (), "restart %d: one placeholder entry" , restart )
350386 assert .Equal (t , daH , cR .daHeight (), "restart %d: daHeight correct" , restart )
0 commit comments