2024-09-21 00:32:03 +00:00
|
|
|
use std::cell::RefCell;
|
2023-11-18 14:00:33 +00:00
|
|
|
|
2024-08-06 23:48:53 +00:00
|
|
|
use monero_serai::ringct::bulletproofs::BatchVerifier as InternalBatchVerifier;
|
2023-11-18 14:00:33 +00:00
|
|
|
use rayon::prelude::*;
|
|
|
|
use thread_local::ThreadLocal;
|
|
|
|
|
2024-08-06 23:48:53 +00:00
|
|
|
use cuprate_consensus_rules::batch_verifier::BatchVerifier;
|
|
|
|
|
2024-05-31 00:52:12 +00:00
|
|
|
/// A multithreaded batch verifier.
|
2023-11-18 14:00:33 +00:00
|
|
|
pub struct MultiThreadedBatchVerifier {
|
2024-08-06 23:48:53 +00:00
|
|
|
internal: ThreadLocal<RefCell<InternalBatchVerifier>>,
|
2023-11-18 14:00:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl MultiThreadedBatchVerifier {
|
|
|
|
/// Create a new multithreaded batch verifier,
|
2024-09-21 00:32:03 +00:00
|
|
|
pub fn new(numb_threads: usize) -> Self {
|
|
|
|
Self {
|
2023-11-18 14:00:33 +00:00
|
|
|
internal: ThreadLocal::with_capacity(numb_threads),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn verify(self) -> bool {
|
|
|
|
self.internal
|
|
|
|
.into_iter()
|
2024-05-31 00:52:12 +00:00
|
|
|
.map(RefCell::into_inner)
|
2023-11-18 14:00:33 +00:00
|
|
|
.par_bridge()
|
2024-08-06 23:48:53 +00:00
|
|
|
.try_for_each(|batch_verifier| {
|
|
|
|
if batch_verifier.verify() {
|
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err(())
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.is_ok()
|
2023-11-18 14:00:33 +00:00
|
|
|
}
|
|
|
|
}
|
2024-06-07 12:34:53 +00:00
|
|
|
|
2024-08-06 23:48:53 +00:00
|
|
|
impl BatchVerifier for &'_ MultiThreadedBatchVerifier {
|
|
|
|
fn queue_statement<R>(&mut self, stmt: impl FnOnce(&mut InternalBatchVerifier) -> R) -> R {
|
2024-06-07 12:34:53 +00:00
|
|
|
let mut verifier = self
|
|
|
|
.internal
|
2024-08-06 23:48:53 +00:00
|
|
|
.get_or(|| RefCell::new(InternalBatchVerifier::new()))
|
2024-06-07 12:34:53 +00:00
|
|
|
.borrow_mut();
|
|
|
|
|
2024-09-21 00:32:03 +00:00
|
|
|
stmt(&mut verifier)
|
2024-06-07 12:34:53 +00:00
|
|
|
}
|
|
|
|
}
|