diff --git a/zcash_client_backend/CHANGELOG.md b/zcash_client_backend/CHANGELOG.md index 1d77875dd..f74aed886 100644 --- a/zcash_client_backend/CHANGELOG.md +++ b/zcash_client_backend/CHANGELOG.md @@ -23,7 +23,10 @@ and this library adheres to Rust's notion of - `testing::MockWalletDb::new` - `wallet::input_sellection::Proposal::{min_target_height, min_anchor_height}`: - `zcash_client_backend::wallet::WalletSaplingOutput::note_commitment_tree_position` -- `zcash_client_backend::scanning::ScanError` +- `zcash_client_backend::scanning`: + - `ScanError` + - `impl ScanningKey for &K` + - `impl ScanningKey for (zip32::Scope, sapling::SaplingIvk, sapling::NullifierDerivingKey)` ### Changed - MSRV is now 1.65.0. diff --git a/zcash_client_backend/src/data_api/chain.rs b/zcash_client_backend/src/data_api/chain.rs index 0f6f94545..e6c512517 100644 --- a/zcash_client_backend/src/data_api/chain.rs +++ b/zcash_client_backend/src/data_api/chain.rs @@ -155,7 +155,7 @@ use crate::{ data_api::{BlockMetadata, NullifierQuery, WalletWrite}, proto::compact_formats::CompactBlock, scan::BatchRunner, - scanning::{add_block_to_runner, check_continuity, scan_block_with_runner}, + scanning::{add_block_to_runner, check_continuity, scan_block_with_runner, ScanningKey}, }; pub mod error; @@ -254,6 +254,15 @@ where .iter() .filter_map(|(account, ufvk)| ufvk.sapling().map(move |k| (account, k))) .collect(); + // Precompute the IVKs instead of doing so per block. + let ivks = dfvks + .iter() + .flat_map(|(account, dfvk)| { + dfvk.to_sapling_keys() + .into_iter() + .map(|key| (*account, key)) + }) + .collect::>(); // Get the nullifiers for the unspent notes we are tracking let mut sapling_nullifiers = data_db @@ -337,7 +346,7 @@ where let scanned_block = scan_block_with_runner( params, block, - &dfvks, + &ivks, &sapling_nullifiers, prior_block_metadata.as_ref(), Some(&mut batch_runner), diff --git a/zcash_client_backend/src/scanning.rs b/zcash_client_backend/src/scanning.rs index 0f25571f9..f8ad56154 100644 --- a/zcash_client_backend/src/scanning.rs +++ b/zcash_client_backend/src/scanning.rs @@ -66,6 +66,21 @@ pub trait ScanningKey { -> Self::Nf; } +impl ScanningKey for &K { + type Scope = K::Scope; + type SaplingNk = K::SaplingNk; + type SaplingKeys = K::SaplingKeys; + type Nf = K::Nf; + + fn to_sapling_keys(&self) -> Self::SaplingKeys { + (*self).to_sapling_keys() + } + + fn sapling_nf(key: &Self::SaplingNk, note: &sapling::Note, position: Position) -> Self::Nf { + K::sapling_nf(key, note, position) + } +} + impl ScanningKey for DiversifiableFullViewingKey { type Scope = Scope; type SaplingNk = sapling::NullifierDerivingKey; @@ -92,6 +107,21 @@ impl ScanningKey for DiversifiableFullViewingKey { } } +impl ScanningKey for (Scope, SaplingIvk, sapling::NullifierDerivingKey) { + type Scope = Scope; + type SaplingNk = sapling::NullifierDerivingKey; + type SaplingKeys = [(Self::Scope, SaplingIvk, Self::SaplingNk); 1]; + type Nf = sapling::Nullifier; + + fn to_sapling_keys(&self) -> Self::SaplingKeys { + [self.clone()] + } + + fn sapling_nf(key: &Self::SaplingNk, note: &sapling::Note, position: Position) -> Self::Nf { + note.nf(key, position.into()) + } +} + /// The [`ScanningKey`] implementation for [`SaplingIvk`]s. /// Nullifiers cannot be derived when scanning with these keys. /// @@ -312,7 +342,7 @@ pub(crate) fn scan_block_with_runner< >( params: &P, block: CompactBlock, - vks: &[(&AccountId, &K)], + vks: &[(&AccountId, K)], nullifiers: &[(AccountId, sapling::Nullifier)], prior_block_metadata: Option<&BlockMetadata>, mut batch_runner: Option<&mut TaggedBatchRunner>,