zcash_client_sqlite: Extract `seed_matches_derived_account` helper
This commit is contained in:
parent
703e50ae03
commit
c67b17dc96
|
@ -321,38 +321,13 @@ impl<C: Borrow<rusqlite::Connection>, P: consensus::Parameters> WalletRead for W
|
|||
account_index,
|
||||
} = account.source()
|
||||
{
|
||||
let seed_fingerprint_match =
|
||||
SeedFingerprint::from_seed(seed.expose_secret()).ok_or_else(|| {
|
||||
SqliteClientError::BadAccountData(
|
||||
"Seed must be between 32 and 252 bytes in length.".to_owned(),
|
||||
)
|
||||
})? == seed_fingerprint;
|
||||
|
||||
let usk = UnifiedSpendingKey::from_seed(
|
||||
wallet::seed_matches_derived_account(
|
||||
&self.params,
|
||||
&seed.expose_secret()[..],
|
||||
seed,
|
||||
&seed_fingerprint,
|
||||
account_index,
|
||||
&account.uivk(),
|
||||
)
|
||||
.map_err(|_| SqliteClientError::KeyDerivationError(account_index))?;
|
||||
|
||||
// Keys are not comparable with `Eq`, but addresses are, so we derive what should
|
||||
// be equivalent addresses for each key and use those to check for key equality.
|
||||
let ufvk_match = UnifiedAddressRequest::all().map_or(
|
||||
Ok::<_, Self::Error>(false),
|
||||
|ua_request| {
|
||||
Ok(usk
|
||||
.to_unified_full_viewing_key()
|
||||
.default_address(ua_request)?
|
||||
== account.default_address(ua_request)?)
|
||||
},
|
||||
)?;
|
||||
|
||||
if seed_fingerprint_match != ufvk_match {
|
||||
// If these mismatch, it suggests database corruption.
|
||||
return Err(SqliteClientError::CorruptedData(format!("Seed fingerprint match: {seed_fingerprint_match}, ufvk match: {ufvk_match}")));
|
||||
}
|
||||
|
||||
Ok(seed_fingerprint_match && ufvk_match)
|
||||
} else {
|
||||
Err(SqliteClientError::UnknownZip32Derivation)
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
|
||||
use incrementalmerkletree::Retention;
|
||||
use rusqlite::{self, named_params, params, OptionalExtension};
|
||||
use secrecy::{ExposeSecret, SecretVec};
|
||||
use shardtree::{error::ShardTreeError, store::ShardStore, ShardTree};
|
||||
use zip32::fingerprint::SeedFingerprint;
|
||||
|
||||
|
@ -75,7 +76,9 @@ use std::io::{self, Cursor};
|
|||
use std::num::NonZeroU32;
|
||||
use std::ops::RangeInclusive;
|
||||
use tracing::debug;
|
||||
use zcash_keys::keys::{AddressGenerationError, UnifiedAddressRequest, UnifiedIncomingViewingKey};
|
||||
use zcash_keys::keys::{
|
||||
AddressGenerationError, UnifiedAddressRequest, UnifiedIncomingViewingKey, UnifiedSpendingKey,
|
||||
};
|
||||
|
||||
use zcash_client_backend::{
|
||||
address::{Address, UnifiedAddress},
|
||||
|
@ -245,6 +248,43 @@ impl ViewingKey {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn seed_matches_derived_account<P: consensus::Parameters>(
|
||||
params: &P,
|
||||
seed: &SecretVec<u8>,
|
||||
seed_fingerprint: &SeedFingerprint,
|
||||
account_index: zip32::AccountId,
|
||||
uivk: &UnifiedIncomingViewingKey,
|
||||
) -> Result<bool, SqliteClientError> {
|
||||
let seed_fingerprint_match =
|
||||
&SeedFingerprint::from_seed(seed.expose_secret()).ok_or_else(|| {
|
||||
SqliteClientError::BadAccountData(
|
||||
"Seed must be between 32 and 252 bytes in length.".to_owned(),
|
||||
)
|
||||
})? == seed_fingerprint;
|
||||
|
||||
let usk = UnifiedSpendingKey::from_seed(params, &seed.expose_secret()[..], account_index)
|
||||
.map_err(|_| SqliteClientError::KeyDerivationError(account_index))?;
|
||||
|
||||
// Keys are not comparable with `Eq`, but addresses are, so we derive what should
|
||||
// be equivalent addresses for each key and use those to check for key equality.
|
||||
let uivk_match =
|
||||
UnifiedAddressRequest::all().map_or(Ok::<_, SqliteClientError>(false), |ua_request| {
|
||||
Ok(usk
|
||||
.to_unified_full_viewing_key()
|
||||
.default_address(ua_request)?
|
||||
== uivk.default_address(ua_request)?)
|
||||
})?;
|
||||
|
||||
if seed_fingerprint_match != uivk_match {
|
||||
// If these mismatch, it suggests database corruption.
|
||||
Err(SqliteClientError::CorruptedData(format!(
|
||||
"Seed fingerprint match: {seed_fingerprint_match}, uivk match: {uivk_match}"
|
||||
)))
|
||||
} else {
|
||||
Ok(seed_fingerprint_match && uivk_match)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn pool_code(pool_type: PoolType) -> i64 {
|
||||
// These constants are *incidentally* shared with the typecodes
|
||||
// for unified addresses, but this is exclusively an internal
|
||||
|
|
Loading…
Reference in New Issue