Skip to content

Commit

Permalink
Merge pull request #1632 from Oscar-Pepper/sync_integration_balance_m…
Browse files Browse the repository at this point in the history
…ethods

Sync integration balance methods
  • Loading branch information
dorianvp authored Feb 5, 2025
2 parents b82fbe1 + 026d9d6 commit 8056551
Show file tree
Hide file tree
Showing 19 changed files with 907 additions and 889 deletions.
490 changes: 248 additions & 242 deletions libtonode-tests/tests/concrete.rs

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions libtonode-tests/tests/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ async fn sync_status() {
let lightclient = LightClient::create_from_wallet_base_async(
WalletBase::from_string(HOSPITAL_MUSEUM_SEED.to_string()),
&config,
2_750_000,
// 2_670_000,
// 2_750_000,
2_496_152,
true,
)
.await
Expand Down
550 changes: 276 additions & 274 deletions libtonode-tests/tests/wallet.rs

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions zingo-sync/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ name = "zingo-sync"
version = "0.1.0"
edition = "2021"

[features]
wallet_pack = []

[dependencies]
# Zingo
zingo-netutils = { path = "../zingo-netutils" }
Expand Down
6 changes: 4 additions & 2 deletions zingo-sync/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
//! Entrypoint: [`crate::sync::sync`]
//!
//! Terminology:
//! Chain height - highest block height of best chain from the server
//! Wallet height - highest block height of blockchain known to the wallet. Commonly used, to determine the chain height
//! Chain height - highest block height of best chain from the server.
//! Wallet height - highest block height of blockchain known to the wallet. Commonly used to determine the chain height
//! of the previous sync, before the server is contacted to update the wallet height to the new chain height.
//! Fully scanned height - block height in which the wallet has completed scanning all blocks equal to and below this height.
Expand All @@ -25,3 +25,5 @@ pub mod sync;
pub mod traits;
pub(crate) mod utils;
pub mod witness;

pub(crate) const MAX_BATCH_OUTPUTS: usize = 16_384; // 2^14
178 changes: 145 additions & 33 deletions zingo-sync/src/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ pub struct WalletBlock {
#[getset(skip)]
txids: Vec<TxId>,
tree_boundaries: TreeBoundaries,
// TODO: optional price
}

impl WalletBlock {
Expand Down Expand Up @@ -282,7 +283,9 @@ pub struct WalletTransaction {
#[getset(get = "pub")]
transaction: zcash_primitives::transaction::Transaction,
#[getset(get_copy = "pub")]
confirmation_status: ConfirmationStatus,
status: ConfirmationStatus,
#[getset(skip)]
transparent_coins: Vec<TransparentCoin>,
#[getset(skip)]
sapling_notes: Vec<SaplingNote>,
#[getset(skip)]
Expand All @@ -291,26 +294,24 @@ pub struct WalletTransaction {
outgoing_sapling_notes: Vec<OutgoingSaplingNote>,
#[getset(skip)]
outgoing_orchard_notes: Vec<OutgoingOrchardNote>,
#[getset(skip)]
transparent_coins: Vec<TransparentCoin>,
}

impl WalletTransaction {
#[allow(clippy::too_many_arguments)]
pub fn from_parts(
txid: TxId,
transaction: zcash_primitives::transaction::Transaction,
confirmation_status: ConfirmationStatus,
status: ConfirmationStatus,
transparent_coins: Vec<TransparentCoin>,
sapling_notes: Vec<SaplingNote>,
orchard_notes: Vec<OrchardNote>,
outgoing_sapling_notes: Vec<OutgoingSaplingNote>,
outgoing_orchard_notes: Vec<OutgoingOrchardNote>,
transparent_coins: Vec<TransparentCoin>,
) -> Self {
Self {
txid,
transaction,
confirmation_status,
status,
sapling_notes,
orchard_notes,
outgoing_sapling_notes,
Expand All @@ -319,6 +320,13 @@ impl WalletTransaction {
}
}

pub fn transparent_coins(&self) -> &[TransparentCoin] {
&self.transparent_coins
}

pub fn transparent_coins_mut(&mut self) -> Vec<&mut TransparentCoin> {
self.transparent_coins.iter_mut().collect()
}
pub fn sapling_notes(&self) -> &[SaplingNote] {
&self.sapling_notes
}
Expand All @@ -342,54 +350,39 @@ impl WalletTransaction {
pub fn outgoing_orchard_notes(&self) -> &[OutgoingOrchardNote] {
&self.outgoing_orchard_notes
}

pub fn transparent_coins(&self) -> &[TransparentCoin] {
&self.transparent_coins
}

pub fn transparent_coins_mut(&mut self) -> Vec<&mut TransparentCoin> {
self.transparent_coins.iter_mut().collect()
}
}

impl std::fmt::Debug for WalletTransaction {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("WalletTransaction")
.field("confirmation_status", &self.confirmation_status)
.field("confirmation_status", &self.status)
.field("transparent_coins", &self.transparent_coins)
.field("sapling_notes", &self.sapling_notes)
.field("orchard_notes", &self.orchard_notes)
.field("outgoing_sapling_notes", &self.outgoing_sapling_notes)
.field("outgoing_orchard_notes", &self.outgoing_orchard_notes)
.field("transparent_coins", &self.transparent_coins)
.finish()
}
}
pub type SaplingNote = WalletNote<sapling_crypto::Note, sapling_crypto::Nullifier>;
pub type OrchardNote = WalletNote<orchard::Note, orchard::note::Nullifier>;

/// Wallet note, shielded output with metadata relevant to the wallet
#[derive(Debug, Getters, CopyGetters, Setters)]
#[derive(Debug, Clone)]
pub struct WalletNote<N, Nf: Copy> {
/// Output ID
#[getset(get_copy = "pub")]
output_id: OutputId,
pub(crate) output_id: OutputId,
/// Identifier for key used to decrypt output
#[getset(get_copy = "pub")]
key_id: KeyId,
pub(crate) key_id: KeyId,
/// Decrypted note with recipient and value
#[getset(get = "pub")]
note: N,
pub(crate) note: N,
/// Derived nullifier
#[getset(get_copy = "pub")]
nullifier: Option<Nf>, //TODO: syncing without nullifier deriving key
pub(crate) nullifier: Option<Nf>, //TODO: syncing without nullifier deriving key
/// Commitment tree leaf position
#[getset(get_copy = "pub")]
position: Option<Position>,
pub(crate) position: Option<Position>,
/// Memo
#[getset(get = "pub")]
memo: Memo,
#[getset(get = "pub", set = "pub")]
spending_transaction: Option<TxId>,
pub(crate) memo: Memo,
/// Transaction this note was spent in.
/// If `None`, note is not spent.
pub(crate) spending_transaction: Option<TxId>,
}

impl<N, Nf: Copy> WalletNote<N, Nf> {
Expand All @@ -414,6 +407,125 @@ impl<N, Nf: Copy> WalletNote<N, Nf> {
}
}

pub trait NoteInterface: Sized {
type ZcashNote;
type Nullifier: Copy;

/// Output ID
fn output_id(&self) -> OutputId;

/// Identifier for key used to decrypt output
fn key_id(&self) -> KeyId;

/// Decrypted note with recipient and value
fn note(&self) -> &Self::ZcashNote;

/// Derived nullifier
fn nullifier(&self) -> Option<Self::Nullifier>;

/// Commitment tree leaf position
fn position(&self) -> Option<Position>;

/// Memo
fn memo(&self) -> &Memo;

/// Txid of transaction this note was spent in.
/// If `None`, note is not spent.
fn spending_transaction(&self) -> Option<TxId>;

/// Note value.
fn value(&self) -> u64;

/// Notes within `transaction`.
fn transaction_notes(transaction: &WalletTransaction) -> &[Self];
}

pub type SaplingNote = WalletNote<sapling_crypto::Note, sapling_crypto::Nullifier>;

impl NoteInterface for SaplingNote {
type ZcashNote = sapling_crypto::Note;
type Nullifier = sapling_crypto::Nullifier;

fn output_id(&self) -> OutputId {
self.output_id
}

fn key_id(&self) -> KeyId {
self.key_id
}

fn note(&self) -> &Self::ZcashNote {
&self.note
}

fn nullifier(&self) -> Option<sapling_crypto::Nullifier> {
self.nullifier
}

fn position(&self) -> Option<Position> {
self.position
}

fn memo(&self) -> &Memo {
&self.memo
}

fn spending_transaction(&self) -> Option<TxId> {
self.spending_transaction
}

fn value(&self) -> u64 {
self.note.value().inner()
}

fn transaction_notes(transaction: &WalletTransaction) -> &[SaplingNote] {
transaction.sapling_notes()
}
}

pub type OrchardNote = WalletNote<orchard::Note, orchard::note::Nullifier>;

impl NoteInterface for OrchardNote {
type ZcashNote = orchard::Note;
type Nullifier = orchard::note::Nullifier;

fn output_id(&self) -> OutputId {
self.output_id
}

fn key_id(&self) -> KeyId {
self.key_id
}

fn note(&self) -> &Self::ZcashNote {
&self.note
}

fn nullifier(&self) -> Option<orchard::note::Nullifier> {
self.nullifier
}

fn position(&self) -> Option<Position> {
self.position
}

fn memo(&self) -> &Memo {
&self.memo
}

fn spending_transaction(&self) -> Option<TxId> {
self.spending_transaction
}

fn value(&self) -> u64 {
self.note.value().inner()
}

fn transaction_notes(transaction: &WalletTransaction) -> &[OrchardNote] {
transaction.orchard_notes()
}
}

pub type OutgoingSaplingNote = OutgoingNote<sapling_crypto::Note>;
pub type OutgoingOrchardNote = OutgoingNote<orchard::Note>;

Expand Down
4 changes: 2 additions & 2 deletions zingo-sync/src/scan/compact_blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::{
keys::{KeyId, ScanningKeyOps, ScanningKeys},
primitives::{NullifierMap, OutputId, TreeBoundaries, WalletBlock},
witness::WitnessData,
MAX_BATCH_OUTPUTS,
};

use self::runners::{BatchRunners, DecryptedOutput};
Expand All @@ -34,8 +35,7 @@ use super::{

mod runners;

// TODO: move parameters to config module
const TRIAL_DECRYPT_TASK_SIZE: usize = 1_024; // 2^10
const TRIAL_DECRYPT_TASK_SIZE: usize = MAX_BATCH_OUTPUTS / 16;

pub(crate) fn scan_compact_blocks<P>(
compact_blocks: Vec<CompactBlock>,
Expand Down
2 changes: 1 addition & 1 deletion zingo-sync/src/scan/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ use crate::{
primitives::{Locator, WalletBlock},
sync,
traits::{SyncBlocks, SyncWallet},
MAX_BATCH_OUTPUTS,
};

use super::{compact_blocks::calculate_block_tree_boundaries, error::ScanError, scan, ScanResults};

const MAX_WORKER_POOLSIZE: usize = 2;
const MAX_BATCH_OUTPUTS: usize = 8_192; // 2^13

pub(crate) enum ScannerState {
Verification,
Expand Down
4 changes: 2 additions & 2 deletions zingo-sync/src/scan/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,11 +297,11 @@ pub(crate) fn scan_transaction<P: consensus::Parameters>(
transaction.txid(),
transaction,
confirmation_status,
transparent_coins,
sapling_notes,
orchard_notes,
outgoing_sapling_notes,
outgoing_orchard_notes,
transparent_coins,
))
}

Expand Down Expand Up @@ -430,7 +430,7 @@ fn parse_encoded_memos<N, Nf: Copy>(
let encoded_memos = wallet_notes
.iter()
.flat_map(|note| {
if let Memo::Arbitrary(ref encoded_memo_bytes) = note.memo() {
if let Memo::Arbitrary(ref encoded_memo_bytes) = note.memo {
Some(zingo_memo::parse_zingo_memo(*encoded_memo_bytes.as_ref()).unwrap())
} else {
None
Expand Down
6 changes: 3 additions & 3 deletions zingo-sync/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub(crate) mod state;
pub(crate) mod transparent;

const VERIFY_BLOCK_RANGE_SIZE: u32 = 10;
const MAX_VERIFICATION_WINDOW: u32 = 100;
pub(crate) const MAX_VERIFICATION_WINDOW: u32 = 100;

/// Syncs a wallet to the latest state of the blockchain
pub async fn sync<P, W>(
Expand Down Expand Up @@ -377,7 +377,7 @@ async fn process_mempool_transaction<W>(
.unwrap()
.get(&transaction.txid())
{
if tx.confirmation_status().is_confirmed() {
if tx.status().is_confirmed() {
return;
}
}
Expand Down Expand Up @@ -537,7 +537,7 @@ where
.get_wallet_transactions()
.unwrap()
.values()
.filter_map(|tx| tx.confirmation_status().get_confirmed_height())
.filter_map(|tx| tx.status().get_confirmed_height())
.collect::<Vec<_>>();

wallet.get_wallet_blocks_mut().unwrap().retain(|height, _| {
Expand Down
Loading

0 comments on commit 8056551

Please sign in to comment.