feat(crypto)!: track leanVM main (internalized XMSS + reworked aggregation) - #539
feat(crypto)!: track leanVM main (internalized XMSS + reworked aggregation)#539MegaRedHand wants to merge 7 commits into
Conversation
…ation)
Point the leanVM dependency at `main`. leanVM's `main` ("Xmss api rework")
removed the `lean-multisig` and `leansig_wrapper` crates ethlambda imported,
internalized XMSS in its own `xmss` crate (dropping the external leanSig
dependency), and reworked the recursive-aggregation API. Tracking main is
therefore a migration of the whole signature stack, not a version bump.
Changes:
- Cargo: replace `leansig`/`lean-multisig`/`leansig_wrapper` with `xmss` +
`rec_aggregation` (git, branch=main), plus `ssz` (ethereum_ssz, used by the
xmss SSZ impls) and `postcard` (secret-key format).
- types::signature: rebuild ValidatorPublicKey/Signature/SecretKey on leanVM's
`xmss` crate. Keys/signatures (de)serialize via SSZ (`PUB_KEY_SSZ_LEN` /
`SIGNATURE_SSZ_LEN`); secret keys via postcard. `SIGNATURE_SIZE` and the new
`PUBLIC_KEY_SIZE` are sourced from the xmss scheme constants. The sliding
preparation-window API becomes a fixed activation range (`advance_preparation`
is now a no-op; keys warm their signing cache on demand).
- crypto: rewrite aggregation/verification against `rec_aggregation`. Proofs now
serialize with `to_bytes()`/`from_bytes()` and embed participant pubkeys, so
the verify paths cross-check the embedded set against the expected validators
instead of attaching them at decode time. `setup_prover`/`setup_verifier` are
replaced by the idempotent `init_aggregation_bytecode`.
- Validator public keys are now 32 bytes (was 52); genesis/state layouts and
fixtures updated accordingly.
BREAKING: this changes the on-wire signature/proof formats and the genesis key
format. It is interop-incompatible with clients still on the previous scheme and
requires regenerated genesis keys; the fixture-driven spec tests need
regenerated fixtures. Landing this needs ecosystem coordination.
🤖 Kimi Code ReviewSecurity & Correctness
Performance & Memory
Code Quality & Maintainability
Testing
Summary The migration from the external Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt |
Greptile SummaryMigrates the validator signature stack to leanVM’s internal XMSS and recursive-aggregation APIs.
Confidence Score: 5/5The PR appears safe to merge from the reviewed code paths, with no concrete changed-code defect identified. Verification still binds each aggregate component to its expected message, slot, and validator key set, while the storage and consensus layouts are consistently migrated to the new XMSS encoding.
|
| Filename | Overview |
|---|---|
| crates/common/crypto/src/lib.rs | Migrates aggregation, verification, serialization, and proof splitting to rec_aggregation while binding embedded public-key sets to caller expectations. |
| crates/common/types/src/signature.rs | Rebuilds validator key and signature wrappers around leanVM XMSS with SSZ wire encoding and postcard secret-key persistence. |
| crates/common/types/src/state.rs | Changes validator public-key fields to the new 32-byte XMSS encoding, thereby updating the consensus state layout. |
| crates/common/types/src/attestation.rs | Updates the fixed XMSS signature representation and simplifies the structurally valid blank-signature construction. |
| crates/blockchain/src/reaggregate.rs | Adapts block-proof splitting to proofs that carry their participant public keys internally. |
| Cargo.toml | Replaces the removed leanSig and lean-multisig dependencies with leanVM XMSS, recursive aggregation, SSZ, and postcard dependencies. |
Sequence Diagram
sequenceDiagram
participant Validator
participant XMSS
participant Aggregator
participant Block
participant Verifier
Validator->>XMSS: Sign message at slot
XMSS-->>Aggregator: SSZ signature + public key
Aggregator->>Aggregator: Build Type-1 proof with embedded keys
Aggregator->>Block: Merge Type-1 proofs into Type-2 proof
Block->>Verifier: Block, aggregation bits, embedded-key proof
Verifier->>Verifier: Derive expected keys from validator state
Verifier->>Verifier: Cross-check messages, slots, and key sets
Verifier->>Verifier: Verify recursive aggregate proof
Reviews (1): Last reviewed commit: "feat(crypto)!: track leanVM main (intern..." | Re-trigger Greptile
🤖 Codex Code Review
Aside from that, the signature/aggregation migration looks internally consistent: the proof-verification paths now bind embedded pubkeys back to the expected validator sets, and the reaggregation path still sits behind full block-proof verification. I couldn’t run Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
…e branch Tracking `branch = main` re-resolves on every fetch, so the build could change under us. Pin the current main HEAD for reproducibility; the comment notes it is main's tip and the rev can be bumped to move forward.
Moves the pin two commits forward from a73ab11 (`Xmss api rework`, #262): - `105c5c69` rec_aggregation: optional pubkey-less aggregate serialization - `c83b40f0` fully single-threaded verifier (`Vec` instead of `ArenaVec`), plus a `forbid-parallelism` feature that asserts it `105c5c69` split `SingleMessageInfo` into a `SingleMessageCore` (message, slot, bytecode claim) plus the pubkey set, so the binding checks in the Type-1 and Type-2 verify paths reach through `.core`. The `xmss` crate is byte-identical between the two revs, so key and pubkey formats are unchanged: the genesis keys generated for a73ab11 verify as-is. `c83b40f0` makes proof verification sequential rather than pool-dispatched. The `forbid_parallelism()` guards it adds are inert unless leanVM's `forbid-parallelism` feature is enabled, which we do not enable. Validated on a 3-node all-ethlambda devnet with fresh new-format genesis: real leanVM proving on every block, Type-2 aggregates verified from gossip in ~50ms, finality advancing one slot per slot, no errors.
leanVM `105c5c69` restored optional pubkey-less aggregate serialization, so the wire format no longer has to change relative to `main`. Proofs serialize via `to_bytes_without_pubkeys()` and the caller attaches the resolved signer set at decode with `from_bytes_without_pubkeys()`, exactly as `compress_without_pubkeys()`/`decompress_without_pubkeys()` did before the migration. Every public signature in the crypto crate now matches `main` again, including `split_type_2_by_message`, which regains its `pubkeys_per_component` argument (`reaggregate.rs` already resolves that layout for its merge step, so the call site just passes it through). Attaching the caller's set is what binds a proof to its participants: leanVM sorts and de-duplicates it, then the SNARK checks it against the hash the proof commits to. So the explicit `PublicKeySetMismatch` comparison the embedded-pubkey form needed is gone, and a wrong set now fails inside the verifier — covered by a new `test_verify_wrong_pubkey_set_fails`. Validated on a 3-node all-ethlambda devnet: 114 block Type-2 aggregates decoded and verified through the pubkey-less path (111 carrying attestation components), p50 43.7ms, finality tracking head at 3 slots, no errors. Reaggregation never triggered there, so `split_type_2_by_message` is covered by the Type-2 merge/verify/split round-trip test instead.
`ensure_prover_ready` only called `init_aggregation_bytecode`, so the arena was never engaged and every prover buffer used the system allocator. `setup_prover` lives in the `lean-multisig` facade, not in `rec_aggregation`, so importing crate by crate hid it. Engaging the arena arms a panic: only one proof may run at a time. Take a permit around each proving entry point; without it 5 of the 7 crypto tests panic. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
What
Moves the leanVM dependency off the
devnet4-eralean-multisig+leansig_wrappercrates and onto currentmain, pinned atc83b40f.leanVM's
mainremoved thelean-multisigandleansig_wrappercrates ethlambda imported, internalized XMSS in its ownxmsscrate (dropping the external leanSig dependency), and reworked the recursive-aggregation API. So this is a migration of the whole signature stack, not a version bump:cargo updatefails outright (no matching package named leansig_wrapper).Changes
rev e2592df)rev c83b40f)lean-multisig,leansig_wrapper,leansig(devnet4)rec_aggregation,xmss+ssz(ethereum_ssz),postcardxmsscratecompress_without_pubkeys()to_bytes_without_pubkeys()— unchanged shape: pubkeys stay off the wirePUB_KEY_SSZ_LEN)setup_prover/setup_verifierinit_aggregation_bytecodeadvance_preparationis now a no-op)c83b40f)types::signature: rebuiltValidatorPublicKey/ValidatorSignature/ValidatorSecretKeyonxmss. Pubkeys/sigs (de)serialize via SSZ; secret keys via postcard.SIGNATURE_SIZE+ newPUBLIC_KEY_SIZEcome from the scheme constants. AddedValidatorSecretKey::public_key()(now that xmss exposes it).crypto: rewired aggregation/verification againstrec_aggregation. The wire format and every public signature are kept as onmain: proofs serialize without their participant pubkeys, and the caller attaches the resolved signer set at decode (from_bytes_without_pubkeys). A set other than the one aggregated attaches fine but fails verification, since the proof binds a hash of the set — covered by a newtest_verify_wrong_pubkey_set_fails.VerificationError::ProofError(#[from] ProofError)becomesVerificationFailed(String): leanVM'sProofErrorlives in itsbackendcrate, whichrec_aggregationimports but does not re-export, so it is not nameable here.The wire format of the proof contents and the genesis key format change, even though the pubkey-less framing matches
main:lean-quickstarthas no generator for this format, so one is needed before a devnet can be stood up.Landing this needs ecosystem coordination; it is not a drop-in for the live devnet.