cuprate_consensus/
batch_verifier.rs1use 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
9pub struct MultiThreadedBatchVerifier {
11 internal: ThreadLocal<RefCell<InternalBatchVerifier>>,
12}
13
14impl MultiThreadedBatchVerifier {
15 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}