Skip to content

Commit

Permalink
Merge branch 'dev' into fix_is_outgoing_double_count_bug
Browse files Browse the repository at this point in the history
  • Loading branch information
zancas authored May 31, 2024
2 parents cdf656e + 314d3e9 commit e8a0549
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 7 deletions.
10 changes: 8 additions & 2 deletions libtonode-tests/tests/legacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1460,7 +1460,10 @@ mod slow {
- first_send_to_transparent
- (2 * u64::from(MINIMUM_FEE));
assert_eq!(
recipient.wallet.maybe_verified_orchard_balance(None).await,
recipient
.wallet
.shielded_balance::<OrchardDomain>(None, &[])
.await,
Some(expected_funds)
);
assert_eq!(
Expand Down Expand Up @@ -1543,7 +1546,10 @@ mod slow {
- third_send_to_transparent
- (3 * u64::from(MINIMUM_FEE));
assert_eq!(
recipient.wallet.maybe_verified_orchard_balance(None).await,
recipient
.wallet
.shielded_balance::<OrchardDomain>(None, &[])
.await,
Some(second_wave_expected_funds),
);

Expand Down
12 changes: 11 additions & 1 deletion zingolib/src/mocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,16 @@ pub mod orchard_note {
build_method!(rho, Rho);
build_method!(random_seed, RandomSeed);

/// selects a default recipient address for the orchard note
pub fn default_recipient(&mut self) -> &mut Self {
let bytes = [0; 32];
let sk = SpendingKey::from_bytes(bytes).unwrap();
let fvk: FullViewingKey = (&sk).into();
let recipient = fvk.address_at(0u32, Scope::External);

self.recipient(recipient)
}

/// selects a random recipient address for the orchard note
pub fn randomize_recipient(&mut self) -> &mut Self {
let mut rng = OsRng;
Expand Down Expand Up @@ -343,7 +353,7 @@ pub mod orchard_note {
impl Default for OrchardCryptoNoteBuilder {
fn default() -> Self {
Self::new()
.randomize_recipient()
.default_recipient()
.randomize_rho_and_rseed()
.value(NoteValue::from_raw(800_000))
.clone()
Expand Down
128 changes: 125 additions & 3 deletions zingolib/src/wallet/describe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use orchard::note_encryption::OrchardDomain;

use sapling_crypto::note_encryption::SaplingDomain;
use zcash_primitives::transaction::fees::zip317::MARGINAL_FEE;

use std::{cmp, sync::Arc};
use tokio::sync::RwLock;
Expand Down Expand Up @@ -82,6 +83,7 @@ impl LightWallet {
}

/// TODO: Add Doc Comment Here!
// TODO: this should minus the fee of sending the confirmed balance!
pub async fn spendable_orchard_balance(&self, target_addr: Option<String>) -> Option<u64> {
if let Capability::Spend(_) = self.wallet_capability().orchard {
self.verified_balance::<OrchardDomain>(target_addr).await
Expand All @@ -91,6 +93,7 @@ impl LightWallet {
}

/// TODO: Add Doc Comment Here!
// TODO: this should minus the fee of sending the confirmed balance!
pub async fn spendable_sapling_balance(&self, target_addr: Option<String>) -> Option<u64> {
if let Capability::Spend(_) = self.wallet_capability().sapling {
self.verified_balance::<SaplingDomain>(target_addr).await
Expand Down Expand Up @@ -161,12 +164,33 @@ impl LightWallet {
self.shielded_balance::<D>(target_addr, filters).await
}

/// TODO: Add Doc Comment Here!
/// Returns balance for a given shielded pool excluding any notes with value less than marginal fee
/// that are confirmed on the block chain (the block has at least 1 confirmation)
pub async fn confirmed_balance_excluding_dust<D: DomainWalletExt>(
&self,
target_addr: Option<String>,
) -> Option<u64>
where
<D as Domain>::Recipient: Recipient,
<D as Domain>::Note: PartialEq + Clone,
{
#[allow(clippy::type_complexity)]
let filters: &[Box<dyn Fn(&&D::WalletNote, &TransactionRecord) -> bool>] = &[
Box::new(|_, transaction| transaction.status.is_confirmed()),
Box::new(|note, _| !note.pending_receipt()),
Box::new(|note, _| note.value() >= MARGINAL_FEE.into_u64()),
];
self.shielded_balance::<D>(target_addr, filters).await
}

/// Deprecated for `shielded_balance`
#[deprecated(note = "deprecated for `shielded_balance` as incorrectly named and unnecessary")]
pub async fn maybe_verified_orchard_balance(&self, addr: Option<String>) -> Option<u64> {
self.shielded_balance::<OrchardDomain>(addr, &[]).await
}

/// TODO: Add Doc Comment Here!
/// Deprecated for `shielded_balance`
#[deprecated(note = "deprecated for `shielded_balance` as incorrectly named and unnecessary")]
pub async fn maybe_verified_sapling_balance(&self, addr: Option<String>) -> Option<u64> {
self.shielded_balance::<SaplingDomain>(addr, &[]).await
}
Expand Down Expand Up @@ -203,7 +227,7 @@ impl LightWallet {
/// Get the height of the anchor block
pub async fn get_anchor_height(&self) -> u32 {
match self.get_target_height_and_anchor_offset().await {
Some((height, anchor_offset)) => height - anchor_offset as u32 - 1,
Some((height, anchor_offset)) => height - anchor_offset as u32 - 1, // what is the purpose of this -1 ?
None => 0,
}
}
Expand Down Expand Up @@ -290,3 +314,101 @@ impl LightWallet {
self.transaction_context.transaction_metadata_set.clone()
}
}

#[cfg(test)]
mod tests {
use orchard::note_encryption::OrchardDomain;
use sapling_crypto::note_encryption::SaplingDomain;

use zingo_status::confirmation_status::ConfirmationStatus;
use zingoconfig::ZingoConfigBuilder;

use crate::{
mocks::{orchard_note::OrchardCryptoNoteBuilder, SaplingCryptoNoteBuilder},
wallet::{
notes::{
orchard::mocks::OrchardNoteBuilder, sapling::mocks::SaplingNoteBuilder,
transparent::mocks::TransparentOutputBuilder,
},
transaction_record::mocks::TransactionRecordBuilder,
LightWallet, WalletBase,
},
};

#[tokio::test]
async fn confirmed_balance_excluding_dust() {
let wallet = LightWallet::new(
ZingoConfigBuilder::default().create(),
WalletBase::FreshEntropy,
1,
)
.unwrap();
let confirmed_tx_record = TransactionRecordBuilder::default()
.status(ConfirmationStatus::Confirmed(80.into()))
.transparent_outputs(TransparentOutputBuilder::default())
.sapling_notes(SaplingNoteBuilder::default())
.sapling_notes(SaplingNoteBuilder::default())
.sapling_notes(
SaplingNoteBuilder::default()
.note(
SaplingCryptoNoteBuilder::default()
.value(sapling_crypto::value::NoteValue::from_raw(3_000))
.clone(),
)
.clone(),
)
.orchard_notes(OrchardNoteBuilder::default())
.orchard_notes(OrchardNoteBuilder::default())
.orchard_notes(
OrchardNoteBuilder::default()
.note(
OrchardCryptoNoteBuilder::default()
.value(orchard::value::NoteValue::from_raw(5_000))
.clone(),
)
.clone(),
)
.orchard_notes(
OrchardNoteBuilder::default()
.note(
OrchardCryptoNoteBuilder::default()
.value(orchard::value::NoteValue::from_raw(2_000))
.clone(),
)
.clone(),
)
.build();
let pending_tx_record = TransactionRecordBuilder::default()
.status(ConfirmationStatus::Pending(95.into()))
.transparent_outputs(TransparentOutputBuilder::default())
.sapling_notes(SaplingNoteBuilder::default())
.orchard_notes(OrchardNoteBuilder::default())
.build();
{
let mut tx_map = wallet
.transaction_context
.transaction_metadata_set
.write()
.await;
tx_map
.transaction_records_by_id
.insert_transaction_record(confirmed_tx_record);
tx_map
.transaction_records_by_id
.insert_transaction_record(pending_tx_record);
}

assert_eq!(
wallet
.confirmed_balance_excluding_dust::<SaplingDomain>(None)
.await,
Some(400_000)
);
assert_eq!(
wallet
.confirmed_balance_excluding_dust::<OrchardDomain>(None)
.await,
Some(1_605_000)
);
}
}
2 changes: 1 addition & 1 deletion zingolib/src/wallet/transaction_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ pub mod mocks {
),
),
datetime: Some(1705077003),
txid: Some(crate::mocks::default_txid()),
txid: Some(crate::mocks::random_txid()),
spent_sapling_nullifiers: vec![],
spent_orchard_nullifiers: vec![],
transparent_outputs: vec![],
Expand Down

0 comments on commit e8a0549

Please sign in to comment.