Skip to content

Commit 87130e2

Browse files
tcoratgerclaude
andauthored
refactor(node): make fork required in _try_load_store_from_database (leanEthereum#987)
The store loader always receives a concrete fork from its only production caller, which asserts the fork is an LstarSpec before calling. The optional, defaulted fork parameter and its None branch were dead: nothing ever fell back to the base Store class. Make fork a required positional parameter, drop the None default, and remove the None-handling branch so the store class always comes from the fork. Update all test callers to pass the fork explicitly. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 762a0a4 commit 87130e2

2 files changed

Lines changed: 27 additions & 11 deletions

File tree

src/lean_spec/node/node.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ def from_genesis(cls, config: NodeConfig) -> Node:
226226
# If the database contains valid state, resume from there.
227227
# Otherwise, fall through to genesis initialization.
228228
store = cls._try_load_store_from_database(
229-
database, validator_index, config.genesis_time, config.time_fn, fork
229+
database, validator_index, fork, config.genesis_time, config.time_fn
230230
)
231231

232232
# An explicit anchor wins over genesis synthesis but loses to the database.
@@ -375,9 +375,9 @@ async def publish_and_process_block(block: SignedBlock) -> None:
375375
def _try_load_store_from_database(
376376
database: Database | None,
377377
validator_index: ValidatorIndex | None,
378+
fork: ForkProtocol,
378379
genesis_time: Uint64 | None = None,
379380
time_fn: Callable[[], float] = time.time,
380-
fork: ForkProtocol | None = None,
381381
) -> Store | None:
382382
"""
383383
Try to load forkchoice store from existing database state.
@@ -393,9 +393,9 @@ def _try_load_store_from_database(
393393
Args:
394394
database: Database to load from.
395395
validator_index: Validator index for the store instance.
396+
fork: Fork specification for store construction.
396397
genesis_time: Unix timestamp of genesis (slot 0).
397398
time_fn: Wall-clock time source.
398-
fork: Fork specification for store construction.
399399
400400
Returns:
401401
Loaded Store or None if no valid state exists.
@@ -443,8 +443,7 @@ def _try_load_store_from_database(
443443
#
444444
# The store starts with just the head block and state.
445445
# Additional blocks can be loaded on demand or via sync.
446-
store_cls = fork.store_class if fork is not None else Store
447-
return store_cls(
446+
return fork.store_class(
448447
time=Interval(store_time),
449448
config=head_state.config,
450449
head=head_root,

tests/node/test_node.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,21 +174,28 @@ class TestDatabaseLoading:
174174

175175
def test_returns_none_when_no_database(self) -> None:
176176
"""No database returns None."""
177-
assert Node._try_load_store_from_database(None, validator_index=None) is None
177+
assert (
178+
Node._try_load_store_from_database(None, validator_index=None, fork=LstarSpec()) is None
179+
)
178180

179181
def test_returns_none_when_no_head_root(self) -> None:
180182
"""Empty database returns None."""
181183
empty_db = SQLiteDatabase(":memory:", State, Block)
182184

183-
assert Node._try_load_store_from_database(empty_db, validator_index=None) is None
185+
assert (
186+
Node._try_load_store_from_database(empty_db, validator_index=None, fork=LstarSpec())
187+
is None
188+
)
184189

185190
def test_returns_none_when_block_missing(self) -> None:
186191
"""A head root pointing at no stored block returns None."""
187192
head_root, _, _, _ = _make_block_state_checkpoint()
188193
db = SQLiteDatabase(":memory:", State, Block)
189194
db.put_head_root(head_root)
190195

191-
assert Node._try_load_store_from_database(db, validator_index=None) is None
196+
assert (
197+
Node._try_load_store_from_database(db, validator_index=None, fork=LstarSpec()) is None
198+
)
192199

193200
def test_returns_none_when_state_missing(self) -> None:
194201
"""A head root with a stored block but no stored state returns None."""
@@ -197,7 +204,9 @@ def test_returns_none_when_state_missing(self) -> None:
197204
db.put_block(block, head_root)
198205
db.put_head_root(head_root)
199206

200-
assert Node._try_load_store_from_database(db, validator_index=None) is None
207+
assert (
208+
Node._try_load_store_from_database(db, validator_index=None, fork=LstarSpec()) is None
209+
)
201210

202211
def test_returns_none_when_justified_missing(self) -> None:
203212
"""A populated head with no justified checkpoint returns None."""
@@ -207,7 +216,9 @@ def test_returns_none_when_justified_missing(self) -> None:
207216
db.put_state(state, head_root)
208217
db.put_head_root(head_root)
209218

210-
assert Node._try_load_store_from_database(db, validator_index=None) is None
219+
assert (
220+
Node._try_load_store_from_database(db, validator_index=None, fork=LstarSpec()) is None
221+
)
211222

212223
def test_returns_none_when_finalized_missing(self) -> None:
213224
"""A populated head with a justified but no finalized checkpoint returns None."""
@@ -218,7 +229,9 @@ def test_returns_none_when_finalized_missing(self) -> None:
218229
db.put_head_root(head_root)
219230
db.put_justified_checkpoint(checkpoint)
220231

221-
assert Node._try_load_store_from_database(db, validator_index=None) is None
232+
assert (
233+
Node._try_load_store_from_database(db, validator_index=None, fork=LstarSpec()) is None
234+
)
222235

223236
def test_successful_load_uses_wall_clock_time(self) -> None:
224237
"""Store time uses wall clock when it exceeds block-based time."""
@@ -230,6 +243,7 @@ def test_successful_load_uses_wall_clock_time(self) -> None:
230243
store = Node._try_load_store_from_database(
231244
db,
232245
validator_index=ValidatorIndex(0),
246+
fork=LstarSpec(),
233247
genesis_time=GENESIS_TIME,
234248
time_fn=lambda: wall_time,
235249
)
@@ -253,6 +267,7 @@ def test_load_uses_block_time_when_wall_clock_behind(self) -> None:
253267
store = Node._try_load_store_from_database(
254268
db,
255269
validator_index=ValidatorIndex(0),
270+
fork=LstarSpec(),
256271
genesis_time=GENESIS_TIME,
257272
time_fn=lambda: wall_time,
258273
)
@@ -389,6 +404,7 @@ def test_falls_back_to_database_genesis_time(self) -> None:
389404
store = Node._try_load_store_from_database(
390405
db,
391406
validator_index=None,
407+
fork=LstarSpec(),
392408
genesis_time=None,
393409
time_fn=lambda: wall_time,
394410
)
@@ -409,6 +425,7 @@ def test_zero_genesis_time_when_database_returns_none(self) -> None:
409425
store = Node._try_load_store_from_database(
410426
db,
411427
validator_index=None,
428+
fork=LstarSpec(),
412429
genesis_time=None,
413430
time_fn=lambda: wall_time,
414431
)

0 commit comments

Comments
 (0)