cuprate_consensus/
batch_verifier.rs

1use std::cell::RefCell;
2
3use monero_serai::ringct::bulletproofs::BatchVerifier as InternalBatchVerifier;
4use rayon::prelude::*;
5use thread_local::ThreadLocal;
6
7use cuprate_consensus_rules::batch_verifier::BatchVerifier;
8
9/// A multithreaded batch verifier.
10pub struct MultiThreadedBatchVerifier {
11    internal: ThreadLocal<RefCell<InternalBatchVerifier>>,
12}
13
14impl MultiThreadedBatchVerifier {
15    /// Create a new multithreaded batch verifier,
16    pub fn new(numb_threads: usize) -> Self {
17        Self {
18            internal: ThreadLocal::with_capacity(numb_threads),
19        }
20    }
21
22    pub fn verify(self) -> bool {
23        self.internal
24            .into_iter()
25            .map(RefCell::into_inner)
26            .par_bridge()
27            .try_for_each(|batch_verifier| {
28                if batch_verifier.verify() {
29                    Ok(())
30                } else {
31                    Err(())
32                }
33            })
34            .is_ok()
35    }
36}
37
38impl BatchVerifier for &'_ MultiThreadedBatchVerifier {
39    fn queue_statement<R>(&mut self, stmt: impl FnOnce(&mut InternalBatchVerifier) -> R) -> R {
40        let mut verifier = self
41            .internal
42            .get_or(|| RefCell::new(InternalBatchVerifier::new()))
43            .borrow_mut();
44
45        stmt(&mut verifier)
46    }
47}