Skip to content

feat(types): add MultiMessageAggregate [Devnet 5]#426

Merged
pablodeymo merged 3 commits into
lambdaclass:devnet5from
dicethedev:feat/devnet5-multi-message-aggregate
Jun 10, 2026
Merged

feat(types): add MultiMessageAggregate [Devnet 5]#426
pablodeymo merged 3 commits into
lambdaclass:devnet5from
dicethedev:feat/devnet5-multi-message-aggregate

Conversation

@dicethedev

@dicethedev dicethedev commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

🗒️ Description / Motivation

  • Adds the MultiMessageAggregate type required by the Devnet 5 specification.
  • Replaces the raw ByteList512KiB used by SignedBlock.proof with the correct SSZ container.
  • Removes manual SSZ offset wrapping and parsing.

What Changed

  • Added MultiMessageAggregate containing a ByteList512KiB proof.
  • Updated SignedBlock.proof to use MultiMessageAggregate.
  • Added constructors and raw proof-byte accessors.
  • Updated block building, verification, reaggregation, storage, RPC, P2P, and test fixtures.
  • Added an SSZ encoding test for the new container.

Correctness / Behavior Guarantees

  • The existing SSZ wire representation is preserved: the aggregate container encodes its variable-length proof with the required offset.
  • Raw lean-multisig proof bytes are passed unchanged to cryptographic operations.
  • Stored block proofs are now encoded and decoded as the specification-defined container.

Tests Added / Run

  • Added multi_message_aggregate_ssz_wraps_proof_bytes.
  • Ran cargo fmt --all.
  • Ran cargo check --workspace --all-targets successfully.

Related Issues / PRs

✅ Verification Checklist

  • Ran formatting — clean
  • Ran make lint (clippy with -D warnings) — clean
  • Ran cargo test --workspace --release — all passing

@greptile-apps

greptile-apps Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR replaces the raw ByteList512KiB on SignedBlock.proof with a proper MultiMessageAggregate SSZ container, aligning the implementation with the Devnet 5 / leanSpec PR #717 specification. The wire format is deliberately preserved — both old and new encodings produce the same 4-byte-offset-prefixed bytes on the wire — so no storage migration is needed.

  • MultiMessageAggregate is introduced in crates/common/types/src/block.rs with clean new / from_bytes / proof_bytes accessors; the manual offset-wrapping/stripping logic in SignedBlock is removed.
  • All call sites (block builder, reaggregation, verification, storage, RPC, P2P, test fixtures) are updated uniformly; the insert_header test helper in crates/storage/src/store.rs still stores vec![0u8; 4] as a dummy proof, which is now invalid SSZ for MultiMessageAggregate and would panic via expect if get_signed_block were ever called on one of those entries.

Confidence Score: 4/5

The production code paths are correct and the wire format is properly preserved; the one concern is confined to a test helper that stores bytes which are no longer valid SSZ for the new type.

All production read/write/verify paths look correct and the SSZ encoding is verified by the new round-trip test. The insert_header helper in the storage tests now writes [0u8; 4] as a dummy proof, which is invalid SSZ for MultiMessageAggregate — if a future test reads back one of those blocks via get_signed_block, the expect would panic. The fix is a one-liner: replace the dummy bytes with MultiMessageAggregate::default().to_ssz().

crates/storage/src/store.rs — specifically the insert_header test helper at line 1431

Important Files Changed

Filename Overview
crates/common/types/src/block.rs Introduces MultiMessageAggregate SSZ container, replaces ByteList512KiB on SignedBlock.proof, and provides clean new/from_bytes/proof_bytes accessors; wire format is preserved.
crates/storage/src/store.rs Read/write paths updated cleanly, but insert_header test helper stores vec![0u8; 4] which is now invalid SSZ for MultiMessageAggregate and would panic via expect if get_signed_block were ever called on those entries.
crates/blockchain/src/lib.rs Removes manual offset-wrapping and uses MultiMessageAggregate::from_bytes; logic is equivalent and simpler.
crates/blockchain/src/reaggregate.rs Drops the fallible merged_proof_bytes() call in favour of the infallible proof.proof_bytes(); empty-proof path now falls through to the crypto call rather than early-returning, which is harmless.
crates/blockchain/src/store.rs Verification path simplified; early envelope-validation error replaced by a downstream crypto error for malformed proofs — behaviorally equivalent for the happy path.
crates/common/test-fixtures/src/verify_signatures.rs Fixture conversion updated to use MultiMessageAggregate::from_bytes; functionally identical to the old wrap_merged_proof for valid input.

Sequence Diagram

sequenceDiagram
    participant Builder as BlockChainServer
    participant Crypto as ethlambda_crypto
    participant Types as MultiMessageAggregate
    participant Storage as Store (BlockSignatures)
    participant Verifier as verify_block_signatures

    Builder->>Crypto: merge_type_1s_into_type_2(inputs)
    Crypto-->>Builder: Vec~u8~ (raw Type-2 bytes)
    Builder->>Types: MultiMessageAggregate::from_bytes(raw)
    Types-->>Builder: MultiMessageAggregate
    Builder->>Storage: proof.to_ssz()

    Storage-->>Verifier: MultiMessageAggregate::from_ssz_bytes(stored)
    Verifier->>Types: proof.proof_bytes()
    Types-->>Verifier: raw Type-2 bytes
    Verifier->>Crypto: verify_type_2_signature(raw bytes, ...)
Loading

Comments Outside Diff (1)

  1. crates/storage/src/store.rs, line 1430-1432 (link)

    P1 vec![0u8; 4] was a valid ByteList512KiB (four raw zero bytes), but it decodes to an invalid MultiMessageAggregate: the SSZ decoder reads those bytes as a variable-field offset of 0, which is below the minimum of 4, so MultiMessageAggregate::from_ssz_bytes returns an error. The expect("valid block proof") at the read site would panic if any test ever called get_signed_block on a block inserted by this helper. Use the correctly-encoded empty aggregate instead.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: crates/storage/src/store.rs
    Line: 1430-1432
    
    Comment:
    `vec![0u8; 4]` was a valid `ByteList512KiB` (four raw zero bytes), but it decodes to an invalid `MultiMessageAggregate`: the SSZ decoder reads those bytes as a variable-field offset of `0`, which is below the minimum of `4`, so `MultiMessageAggregate::from_ssz_bytes` returns an error. The `expect("valid block proof")` at the read site would panic if any test ever called `get_signed_block` on a block inserted by this helper. Use the correctly-encoded empty aggregate instead.
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
crates/storage/src/store.rs:1430-1432
`vec![0u8; 4]` was a valid `ByteList512KiB` (four raw zero bytes), but it decodes to an invalid `MultiMessageAggregate`: the SSZ decoder reads those bytes as a variable-field offset of `0`, which is below the minimum of `4`, so `MultiMessageAggregate::from_ssz_bytes` returns an error. The `expect("valid block proof")` at the read site would panic if any test ever called `get_signed_block` on a block inserted by this helper. Use the correctly-encoded empty aggregate instead.

```suggestion
        batch
            .put_batch(Table::BlockSignatures, vec![(key, MultiMessageAggregate::default().to_ssz())])
            .expect("put sigs");
```

Reviews (1): Last reviewed commit: "feat(types): add MultiMessageAggregate" | Re-trigger Greptile

Comment thread crates/common/types/src/block.rs
@pablodeymo pablodeymo merged commit baeec9e into lambdaclass:devnet5 Jun 10, 2026
2 checks passed
@MegaRedHand

Copy link
Copy Markdown
Collaborator

Great work! 👍

@dicethedev

Copy link
Copy Markdown
Contributor Author

Great work! 👍

Thanks you!

MegaRedHand added a commit that referenced this pull request Jun 10, 2026
Addresses [review feedback on
#426](#426 (comment))
left after merge: use `thiserror` instead of manual `Display` /
`std::error::Error` impls for `MultiMessageAggregateError`.

No behavior change; the error message is identical.
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.

[Devnet 5] Add MultiMessageAggregate type

3 participants