use std::sync::Arc;
use orchard::bundle::{Authorized, Bundle};
use zakura_chain::{
block::Block,
parameters::NetworkUpgrade,
serialization::ZcashDeserializeInto,
transaction::{HashType, SigHash},
transparent,
};
use zcash_protocol::value::ZatBalance;
use super::{
verifier_for, Item, VERIFIER_NU6_2, VERIFIER_NU6_3_ONWARD, VERIFIER_PRE_NU6_2,
VERIFYING_KEY_NU6_2, VERIFYING_KEY_PRE_NU6_2,
};
fn pre_nu6_2_bundle_and_sighash() -> (Bundle<Authorized, ZatBalance>, SigHash) {
for bytes in zakura_test::vectors::MAINNET_BLOCKS.values() {
let block: Block = bytes
.zcash_deserialize_into()
.expect("hard-coded test vector must deserialize");
for tx in &block.transactions {
if tx.orchard_shielded_data().is_none() || !tx.inputs().is_empty() {
continue;
}
let all_previous_outputs: Arc<Vec<transparent::Output>> = Arc::new(Vec::new());
let Ok(sighasher) = tx.sighasher(NetworkUpgrade::Nu5, all_previous_outputs) else {
continue;
};
let Some(bundle) = sighasher.orchard_bundle() else {
continue;
};
let sighash = sighasher.sighash(HashType::ALL, None);
return (bundle, sighash);
}
}
panic!("mainnet test blocks must contain a transparent-input-free Orchard transaction");
}
#[test]
fn pre_nu6_2_proof_only_verifies_under_pre_nu6_2_key() {
let (bundle, sighash) = pre_nu6_2_bundle_and_sighash();
assert!(
Item::new(bundle.clone(), sighash).verify_single(&VERIFYING_KEY_PRE_NU6_2),
"a real pre-NU6.2 Orchard proof must verify under the pre-NU6.2 (insecure) key"
);
assert!(
!Item::new(bundle, sighash).verify_single(&VERIFYING_KEY_NU6_2),
"a pre-NU6.2 Orchard proof must be REJECTED by the post-NU6.2 (fixed) key; \
verifying it would mean the era selection is fail-open"
);
}
#[tokio::test(flavor = "multi_thread")]
async fn verifier_routes_each_network_upgrade_to_the_correct_key() {
let pre: &'static super::VerifierService = &VERIFIER_PRE_NU6_2;
let nu6_2: &'static super::VerifierService = &VERIFIER_NU6_2;
let nu6_3_onward: &'static super::VerifierService = &VERIFIER_NU6_3_ONWARD;
for nu in [
NetworkUpgrade::Nu5,
NetworkUpgrade::Nu6,
NetworkUpgrade::Nu6_1,
] {
assert!(
std::ptr::eq(verifier_for(nu), pre),
"{nu:?} must route to the pre-NU6.2 (insecure) verifier"
);
}
assert!(
std::ptr::eq(verifier_for(NetworkUpgrade::Nu6_2), nu6_2),
"Nu6_2 must route to the NU6.2 (fixed) verifier"
);
for nu in [NetworkUpgrade::Nu6_3, NetworkUpgrade::Nu7] {
assert!(
std::ptr::eq(verifier_for(nu), nu6_3_onward),
"{nu:?} must route to the NU6.3-onward verifier even for v5 Orchard bundles"
);
}
assert!(
std::ptr::eq(verifier_for(NetworkUpgrade::Nu6_3), nu6_3_onward),
"a v5 Orchard bundle at NU6.3 must use the same key as v6 Orchard and Ironwood"
);
}