@@ -4,6 +4,7 @@ package whitelist
44import (
55 "errors"
66 "fmt"
7+ "math"
78 "math/big"
89 "reflect"
910 "sort"
@@ -1533,3 +1534,61 @@ func TestForkCorrectness(t *testing.T) {
15331534 require .Equal (t , chain3 [1 ].Number .Uint64 (), s .lastValidForkBlock , "expected last known valid block to be unchanged" )
15341535 })
15351536}
1537+
1538+ // TestNewServiceDiscardsInvalidLockedMilestone verifies that NewService detects and clears
1539+ // a LockedMilestoneNumber that is beyond the safe range when loading from DB.
1540+ func TestNewServiceDiscardsInvalidLockedMilestone (t * testing.T ) {
1541+ db := rawdb .NewMemoryDatabase ()
1542+
1543+ // Write a locked milestone with an unreachable block number to the DB,
1544+ // simulating a previously corrupted state.
1545+ lockedIDs := map [string ]struct {}{"bad-id" : {}}
1546+ err := rawdb .WriteLockField (db , true , math .MaxUint64 , common.Hash {0xAB }, lockedIDs )
1547+ require .NoError (t , err )
1548+
1549+ // NewService should detect the out-of-range value and clear it.
1550+ svc := NewService (db , false , 0 )
1551+
1552+ m , ok := svc .milestoneService .(* milestone )
1553+ require .True (t , ok )
1554+
1555+ m .finality .RLock ()
1556+ defer m .finality .RUnlock ()
1557+
1558+ require .False (t , m .Locked , "expected Locked to be false after discarding invalid milestone" )
1559+ require .Equal (t , uint64 (0 ), m .LockedMilestoneNumber , "expected LockedMilestoneNumber to be reset to 0" )
1560+ require .Equal (t , common.Hash {}, m .LockedMilestoneHash , "expected LockedMilestoneHash to be reset" )
1561+ require .Empty (t , m .LockedMilestoneIDs , "expected LockedMilestoneIDs to be cleared" )
1562+
1563+ // Verify the corrected state was persisted to DB.
1564+ locked , lockedNum , lockedHash , ids , err := rawdb .ReadLockField (db )
1565+ require .NoError (t , err )
1566+ require .False (t , locked )
1567+ require .Equal (t , uint64 (0 ), lockedNum )
1568+ require .Equal (t , common.Hash {}, lockedHash )
1569+ require .Empty (t , ids )
1570+ }
1571+
1572+ // TestNewServicePreservesValidLockedMilestone verifies that NewService does not
1573+ // interfere with a legitimate locked milestone stored in DB.
1574+ func TestNewServicePreservesValidLockedMilestone (t * testing.T ) {
1575+ db := rawdb .NewMemoryDatabase ()
1576+
1577+ expectedHash := common.Hash {0x42 }
1578+ lockedIDs := map [string ]struct {}{"valid-id" : {}}
1579+ err := rawdb .WriteLockField (db , true , 1000 , expectedHash , lockedIDs )
1580+ require .NoError (t , err )
1581+
1582+ svc := NewService (db , false , 0 )
1583+
1584+ m , ok := svc .milestoneService .(* milestone )
1585+ require .True (t , ok )
1586+
1587+ m .finality .RLock ()
1588+ defer m .finality .RUnlock ()
1589+
1590+ require .True (t , m .Locked , "expected Locked to remain true for valid milestone" )
1591+ require .Equal (t , uint64 (1000 ), m .LockedMilestoneNumber )
1592+ require .Equal (t , expectedHash , m .LockedMilestoneHash )
1593+ require .Len (t , m .LockedMilestoneIDs , 1 )
1594+ }
0 commit comments