Skip to content

refactor(ssz): consolidate to 4 files, modernize idioms, tighten tests#782

Merged
tcoratger merged 1 commit into
leanEthereum:mainfrom
tcoratger:refactor/ssz-tighten
May 26, 2026
Merged

refactor(ssz): consolidate to 4 files, modernize idioms, tighten tests#782
tcoratger merged 1 commit into
leanEthereum:mainfrom
tcoratger:refactor/ssz-tighten

Conversation

@tcoratger
Copy link
Copy Markdown
Collaborator

Summary

Cleanup pass on src/lean_spec/subspecs/ssz/ and tests/lean_spec/subspecs/ssz/ to bring the SSZ submodule closer to a spec-quality reference implementation: fewer files, more modern Python, sharper tests.

  • Source: 6 files / 401 lines → 4 files / 332 lines (__init__, constants, hash, merkleization)
  • Tests: 9 files / 2,585 lines → 2 files / 877 lines
  • Coverage: 100% line + branch on all 4 SSZ source files (107 tests)

Source changes

  • Deleted pack.py and utils.py — their helpers are now private members of hash.py / merkleization.py.
  • Collapsed the 4 packing functions into a single _pack_bytes using bytes.ljust.
  • Rewrote _pack_bits using int.to_bytes instead of bytearray bit-twiddling.
  • Inlined hash_nodes at its 5 call sites.
  • Removed dead code in _merkleize_efficient (unreachable second loop and fallback); added an assert that documents the invariant.
  • Standardized ceiling division on math.ceil everywhere.
  • Rewrote docstrings per .claude/rules/documentation.md — no backticks, no identifier names in prose, one sentence per line.
  • Documented constants.py with the WHY of each value.
  • Added ASCII diagrams to merkleize and _pack_bits.

Test changes

  • Deleted fork-specific tests that were misplaced in the SSZ folder (test_block, test_state, test_signed_attestation).
  • Deleted tests redundant with public-surface coverage (test_pack, test_utils_ssz, test_boundary_values, test_edge_cases, test_malformed_data, test_nested_structures).
  • Rewrote test_hash.py with parametric coverage of every hash_tree_root dispatch arm; expected values are built from first principles (sha256 + chunking + zero-tree table), not by re-running the system under test.
  • Rewrote test_merkleization.py, absorbing _next_pow2 coverage; deleted two tests that probed the now-removed dead code.
  • Every test function has a one-line docstring.

What is not in this PR (deliberate out-of-scope items)

These were surfaced during the analysis but are spec-policy decisions, not cleanup:

  • Type surface tightening — hash_tree_root still silently accepts bytes/bytearray/memoryview/Fp without explicit spec backing.
  • Missing public proof API — verify_merkle_proof, compute_merkle_proof, generalized indices.

Happy to do either in a follow-up if desired.

Test plan

  • uv run pytest tests/lean_spec/subspecs/ssz/ — 107 passed
  • uv run pytest tests/lean_spec/subspecs/ssz/ --cov=src/lean_spec/subspecs/ssz --cov-branch — 100% line + branch on all 4 files
  • uv run pytest (full suite) — 3012 passed (run after the source refactor)
  • just lint — clean
  • just format-check — clean

🤖 Generated with Claude Code

Source (src/lean_spec/subspecs/ssz/):
- Delete pack.py and utils.py; inline their helpers as private members of
  hash.py and merkleization.py
- Collapse the 4 pack functions into a single _pack_bytes using bytes.ljust
- Rewrite _pack_bits using int.to_bytes instead of bytearray bit-twiddling
- Inline hash_nodes at its 5 call sites
- Remove dead code in _merkleize_efficient (unreachable second loop and
  zero-tree fallback); add an assertion that documents the invariant
- Standardize ceiling division on math.ceil everywhere
- Rewrite docstrings per .claude/rules/documentation.md (no backticks,
  no identifier names in prose, one sentence per line)
- Document constants with WHY, not what
- Add ASCII diagrams to merkleize and _pack_bits

Tests (tests/lean_spec/subspecs/ssz/):
- Delete fork-specific tests that were misplaced in the SSZ folder
  (test_block, test_state, test_signed_attestation)
- Delete tests redundant with the public-surface coverage
  (test_pack, test_utils_ssz, test_boundary_values, test_edge_cases,
  test_malformed_data, test_nested_structures)
- Rewrite test_hash.py with parametric coverage of every dispatch arm
  built from first-principles expected values
- Rewrite test_merkleization.py absorbing _next_pow2 coverage
- Every test function has a one-line docstring

Result: 100% line + branch coverage on all 4 SSZ source files (107 tests).
Source goes from 6 files / 401 lines to 4 files / 332 lines.
Tests go from 9 files / 2,585 lines to 2 files / 877 lines.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tcoratger tcoratger merged commit 82f7c92 into leanEthereum:main May 26, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant