refactor(forks): move fork-stable types to lean_spec.types (Stage 2 of #686)#695
Merged
tcoratger merged 1 commit intoMay 1, 2026
Conversation
…leanEthereum#686) Promote the data primitives whose shape is stable across the leanSpec fork chain out of the lstar fork package and into lean_spec.types: - Slot (with its 3SF-mini justifiability methods) - ValidatorIndex, SubnetId - Checkpoint Validator and Validators stay in the fork because their XMSS-bound key shape is signature-scheme specific. ValidatorIndices stays for now because to_aggregation_bits couples it to the fork's AggregationBits; that decomposition can land as a follow-up. Config also stays in the fork: the single-field shape is the most likely container to grow per fork (deposits, RANDAO, fee parameters), so promoting it to subspecs/chain/ would just churn it back out later. Tighten the ForkProtocol surface using the freshly promoted types: SpecStoreType.from_anchor and ForkProtocol.create_store now take ValidatorIndex | None instead of Uint64 | None. Also drop the fork-side re-exports per CLAUDE.md (no compat shims) and update all call sites across src/, tests/, and packages/. Refs leanEthereum#686 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
tcoratger
commented
May 1, 2026
Comment on lines
21
to
+34
| @@ -27,7 +31,7 @@ def justified_index_after(self, finalized_slot: Slot) -> int | None: | |||
| # Slot (finalized_slot + 1) maps to index 0. | |||
| return int(self - finalized_slot) - 1 | |||
|
|
|||
| def is_justifiable_after(self, finalized_slot: Slot) -> bool: | |||
| def is_justifiable_after(self, finalized_slot: "Slot") -> bool: | |||
Collaborator
Author
There was a problem hiding this comment.
@leolara Are we sure that these stuffs that are inside the Slot implementation should not be fork specific in case consensus rules evolve in the future?
38 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stage 2 of the multi-fork architecture refactor (#686). Promotes data primitives whose shape is stable across the leanSpec fork chain out of
forks/lstar/containers/and intolean_spec.types, so the fork package contains only what genuinely changes per fork.Moved to
lean_spec.types:Slot(withis_justifiable_after,justified_index_after,IMMEDIATE_JUSTIFICATION_WINDOW)ValidatorIndex,SubnetIdCheckpointStayed in the fork (intentionally):
Validator/Validators— XMSS-boundBytes52keys are signature-scheme specific.ValidatorIndices—to_aggregation_bitscouples it to the fork'sAggregationBits; the decomposition (e.g. moving the conversion ontoAggregationBits.from_validator_indices) is a clean follow-up.Config— single-field today, but the most likely container to grow per fork (deposits, RANDAO, fee parameters). Both reviewers agreed promoting it tosubspecs/chain/now would just churn it back out.Method placement: kept current methods on the moved types (
Slot.is_justifiable_after,ValidatorIndex.is_proposer_for, etc.) rather than pre-emptively pushing them to the fork class. Per CLAUDE.md ("don't design for hypothetical future requirements"), the migration to fork-class methods can happen when divergence is real.Notable changes
src/lean_spec/types/{slot,checkpoint,validator}.py— new files; re-exported fromtypes/__init__.py.src/lean_spec/forks/lstar/containers/{slot,checkpoint}.py— deleted.src/lean_spec/forks/lstar/containers/validator.py— keeps onlyValidator,Validators,ValidatorIndices.src/lean_spec/forks/lstar/containers/__init__.py— drops moved names (no re-export shim per CLAUDE.md).ForkProtocol:validator_id: Uint64 | None→ValidatorIndex | NoneinSpecStoreType.from_anchorandForkProtocol.create_store.src/,tests/, andpackages/updated to import fromlean_spec.typesdirectly.Reviewer input
Pre-implementation reviews from the consensus-researcher and py-architect agents confirmed the moves. They diverged on whether the methods (e.g.
Slot.is_justifiable_after) should travel with the types or move to the fork class — the py-architect's "don't pre-emptively abstract" view prevailed and matches the CLAUDE.md guidance.Test plan
uvx tox -e all-checks— passes (ruff, ruff-format, ty, codespell, mdformat).uv run pytest --co— all 3290 tests collect cleanly.Refs #686
🤖 Generated with Claude Code