From e6bc21b4613ef17690023c64d026e497fbc4fe3c Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 18 Mar 2024 22:41:39 +0000 Subject: [PATCH] Add `WalletRead::is_seed_relevant_to_any_derived_accounts` --- zcash_client_backend/CHANGELOG.md | 3 ++- zcash_client_backend/src/data_api.rs | 14 ++++++++++++ zcash_client_sqlite/src/lib.rs | 33 ++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/zcash_client_backend/CHANGELOG.md b/zcash_client_backend/CHANGELOG.md index d4fc361df..1b82c0bb9 100644 --- a/zcash_client_backend/CHANGELOG.md +++ b/zcash_client_backend/CHANGELOG.md @@ -59,6 +59,8 @@ and this library adheres to Rust's notion of - Arguments to `ScannedBlock::from_parts` have changed. - Changes to the `WalletRead` trait: - Added `Account` associated type. + - Added `validate_seed` method. + - Added `is_seed_relevant_to_any_derived_accounts` method. - Added `get_account` method. - Added `get_derived_account` method. - `get_account_for_ufvk` now returns `Self::Account` instead of a bare @@ -80,7 +82,6 @@ and this library adheres to Rust's notion of - `type OrchardShardStore` - `fn with_orchard_tree_mut` - `fn put_orchard_subtree_roots` - - Added method `WalletRead::validate_seed` - Removed `Error::AccountNotFound` variant. - `WalletSummary::new` now takes an additional `next_orchard_subtree_index` argument when the `orchard` feature flag is enabled. diff --git a/zcash_client_backend/src/data_api.rs b/zcash_client_backend/src/data_api.rs index 909aa6884..c27d9b137 100644 --- a/zcash_client_backend/src/data_api.rs +++ b/zcash_client_backend/src/data_api.rs @@ -740,6 +740,13 @@ pub trait WalletRead { seed: &SecretVec, ) -> Result; + /// Checks whether the given seed is relevant to any of the derived accounts (where + /// [`Account::source`] is [`AccountSource::Derived`]) in the wallet. + fn is_seed_relevant_to_any_derived_accounts( + &self, + seed: &SecretVec, + ) -> Result; + /// Returns the account corresponding to a given [`UnifiedFullViewingKey`], if any. fn get_account_for_ufvk( &self, @@ -1719,6 +1726,13 @@ pub mod testing { Ok(false) } + fn is_seed_relevant_to_any_derived_accounts( + &self, + _seed: &SecretVec, + ) -> Result { + Ok(false) + } + fn get_account_for_ufvk( &self, _ufvk: &UnifiedFullViewingKey, diff --git a/zcash_client_sqlite/src/lib.rs b/zcash_client_sqlite/src/lib.rs index fb9ca3777..6b8fd2982 100644 --- a/zcash_client_sqlite/src/lib.rs +++ b/zcash_client_sqlite/src/lib.rs @@ -337,6 +337,39 @@ impl, P: consensus::Parameters> WalletRead for W } } + fn is_seed_relevant_to_any_derived_accounts( + &self, + seed: &SecretVec, + ) -> Result { + for account_id in self.get_account_ids()? { + let account = self.get_account(account_id)?.expect("account ID exists"); + + // If the account is imported, the seed _might_ be relevant, but the only + // way we could determine that is by brute-forcing the ZIP 32 account + // index space, which we're not going to do. The method name indicates to + // the caller that we only check derived accounts. + if let AccountSource::Derived { + seed_fingerprint, + account_index, + } = account.source() + { + if wallet::seed_matches_derived_account( + &self.params, + seed, + &seed_fingerprint, + account_index, + &account.uivk(), + )? { + // The seed is relevant to this account. No need to check any others. + return Ok(true); + } + } + } + + // The seed was not relevant to any of the accounts in the wallet. + Ok(false) + } + fn get_account_for_ufvk( &self, ufvk: &UnifiedFullViewingKey,