diff --git a/zingolib/src/wallet/transaction_record.rs b/zingolib/src/wallet/transaction_record.rs index c4b7eda91..c67efd962 100644 --- a/zingolib/src/wallet/transaction_record.rs +++ b/zingolib/src/wallet/transaction_record.rs @@ -1,21 +1,26 @@ //! TODO: Add Mod Description Here! +use crate::wallet::notes::interface::ShieldedNoteInterface as _; +use std::io::{self, Read, Write}; + +use byteorder::{LittleEndian, ReadBytesExt as _, WriteBytesExt as _}; use incrementalmerkletree::witness::IncrementalWitness; -use zcash_primitives::transaction::TxId; +use orchard::tree::MerkleHashOrchard; +use zcash_primitives::{consensus::BlockHeight, transaction::TxId}; use crate::error::ZingoLibError; use crate::wallet::notes; use super::{ - data::{OutgoingTxData, PoolNullifier}, - traits::DomainWalletExt, - *, + data::{OutgoingTxData, PoolNullifier, COMMITMENT_TREE_LEVELS}, + keys::unified::WalletCapability, + traits::{DomainWalletExt, ReadableWriteable as _}, }; /// Everything (SOMETHING) about a transaction #[derive(Debug)] pub struct TransactionRecord { /// the relationship of the transaction to the blockchain. can be either Broadcast (to mempool}, or Confirmed. - pub status: ConfirmationStatus, + pub status: zingo_status::confirmation_status::ConfirmationStatus, /// Timestamp of Tx. Added in v4 pub datetime: u64, @@ -58,7 +63,11 @@ pub struct TransactionRecord { // set impl TransactionRecord { /// TODO: Add Doc Comment Here! - pub fn new(status: ConfirmationStatus, datetime: u64, transaction_id: &TxId) -> Self { + pub fn new( + status: zingo_status::confirmation_status::ConfirmationStatus, + datetime: u64, + transaction_id: &TxId, + ) -> Self { TransactionRecord { status, datetime, @@ -126,8 +135,13 @@ impl TransactionRecord { /// TODO: Add Doc Comment Here! pub fn is_incoming_transaction(&self) -> bool { - self.sapling_notes.iter().any(|note| !note.is_change()) - || self.orchard_notes.iter().any(|note| !note.is_change()) + self.sapling_notes + .iter() + .any(|note| !notes::ShieldedNoteInterface::is_change(note)) + || self + .orchard_notes + .iter() + .any(|note| !notes::ShieldedNoteInterface::is_change(note)) || !self.transparent_notes.is_empty() } @@ -140,8 +154,8 @@ impl TransactionRecord { /// TODO: Add Doc Comment Here! fn pool_change_returned(&self) -> u64 where - ::Note: PartialEq + Clone, - ::Recipient: traits::Recipient, + ::Note: PartialEq + Clone, + ::Recipient: super::traits::Recipient, { D::sum_pool_change(self) } @@ -149,8 +163,8 @@ impl TransactionRecord { /// TODO: Add Doc Comment Here! pub fn pool_value_received(&self) -> u64 where - ::Note: PartialEq + Clone, - ::Recipient: traits::Recipient, + ::Note: PartialEq + Clone, + ::Recipient: super::traits::Recipient, { D::to_notes_vec(self) .iter() @@ -160,13 +174,14 @@ impl TransactionRecord { /// TODO: Add Doc Comment Here! pub fn total_change_returned(&self) -> u64 { - self.pool_change_returned::() + self.pool_change_returned::() + self.pool_change_returned::() + + self.pool_change_returned::() } /// TODO: Add Doc Comment Here! pub fn total_value_received(&self) -> u64 { - self.pool_value_received::() - + self.pool_value_received::() + self.pool_value_received::() + + self.pool_value_received::() + self .transparent_notes .iter() @@ -236,17 +251,17 @@ impl TransactionRecord { let transaction_id = TxId::from_bytes(transaction_id_bytes); - let sapling_notes = Vector::read_collected_mut(&mut reader, |r| { + let sapling_notes = zcash_encoding::Vector::read_collected_mut(&mut reader, |r| { notes::SaplingNote::read(r, (wallet_capability, trees.as_mut().map(|t| &mut t.0))) })?; let orchard_notes = if version > 22 { - Vector::read_collected_mut(&mut reader, |r| { + zcash_encoding::Vector::read_collected_mut(&mut reader, |r| { notes::OrchardNote::read(r, (wallet_capability, trees.as_mut().map(|t| &mut t.1))) })? } else { vec![] }; - let utxos = Vector::read(&mut reader, |r| notes::TransparentNote::read(r))?; + let utxos = zcash_encoding::Vector::read(&mut reader, |r| notes::TransparentNote::read(r))?; let total_sapling_value_spent = reader.read_u64::()?; let total_transparent_value_spent = reader.read_u64::()?; @@ -257,20 +272,21 @@ impl TransactionRecord { }; // Outgoing metadata was only added in version 2 - let outgoing_metadata = Vector::read(&mut reader, |r| OutgoingTxData::read(r))?; + let outgoing_metadata = + zcash_encoding::Vector::read(&mut reader, |r| OutgoingTxData::read(r))?; let _full_tx_scanned = reader.read_u8()? > 0; let zec_price = if version <= 4 { None } else { - Optional::read(&mut reader, |r| r.read_f64::())? + zcash_encoding::Optional::read(&mut reader, |r| r.read_f64::())? }; let spent_sapling_nullifiers = if version <= 5 { vec![] } else { - Vector::read(&mut reader, |r| { + zcash_encoding::Vector::read(&mut reader, |r| { let mut n = [0u8; 32]; r.read_exact(&mut n)?; Ok(sapling_crypto::Nullifier(n)) @@ -280,13 +296,13 @@ impl TransactionRecord { let spent_orchard_nullifiers = if version <= 21 { vec![] } else { - Vector::read(&mut reader, |r| { + zcash_encoding::Vector::read(&mut reader, |r| { let mut n = [0u8; 32]; r.read_exact(&mut n)?; Ok(orchard::note::Nullifier::from_bytes(&n).unwrap()) })? }; - let status = ConfirmationStatus::from_blockheight_and_unconfirmed_bool(block, unconfirmed); + let status = zingo_status::confirmation_status::ConfirmationStatus::from_blockheight_and_unconfirmed_bool(block, unconfirmed); Ok(Self { status, datetime, @@ -322,27 +338,27 @@ impl TransactionRecord { writer.write_all(self.txid.as_ref())?; - Vector::write(&mut writer, &self.sapling_notes, |w, nd| nd.write(w))?; - Vector::write(&mut writer, &self.orchard_notes, |w, nd| nd.write(w))?; - Vector::write(&mut writer, &self.transparent_notes, |w, u| u.write(w))?; + zcash_encoding::Vector::write(&mut writer, &self.sapling_notes, |w, nd| nd.write(w))?; + zcash_encoding::Vector::write(&mut writer, &self.orchard_notes, |w, nd| nd.write(w))?; + zcash_encoding::Vector::write(&mut writer, &self.transparent_notes, |w, u| u.write(w))?; for pool in self.value_spent_by_pool() { writer.write_u64::(pool)?; } // Write the outgoing metadata - Vector::write(&mut writer, &self.outgoing_tx_data, |w, om| om.write(w))?; + zcash_encoding::Vector::write(&mut writer, &self.outgoing_tx_data, |w, om| om.write(w))?; writer.write_u8(0)?; - Optional::write(&mut writer, self.price, |w, p| { + zcash_encoding::Optional::write(&mut writer, self.price, |w, p| { w.write_f64::(p) })?; - Vector::write(&mut writer, &self.spent_sapling_nullifiers, |w, n| { + zcash_encoding::Vector::write(&mut writer, &self.spent_sapling_nullifiers, |w, n| { w.write_all(&n.0) })?; - Vector::write(&mut writer, &self.spent_orchard_nullifiers, |w, n| { + zcash_encoding::Vector::write(&mut writer, &self.spent_orchard_nullifiers, |w, n| { w.write_all(&n.to_bytes()) })?; @@ -416,8 +432,6 @@ mod tests { use crate::wallet::notes::transparent::mocks::TransparentNoteBuilder; use crate::wallet::transaction_record::mocks::TransactionRecordBuilder; - use super::*; - #[test] pub fn blank_record() { let new = TransactionRecordBuilder::default().build(); @@ -426,8 +440,14 @@ mod tests { assert!(!new.is_outgoing_transaction()); assert!(!new.is_incoming_transaction()); // assert_eq!(new.net_spent(), 0); - assert_eq!(new.pool_change_returned::(), 0); - assert_eq!(new.pool_change_returned::(), 0); + assert_eq!( + new.pool_change_returned::(), + 0 + ); + assert_eq!( + new.pool_change_returned::(), + 0 + ); assert_eq!(new.total_value_received(), 0); assert_eq!(new.total_value_spent(), 0); assert_eq!(new.value_outgoing(), 0);