diff --git a/zcash_client_backend/src/data_api/chain.rs b/zcash_client_backend/src/data_api/chain.rs index 1555785f85..143e45ca97 100644 --- a/zcash_client_backend/src/data_api/chain.rs +++ b/zcash_client_backend/src/data_api/chain.rs @@ -161,6 +161,8 @@ use crate::{ pub mod error; use error::Error; +use super::WalletRead; + /// A struct containing metadata about a subtree root of the note commitment tree. /// /// This stores the block height at which the leaf that completed the subtree was @@ -277,6 +279,7 @@ where ParamsT: consensus::Parameters + Send + 'static, BlockSourceT: BlockSource, DbT: WalletWrite, + ::AccountPK: 'static, { // Fetch the UnifiedFullViewingKeys we are tracking let ufvks = data_db diff --git a/zcash_client_backend/src/scanning.rs b/zcash_client_backend/src/scanning.rs index 6e521165d1..f3eb61a178 100644 --- a/zcash_client_backend/src/scanning.rs +++ b/zcash_client_backend/src/scanning.rs @@ -255,7 +255,7 @@ pub fn scan_block, ) -> Result, ScanError> where - AccountPK: Copy + Clone + Send + PartialEq + Eq + std::hash::Hash, + AccountPK: Copy + Clone + Send + PartialEq + Eq + std::hash::Hash + 'static, { scan_block_with_runner::<_, _, (), AccountPK>( params, @@ -268,10 +268,14 @@ where } type TaggedBatch = - Batch<(AccountId, S), SaplingDomain, CompactOutputDescription, CompactDecryptor>; -type TaggedBatchRunner = - BatchRunner<(AccountId, S), SaplingDomain, CompactOutputDescription, CompactDecryptor, T>; +type TaggedBatchRunner = BatchRunner< + (AccountId, S), + SaplingDomain, + CompactOutputDescription, + CompactDecryptor, + T, +>; #[tracing::instrument(skip_all, fields(height = block.height))] pub(crate) fn add_block_to_runner( @@ -282,7 +286,7 @@ pub(crate) fn add_block_to_runner( P: consensus::Parameters + Send + 'static, S: Clone + Send + 'static, T: Tasks>, - AccountPK: Copy + Clone + Send + PartialEq + Eq + std::hash::Hash, + AccountPK: Copy + Clone + Send + PartialEq + Eq + std::hash::Hash + 'static, { let block_hash = block.hash(); let block_height = block.height(); @@ -345,7 +349,7 @@ pub(crate) fn scan_block_with_runner< mut batch_runner: Option<&mut TaggedBatchRunner>, ) -> Result, ScanError> where - AccountPK: std::cmp::Eq + std::hash::Hash + Clone + Send + Copy, + AccountPK: std::cmp::Eq + std::hash::Hash + Clone + Send + Copy + 'static, { if let Some(scan_error) = check_hash_continuity(&block, prior_block_metadata) { return Err(scan_error); diff --git a/zcash_client_sqlite/src/error.rs b/zcash_client_sqlite/src/error.rs index b28a139645..70f1fa32fb 100644 --- a/zcash_client_sqlite/src/error.rs +++ b/zcash_client_sqlite/src/error.rs @@ -4,6 +4,8 @@ use std::error; use std::fmt; use shardtree::error::ShardTreeError; +use zcash_client_backend::data_api::AccountParameters; +use zcash_client_backend::data_api::HDSeedAccount; use zcash_client_backend::{ data_api::AccountId, encoding::{Bech32DecodeError, TransparentCodecError}, @@ -71,11 +73,11 @@ pub enum SqliteClientError { DiversifierIndexOutOfRange, /// The account for which information was requested does not belong to the wallet. - AccountUnknown(AccountId), + AccountUnknown(AccountParameters), // TODO: AccountId would probably be a bit better here, but would make the error type generic /// An error occurred deriving a spending key from a seed and an account /// identifier. - KeyDerivationError(AccountId), // Is there a way to constrain this to AccountId::Zip32? + KeyDerivationError(HDSeedAccount), /// A caller attempted to initialize the accounts table with a discontinuous /// set of account identifiers. diff --git a/zcash_client_sqlite/src/lib.rs b/zcash_client_sqlite/src/lib.rs index 241bac52f6..cbba65681a 100644 --- a/zcash_client_sqlite/src/lib.rs +++ b/zcash_client_sqlite/src/lib.rs @@ -184,14 +184,15 @@ impl, P: consensus::Parameters> InputSource for wallet::sapling::get_spendable_sapling_note(self.conn.borrow(), &self.params, txid, index) } - fn select_spendable_notes( + fn select_spendable_notes( &self, - account: AccountId, + account: AccountId, target_value: Amount, _sources: &[ShieldedProtocol], anchor_height: BlockHeight, exclude: &[Self::NoteRef], - ) -> Result>, Self::Error> { + ) -> Result>, Self::Error> + where AccountPK : Copy + Clone + Send + PartialEq + Eq + std::hash::Hash{ wallet::sapling::select_spendable_sapling_notes( self.conn.borrow(), &self.params, @@ -282,13 +283,16 @@ impl, P: consensus::Parameters> WalletRead for W wallet::wallet_birthday(self.conn.borrow()).map_err(SqliteClientError::from) } - fn get_account_birthday(&self, account: AccountId) -> Result { + fn get_account_birthday( + &self, + account: AccountId, + ) -> Result { wallet::account_birthday(self.conn.borrow(), account).map_err(SqliteClientError::from) } fn get_current_address( &self, - account: AccountId, + account: AccountId, ) -> Result, Self::Error> { wallet::get_current_address(self.conn.borrow(), &self.params, account) .map(|res| res.map(|(addr, _)| addr)) @@ -296,21 +300,21 @@ impl, P: consensus::Parameters> WalletRead for W fn get_unified_full_viewing_keys( &self, - ) -> Result, Self::Error> { + ) -> Result, UnifiedFullViewingKey>, Self::Error> { wallet::get_unified_full_viewing_keys(self.conn.borrow(), &self.params) } fn get_account_for_ufvk( &self, ufvk: &UnifiedFullViewingKey, - ) -> Result, Self::Error> { + ) -> Result>, Self::Error> { wallet::get_account_for_ufvk(self.conn.borrow(), &self.params, ufvk) } fn get_wallet_summary( &self, min_confirmations: u32, - ) -> Result, Self::Error> { + ) -> Result>, Self::Error> { // This will return a runtime error if we call `get_wallet_summary` from two // threads at the same time, as transactions cannot nest. wallet::get_wallet_summary( @@ -337,7 +341,7 @@ impl, P: consensus::Parameters> WalletRead for W fn get_sapling_nullifiers( &self, query: NullifierQuery, - ) -> Result, Self::Error> { + ) -> Result, 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()), @@ -346,7 +350,7 @@ impl, P: consensus::Parameters> WalletRead for W fn get_transparent_receivers( &self, - _account: AccountId, + _account: AccountId, ) -> Result, Self::Error> { #[cfg(feature = "transparent-inputs")] return wallet::get_transparent_receivers(self.conn.borrow(), &self.params, _account); @@ -359,7 +363,7 @@ impl, P: consensus::Parameters> WalletRead for W fn get_transparent_balances( &self, - _account: AccountId, + _account: AccountId, _max_height: BlockHeight, ) -> Result, Self::Error> { #[cfg(feature = "transparent-inputs")] @@ -380,11 +384,11 @@ impl, P: consensus::Parameters> WalletRead for W fn get_orchard_nullifiers( &self, _query: NullifierQuery, - ) -> Result, Self::Error> { + ) -> Result, orchard::note::Nullifier)>, Self::Error> { todo!() } - fn get_account_ids(&self) -> Result, Self::Error> { + fn get_account_ids(&self) -> Result>, Self::Error> { wallet::get_account_ids(self.conn.borrow()) } } @@ -396,7 +400,7 @@ impl WalletWrite for WalletDb &mut self, seed: &SecretVec, birthday: AccountBirthday, - ) -> Result<(AccountId, UnifiedSpendingKey), Self::Error> { + ) -> Result<(AccountId, UnifiedSpendingKey), Self::Error> { let seed_id = HDSeedFingerprint::from_seed(seed); self.transactionally(|wdb| { let account_id = wallet::get_max_account_id(wdb.conn.0, &seed_id)? @@ -420,7 +424,7 @@ impl WalletWrite for WalletDb fn get_next_available_address( &mut self, - account: AccountId, + account: AccountId, request: UnifiedAddressRequest, ) -> Result, Self::Error> { self.transactionally( @@ -460,7 +464,7 @@ impl WalletWrite for WalletDb #[allow(clippy::type_complexity)] fn put_blocks( &mut self, - blocks: Vec>, + blocks: Vec>, ) -> Result<(), Self::Error> { self.transactionally(|wdb| { let start_positions = blocks.first().map(|block| { @@ -599,11 +603,14 @@ impl WalletWrite for WalletDb Ok(()) } - fn store_decrypted_tx(&mut self, d_tx: DecryptedTransaction) -> Result<(), Self::Error> { + fn store_decrypted_tx( + &mut self, + d_tx: DecryptedTransaction, + ) -> Result<(), Self::Error> { self.transactionally(|wdb| { let tx_ref = wallet::put_tx_data(wdb.conn.0, d_tx.tx, None, None)?; - let mut spending_account_id: Option = None; + let mut spending_account_id: Option> = None; for output in d_tx.sapling_outputs { match output.transfer_type { TransferType::Outgoing | TransferType::WalletInternal => { @@ -690,7 +697,10 @@ impl WalletWrite for WalletDb }) } - fn store_sent_tx(&mut self, sent_tx: &SentTransaction) -> Result<(), Self::Error> { + fn store_sent_tx( + &mut self, + sent_tx: &SentTransaction, + ) -> Result<(), Self::Error> { self.transactionally(|wdb| { let tx_ref = wallet::put_tx_data( wdb.conn.0, @@ -1132,7 +1142,7 @@ extern crate assert_matches; mod tests { use zcash_client_backend::data_api::{AccountBirthday, WalletRead, WalletWrite}; - use crate::{testing::TestBuilder, AccountId, DEFAULT_UA_REQUEST}; + use crate::{testing::TestBuilder, DEFAULT_UA_REQUEST}; #[cfg(feature = "unstable")] use { diff --git a/zcash_client_sqlite/src/testing.rs b/zcash_client_sqlite/src/testing.rs index 31ca460d32..9485031406 100644 --- a/zcash_client_sqlite/src/testing.rs +++ b/zcash_client_sqlite/src/testing.rs @@ -91,6 +91,8 @@ pub(crate) struct TestBuilder { test_account_birthday: Option, } +type AccountPK = (); + impl TestBuilder<()> { /// Constructs a new test. pub(crate) fn new() -> Self { @@ -160,7 +162,7 @@ pub(crate) struct TestState { latest_cached_block: Option<(BlockHeight, BlockHash, u32)>, _data_file: NamedTempFile, db_data: WalletDb, - test_account: Option<(AccountId, UnifiedSpendingKey, AccountBirthday)>, + test_account: Option<(AccountId, UnifiedSpendingKey, AccountBirthday)>, } impl TestState @@ -418,7 +420,7 @@ impl TestState { } /// Exposes the test account, if enabled via [`TestBuilder::with_test_account`]. - pub(crate) fn test_account(&self) -> Option<(AccountId, UnifiedSpendingKey, AccountBirthday)> { + pub(crate) fn test_account(&self) -> Option<(AccountId, UnifiedSpendingKey, AccountBirthday)> { self.test_account.as_ref().cloned() } @@ -508,7 +510,7 @@ impl TestState { #[allow(clippy::type_complexity)] pub(crate) fn propose_transfer( &mut self, - spend_from_account: AccountId, + spend_from_account: AccountId, input_selector: &InputsT, request: zip321::TransactionRequest, min_confirmations: NonZeroU32, @@ -540,7 +542,7 @@ impl TestState { #[allow(clippy::too_many_arguments)] pub(crate) fn propose_standard_transfer( &mut self, - spend_from_account: AccountId, + spend_from_account: AccountId, fee_rule: StandardFeeRule, min_confirmations: NonZeroU32, to: &Address, @@ -679,7 +681,7 @@ impl TestState { fn with_account_balance T>( &self, - account: AccountId, + account: AccountId, min_confirmations: u32, f: F, ) -> T { @@ -687,13 +689,13 @@ impl TestState { f(binding.account_balances().get(&account).unwrap()) } - pub(crate) fn get_total_balance(&self, account: AccountId) -> NonNegativeAmount { + pub(crate) fn get_total_balance(&self, account: AccountId) -> NonNegativeAmount { self.with_account_balance(account, 0, |balance| balance.total()) } pub(crate) fn get_spendable_balance( &self, - account: AccountId, + account: AccountId, min_confirmations: u32, ) -> NonNegativeAmount { self.with_account_balance(account, min_confirmations, |balance| { @@ -703,7 +705,7 @@ impl TestState { pub(crate) fn get_pending_shielded_balance( &self, - account: AccountId, + account: AccountId, min_confirmations: u32, ) -> NonNegativeAmount { self.with_account_balance(account, min_confirmations, |balance| { @@ -716,7 +718,7 @@ impl TestState { #[allow(dead_code)] pub(crate) fn get_pending_change( &self, - account: AccountId, + account: AccountId, min_confirmations: u32, ) -> NonNegativeAmount { self.with_account_balance(account, min_confirmations, |balance| { @@ -724,7 +726,7 @@ impl TestState { }) } - pub(crate) fn get_wallet_summary(&self, min_confirmations: u32) -> Option { + pub(crate) fn get_wallet_summary(&self, min_confirmations: u32) -> Option> { get_wallet_summary( &self.wallet().conn.unchecked_transaction().unwrap(), &self.wallet().params, diff --git a/zcash_client_sqlite/src/wallet.rs b/zcash_client_sqlite/src/wallet.rs index 676fde6ac8..0d2f905479 100644 --- a/zcash_client_sqlite/src/wallet.rs +++ b/zcash_client_sqlite/src/wallet.rs @@ -90,7 +90,7 @@ use zcash_client_backend::{ address::{Address, UnifiedAddress}, data_api::{ scanning::{ScanPriority, ScanRange}, - AccountBirthday, AccountId, BlockMetadata, SentTransactionOutput, SAPLING_SHARD_HEIGHT, + AccountBirthday, BlockMetadata, SentTransactionOutput, SAPLING_SHARD_HEIGHT, }, encoding::AddressCodec, keys::UnifiedFullViewingKey, @@ -119,6 +119,9 @@ use { }, }; +type AccountPK = u32; +type AccountId = zcash_client_backend::data_api::AccountId; + pub mod commitment_tree; pub mod init; pub(crate) mod sapling; @@ -178,7 +181,7 @@ pub(crate) fn get_max_account_id( }) } -pub(crate) fn add_account( +pub(crate) fn add_account( conn: &rusqlite::Transaction, params: &P, account: AccountId, @@ -583,7 +586,7 @@ pub(crate) fn get_wallet_summary( params: &P, min_confirmations: u32, progress: &impl ScanProgress, -) -> Result, SqliteClientError> { +) -> Result>, SqliteClientError> { let chain_tip_height = match scan_queue_extrema(tx)? { Some(range) => *range.end(), None => { @@ -1589,7 +1592,7 @@ pub(crate) fn put_block( /// contain a note related to this wallet into the database. pub(crate) fn put_tx_meta( conn: &rusqlite::Connection, - tx: &WalletTx, + tx: &WalletTx, height: BlockHeight, ) -> Result { // It isn't there, so insert our transaction into the database. @@ -1776,7 +1779,7 @@ pub(crate) fn update_expired_notes( // and `put_sent_output` fn recipient_params( params: &P, - to: &Recipient, + to: &Recipient, ) -> (Option, Option, PoolType) { match to { Recipient::Transparent(addr) => (Some(addr.encode(params)), None, PoolType::Transparent), @@ -1796,7 +1799,7 @@ pub(crate) fn insert_sent_output( params: &P, tx_ref: i64, from_account: AccountId, - output: &SentTransactionOutput, + output: &SentTransactionOutput, ) -> Result<(), SqliteClientError> { let mut stmt_insert_sent_output = conn.prepare_cached( "INSERT INTO sent_notes ( @@ -1842,7 +1845,7 @@ pub(crate) fn put_sent_output( from_account: AccountId, tx_ref: i64, output_index: usize, - recipient: &Recipient, + recipient: &Recipient, value: NonNegativeAmount, memo: Option<&MemoBytes>, ) -> Result<(), SqliteClientError> { diff --git a/zcash_client_sqlite/src/wallet/init.rs b/zcash_client_sqlite/src/wallet/init.rs index d605332552..33d0f7c635 100644 --- a/zcash_client_sqlite/src/wallet/init.rs +++ b/zcash_client_sqlite/src/wallet/init.rs @@ -18,6 +18,8 @@ use crate::WalletDb; use super::commitment_tree::{self}; +type AccountId = zcash_client_backend::data_api::AccountId; + mod migrations; #[derive(Debug)] @@ -169,7 +171,7 @@ mod tests { use zcash_client_backend::{ address::Address, - data_api::{scanning::ScanPriority, AccountId}, + data_api::scanning::ScanPriority, encoding::{encode_extended_full_viewing_key, encode_payment_address}, keys::{sapling, UnifiedFullViewingKey, UnifiedSpendingKey}, }; @@ -185,7 +187,7 @@ mod tests { testing::TestBuilder, wallet::scanning::priority_code, WalletDb, DEFAULT_UA_REQUEST, }; - use super::init_wallet_db; + use super::{init_wallet_db, AccountId}; #[cfg(feature = "transparent-inputs")] use { diff --git a/zcash_client_sqlite/src/wallet/init/migrations.rs b/zcash_client_sqlite/src/wallet/init/migrations.rs index 1285fffa9c..e044f0bb73 100644 --- a/zcash_client_sqlite/src/wallet/init/migrations.rs +++ b/zcash_client_sqlite/src/wallet/init/migrations.rs @@ -60,9 +60,9 @@ pub(super) fn all_migrations( params: params.clone(), seed, }), - Box::new(full_account_ids::Migration) { + Box::new(full_account_ids::Migration { seed, - }, + }), Box::new(addresses_table::Migration { params: params.clone(), }), diff --git a/zcash_client_sqlite/src/wallet/init/migrations/full_account_ids.rs b/zcash_client_sqlite/src/wallet/init/migrations/full_account_ids.rs index b20529e7c7..6548821e3e 100644 --- a/zcash_client_sqlite/src/wallet/init/migrations/full_account_ids.rs +++ b/zcash_client_sqlite/src/wallet/init/migrations/full_account_ids.rs @@ -1,11 +1,12 @@ +use std::collections::HashSet; + use rusqlite::{params, Transaction}; use schemer_rusqlite::RusqliteMigration; +use secrecy::SecretVec; +use uuid::Uuid; use zcash_client_backend::data_api::HDSeedFingerprint; -use crate::{ - wallet::{init::WalletMigrationError, insert_address}, - UA_TRANSPARENT, -}; +use crate::wallet::init::WalletMigrationError; use super::ufvk_support; diff --git a/zcash_client_sqlite/src/wallet/sapling.rs b/zcash_client_sqlite/src/wallet/sapling.rs index 81c77e7752..cb9b12316b 100644 --- a/zcash_client_sqlite/src/wallet/sapling.rs +++ b/zcash_client_sqlite/src/wallet/sapling.rs @@ -17,7 +17,6 @@ use zcash_primitives::{ }; use zcash_client_backend::{ - data_api::AccountId, keys::UnifiedFullViewingKey, wallet::{Note, ReceivedNote, WalletSaplingOutput}, DecryptedOutput, TransferType, @@ -27,6 +26,9 @@ use crate::{error::SqliteClientError, ReceivedNoteId}; use super::{memo_repr, parse_scope, scope_code, wallet_birthday}; +type AccountPK = u32; +type AccountId = zcash_client_backend::data_api::AccountId; + /// This trait provides a generalization over shielded output representations. pub(crate) trait ReceivedSaplingOutput { fn index(&self) -> usize; @@ -39,7 +41,7 @@ pub(crate) trait ReceivedSaplingOutput { fn recipient_key_scope(&self) -> Scope; } -impl ReceivedSaplingOutput for WalletSaplingOutput { +impl ReceivedSaplingOutput for WalletSaplingOutput { fn index(&self) -> usize { self.index() } @@ -67,7 +69,7 @@ impl ReceivedSaplingOutput for WalletSaplingOutput { } } -impl ReceivedSaplingOutput for DecryptedOutput { +impl ReceivedSaplingOutput for DecryptedOutput { fn index(&self) -> usize { self.index }