Skip to content

Commit

Permalink
zcash_client_sqlite: Implement get_orchard_nullifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
nuttycom committed Mar 7, 2024
1 parent ece4cef commit 0f5a8fe
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 35 deletions.
10 changes: 3 additions & 7 deletions zcash_client_sqlite/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,19 +405,15 @@ impl<C: Borrow<rusqlite::Connection>, P: consensus::Parameters> WalletRead for W
&self,
query: NullifierQuery,
) -> Result<Vec<(AccountId, sapling::Nullifier)>, Self::Error> {
match query {
NullifierQuery::Unspent => wallet::sapling::get_sapling_nullifiers(self.conn.borrow()),
NullifierQuery::All => wallet::sapling::get_all_sapling_nullifiers(self.conn.borrow()),
}
wallet::sapling::get_sapling_nullifiers(self.conn.borrow(), query)
}

#[cfg(feature = "orchard")]
fn get_orchard_nullifiers(
&self,
_query: NullifierQuery,
query: NullifierQuery,
) -> Result<Vec<(AccountId, orchard::note::Nullifier)>, Self::Error> {
// FIXME! Orchard.
Ok(vec![])
wallet::orchard::get_orchard_nullifiers(self.conn.borrow(), query)
}

#[cfg(feature = "transparent-inputs")]
Expand Down
44 changes: 43 additions & 1 deletion zcash_client_sqlite/src/wallet/orchard.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use incrementalmerkletree::Position;
use rusqlite::{named_params, Connection};

use zcash_client_backend::{wallet::WalletOrchardOutput, DecryptedOutput, TransferType};
use zcash_client_backend::{
data_api::NullifierQuery, wallet::WalletOrchardOutput, DecryptedOutput, TransferType,
};
use zcash_protocol::memo::MemoBytes;
use zip32::Scope;

Expand Down Expand Up @@ -153,3 +155,43 @@ pub(crate) fn put_received_note<T: ReceivedOrchardOutput>(

Ok(())
}

/// Retrieves the set of nullifiers for "potentially spendable" Orchard notes that the
/// wallet is tracking.
///
/// "Potentially spendable" means:
/// - The transaction in which the note was created has been observed as mined.
/// - No transaction in which the note's nullifier appears has been observed as mined.
pub(crate) fn get_orchard_nullifiers(
conn: &Connection,
query: NullifierQuery,
) -> Result<Vec<(AccountId, orchard::note::Nullifier)>, SqliteClientError> {
// Get the nullifiers for the notes we are tracking
let mut stmt_fetch_nullifiers = match query {
NullifierQuery::Unspent => conn.prepare(
"SELECT rn.id, rn.account_id, rn.nf
FROM orchard_received_notes rn
LEFT OUTER JOIN transactions tx
ON tx.id_tx = rn.spent
WHERE tx.block IS NULL
AND nf IS NOT NULL",
)?,
NullifierQuery::All => conn.prepare(
"SELECT rn.id, rn.account_id, rn.nf
FROM orchard_received_notes rn
WHERE nf IS NOT NULL",
)?,
};

let nullifiers = stmt_fetch_nullifiers.query_and_then([], |row| {
let account = AccountId(row.get(1)?);
let nf_bytes: [u8; 32] = row.get(2)?;
Ok::<_, rusqlite::Error>((
account,
orchard::note::Nullifier::from_bytes(&nf_bytes).unwrap(),
))
})?;

let res: Vec<_> = nullifiers.collect::<Result<_, _>>()?;
Ok(res)
}
44 changes: 17 additions & 27 deletions zcash_client_sqlite/src/wallet/sapling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::rc::Rc;

use sapling::{self, Diversifier, Nullifier, Rseed};
use zcash_client_backend::{
data_api::NullifierQuery,
keys::UnifiedFullViewingKey,
wallet::{Note, ReceivedNote, WalletSaplingOutput},
DecryptedOutput, TransferType,
Expand Down Expand Up @@ -323,36 +324,25 @@ pub(crate) fn select_spendable_sapling_notes<P: consensus::Parameters>(
/// - No transaction in which the note's nullifier appears has been observed as mined.
pub(crate) fn get_sapling_nullifiers(
conn: &Connection,
query: NullifierQuery,
) -> Result<Vec<(AccountId, Nullifier)>, SqliteClientError> {
// Get the nullifiers for the notes we are tracking
let mut stmt_fetch_nullifiers = conn.prepare(
"SELECT rn.id, rn.account_id, rn.nf, tx.block as block
FROM sapling_received_notes rn
LEFT OUTER JOIN transactions tx
ON tx.id_tx = rn.spent
WHERE block IS NULL
AND nf IS NOT NULL",
)?;
let nullifiers = stmt_fetch_nullifiers.query_and_then([], |row| {
let account = AccountId(row.get(1)?);
let nf_bytes: Vec<u8> = row.get(2)?;
Ok::<_, rusqlite::Error>((account, sapling::Nullifier::from_slice(&nf_bytes).unwrap()))
})?;

let res: Vec<_> = nullifiers.collect::<Result<_, _>>()?;
Ok(res)
}
let mut stmt_fetch_nullifiers = match query {
NullifierQuery::Unspent => conn.prepare(
"SELECT rn.id, rn.account_id, rn.nf
FROM sapling_received_notes rn
LEFT OUTER JOIN transactions tx
ON tx.id_tx = rn.spent
WHERE tx.block IS NULL
AND nf IS NOT NULL",
),
NullifierQuery::All => conn.prepare(
"SELECT rn.id, rn.account_id, rn.nf
FROM sapling_received_notes rn
WHERE nf IS NOT NULL",
),
}?;

/// Returns the nullifiers for the notes that this wallet is tracking.
pub(crate) fn get_all_sapling_nullifiers(
conn: &Connection,
) -> Result<Vec<(AccountId, Nullifier)>, SqliteClientError> {
// Get the nullifiers for the notes we are tracking
let mut stmt_fetch_nullifiers = conn.prepare(
"SELECT rn.id, rn.account_id, rn.nf
FROM sapling_received_notes rn
WHERE nf IS NOT NULL",
)?;
let nullifiers = stmt_fetch_nullifiers.query_and_then([], |row| {
let account = AccountId(row.get(1)?);
let nf_bytes: Vec<u8> = row.get(2)?;
Expand Down

0 comments on commit 0f5a8fe

Please sign in to comment.