Jack Grigg
5 years ago
2 changed files with 79 additions and 0 deletions
@ -0,0 +1,76 @@ |
|||||||
|
use pairing::bls12_381::Bls12; |
||||||
|
use zcash_primitives::{ |
||||||
|
note_encryption::{try_sapling_note_decryption, try_sapling_output_recovery, Memo}, |
||||||
|
primitives::{Note, PaymentAddress}, |
||||||
|
transaction::Transaction, |
||||||
|
zip32::ExtendedFullViewingKey, |
||||||
|
JUBJUB, |
||||||
|
}; |
||||||
|
|
||||||
|
/// A decrypted shielded output.
|
||||||
|
pub struct DecryptedOutput { |
||||||
|
/// The index of the output within [`shielded_outputs`].
|
||||||
|
///
|
||||||
|
/// [`shielded_outputs`]: zcash_primitives::transaction::TransactionData
|
||||||
|
pub index: usize, |
||||||
|
/// The note within the output.
|
||||||
|
pub note: Note<Bls12>, |
||||||
|
/// The address the note was sent to.
|
||||||
|
pub to: PaymentAddress<Bls12>, |
||||||
|
/// The memo included with the note.
|
||||||
|
pub memo: Memo, |
||||||
|
/// True if this output was recovered using an [`OutgoingViewingKey`], meaning that
|
||||||
|
/// this is a logical output of the transaction.
|
||||||
|
///
|
||||||
|
/// [`OutgoingViewingKey`]: zcash_primitives::keys::OutgoingViewingKey
|
||||||
|
pub outgoing: bool, |
||||||
|
} |
||||||
|
|
||||||
|
/// Scans a [`Transaction`] for any information that can be decrypted by the set of
|
||||||
|
/// [`ExtendedFullViewingKey`]s.
|
||||||
|
pub fn decrypt_transaction( |
||||||
|
tx: &Transaction, |
||||||
|
extfvks: &[ExtendedFullViewingKey], |
||||||
|
) -> Vec<DecryptedOutput> { |
||||||
|
let mut decrypted = vec![]; |
||||||
|
|
||||||
|
// Cache IncomingViewingKey calculation
|
||||||
|
let vks: Vec<_> = extfvks |
||||||
|
.iter() |
||||||
|
.map(|extfvk| (extfvk.fvk.vk.ivk(), extfvk.fvk.ovk)) |
||||||
|
.collect(); |
||||||
|
|
||||||
|
for (index, output) in tx.shielded_outputs.iter().enumerate() { |
||||||
|
let epk = match output.ephemeral_key.as_prime_order(&JUBJUB) { |
||||||
|
Some(p) => p, |
||||||
|
None => continue, |
||||||
|
}; |
||||||
|
|
||||||
|
for (ivk, ovk) in &vks { |
||||||
|
let ((note, to, memo), outgoing) = |
||||||
|
match try_sapling_note_decryption(ivk, &epk, &output.cmu, &output.enc_ciphertext) { |
||||||
|
Some(ret) => (ret, false), |
||||||
|
None => match try_sapling_output_recovery( |
||||||
|
ovk, |
||||||
|
&output.cv, |
||||||
|
&output.cmu, |
||||||
|
&epk, |
||||||
|
&output.enc_ciphertext, |
||||||
|
&output.out_ciphertext, |
||||||
|
) { |
||||||
|
Some(ret) => (ret, true), |
||||||
|
None => continue, |
||||||
|
}, |
||||||
|
}; |
||||||
|
decrypted.push(DecryptedOutput { |
||||||
|
index, |
||||||
|
note, |
||||||
|
to, |
||||||
|
memo, |
||||||
|
outgoing, |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
decrypted |
||||||
|
} |
Loading…
Reference in new issue