@@ -39,7 +39,7 @@ crates/
3939 └─ src/metrics.rs # State transition timing + counters
4040 common/
4141 ├─ types/ # Core types (State, Block, Attestation, Checkpoint)
42- ├─ crypto/ # XMSS aggregation (leansig wrapper)
42+ ├─ crypto/ # XMSS sign/verify + aggregation (leanVM wrapper)
4343 ├─ ssz-tree/ # Persistent Merkle tree (List/Vector) behind the beacon registry and balances
4444 ├─ metrics/ # Prometheus re-exports, TimingGuard, gather utilities
4545 └─ test-fixtures/ # Spec-fixture loading (prod dep of rpc's Hive test driver)
@@ -279,9 +279,39 @@ actual_slot = finalized_slot + 1 + relative_index
279279
280280** XMSS (eXtended Merkle Signature Scheme):**
281281- Post-quantum signature scheme
282- - 52-byte public keys, 2536-byte signatures (` SIGNATURE_SIZE ` in ` common/types/src/signature.rs ` )
282+ - Wire sizes: ` PUBLIC_KEY_SIZE ` (` common/types/src/state.rs ` ) and ` SIGNATURE_SIZE `
283+ (` common/types/src/attestation.rs ` ), static-asserted against leanVM's scheme
284+ constants in ` common/crypto/src/signature.rs `
283285- Epoch-based to prevent reuse
284- - Aggregation via leanVM (previously leanMultisig) for efficiency
286+ - Signing, verification, and aggregation all come from leanVM, which internalized
287+ XMSS in its own ` xmss ` crate; there is no external leanSig dependency
288+ - BLAKE2s over binary fields, not Poseidon over KoalaBear: a leanVM ` main ` bump
289+ across that rewrite invalidates every genesis key and every stored proof, even
290+ when the wire sizes happen to match
291+ - ` ethlambda_crypto::init_leanvm(use_arena) ` must run once at startup, before any
292+ proving or proof decoding. ` --prover-arena ` opts into leanVM's bump arena,
293+ which recycles the prover's large buffers across proofs instead of re-faulting
294+ them, so its pages stay resident for the node's lifetime
295+ - ` ethlambda keygen ` generates genesis validator keys through the same
296+ ` ValidatorSecretKey ` the node loads them with, so a key set cannot be built
297+ against a different leanVM than the client reading it. Keys are only usable by
298+ a client on the matching revision, and no file size changes when the scheme
299+ does, so the manifest records ` leanvm_rev ` . See [ ` docs/keygen.md ` ] ( docs/keygen.md )
300+
301+ ** Aggregation shape (one leanVM ` AggregateSignature ` , grouped by ` (epoch, message) ` ):**
302+ - Type-1 and Type-2 are the same object: one ` XmssGroup ` per ` (epoch, message) `
303+ pair, carrying that group's sorted, deduplicated keys
304+ - ** A slot can carry several messages.** Validators attesting moments apart
305+ disagree within a slot, so two distinct ` AttestationData ` at one slot is
306+ ordinary rather than equivocation and a block routinely carries both. The
307+ groups are sorted on the whole pair: with two of them at one slot, sorting on
308+ the epoch alone rebuilds a different signer set and fails a valid proof
309+ - ** The binding is off the wire.** ` to_bytes_without_pubkeys() ` carries neither
310+ the keys nor the ` (slot, message) ` pairs, so every decode rebuilds the whole
311+ signer set from a ` SignerSet ` per claim. A wrong set, message or slot decodes
312+ fine and fails inside the SNARK verifier, so there is no cheap binding check
313+ - Narrowing replaces splitting: re-aggregate the parent with a ` declare ` naming
314+ the group to keep (` split_type_2_by_message ` )
285315
286316** Signature Aggregation (Two-Phase):**
2873171 . ** Gossip signatures** : Fresh XMSS from network → aggregate via leanVM
@@ -674,7 +704,7 @@ transitions are in `ethlambda-types`, per the section above. Nothing above
674704GENESIS_TIME : 1770407233
675705MILLISECONDS_PER_SLOT : 4000 # optional, defaults to DEFAULT_MILLISECONDS_PER_SLOT
676706GENESIS_VALIDATORS :
677- - attestation_pubkey : " cd323f232b34ab26d6db7402c886e74ca81cfd3a..." # 52-byte XMSS pubkeys ( hex)
707+ - attestation_pubkey : " cd323f232b34ab26d6db7402c886e74ca81cfd3a..." # XMSS pubkeys, hex, PUBLIC_KEY_SIZE bytes
678708 proposal_pubkey : " b7b0f72e24801b02bda64073cb4de6699a416b37..."
679709` ` `
680710- Validator indices are assigned sequentially (0, 1, 2, ...) based on array order
@@ -780,7 +810,9 @@ behavior.
780810# # External Dependencies
781811
782812**Critical:**
783- - `leansig` : XMSS signatures (leanEthereum project)
813+ - `leanvm` : XMSS signatures and recursive aggregation, taken from leanVM's facade
814+ crate (which re-exports `xmss`, `rec_aggregation` and its `rand`) and pinned to
815+ one `main` revision (leanEthereum project)
784816- `libssz` / `libssz-derive` / `libssz-types` : SSZ serialization
785817- `libssz-merkle` : Merkle tree hashing (`hash_tree_root()`)
786818- `spawned-concurrency` : Actor model
0 commit comments