zebra_chain/primitives/
zcash_note_encryption.rs1use std::ops::Deref;
5
6use crate::{
7 block::Height,
8 parameters::{Network, NetworkUpgrade},
9 transaction::Transaction,
10};
11
12pub fn decrypts_successfully(tx: &Transaction, network: &Network, height: Height) -> bool {
15 let nu = NetworkUpgrade::current(network, height);
16
17 let null_sapling_ovk = sapling_crypto::keys::OutgoingViewingKey([0u8; 32]);
18
19 let zip_212_enforcement = if nu >= NetworkUpgrade::Canopy {
22 sapling_crypto::note_encryption::Zip212Enforcement::On
23 } else {
24 sapling_crypto::note_encryption::Zip212Enforcement::Off
25 };
26
27 if let Some(bundle) = tx.inner().deref().sapling_bundle() {
28 for output in bundle.shielded_outputs().iter() {
29 let recovery = sapling_crypto::note_encryption::try_sapling_output_recovery(
30 &null_sapling_ovk,
31 output,
32 zip_212_enforcement,
33 );
34 if recovery.is_none() {
35 return false;
36 }
37 }
38 }
39
40 if let Some(bundle) = tx.inner().deref().orchard_bundle() {
41 for act in bundle.actions() {
42 if zcash_note_encryption::try_output_recovery_with_ovk(
43 &orchard::note_encryption::OrchardDomain::for_action(act),
44 &orchard::keys::OutgoingViewingKey::from([0u8; 32]),
45 act,
46 act.cv_net(),
47 &act.encrypted_note().out_ciphertext,
48 )
49 .is_none()
50 {
51 return false;
52 }
53 }
54 }
55
56 if let Some(bundle) = tx.ironwood_bundle() {
60 for act in bundle.actions() {
61 if zcash_note_encryption::try_output_recovery_with_ovk(
62 &orchard::note_encryption::IronwoodDomain::for_action(act),
63 &orchard::keys::OutgoingViewingKey::from([0u8; 32]),
64 act,
65 act.cv_net(),
66 &act.encrypted_note().out_ciphertext,
67 )
68 .is_none()
69 {
70 return false;
71 }
72 }
73 }
74
75 true
76}