use std::convert::TryInto; use ff::PrimeField; use zcash_note_encryption::Domain; use zcash_primitives::consensus::{BlockHeight, Parameters}; use zcash_primitives::sapling::note_encryption::SaplingDomain; use zcash_primitives::sapling::{PaymentAddress, SaplingIvk}; use zcash_primitives::zip32::ExtendedFullViewingKey; use crate::chain::Nf; use crate::CompactTx; use crate::db::ReceivedNote; use crate::sync::Node; use crate::sync::{CompactOutputBytes, DecryptedNote, OutputPosition, TrialDecrypter, ViewKey}; #[derive(Clone)] pub struct SaplingViewKey { pub account: u32, pub fvk: ExtendedFullViewingKey, pub ivk: SaplingIvk, } impl ViewKey> for SaplingViewKey { fn account(&self) -> u32 { self.account } fn ivk(&self) -> as Domain>::IncomingViewingKey { self.ivk.clone() } } pub struct DecryptedSaplingNote { pub vk: SaplingViewKey, pub note: zcash_primitives::sapling::Note, pub pa: PaymentAddress, pub output_position: OutputPosition, pub cmx: Node, } impl DecryptedNote, SaplingViewKey> for DecryptedSaplingNote { fn from_parts(vk: SaplingViewKey, note: zcash_primitives::sapling::Note, pa: PaymentAddress, output_position: OutputPosition, cmx: Node) -> Self { DecryptedSaplingNote { vk, note, pa, output_position, cmx, } } fn position(&self, block_offset: usize) -> usize { block_offset + self.output_position.position_in_block } fn cmx(&self) -> Node { self.cmx } fn to_received_note(&self, position: u64) -> ReceivedNote { let viewing_key = &self.vk.fvk.fvk.vk; ReceivedNote { account: self.vk.account, height: self.output_position.height, output_index: self.output_position.output_index as u32, diversifier: self.pa.diversifier().0.to_vec(), value: self.note.value, rcm: self.note.rcm().to_repr().to_vec(), nf: self.note.nf(viewing_key, position).to_vec(), rho: None, spent: None } } } #[derive(Clone)] pub struct SaplingDecrypter { pub network: N, } impl SaplingDecrypter { pub fn new(network: N) -> Self { SaplingDecrypter { network, } } } impl TrialDecrypter, SaplingViewKey, DecryptedSaplingNote> for SaplingDecrypter { fn domain(&self, height: BlockHeight) -> SaplingDomain { SaplingDomain::::for_height(self.network.clone(), height) } fn spends(&self, vtx: &CompactTx) -> Vec { vtx.spends.iter().map(|co| { let nf: [u8; 32] = co.nf.clone().try_into().unwrap(); Nf(nf) }).collect() } fn outputs(&self, vtx: &CompactTx) -> Vec { vtx.outputs.iter().map(|co| co.into()).collect() } }