refactor(forks/lstar): type SignedBlock.proof and rename multi-signature types#799
Merged
tcoratger merged 3 commits intoMay 29, 2026
Merged
Conversation
The field was typed as raw ByteList512KiB and producers manually called encode_bytes before storing the result; verify_signatures and the post-block split path then decode_bytes-ed it back. Promote the field to its real type so SSZ handles the (de)serialization once at the container boundary. - Removes the encode-then-wrap dance in the validator service and test builders. - Removes the try/decode_bytes/except blocks in verify_signatures and the sync service post-block handler. - Updates SSZ round-trip tests, fork choice tests, and reqresp client helpers to construct the typed envelope directly. - Deletes four tautological decode-smoke assertions in test_service.py now that the Pydantic-validated field guarantees the shape. The on-wire SSZ encoding of SignedBlock is unchanged; hash_tree_root will change because Container merkleization differs from List[byte] merkleization, so consensus fixtures that hardcode block roots need regeneration. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both call sites used the local alias exactly once. Drop it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ggregate / MultiMessageAggregate TypeOneMultiSignature and TypeTwoMultiSignature were named after the underlying Rust prover convention, not what they semantically are. Rename them to express the actual data: an aggregate over a single message versus an aggregate over many distinct messages. - Classes: TypeOneMultiSignature -> SingleMessageAggregate, TypeTwoMultiSignature -> MultiMessageAggregate - Variables and locals follow the snake_case form: type_1 -> single_message_aggregate, type_2 -> multi_message_aggregate (plus the compound forms type1_wire, type2_wire, block_t1, proposer_type_1, etc.) - Test function names match: test_type_one_* -> test_single_message_*, test_type_two_* -> test_multi_message_* - Prose mentions of "Type-1" / "Type-2" in docstrings and comments become "single-message aggregate" / "multi-message aggregate" External Rust binding names (aggregate_type_1, verify_type_1, merge_many_type_1, split_type_2_by_msg, verify_type_2_with_messages) come from the leanMultisig-py package and are left untouched. The "Type 1" / "Type 2" mentions in node/snappy/encoding.py refer to Snappy's Copy Type 1 / Copy Type 2 wire encodings and are unrelated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
Three related commits that clean up the block-level proof field:
fdd0f947— TypeSignedBlock.proofas the typed envelope (later renamed toMultiMessageAggregate— see below). The field was typed as rawByteList512KiBand producers manually calledencode_bytesbefore storing the result; verify and post-block split paths thendecode_bytes-ed it back. Promoting the field to its real type lets SSZ handle (de)serialization at the container boundary.76ac8481— Inline single-usetype_twoalias. Bothverify_signaturesand the sync post-block handler boundtype_two = signed_block.proofand used the alias exactly once. Drop it.7facb6d2— Rename the multi-signature types to express what they are, not their Rust-prover convention.TypeOneMultiSignature→SingleMessageAggregate,TypeTwoMultiSignature→MultiMessageAggregate.leanMultisig-py(aggregate_type_1,verify_type_1,merge_many_type_1,split_type_2_by_msg,verify_type_2_with_messages) are unchanged. Snappy's unrelated "Copy Type 1/2" innode/snappy/encoding.pyis also untouched.Notes
SignedBlockis unchanged —Container { proof: ByteList512KiB }and a bareByteList512KiBproduce the same[4-byte offset = 4][bytes]layout under a parent container's offset region.hash_tree_root(SignedBlock)will change because Container merkleization differs fromList[byte]merkleization. Any consensus fixtures or downstream code that hardcode block roots will need regeneration.Diff size
Test plan
just check— lint, format, ty, codespell, mdformat all cleanuv run fill --fork=lstar --clean -n auto) and confirm any block-root-dependent vectors update cleanly🤖 Generated with Claude Code