bitcoin_rs_script/
batch.rs1use rayon::prelude::*;
2use secp256k1::{Message, XOnlyPublicKey, schnorr::Signature};
3
4#[must_use]
10pub fn verify_schnorr_batch(items: &[(Signature, Message, XOnlyPublicKey)]) -> bool {
11 items.par_iter().all(|(signature, message, public_key)| {
12 secp256k1::SECP256K1
13 .verify_schnorr(signature, message.as_ref(), public_key)
14 .is_ok()
15 })
16}
17
18#[cfg(test)]
19mod tests {
20 use secp256k1::{Keypair, Message, Secp256k1, SecretKey, XOnlyPublicKey};
21
22 use super::verify_schnorr_batch;
23
24 #[test]
25 fn batch_verify_is_conjunction_of_individual_verification() {
26 let secp = Secp256k1::new();
27 let secret = match SecretKey::from_byte_array([3; 32]) {
28 Ok(secret) => secret,
29 Err(error) => panic!("fixed secret key should be valid: {error}"),
30 };
31 let keypair = Keypair::from_secret_key(&secp, &secret);
32 let (public_key, _) = XOnlyPublicKey::from_keypair(&keypair);
33 let items: Vec<_> = (0u8..20)
34 .map(|byte| {
35 let message = Message::from_digest([byte; 32]);
36 let signature = secp.sign_schnorr(message.as_ref(), &keypair);
37 (signature, message, public_key)
38 })
39 .collect();
40
41 assert!(verify_schnorr_batch(&items));
42 }
43}