Fix importing of UFVKs with fewer keys than possible

This commit is contained in:
Andrew Arnott 2024-06-17 08:57:12 -06:00
parent ce40387511
commit d27bf4fc12
No known key found for this signature in database
GPG Key ID: 251505B99C25745D
3 changed files with 47 additions and 3 deletions

View File

@ -213,9 +213,13 @@ impl Account {
&self,
request: UnifiedAddressRequest,
) -> Result<(UnifiedAddress, DiversifierIndex), AddressGenerationError> {
self.uivk().default_address(request)
}
pub(crate) fn uivk(&self) -> UnifiedIncomingViewingKey {
match &self.viewing_key {
ViewingKey::Full(ufvk) => ufvk.default_address(request),
ViewingKey::Incoming(uivk) => uivk.default_address(request),
ViewingKey::Full(ufvk) => ufvk.to_unified_incoming_viewing_key(),
ViewingKey::Incoming(uivk) => *uivk.clone(),
}
}
}
@ -521,7 +525,14 @@ pub(crate) fn add_account<P: consensus::Parameters>(
}
// Always derive the default Unified Address for the account.
let (address, d_idx) = account.default_address(DEFAULT_UA_REQUEST)?;
let ua_request = account
.uivk()
.to_address_request()
.and_then(|ua_request| ua_request.intersect(&DEFAULT_UA_REQUEST))
.ok_or_else(|| {
SqliteClientError::AddressGeneration(AddressGenerationError::ShieldedReceiverRequired)
})?;
let (address, d_idx) = account.default_address(ua_request)?;
insert_address(conn, params, account_id, d_idx, &address)?;
Ok(account)

View File

@ -8,6 +8,9 @@ and this library adheres to Rust's notion of
### Added
- `zcash_keys::address::Address::try_from_zcash_address`
- `zcash_keys::address::Receiver`
- `zcash_keys::keys::UnifiedAddressRequest`
- `intersect`
- `to_address_request`
### Changed
- MSRV is now 1.70.0.

View File

@ -587,6 +587,16 @@ impl UnifiedAddressRequest {
Self::new(_has_orchard, _has_sapling, _has_p2pkh)
}
/// Constructs a new unified address request that includes only the receivers
/// that appear both in itself and a given other request.
pub fn intersect(&self, other: &UnifiedAddressRequest) -> Option<UnifiedAddressRequest> {
Self::new(
self.has_orchard && other.has_orchard,
self.has_sapling && other.has_sapling,
self.has_p2pkh && other.has_p2pkh,
)
}
/// Construct a new unified address request from its constituent parts.
///
/// Panics: at least one of `has_orchard` or `has_sapling` must be `true`.
@ -1201,6 +1211,26 @@ impl UnifiedIncomingViewingKey {
) -> Result<(UnifiedAddress, DiversifierIndex), AddressGenerationError> {
self.find_address(DiversifierIndex::new(), request)
}
/// Constructs a [`UnifiedAddressRequest`] that includes the components of this UIVK.
pub fn to_address_request(&self) -> Option<UnifiedAddressRequest> {
#[cfg(feature = "orchard")]
let has_orchard = self.orchard.is_some();
#[cfg(not(feature = "orchard"))]
let has_orchard = false;
#[cfg(feature = "sapling")]
let has_sapling = self.sapling.is_some();
#[cfg(not(feature = "sapling"))]
let has_sapling = false;
#[cfg(feature = "transparent-inputs")]
let has_p2pkh = self.transparent.is_some();
#[cfg(not(feature = "transparent-inputs"))]
let has_p2pkh = false;
UnifiedAddressRequest::new(has_orchard, has_sapling, has_p2pkh)
}
}
#[cfg(any(test, feature = "test-dependencies"))]