Skip to main content

kimchi_stubs/
lib.rs

1//! The Marlin_plonk_stubs crate exports some functionalities
2//! and structures from the following the Rust crates to OCaml:
3//!
4//! * [Proof-systems](https://github.com/o1-labs/proof-systems),
5//!   a PLONK implementation.
6//! * [Arkworks](http://arkworks.rs/),
7//!   a math library that Proof-systems builds on top of.
8//!
9
10// Allow lints from ocaml derive macros until upstream crates are updated.
11// See https://github.com/o1-labs/mina-rust/issues/1954
12#![allow(non_local_definitions)]
13#![allow(unexpected_cfgs)]
14
15extern crate libc;
16
17/// Caml helpers
18#[macro_use]
19pub mod caml;
20
21/// Arkworks types
22pub mod arkworks;
23
24/// Utils
25pub mod urs_utils; // TODO: move this logic to proof-systems
26
27/// Error plumbing for the cached-index FFI wrappers
28pub mod cache_error;
29
30/// Vectors
31pub mod field_vector;
32pub mod gate_vector;
33
34/// Curves
35pub mod projective;
36
37/// SRS
38pub mod srs;
39
40/// Indexes
41pub mod pasta_fp_plonk_index;
42pub mod pasta_fq_plonk_index;
43
44/// Verifier indexes/keys
45pub mod plonk_verifier_index;
46
47pub mod pasta_fp_plonk_verifier_index;
48pub mod pasta_fq_plonk_verifier_index;
49
50/// Oracles
51pub mod oracles;
52
53/// Proofs
54pub mod pasta_fp_plonk_proof;
55pub mod pasta_fq_plonk_proof;
56
57/// Poseidon
58pub mod pasta_fp_poseidon;
59pub mod pasta_fq_poseidon;
60
61/// Linearization helpers
62pub mod linearization;
63
64/// Handy re-exports
65pub use {
66    kimchi::circuits::{
67        gate::{caml::CamlCircuitGate, CurrOrNext, GateType},
68        scalars::caml::CamlRandomOracles,
69        wires::caml::CamlWire,
70    },
71    kimchi::proof::caml::CamlProofEvaluations,
72    kimchi::prover::caml::{
73        CamlLookupCommitments, CamlProofWithPublic, CamlProverCommitments, CamlProverProof,
74    },
75    mina_poseidon::sponge::caml::CamlScalarChallenge,
76    poly_commitment::{commitment::caml::CamlPolyComm, ipa::caml::CamlOpeningProof},
77};
78
79/// Per-thread-count freelist of warm rayon pools, reused across proves so a
80/// long-running worker does not pay thread-spawn + cold-cache cost on every
81/// compression proof.
82fn prove_pool_cache() -> &'static std::sync::Mutex<
83    std::collections::HashMap<usize, Vec<std::sync::Arc<rayon::ThreadPool>>>,
84> {
85    static CACHE: std::sync::OnceLock<
86        std::sync::Mutex<std::collections::HashMap<usize, Vec<std::sync::Arc<rayon::ThreadPool>>>>,
87    > = std::sync::OnceLock::new();
88    CACHE.get_or_init(|| std::sync::Mutex::new(std::collections::HashMap::new()))
89}
90
91/// Run a proving closure in a scoped rayon thread pool sized by
92/// `KIMCHI_PROVE_THREADS`, falling back to the global pool when unset. Lets a
93/// long-running worker prove different tasks at different thread counts -- e.g.
94/// low rayon for the many parallel base proofs, high rayon for the
95/// low-concurrency compression proofs -- without rebuilding its global pool.
96///
97/// The thread count does not affect the proof, so this is VK-preserving.
98///
99/// Pools are checked out of a per-N freelist and returned after use: warm
100/// threads are reused, but concurrent proves of the same N each get their own
101/// pool (the freelist grows to the peak concurrency for that N), so parallelism
102/// is preserved.
103pub(crate) fn with_prove_pool<R: Send>(f: impl FnOnce() -> R + Send) -> R {
104    let n = match std::env::var("KIMCHI_PROVE_THREADS")
105        .ok()
106        .and_then(|s| s.parse::<usize>().ok())
107    {
108        Some(n) if n >= 1 => n,
109        _ => return f(),
110    };
111    let pool = {
112        let mut cache = prove_pool_cache().lock().unwrap();
113        cache
114            .get_mut(&n)
115            .and_then(|free| free.pop())
116            .unwrap_or_else(|| {
117                std::sync::Arc::new(
118                    rayon::ThreadPoolBuilder::new()
119                        .num_threads(n)
120                        .build()
121                        .expect("KIMCHI_PROVE_THREADS thread pool"),
122                )
123            })
124    };
125    let result = pool.install(f);
126    // Return the warm pool for reuse, but bound the freelist (default 2 per N,
127    // override with KIMCHI_PROVE_POOL_CAP) so idle pools do not accumulate
128    // unbounded resident memory across a long conversion; overflow pools are
129    // dropped, joining their threads.
130    let cap = std::env::var("KIMCHI_PROVE_POOL_CAP")
131        .ok()
132        .and_then(|s| s.parse::<usize>().ok())
133        .unwrap_or(2);
134    {
135        let mut cache = prove_pool_cache().lock().unwrap();
136        let free = cache.entry(n).or_default();
137        if free.len() < cap {
138            free.push(pool);
139        }
140    }
141    result
142}