diff --git a/controller/tests/accounts.rs b/controller/tests/accounts.rs index 35413bdb6..9a47e41f0 100644 --- a/controller/tests/accounts.rs +++ b/controller/tests/accounts.rs @@ -256,6 +256,15 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { }, )?; + // Use the requested account's stored height + { + wallet_inst!(wallet1, w); + assert_eq!(w.parent_key_id(), ExtKeychain::derive_key_id(2, 1, 0, 0, 0)); + let account2 = ExtKeychain::derive_key_id(2, 2, 0, 0, 0); + let account2_info = libwallet::retrieve_info(w, &account2, 1)?; + assert_eq!(account2_info.last_confirmed_height, 12); + } + // other account should be untouched { wallet_inst!(wallet1, w); diff --git a/libwallet/src/api_impl/foreign.rs b/libwallet/src/api_impl/foreign.rs index 036027aa2..76b60147d 100644 --- a/libwallet/src/api_impl/foreign.rs +++ b/libwallet/src/api_impl/foreign.rs @@ -94,7 +94,7 @@ where ret_slate.tx = Some(Slate::empty_transaction()); - let height = w.last_confirmed_height()?; + let height = w.last_confirmed_height_for_parent(&parent_key_id)?; let keychain = w.keychain(keychain_mask)?; let context = tx::add_output_to_slate( diff --git a/libwallet/src/api_impl/owner.rs b/libwallet/src/api_impl/owner.rs index ecfa43774..10a8d4a64 100644 --- a/libwallet/src/api_impl/owner.rs +++ b/libwallet/src/api_impl/owner.rs @@ -322,7 +322,7 @@ where let parent_key_id = w.parent_key_id(); let wallet_info = updater::retrieve_info(w, &parent_key_id, minimum_confirmations)?; - let current_height = w.last_confirmed_height()?; + let current_height = w.last_confirmed_height_for_parent(&parent_key_id)?; let max_outputs = 500; let change_outputs = 1; let (amount, fee, input_count) = match selection::select_coins_and_fee( diff --git a/libwallet/src/backend.rs b/libwallet/src/backend.rs index 2fa0a08aa..1fdd3101f 100644 --- a/libwallet/src/backend.rs +++ b/libwallet/src/backend.rs @@ -482,13 +482,22 @@ where Ok(Identifier::from_path(&return_path)) } - /// Last verified height of outputs directly descending from the given parent key. + /// Last verified height of outputs directly descending from the current parent key. pub fn last_confirmed_height(&mut self) -> Result { + let parent_key_id = self.parent_key_id.clone(); + self.last_confirmed_height_for_parent(&parent_key_id) + } + + /// Last verified height of outputs directly descending from the given parent key. + pub(crate) fn last_confirmed_height_for_parent( + &mut self, + parent_key_id: &Identifier, + ) -> Result { let batch = self.db.batch()?; let last_confirmed_height = batch .get_ser( Some(CONFIRMED_HEIGHT_PREFIX), - &self.parent_key_id.to_bytes(), + &parent_key_id.to_bytes(), None, )? .unwrap_or_else(|| 0); diff --git a/libwallet/src/internal/updater.rs b/libwallet/src/internal/updater.rs index 3383d9e06..9590f23d9 100644 --- a/libwallet/src/internal/updater.rs +++ b/libwallet/src/internal/updater.rs @@ -91,7 +91,7 @@ where } /// Apply advanced filtering to resultset from retrieve_txs below -pub fn apply_advanced_tx_list_filtering( +fn apply_advanced_tx_list_filtering( wallet: &mut WalletBackend, parent_key_id: Option<&Identifier>, query_args: &RetrieveTxQueryArgs, @@ -402,6 +402,7 @@ where /// Refreshes the outputs in a wallet with the latest information /// from a node +/// Also removes stale unconfirmed coinbase outputs across all accounts pub fn refresh_outputs( wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, @@ -417,8 +418,12 @@ where Ok(()) } -/// build a local map of wallet outputs keyed by commit -/// and a list of outputs we want to query the node for +/// Build a local map of wallet outputs keyed by commit. +/// The map keys identify outputs to query from the node. +/// If `update_all` is `false`, select outputs involved in outstanding +/// transactions for the account and outputs without a transaction log entry. +/// Returns mapping of output commit to tuple of derived key for output, +/// PMMR index, tx entry log identifier and check if output is unspent pub fn map_wallet_outputs( wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, @@ -505,7 +510,7 @@ where } /// Apply refreshed API output data to the wallet -pub fn apply_api_outputs( +fn apply_api_outputs( wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, wallet_outputs: &HashMap, Option, bool)>, @@ -522,7 +527,7 @@ where // api output (if it exists) and refresh it in-place in the wallet. // Note: minimizing the time we spend holding the wallet lock. { - let last_confirmed_height = wallet.last_confirmed_height()?; + let last_confirmed_height = wallet.last_confirmed_height_for_parent(parent_key_id)?; // If the server height is less than our confirmed height, don't apply // these changes as the chain is syncing, incorrect or forking if height < last_confirmed_height { @@ -799,7 +804,7 @@ where C: NodeClient, K: Keychain, { - let current_height = wallet.last_confirmed_height()?; + let current_height = wallet.last_confirmed_height_for_parent(parent_key_id)?; let outputs = wallet .iter()? .filter(|out| out.root_key_id == *parent_key_id); @@ -876,7 +881,7 @@ where //TODO: Split up the output creation and the wallet insertion /// Build a coinbase output and the corresponding kernel -pub fn receive_coinbase( +fn receive_coinbase( wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, block_fees: &BlockFees, diff --git a/libwallet/src/lib.rs b/libwallet/src/lib.rs index a73cdb4c1..a21283674 100644 --- a/libwallet/src/lib.rs +++ b/libwallet/src/lib.rs @@ -72,6 +72,9 @@ pub use api_impl::types::{ }; pub use backend::{WalletBackend, WalletBatch}; pub use internal::scan::scan; +pub use internal::updater::{ + map_wallet_outputs, refresh_outputs, retrieve_info, retrieve_outputs, retrieve_txs, +}; pub use slate_versions::ser as dalek_ser; pub use types::{ AcctPathMapping, BlockIdentifier, CbData, Context, NodeClient, NodeVersionInfo, OutputData,