77
88from __future__ import annotations
99
10+ from collections .abc import Generator
11+ from contextlib import contextmanager
1012from typing import TYPE_CHECKING , Protocol
1113
1214if TYPE_CHECKING :
1315 from lean_spec .subspecs .containers import Block , Checkpoint , State
1416 from lean_spec .subspecs .containers .attestation import AttestationData
1517 from lean_spec .subspecs .containers .slot import Slot
1618 from lean_spec .subspecs .containers .validator import ValidatorIndex
17- from lean_spec .types import Bytes32
19+ from lean_spec .types import Bytes32 , Uint64
1820
1921
2022class Database (Protocol ):
@@ -26,10 +28,11 @@ class Database(Protocol):
2628
2729 Storage Organization
2830 --------------------
29- - Blocks: Indexed by root hash
30- - States: Indexed by root hash
31+ - Blocks: Indexed by block root hash
32+ - States: Indexed by associated block root hash (not state root)
3133 - Checkpoints: Justified and finalized tracking
3234 - Attestations: Latest attestation per validator
35+ - State root index: Maps state roots to block roots
3336 """
3437
3538 # Block Operations
@@ -72,10 +75,10 @@ def has_block(self, root: Bytes32) -> bool:
7275
7376 def get_state (self , root : Bytes32 ) -> State | None :
7477 """
75- Retrieve a state by its root hash .
78+ Retrieve a state by its associated block root .
7679
7780 Args:
78- root: SSZ hash tree root of the state.
81+ root: Block root hash associated with this state.
7982
8083 Returns:
8184 State if found, None otherwise.
@@ -84,11 +87,11 @@ def get_state(self, root: Bytes32) -> State | None:
8487
8588 def put_state (self , state : State , root : Bytes32 ) -> None :
8689 """
87- Store a state with its root hash .
90+ Store a state indexed by its associated block root .
8891
8992 Args:
9093 state: State to store.
91- root: Pre-computed root hash (avoids recomputation) .
94+ root: Block root hash associated with this state .
9295 """
9396 ...
9497
@@ -97,7 +100,7 @@ def has_state(self, root: Bytes32) -> bool:
97100 Check if a state exists in storage.
98101
99102 Args:
100- root: SSZ hash tree root of the state.
103+ root: Block root hash associated with the state.
101104
102105 Returns:
103106 True if state exists.
@@ -223,6 +226,93 @@ def put_block_root_by_slot(self, slot: Slot, root: Bytes32) -> None:
223226 """
224227 ...
225228
229+ # State Root Index Operations
230+
231+ def get_block_root_by_state_root (self , state_root : Bytes32 ) -> Bytes32 | None :
232+ """
233+ Look up the block root associated with a state root.
234+
235+ Needed for checkpoint sync and API endpoints that query by state root.
236+
237+ Args:
238+ state_root: SSZ hash tree root of the state.
239+
240+ Returns:
241+ Associated block root, or None if not indexed.
242+ """
243+ ...
244+
245+ def put_block_root_by_state_root (self , state_root : Bytes32 , block_root : Bytes32 ) -> None :
246+ """
247+ Index a block root by the state root it produced.
248+
249+ Args:
250+ state_root: SSZ hash tree root of the post-state.
251+ block_root: Root of the block that produced this state.
252+ """
253+ ...
254+
255+ # Genesis Time
256+
257+ def get_genesis_time (self ) -> Uint64 | None :
258+ """
259+ Retrieve the stored genesis time.
260+
261+ Enables self-contained restarts without external genesis config.
262+
263+ Returns:
264+ Genesis time as Unix timestamp, or None if not set.
265+ """
266+ ...
267+
268+ def put_genesis_time (self , genesis_time : Uint64 ) -> None :
269+ """
270+ Store genesis time for future restarts.
271+
272+ Args:
273+ genesis_time: Unix timestamp of genesis (slot 0).
274+ """
275+ ...
276+
277+ # Transaction Control
278+
279+ def commit (self ) -> None :
280+ """
281+ Commit pending writes to durable storage.
282+
283+ All writes via put_* methods are buffered until commit() or batch_write().
284+ Callers must explicitly commit after writes.
285+ """
286+ ...
287+
288+ @contextmanager
289+ def batch_write (self ) -> Generator [None ]:
290+ """
291+ Context manager for atomic multi-write operations.
292+
293+ All writes within the block are committed atomically on exit.
294+ Rolls back on exception to prevent partial writes.
295+ """
296+ ...
297+
298+ # Pruning
299+
300+ def prune_before_slot (self , slot : Slot , keep_roots : frozenset [Bytes32 ]) -> int :
301+ """
302+ Remove blocks and states with slots strictly before the given slot.
303+
304+ Preserves entries whose roots are in keep_roots (e.g., the finalized block).
305+ Cleans up associated slot index entries.
306+
307+ Args:
308+ slot: Prune entries with slots strictly below this value.
309+ keep_roots: Roots to preserve regardless of slot.
310+
311+ Returns:
312+ Total number of entries pruned across all tables.
313+ """
314+ ...
315+
226316 # Lifecycle
227317
228318 def close (self ) -> None :
0 commit comments