diff --git a/src/bundle.rs b/src/bundle.rs index 890c3303..a9d4b4e3 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -7,11 +7,15 @@ use std::mem; use blake2b_simd::Hash as Blake2bHash; use nonempty::NonEmpty; +use zcash_note_encryption::try_note_decryption; use crate::{ + address::Address, bundle::commitments::{hash_bundle_auth_data, hash_bundle_txid_data}, circuit::{Instance, Proof, VerifyingKey}, - note::{ExtractedNoteCommitment, Nullifier, TransmittedNoteCiphertext}, + keys::IncomingViewingKey, + note::{ExtractedNoteCommitment, Note, Nullifier, TransmittedNoteCiphertext}, + note_encryption::OrchardDomain, primitives::redpallas::{self, Binding, SpendAuth}, tree::Anchor, value::{ValueCommitTrapdoor, ValueCommitment, ValueSum}, @@ -354,6 +358,25 @@ impl Bundle { .map(|a| a.to_instance(self.flags, self.anchor)) .collect() } + + /// Perform trial decryption of each action in the bundle with each of the + /// specified incoming viewing keys, and return the decrypted note contents + /// along with the index of the action from which it was derived. + pub fn decrypt_outputs_for_keys( + &self, + keys: &[IncomingViewingKey], + ) -> Vec<(usize, Note, Address, [u8; 512])> { + self.actions + .iter() + .enumerate() + .filter_map(|(idx, action)| { + let domain = OrchardDomain::for_action(action); + keys.iter().find_map(move |ivk| { + try_note_decryption(&domain, ivk, action).map(|(n, a, m)| (idx, n, a, m)) + }) + }) + .collect() + } } impl> Bundle { diff --git a/src/keys.rs b/src/keys.rs index 571b0dc6..4e474168 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -311,7 +311,7 @@ impl DiversifierKey { &self.0 } - /// Construct a diversifier key from bytes + /// Construct a diversifier key from bytes pub fn from_bytes(bytes: [u8; 32]) -> Self { DiversifierKey(bytes) }