shared_types/config/
global_config.rs

1use once_cell::sync::Lazy;
2use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
3
4use crate::circuit_hash::CircuitHashType;
5
6use super::{
7    ClaimAggregationStrategy, GKRCircuitProverConfig, GKRCircuitVerifierConfig, ProofConfig,
8};
9
10/// Default prover/verifier config is runtime-optimized for both! Note that this
11/// is a global static variable with atomic read/write access. In particular:
12/// * The [Lazy] component allows there to be a single static global config.
13///   This ensures that all prover/verifier functionality is "viewing" the
14///   same global config and we don't need to pass the options around.
15/// * The [RwLock] component ensures that there is atomic access to the prover
16///   and verifier configs. This ensures that we are able to atomically (with
17///   respect to the config) check that the global static config matches the
18///   locally expected config (e.g. one which you might specify for a specific
19///   test or binary run) and run the proving/verifying functions under that
20///   global config with the guarantee that the global config remains the same
21///   (since we simply hold onto a reader for the lifetime of the function
22///   call).
23/// * Finally, the idea of having the [GKRCircuitProverConfig] and
24///   [GKRCircuitVerifierConfig] together in the same [RwLock] is so that
25///   we can run an atomic prove + verify test. This is technically less
26///   efficient vs. keeping each of the configs in independent [`Lazy<RwLock>`],
27///   but gives a nicer abstraction.
28pub static PROVER_VERIFIER_CONFIG: Lazy<
29    RwLock<(GKRCircuitProverConfig, GKRCircuitVerifierConfig)>,
30> = Lazy::new(|| {
31    let default_prover_config = GKRCircuitProverConfig::runtime_optimized_default();
32    let default_verifier_config =
33        GKRCircuitVerifierConfig::new_from_prover_config(&default_prover_config, false);
34    RwLock::new((default_prover_config, default_verifier_config))
35});
36
37// -------------------- Helper functions for setting global config --------------------
38
39/// Sets the global prover config to be equivalent to the expected config passed in.
40pub fn set_global_prover_config(
41    expected_prover_config: &GKRCircuitProverConfig,
42    prover_verifier_config_instance: &mut RwLockWriteGuard<
43        '_,
44        (GKRCircuitProverConfig, GKRCircuitVerifierConfig),
45    >,
46) {
47    prover_verifier_config_instance.0 = expected_prover_config.clone();
48}
49
50/// Sets the global verifier config to be equivalent to the expected config passed in.
51pub fn set_global_verifier_config(
52    expected_verifier_config: &GKRCircuitVerifierConfig,
53    prover_verifier_config_instance: &mut RwLockWriteGuard<
54        '_,
55        (GKRCircuitProverConfig, GKRCircuitVerifierConfig),
56    >,
57) {
58    prover_verifier_config_instance.1 = *expected_verifier_config;
59}
60
61// -------------------- Helper functions for accessing global fields (prover) --------------------
62
63/// Whether to turn on "lazy beta evals" optimization
64/// (see documentation within [GKRCircuitProverConfig])
65pub fn global_prover_lazy_beta_evals() -> bool {
66    let prover_verifier_config_instance = PROVER_VERIFIER_CONFIG.read();
67    prover_verifier_config_instance.0.get_lazy_beta_evals()
68}
69
70/// Circuit description to be hashed and sent to verifier within transcript
71/// (see documentation within [GKRCircuitProverConfig])
72pub fn global_prover_circuit_description_hash_type() -> CircuitHashType {
73    let prover_verifier_config_instance = PROVER_VERIFIER_CONFIG.read();
74    prover_verifier_config_instance
75        .0
76        .get_circuit_description_hash_type()
77}
78/// The variant of claim aggregation to be used
79/// (see documentation within [GKRCircuitProverConfig])
80/// NOTE: No distinction between "prover" and "verifier",
81/// for correctness both must be using the same strategy.
82pub fn global_claim_agg_strategy() -> ClaimAggregationStrategy {
83    let prover_verifier_config_instance = PROVER_VERIFIER_CONFIG.read();
84    prover_verifier_config_instance.0.get_claim_agg_strategy()
85}
86/// Whether to turn on "constant columns" optimization for deterministic claim agg
87/// (see documentation within [GKRCircuitProverConfig])
88pub fn global_prover_claim_agg_constant_column_optimization() -> bool {
89    let prover_verifier_config_instance = PROVER_VERIFIER_CONFIG.read();
90    prover_verifier_config_instance
91        .0
92        .get_claim_agg_constant_column_optimization()
93}
94/// Whether to turn on "hyrax batch opening"
95/// (see documentation within [GKRCircuitProverConfig])
96pub fn global_prover_hyrax_batch_opening() -> bool {
97    let prover_verifier_config_instance = PROVER_VERIFIER_CONFIG.read();
98    prover_verifier_config_instance.0.get_hyrax_batch_opening()
99}
100
101/// Whether to turn on the "bit packed vector" optimization
102/// (see documentation within [GKRCircuitProverConfig])
103pub fn global_prover_enable_bit_packing() -> bool {
104    let prover_verifier_config_instance = PROVER_VERIFIER_CONFIG.read();
105    prover_verifier_config_instance.0.get_enable_bit_packing()
106}
107
108/// Returns a copy of the global [GKRCircuitProverConfig].
109pub fn get_current_global_prover_config() -> GKRCircuitProverConfig {
110    let prover_verifier_config_instance = PROVER_VERIFIER_CONFIG.read();
111    GKRCircuitProverConfig::new(
112        prover_verifier_config_instance.0.get_lazy_beta_evals(),
113        prover_verifier_config_instance
114            .0
115            .get_circuit_description_hash_type(),
116        prover_verifier_config_instance.0.get_claim_agg_strategy(),
117        prover_verifier_config_instance
118            .0
119            .get_claim_agg_constant_column_optimization(),
120        prover_verifier_config_instance.0.get_hyrax_batch_opening(),
121        prover_verifier_config_instance.0.get_enable_bit_packing(),
122    )
123}
124
125// -------------------- Helper functions for accessing global fields (verifier) --------------------
126
127/// Whether to turn on the "lazy beta evals" optimization
128/// (see documentation within [GKRCircuitVerifierConfig])
129pub fn global_verifier_lazy_beta_evals() -> bool {
130    let prover_verifier_config_instance = PROVER_VERIFIER_CONFIG.read();
131    prover_verifier_config_instance.1.get_lazy_beta_evals()
132}
133/// The type of hash function to use for hashing the circuit into the transcript
134/// (see documentation within [GKRCircuitVerifierConfig])
135pub fn global_verifier_circuit_description_hash_type() -> CircuitHashType {
136    let prover_verifier_config_instance = PROVER_VERIFIER_CONFIG.read();
137    prover_verifier_config_instance
138        .1
139        .get_circuit_description_hash_type()
140}
141/// Whether to use RLC or deterministic claim agg for verification
142/// (see documentation within [GKRCircuitVerifierConfig])
143pub fn global_verifier_claim_agg_strategy() -> ClaimAggregationStrategy {
144    let prover_verifier_config_instance = PROVER_VERIFIER_CONFIG.read();
145    prover_verifier_config_instance.1.get_claim_agg_strategy()
146}
147/// Whether to turn on the "constant columns" optimization for claim agg.
148/// (see documentation within [GKRCircuitVerifierConfig])
149pub fn global_verifier_claim_agg_constant_column_optimization() -> bool {
150    let prover_verifier_config_instance = PROVER_VERIFIER_CONFIG.read();
151    prover_verifier_config_instance
152        .1
153        .get_claim_agg_constant_column_optimization()
154}
155
156/// Returns a copy of the global [GKRCircuitVerifierConfig].
157pub fn get_current_global_verifier_config() -> GKRCircuitVerifierConfig {
158    let prover_verifier_config_instance = PROVER_VERIFIER_CONFIG.read();
159    GKRCircuitVerifierConfig::new(
160        prover_verifier_config_instance.1.get_lazy_beta_evals(),
161        prover_verifier_config_instance
162            .1
163            .get_circuit_description_hash_type(),
164        prover_verifier_config_instance.1.get_claim_agg_strategy(),
165        prover_verifier_config_instance
166            .1
167            .get_claim_agg_constant_column_optimization(),
168    )
169}
170
171// -------------------- Helper functions for checking prover/verifier readiness --------------------
172impl GKRCircuitProverConfig {
173    /// Returns whether the calling [GKRCircuitProverConfig], i.e. the "expected"
174    /// config, matches the one which is currently configured globally. A match
175    /// implies that we are ready to start proving.
176    ///
177    /// Note that the `prover_verifier_config_instance` should be held for
178    /// the ENTIRE DURATION of proving (and verifying) to prevent any changes
179    /// from happening to the config in the middle of proving!
180    pub fn matches_global_prover_config(
181        &self,
182        prover_verifier_config_instance: &RwLockReadGuard<
183            '_,
184            (GKRCircuitProverConfig, GKRCircuitVerifierConfig),
185        >,
186    ) -> bool {
187        self.get_claim_agg_constant_column_optimization()
188            == prover_verifier_config_instance
189                .0
190                .get_claim_agg_constant_column_optimization()
191            && self.get_enable_bit_packing()
192                == prover_verifier_config_instance.0.get_enable_bit_packing()
193            && self.get_lazy_beta_evals() == prover_verifier_config_instance.0.get_lazy_beta_evals()
194            && self.get_circuit_description_hash_type()
195                == prover_verifier_config_instance
196                    .0
197                    .get_circuit_description_hash_type()
198            && self.get_claim_agg_strategy()
199                == prover_verifier_config_instance.0.get_claim_agg_strategy()
200    }
201}
202
203impl GKRCircuitVerifierConfig {
204    /// Returns whether the calling [GKRCircuitVerifierConfig], i.e. the "expected"
205    /// config, matches the one which is currently configured globally. A match
206    /// implies that we are ready to start verifying.
207    ///
208    /// Note that the `prover_verifier_config_instance` should be held for
209    /// the ENTIRE DURATION of verifying to prevent any changes
210    /// from happening to the config in the middle of verifying!
211    pub fn matches_global_verifier_config(
212        &self,
213        prover_verifier_config_instance: &RwLockReadGuard<
214            '_,
215            (GKRCircuitProverConfig, GKRCircuitVerifierConfig),
216        >,
217    ) -> bool {
218        self.get_claim_agg_constant_column_optimization()
219            == prover_verifier_config_instance
220                .1
221                .get_claim_agg_constant_column_optimization()
222            && self.get_lazy_beta_evals() == prover_verifier_config_instance.1.get_lazy_beta_evals()
223            && self.get_circuit_description_hash_type()
224                == prover_verifier_config_instance
225                    .1
226                    .get_circuit_description_hash_type()
227            && self.get_claim_agg_strategy()
228                == prover_verifier_config_instance.1.get_claim_agg_strategy()
229    }
230
231    /// Returns whether the current (expected) [GKRCircuitVerifierConfig] matches
232    /// the [ProofConfig] for the given proof.
233    pub fn matches_proof_config(&self, proof_config: &ProofConfig) -> bool {
234        self.get_claim_agg_constant_column_optimization()
235            == proof_config.get_claim_agg_constant_column_optimization()
236            && self.get_circuit_description_hash_type()
237                == proof_config.get_circuit_description_hash_type()
238            && self.get_claim_agg_strategy() == proof_config.get_claim_agg_strategy()
239    }
240}
241
242// -------------------- Wrapper fns for ease of non-import --------------------
243/// Simple wrapper around [parking_lot::RwLockWriteGuard::downgrade] so that
244/// dependent libraries don't have to include the dependency within their
245/// `Cargo.toml` files.
246pub fn downgrade<T>(write_guard: RwLockWriteGuard<'_, T>) -> RwLockReadGuard<'_, T> {
247    RwLockWriteGuard::downgrade(write_guard)
248}
249
250// -------------------- Helper fns for execution --------------------
251
252/// This function will run the given function _only_ under the given configs!
253/// It does this by first reading the global config and checking whether
254/// that config matches the expected configs which are passed in, then
255/// * If matches, it performs the function immediately while holding the read
256///   lock and returns.
257/// * If doesn't match, it attempts to acquire a write lock, then writes the
258///   config to the global one, downgrades the write lock to a read lock
259///   (thereby unblocking all other readers), and performs the function.
260#[macro_export]
261macro_rules! perform_function_under_expected_configs {
262    ($func:expr, $expected_prover_config: expr, $expected_verifier_config:expr, $($arg:expr),*) => {{
263
264        loop {
265            // Extra scope allows us to automatically drop the reader reference
266            {
267                // Attempt to get read lock and check prover/verifier config matches
268                let prover_verifier_static_config_read_instance = shared_types::config::global_config::PROVER_VERIFIER_CONFIG.read();
269                if $expected_prover_config
270                    .matches_global_prover_config(&prover_verifier_static_config_read_instance)
271                    && $expected_verifier_config
272                        .matches_global_verifier_config(&prover_verifier_static_config_read_instance)
273                {
274                    let ret = $func($($arg),*);
275                    break ret;
276                }
277            }
278
279            // Otherwise, write the desired prover/verifier config to the global static var, downgrade into a read lock, and perform the action
280            if let Some(mut prover_verifier_static_config_write_instance) =
281                shared_types::config::global_config::PROVER_VERIFIER_CONFIG.try_write()
282            {
283                shared_types::config::global_config::set_global_prover_config(
284                    $expected_prover_config,
285                    &mut prover_verifier_static_config_write_instance,
286                );
287                shared_types::config::global_config::set_global_verifier_config(
288                    $expected_verifier_config,
289                    &mut prover_verifier_static_config_write_instance,
290                );
291
292                // Downgrade into a read lock and perform the function (this should unblock other readers)
293                let _prover_verifier_static_config_read_instance =
294                    shared_types::config::global_config::downgrade(prover_verifier_static_config_write_instance);
295
296                // Execute the function with the provided arguments
297                let ret = $func($($arg),*);
298                break ret;
299            }
300        }
301    }};
302}
303
304/// Similar function to [perform_function_under_expected_configs], but only
305/// checks against an expected [GKRCircuitProverConfig].
306#[macro_export]
307macro_rules! perform_function_under_prover_config {
308    ($func:expr, $expected_prover_config:expr, $($arg:expr),*) => {{
309
310        loop {
311            // Additional scope so that the read lock is dropped immediately
312            {
313                // Attempt to get read lock and check prover/verifier config matches
314                let prover_verifier_static_config_read_instance = shared_types::config::global_config::PROVER_VERIFIER_CONFIG.read();
315                if $expected_prover_config
316                    .matches_global_prover_config(&prover_verifier_static_config_read_instance)
317                {
318                    // Execute the function with the provided arguments
319                    let ret = $func($($arg),*);
320                    break ret;
321                }
322            }
323
324            // Otherwise, write the desired prover/verifier config to the global static var
325            if let Some(mut prover_verifier_static_config_write_instance) =
326                shared_types::config::global_config::PROVER_VERIFIER_CONFIG.try_write()
327            {
328                shared_types::config::global_config::set_global_prover_config(
329                    $expected_prover_config,
330                    &mut prover_verifier_static_config_write_instance,
331                );
332
333                // Downgrade into a read lock and perform the function (this should unblock other readers)
334                let _prover_verifier_static_config_read_instance =
335                    shared_types::config::global_config::downgrade(prover_verifier_static_config_write_instance);
336
337                // Execute the function with the provided arguments
338                let ret = $func($($arg),*);
339                break ret;
340            }
341        }
342    }};
343}
344
345/// Similar function to [perform_function_under_expected_configs], but only
346/// checks against an expected [GKRCircuitVerifierConfig].
347#[macro_export]
348macro_rules! perform_function_under_verifier_config {
349    ($func:expr, $expected_verifier_config:expr, $($arg:expr),*) => {{
350
351        loop {
352            // Additional scope so that the read lock is dropped immediately
353            {
354                // Attempt to get read lock and check prover/verifier config matches
355                let prover_verifier_static_config_read_instance = shared_types::config::global_config::PROVER_VERIFIER_CONFIG.read();
356                if $expected_verifier_config
357                    .matches_global_verifier_config(&prover_verifier_static_config_read_instance)
358                {
359                    let ret = $func($($arg),*);
360                    break ret;
361                }
362            }
363
364            // Otherwise, write the desired prover/verifier config to the global static var
365            if let Some(mut prover_verifier_static_config_write_instance) =
366                shared_types::config::global_config::PROVER_VERIFIER_CONFIG.try_write()
367            {
368                shared_types::config::global_config::set_global_verifier_config(
369                    $expected_verifier_config,
370                    &mut prover_verifier_static_config_write_instance,
371                );
372
373                // Downgrade into a read lock and perform the function (this should unblock other readers)
374                let _prover_verifier_static_config_read_instance =
375                    shared_types::config::global_config::downgrade(prover_verifier_static_config_write_instance);
376
377                // Execute the function with the provided arguments
378                let ret = $func($($arg),*);
379                break ret;
380            }
381        }
382    }};
383}