Skip to content

Commit 08868e7

Browse files
tcoratgerclaude
andauthored
refactor(sync): inline make_default_block_processor as method (leanEthereum#731)
The factory existed only to capture `spec` in a closure for the SyncService.process_block field. SyncService already has self.spec, so the closure is unnecessary indirection. Inlines the body as _default_process_block(self, store, block) and binds it as the default in __post_init__. The process_block field stays as a legitimate test-injection point. Tests use it to substitute mock processors that exercise the metrics and database-persistence wrapper without requiring a full spec or state transition. Net: -8 lines, zero behavior change, no test updates needed. A reader of SyncService now finds the block-processing logic as a method on the class instead of a module-level factory closure. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent d0d0422 commit 08868e7

1 file changed

Lines changed: 27 additions & 35 deletions

File tree

src/lean_spec/subspecs/sync/service.py

Lines changed: 27 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -79,39 +79,6 @@ def _ancestor_set(blocks: dict[Bytes32, Block], head: Bytes32) -> set[Bytes32]:
7979
return seen
8080

8181

82-
def make_default_block_processor(
83-
spec: LstarSpec,
84-
) -> Callable[[Store, SignedBlock], Store]:
85-
"""
86-
Build a default block processor bound to the given spec.
87-
88-
Wraps the pure spec entry point with caller-side fork-choice telemetry.
89-
State transition and block processing timings are emitted by the spec
90-
itself through the observer, wired at node startup. Everything else
91-
here is derived by diffing pre- and post-stores.
92-
"""
93-
94-
def default_block_processor(store: Store, block: SignedBlock) -> Store:
95-
new_store = spec.on_block(store, block)
96-
97-
metrics.lean_head_slot.set(new_store.blocks[new_store.head].slot)
98-
metrics.lean_safe_target_slot.set(new_store.blocks[new_store.safe_target].slot)
99-
metrics.lean_latest_justified_slot.set(new_store.latest_justified.slot)
100-
metrics.lean_latest_finalized_slot.set(new_store.latest_finalized.slot)
101-
102-
if new_store.head != store.head:
103-
depth = len(
104-
_ancestor_set(new_store.blocks, store.head)
105-
- _ancestor_set(new_store.blocks, new_store.head)
106-
)
107-
metrics.lean_fork_choice_reorgs_total.inc()
108-
metrics.lean_fork_choice_reorg_depth.observe(depth)
109-
110-
return new_store
111-
112-
return default_block_processor
113-
114-
11582
async def _noop_publish_agg(signed_attestation: SignedAggregatedAttestation) -> None:
11683
"""No-op default for aggregated attestation publishing."""
11784

@@ -257,11 +224,11 @@ def set_publish_agg_fn(
257224

258225
def __post_init__(self) -> None:
259226
"""Initialize sync components."""
260-
# Bind the default processor to the injected spec when no override is provided.
227+
# Bind the default processor when no override is provided.
261228
#
262229
# Tests pass an explicit processor and skip this path.
263230
if self.process_block is None:
264-
self.process_block = make_default_block_processor(self.spec)
231+
self.process_block = self._default_process_block
265232

266233
self._init_components()
267234

@@ -298,6 +265,31 @@ def _init_components(self) -> None:
298265
process_block=self._process_block_wrapper,
299266
)
300267

268+
def _default_process_block(self, store: Store, block: SignedBlock) -> Store:
269+
"""Run the spec's block processor and emit forkchoice telemetry.
270+
271+
Wraps the pure spec entry point with caller-side metrics.
272+
State transition and block processing timings are emitted by the spec
273+
itself through the observer, wired at node startup.
274+
Everything below is derived by diffing pre- and post-stores.
275+
"""
276+
new_store = self.spec.on_block(store, block)
277+
278+
metrics.lean_head_slot.set(new_store.blocks[new_store.head].slot)
279+
metrics.lean_safe_target_slot.set(new_store.blocks[new_store.safe_target].slot)
280+
metrics.lean_latest_justified_slot.set(new_store.latest_justified.slot)
281+
metrics.lean_latest_finalized_slot.set(new_store.latest_finalized.slot)
282+
283+
if new_store.head != store.head:
284+
depth = len(
285+
_ancestor_set(new_store.blocks, store.head)
286+
- _ancestor_set(new_store.blocks, new_store.head)
287+
)
288+
metrics.lean_fork_choice_reorgs_total.inc()
289+
metrics.lean_fork_choice_reorg_depth.observe(depth)
290+
291+
return new_store
292+
301293
def _process_block_wrapper(
302294
self,
303295
store: Store,

0 commit comments

Comments
 (0)