From 08ee1f8dae8a4ba128b3ceec72af097a761d5be6 Mon Sep 17 00:00:00 2001 From: Tom Wambsgans Date: Mon, 27 Jul 2026 19:58:01 +0100 Subject: [PATCH] fix(crypto): use leanVM's facade and prove one at a time `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) --- Cargo.lock | 61 +++++++++++++++++++++------------ Cargo.toml | 7 ++-- crates/common/crypto/Cargo.toml | 6 ++-- crates/common/crypto/src/lib.rs | 42 +++++++++++++++-------- 4 files changed, 72 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 20c6e160..b99ebe33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,9 +88,10 @@ dependencies = [ [[package]] name = "air" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "field", + "koala-bear", "poly", ] @@ -661,7 +662,7 @@ dependencies = [ [[package]] name = "backend" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "air", "fiat-shamir", @@ -2068,10 +2069,10 @@ dependencies = [ "ethereum_ssz", "ethlambda-types", "hex", + "lean-multisig", "rand 0.10.1", - "rec_aggregation", "thiserror 2.0.18", - "xmss", + "tracing", ] [[package]] @@ -2564,7 +2565,7 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "fiat-shamir" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "field", "koala-bear", @@ -2577,7 +2578,7 @@ dependencies = [ [[package]] name = "field" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "paste", "rand 0.10.1", @@ -3646,7 +3647,7 @@ dependencies = [ [[package]] name = "koala-bear" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "field", "paste", @@ -3705,10 +3706,26 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "lean-multisig" +version = "0.1.0" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" +dependencies = [ + "backend", + "clap", + "lean_vm", + "rec_aggregation", + "serde_json", + "sub_protocols", + "system-info", + "xmss", + "zk-alloc", +] + [[package]] name = "lean_compiler" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "backend", "include_dir", @@ -3722,7 +3739,7 @@ dependencies = [ [[package]] name = "lean_prover" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "backend", "lean_compiler", @@ -3737,7 +3754,7 @@ dependencies = [ [[package]] name = "lean_vm" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "backend", "tracing", @@ -5289,7 +5306,7 @@ dependencies = [ [[package]] name = "parallel" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "system-info", ] @@ -5484,9 +5501,10 @@ dependencies = [ [[package]] name = "poly" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "field", + "koala-bear", "parallel", "rand 0.10.1", "serde", @@ -6067,7 +6085,7 @@ dependencies = [ [[package]] name = "rec_aggregation" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "backend", "include_dir", @@ -7097,7 +7115,7 @@ dependencies = [ [[package]] name = "sub_protocols" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "backend", "lean_vm", @@ -7113,11 +7131,12 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "sumcheck" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "air", "fiat-shamir", "field", + "koala-bear", "parallel", "poly", "tracing", @@ -7127,7 +7146,7 @@ dependencies = [ [[package]] name = "symetric" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "field", "koala-bear", @@ -7215,7 +7234,7 @@ dependencies = [ [[package]] name = "system-info" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "libc", ] @@ -7748,7 +7767,7 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "utils" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "parallel", "serde", @@ -8012,7 +8031,7 @@ dependencies = [ [[package]] name = "whir" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "fiat-shamir", "field", @@ -8570,7 +8589,7 @@ dependencies = [ [[package]] name = "xmss" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "backend", "ethereum_ssz", @@ -8745,7 +8764,7 @@ dependencies = [ [[package]] name = "zk-alloc" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanVM.git?rev=c83b40f01e809f1bd3238d17a821a1ff3ed8171d#c83b40f01e809f1bd3238d17a821a1ff3ed8171d" +source = "git+https://github.com/leanEthereum/leanVM.git?rev=380da82c330eac2841252a655a86ea48ec173bb6#380da82c330eac2841252a655a86ea48ec173bb6" dependencies = [ "libc", "parallel", diff --git a/Cargo.toml b/Cargo.toml index 556a3fcc..b201f875 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,10 +58,9 @@ clap = { version = "4.3", features = ["derive", "env"] } # XMSS signatures + recursive aggregation (leanVM). # leanVM's `main` internalized XMSS (dropping the external leanSig dependency) # and reworked the aggregation API (see "Xmss api rework"). -# Pinned to a `main` commit (`c83b40f`) for reproducible builds; bump the rev to -# track main forward. -xmss = { git = "https://github.com/leanEthereum/leanVM.git", rev = "c83b40f01e809f1bd3238d17a821a1ff3ed8171d" } -rec_aggregation = { git = "https://github.com/leanEthereum/leanVM.git", rev = "c83b40f01e809f1bd3238d17a821a1ff3ed8171d" } +# Pinned to a `main` commit for reproducible builds; bump the revs to track main. +xmss = { git = "https://github.com/leanEthereum/leanVM.git", rev = "380da82c330eac2841252a655a86ea48ec173bb6" } +lean-multisig = { git = "https://github.com/leanEthereum/leanVM.git", rev = "380da82c330eac2841252a655a86ea48ec173bb6" } # SSZ codec used by leanVM's xmss pubkey/signature types (ethereum_ssz, not libssz). ssz = { package = "ethereum_ssz", version = "0.10" } diff --git a/crates/common/crypto/Cargo.toml b/crates/common/crypto/Cargo.toml index 83291605..57db14dd 100644 --- a/crates/common/crypto/Cargo.toml +++ b/crates/common/crypto/Cargo.toml @@ -12,13 +12,11 @@ version.workspace = true [dependencies] ethlambda-types.workspace = true -# rec_aggregation is leanVM's recursive XMSS aggregation prover/verifier; -# xmss provides the public-key/signature types its API consumes. -rec_aggregation.workspace = true -xmss.workspace = true +lean-multisig.workspace = true thiserror.workspace = true rand.workspace = true +tracing.workspace = true [features] shadow-integration = [] diff --git a/crates/common/crypto/src/lib.rs b/crates/common/crypto/src/lib.rs index 1ae4907a..39eb75d0 100644 --- a/crates/common/crypto/src/lib.rs +++ b/crates/common/crypto/src/lib.rs @@ -3,13 +3,15 @@ use ethlambda_types::{ primitives::H256, signature::{LeanSigPublicKey, LeanSigSignature, ValidatorPublicKey, ValidatorSignature}, }; -use rec_aggregation::{ +use lean_multisig::{ MultiMessageAggregateSignature as LMType2, SingleMessageAggregateSignature as LMType1, - aggregate_single_message_signatures, init_aggregation_bytecode, - merge_single_message_aggregates, split_multi_message_aggregate, verify_multi_message_aggregate, + aggregate_single_message_signatures, merge_single_message_aggregates, setup_prover, + setup_verifier, split_multi_message_aggregate, verify_multi_message_aggregate, verify_single_message_aggregate, }; +use std::sync::{Mutex, MutexGuard}; use thiserror::Error; +use tracing::error; #[cfg(feature = "shadow-integration")] pub mod shadow_cost; @@ -17,21 +19,26 @@ pub mod shadow_cost; /// log(1/rate) for the WHIR commitment scheme used inside the aggregation prover. const LOG_INV_RATE: usize = 2; -/// Ensure the aggregation bytecode is compiled. Safe to call multiple times. -/// -/// leanVM's `main` replaced the old `setup_prover`/`setup_verifier` split with a -/// single self-referential aggregation bytecode used by both the prover and the -/// verifier; `init_aggregation_bytecode` is idempotent (`OnceLock::get_or_init`). +/// leanVM allows one proof at a time per process; a second one panics. +static PROVER_PERMIT: Mutex<()> = Mutex::new(()); + +/// The permit guards no data, so a poisoned lock is recovered rather than propagated: +/// one panicking prover must not brick every later proof. It is still an incident. +fn prover_permit() -> MutexGuard<'static, ()> { + PROVER_PERMIT.lock().unwrap_or_else(|poisoned| { + error!("a previous proving job panicked while holding the permit; continuing"); + poisoned.into_inner() + }) +} + +/// Engages leanVM's arena; skipping it stays correct but slow. pub fn ensure_prover_ready() { - init_aggregation_bytecode(); + setup_prover(); } -/// Ensure the aggregation bytecode is compiled. Safe to call multiple times. -/// -/// Deserializing any proof (`from_bytes`) also requires the bytecode, so this -/// must run before any verification path. +/// Needed before any decode, not just before verifying. pub fn ensure_verifier_ready() { - init_aggregation_bytecode(); + setup_verifier(); } /// Error type for signature aggregation operations. @@ -187,6 +194,7 @@ pub fn aggregate_signatures( } ensure_prover_ready(); + let _permit = prover_permit(); let raw_xmss: Vec<(LeanSigPublicKey, LeanSigSignature)> = public_keys .into_iter() @@ -242,6 +250,7 @@ pub fn aggregate_mixed( } ensure_prover_ready(); + let _permit = prover_permit(); let children_native: Vec = children .into_iter() @@ -296,6 +305,7 @@ pub fn aggregate_proofs( } ensure_prover_ready(); + let _permit = prover_permit(); let children_native: Vec = children .into_iter() @@ -391,6 +401,7 @@ pub fn merge_type_1s_into_type_2( } ensure_prover_ready(); + let _permit = prover_permit(); let type_1s_native: Vec = type_1s .into_iter() @@ -485,6 +496,7 @@ pub fn split_type_2_by_message( } ensure_prover_ready(); + let _permit = prover_permit(); let pubkeys_per_info: Vec> = pubkeys_per_component .into_iter() @@ -515,8 +527,8 @@ pub fn split_type_2_by_message( #[cfg(test)] mod tests { use super::*; + use lean_multisig::{xmss_key_gen_from_seed, xmss_sign}; use ssz::Encode as _; - use xmss::{xmss_key_gen_from_seed, xmss_sign}; /// Generate a test keypair and sign a message. ///