Skip to main content

pczt/roles/tx_extractor/
orchard.rs

1use orchard::{Bundle, bundle::Authorized, circuit::VerifyingKey};
2use rand_core::CryptoRng;
3use zcash_protocol::value::ZatBalance;
4
5pub(super) fn verify_bundle(
6    rng: impl CryptoRng,
7    bundle: &Bundle<Authorized, ZatBalance>,
8    orchard_vk: Option<&VerifyingKey>,
9    sighash: [u8; 32],
10) -> Result<(), OrchardError> {
11    match orchard_vk {
12        Some(vk) => verify_bundle_with_key(rng, bundle, vk, sighash),
13        // The circuit version is fixed by the bundle's own `BundleVersion`, which
14        // `extract_tx_data` derives from the PCZT's consensus branch ID.
15        None => verify_bundle_with_key(
16            rng,
17            bundle,
18            &VerifyingKey::build(bundle.bundle_version().circuit_version()),
19            sighash,
20        ),
21    }
22}
23
24fn verify_bundle_with_key(
25    rng: impl CryptoRng,
26    bundle: &Bundle<Authorized, ZatBalance>,
27    vk: &VerifyingKey,
28    sighash: [u8; 32],
29) -> Result<(), OrchardError> {
30    let mut validator = orchard::bundle::BatchValidator::new(vk);
31    validator
32        .add_bundle(bundle, sighash)
33        .map_err(|_| OrchardError::InvalidProof)?;
34
35    if validator.validate(rng) {
36        Ok(())
37    } else {
38        Err(OrchardError::InvalidProof)
39    }
40}
41
42#[derive(Debug)]
43pub enum OrchardError {
44    Extract(orchard::pczt::TxExtractorError),
45    InvalidProof,
46}