diff --git a/zcash_client_sqlite/src/chain.rs b/zcash_client_sqlite/src/chain.rs index 51f40723ba..fdc3ca6f2f 100644 --- a/zcash_client_sqlite/src/chain.rs +++ b/zcash_client_sqlite/src/chain.rs @@ -16,6 +16,12 @@ struct CompactBlockRow { data: Vec, } +/// Implements a traversal of `limit` blocks of the block cache database. +/// +/// Starting at `from_height`, the `with_row` callback is invoked +/// with each block retrieved from the backing store. If the `limit` +/// value provided is `None`, all blocks are traversed up to the +/// maximum height. pub fn with_blocks( cache: &BlockDB, from_height: BlockHeight, diff --git a/zcash_client_sqlite/src/error.rs b/zcash_client_sqlite/src/error.rs index 0cc1754f8a..e67f3dcf0a 100644 --- a/zcash_client_sqlite/src/error.rs +++ b/zcash_client_sqlite/src/error.rs @@ -1,3 +1,5 @@ +//! Error types for problems that may arise when reading or storing wallet data to SQLite. + use std::error; use std::fmt; @@ -5,6 +7,7 @@ use zcash_client_backend::data_api; use crate::NoteId; +/// The primary error type for the SQLite wallet backend. #[derive(Debug)] pub enum SqliteClientError { /// Decoding of a stored value from its serialized form has failed. diff --git a/zcash_client_sqlite/src/lib.rs b/zcash_client_sqlite/src/lib.rs index 22825b5a23..2b62ed93f3 100644 --- a/zcash_client_sqlite/src/lib.rs +++ b/zcash_client_sqlite/src/lib.rs @@ -1,7 +1,9 @@ //! *An SQLite-based Zcash light client.* //! -//! `zcash_client_backend` contains a set of APIs that collectively implement an -//! SQLite-based light client for the Zcash network. +//! `zcash_client_sqlite` contains complete SQLite-based implementations of the [`WalletRead`], +//! [`WalletWrite`], and [`BlockSource`] traits from the [`zcash_client_backend`] crate. In +//! combination with [`zcash_client_backend`], it provides a full implementation of a SQLite-backed +//! client for the Zcash network. //! //! # Design //! @@ -21,6 +23,9 @@ //! The `mainnet` feature configures the light client for use with the Zcash mainnet. By //! default, the light client is configured for use with the Zcash testnet. //! +//! [`WalletRead`]: zcash_client_backend::data_api::WalletRead +//! [`WalletWrite`]: zcash_client_backend::data_api::WalletWrite +//! [`BlockSource`]: zcash_client_backend::data_api::BlockSource //! [`CompactBlock`]: zcash_client_backend::proto::compact_formats::CompactBlock //! [`init_cache_database`]: crate::chain::init::init_cache_database @@ -73,7 +78,7 @@ impl fmt::Display for NoteId { } } -/// A wrapper for the sqlite connection to the wallet database. +/// A wrapper for the SQLite connection to the wallet database. pub struct WalletDB

{ conn: Connection, params: P, @@ -250,6 +255,13 @@ impl WalletRead for WalletDB

{ } } +/// The primary type used to implement [`WalletWrite`] for the SQLite database. +/// +/// A data structure that stores the SQLite prepared statements that are +/// required for the implementation of [`WalletWrite`] against the backing +/// store. +/// +/// [`WalletWrite`]: zcash_client_backend::data_api::WalletWrite pub struct DataConnStmtCache<'a, P> { wallet_db: &'a WalletDB

, stmt_insert_block: Statement<'a>, @@ -499,9 +511,11 @@ impl<'a, P: consensus::Parameters> WalletWrite for DataConnStmtCache<'a, P> { } } +/// A wrapper for the SQLite connection to the block cache database. pub struct BlockDB(Connection); impl BlockDB { + /// Opens a connection to the wallet database stored at the specified path. pub fn for_path>(path: P) -> Result { Connection::open(path).map(BlockDB) } diff --git a/zcash_client_sqlite/src/wallet.rs b/zcash_client_sqlite/src/wallet.rs index 02cc513bcd..a4821e07a6 100644 --- a/zcash_client_sqlite/src/wallet.rs +++ b/zcash_client_sqlite/src/wallet.rs @@ -1,4 +1,11 @@ //! Functions for querying information in the wdb database. +//! +//! These functions should generally not be used directly; instead, +//! their functionality is available via the [`WalletRead`] and +//! [`WalletWrite`] traits. +//! +//! [`WalletRead`]: zcash_client_backend::data_api::WalletRead +//! [`WalletWrite`]: zcash_client_backend::data_api::WalletWrite use ff::PrimeField; use rusqlite::{params, OptionalExtension, ToSql, NO_PARAMS}; @@ -32,11 +39,7 @@ use crate::{error::SqliteClientError, DataConnStmtCache, NoteId, WalletDB}; pub mod init; pub mod transact; -/// This trait provides a generalization over shielded output representations -/// that allows a wallet to avoid coupling to a specific one. -// TODO: it'd probably be better not to unify the definitions of -// `WalletShieldedOutput` and `DecryptedOutput` via a compositional -// approach, if possible. +/// This trait provides a generalization over shielded output representations. pub trait ShieldedOutput { fn index(&self) -> usize; fn account(&self) -> AccountId; @@ -130,6 +133,9 @@ pub fn get_address( .map_err(SqliteClientError::Bech32) } +/// Returns the [`ExtendedFullViewingKey`]s for the wallet. +/// +/// [`ExtendedFullViewingKey`]: zcash_primitives::zip32::ExtendedFullViewingKey pub fn get_extended_full_viewing_keys( wdb: &WalletDB

, ) -> Result, SqliteClientError> { @@ -163,6 +169,10 @@ pub fn get_extended_full_viewing_keys( Ok(res) } +/// Checks whether the specified [`ExtendedFullViewingKey`] is valid and corresponds to the +/// specified account. +/// +/// [`ExtendedFullViewingKey`]: zcash_primitives::zip32::ExtendedFullViewingKey pub fn is_valid_account_extfvk( wdb: &WalletDB

, account: AccountId, @@ -327,6 +337,22 @@ pub fn get_sent_memo

(wdb: &WalletDB

, id_note: i64) -> Result( wdb: &WalletDB

, ) -> Result, rusqlite::Error> { @@ -348,6 +374,24 @@ pub fn block_height_extrema

( .or(Ok(None)) } +/// Returns the block height at which the specified transaction was mined, +/// if any. +/// +/// # Examples +/// +/// ``` +/// use tempfile::NamedTempFile; +/// use zcash_primitives::consensus::Network; +/// use zcash_primitives::transaction::TxId; +/// use zcash_client_sqlite::{ +/// WalletDB, +/// wallet::get_tx_height, +/// }; +/// +/// let data_file = NamedTempFile::new().unwrap(); +/// let db = WalletDB::for_path(data_file, Network::TestNetwork).unwrap(); +/// let height = get_tx_height(&db, TxId([0u8; 32])); +/// ``` pub fn get_tx_height

( wdb: &WalletDB

, txid: TxId, @@ -361,6 +405,23 @@ pub fn get_tx_height

( .optional() } +/// Returns the block hash for the block at the specified height, +/// if any. +/// +/// # Examples +/// +/// ``` +/// use tempfile::NamedTempFile; +/// use zcash_primitives::consensus::{H0, Network}; +/// use zcash_client_sqlite::{ +/// WalletDB, +/// wallet::get_block_hash, +/// }; +/// +/// let data_file = NamedTempFile::new().unwrap(); +/// let db = WalletDB::for_path(data_file, Network::TestNetwork).unwrap(); +/// let hash = get_block_hash(&db, H0); +/// ``` pub fn get_block_hash

( wdb: &WalletDB

, block_height: BlockHeight, @@ -427,6 +488,23 @@ pub fn rewind_to_height( } } +/// Returns the commitment tree for the block at the specified height, +/// if any. +/// +/// # Examples +/// +/// ``` +/// use tempfile::NamedTempFile; +/// use zcash_primitives::consensus::{Network, H0}; +/// use zcash_client_sqlite::{ +/// WalletDB, +/// wallet::get_commitment_tree, +/// }; +/// +/// let data_file = NamedTempFile::new().unwrap(); +/// let db = WalletDB::for_path(data_file, Network::TestNetwork).unwrap(); +/// let tree = get_commitment_tree(&db, H0); +/// ``` pub fn get_commitment_tree

( wdb: &WalletDB

, block_height: BlockHeight, @@ -450,6 +528,23 @@ pub fn get_commitment_tree

( .map_err(SqliteClientError::from) } +/// Returns the incremental witnesses for the block at the specified height, +/// if any. +/// +/// # Examples +/// +/// ``` +/// use tempfile::NamedTempFile; +/// use zcash_primitives::consensus::{Network, H0}; +/// use zcash_client_sqlite::{ +/// WalletDB, +/// wallet::get_witnesses, +/// }; +/// +/// let data_file = NamedTempFile::new().unwrap(); +/// let db = WalletDB::for_path(data_file, Network::TestNetwork).unwrap(); +/// let witnesses = get_witnesses(&db, H0); +/// ``` pub fn get_witnesses

( wdb: &WalletDB

, block_height: BlockHeight, @@ -494,6 +589,7 @@ pub fn get_nullifiers

( Ok(res) } +/// Inserts information about a scanned block into the database. pub fn insert_block<'a, P>( stmts: &mut DataConnStmtCache<'a, P>, block_height: BlockHeight, @@ -514,6 +610,8 @@ pub fn insert_block<'a, P>( Ok(()) } +/// Inserts information about a mined transaction that was observed to +/// contain a note related to this wallet into the database. pub fn put_tx_meta<'a, P, N>( stmts: &mut DataConnStmtCache<'a, P>, tx: &WalletTx, @@ -540,6 +638,7 @@ pub fn put_tx_meta<'a, P, N>( } } +/// Inserts full transaction data into the database. pub fn put_tx_data<'a, P>( stmts: &mut DataConnStmtCache<'a, P>, tx: &Transaction, @@ -573,6 +672,11 @@ pub fn put_tx_data<'a, P>( } } +/// Marks a given nullifier as having been revealed in the construction +/// of the specified transaction. +/// +/// Marking a note spent in this fashion does NOT imply that the +/// spending transaction has been mined. pub fn mark_spent<'a, P>( stmts: &mut DataConnStmtCache<'a, P>, tx_ref: i64, @@ -584,6 +688,7 @@ pub fn mark_spent<'a, P>( Ok(()) } +/// Records the specified shielded output as having been received. // Assumptions: // - A transaction will not contain more than 2^63 shielded outputs. // - A note value will never exceed 2^63 zatoshis. @@ -634,6 +739,8 @@ pub fn put_received_note<'a, P, T: ShieldedOutput>( } } +/// Records the incremental witness for the specified note, +/// as of the given block height. pub fn insert_witness<'a, P>( stmts: &mut DataConnStmtCache<'a, P>, note_id: i64, @@ -650,6 +757,7 @@ pub fn insert_witness<'a, P>( Ok(()) } +/// Removes old incremental witnesses up to the given block height. pub fn prune_witnesses<'a, P>( stmts: &mut DataConnStmtCache<'a, P>, below_height: BlockHeight, @@ -660,6 +768,8 @@ pub fn prune_witnesses<'a, P>( Ok(()) } +/// Marks notes that have not been mined in transactions +/// as expired, up to the given block height. pub fn update_expired_notes<'a, P>( stmts: &mut DataConnStmtCache<'a, P>, height: BlockHeight, @@ -668,6 +778,7 @@ pub fn update_expired_notes<'a, P>( Ok(()) } +/// Records information about a note that your wallet created. pub fn put_sent_note<'a, P: consensus::Parameters>( stmts: &mut DataConnStmtCache<'a, P>, output: &DecryptedOutput,