Skip to content

Commit

Permalink
zcash_keys: Add ReceiverRequirement enum.
Browse files Browse the repository at this point in the history
This permits `UnifiedAddressRequest` values an additional dimension of
flexibility, permitting generation of unified addresses having receivers
for all recever types for which a key item exists and a diversifier
index is valid.
  • Loading branch information
nuttycom committed Dec 30, 2024
1 parent 4c61be0 commit a250648
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 116 deletions.
11 changes: 6 additions & 5 deletions zcash_client_sqlite/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ use zcash_client_backend::{
use zcash_keys::{
address::UnifiedAddress,
keys::{
AddressGenerationError, UnifiedAddressRequest, UnifiedFullViewingKey, UnifiedSpendingKey,
AddressGenerationError, ReceiverRequirement, UnifiedAddressRequest, UnifiedFullViewingKey,
UnifiedSpendingKey,
},
};
use zcash_primitives::{
Expand Down Expand Up @@ -154,14 +155,14 @@ pub(crate) const SAPLING_TABLES_PREFIX: &str = "sapling";
pub(crate) const ORCHARD_TABLES_PREFIX: &str = "orchard";

#[cfg(not(feature = "orchard"))]
pub(crate) const UA_ORCHARD: bool = false;
pub(crate) const UA_ORCHARD: ReceiverRequirement = ReceiverRequirement::Omit;
#[cfg(feature = "orchard")]
pub(crate) const UA_ORCHARD: bool = true;
pub(crate) const UA_ORCHARD: ReceiverRequirement = ReceiverRequirement::Require;

#[cfg(not(feature = "transparent-inputs"))]
pub(crate) const UA_TRANSPARENT: bool = false;
pub(crate) const UA_TRANSPARENT: ReceiverRequirement = ReceiverRequirement::Omit;
#[cfg(feature = "transparent-inputs")]
pub(crate) const UA_TRANSPARENT: bool = true;
pub(crate) const UA_TRANSPARENT: ReceiverRequirement = ReceiverRequirement::Require;

/// Unique identifier for a specific account tracked by a [`WalletDb`].
///
Expand Down
5 changes: 1 addition & 4 deletions zcash_client_sqlite/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,10 +292,7 @@ pub(crate) fn seed_matches_derived_account<P: consensus::Parameters>(
let usk = UnifiedSpendingKey::from_seed(params, &seed.expose_secret()[..], account_index)
.map_err(|_| SqliteClientError::KeyDerivationError(account_index))?;

let (seed_addr, _) = usk.to_unified_full_viewing_key().default_address(Some(
UnifiedAddressRequest::all().expect("At least one supported pool feature is enabled."),
))?;

let (seed_addr, _) = usk.to_unified_full_viewing_key().default_address(None)?;
let (uivk_addr, _) = uivk.default_address(None)?;

#[cfg(not(feature = "orchard"))]
Expand Down
9 changes: 6 additions & 3 deletions zcash_client_sqlite/src/wallet/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,10 @@ mod tests {
use zcash_keys::{
address::Address,
encoding::{encode_extended_full_viewing_key, encode_payment_address},
keys::{sapling, UnifiedAddressRequest, UnifiedFullViewingKey, UnifiedSpendingKey},
keys::{
sapling, ReceiverRequirement::*, UnifiedAddressRequest, UnifiedFullViewingKey,
UnifiedSpendingKey,
},
};
use zcash_primitives::transaction::{TransactionData, TxVersion};
use zcash_protocol::consensus::{self, BlockHeight, BranchId, Network, NetworkConstants};
Expand Down Expand Up @@ -984,7 +987,7 @@ mod tests {

// Unified addresses at the time of the addition of migrations did not contain an
// Orchard component.
let ua_request = UnifiedAddressRequest::unsafe_new(false, true, UA_TRANSPARENT);
let ua_request = UnifiedAddressRequest::unsafe_new(Omit, Require, UA_TRANSPARENT);
let address_str = Address::Unified(
ufvk.default_address(Some(ua_request))
.expect("A valid default address exists for the UFVK")
Expand Down Expand Up @@ -1111,7 +1114,7 @@ mod tests {
assert_eq!(tv.unified_addr, ua.encode(&Network::MainNetwork));

// hardcoded with knowledge of what's coming next
let ua_request = UnifiedAddressRequest::unsafe_new(false, true, true);
let ua_request = UnifiedAddressRequest::unsafe_new(Omit, Require, Require);
db_data
.get_next_available_address(account_id, Some(ua_request))
.unwrap()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,8 @@ mod tests {
#[cfg(feature = "transparent-inputs")]
fn migrate_from_wm2() {
use ::transparent::keys::NonHardenedChildIndex;
use zcash_keys::keys::UnifiedAddressRequest;
use zcash_client_backend::keys::UnifiedAddressRequest;
use zcash_keys::keys::ReceiverRequirement::*;
use zcash_protocol::value::Zatoshis;

use crate::UA_TRANSPARENT;
Expand Down Expand Up @@ -441,8 +442,8 @@ mod tests {
let ufvk = usk.to_unified_full_viewing_key();
let (ua, _) = ufvk
.default_address(Some(UnifiedAddressRequest::unsafe_new(
false,
true,
Omit,
Require,
UA_TRANSPARENT,
)))
.expect("A valid default address exists for the UFVK");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ use std::collections::HashSet;
use rusqlite::{named_params, Transaction};
use schemerz_rusqlite::RusqliteMigration;
use uuid::Uuid;
use zcash_keys::{address::Address, keys::UnifiedFullViewingKey};
use zcash_keys::{address::UnifiedAddress, encoding::AddressCodec, keys::UnifiedAddressRequest};

use zcash_keys::{
address::{Address, UnifiedAddress},
encoding::AddressCodec,
keys::{ReceiverRequirement::*, UnifiedAddressRequest, UnifiedFullViewingKey},
};
use zcash_protocol::consensus;
use zip32::{AccountId, DiversifierIndex};

Expand Down Expand Up @@ -87,7 +91,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
));
};
let (expected_address, idx) = ufvk.default_address(Some(
UnifiedAddressRequest::unsafe_new(false, true, UA_TRANSPARENT),
UnifiedAddressRequest::unsafe_new(Omit, Require, UA_TRANSPARENT),
))?;
if decoded_address != expected_address {
return Err(WalletMigrationError::CorruptedData(format!(
Expand Down Expand Up @@ -159,7 +163,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
)?;

let (address, d_idx) = ufvk.default_address(Some(
UnifiedAddressRequest::unsafe_new(false, true, UA_TRANSPARENT),
UnifiedAddressRequest::unsafe_new(Omit, Require, UA_TRANSPARENT),
))?;
insert_address(transaction, &self.params, account, d_idx, &address)?;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use rusqlite::named_params;
use schemerz_rusqlite::RusqliteMigration;
use uuid::Uuid;

use zcash_keys::keys::{UnifiedAddressRequest, UnifiedFullViewingKey, UnifiedIncomingViewingKey};
use zcash_keys::keys::{
ReceiverRequirement::*, UnifiedAddressRequest, UnifiedFullViewingKey, UnifiedIncomingViewingKey,
};
use zcash_protocol::consensus;

use super::orchard_received_notes;
Expand Down Expand Up @@ -64,7 +66,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
};

let (default_addr, diversifier_index) = uivk.default_address(Some(
UnifiedAddressRequest::unsafe_new(UA_ORCHARD, true, UA_TRANSPARENT),
UnifiedAddressRequest::unsafe_new(UA_ORCHARD, Require, UA_TRANSPARENT),
))?;

let mut di_be = *diversifier_index.as_bytes();
Expand All @@ -90,8 +92,10 @@ mod tests {
use secrecy::SecretVec;
use tempfile::NamedTempFile;

use zcash_keys::address::Address;
use zcash_keys::keys::{UnifiedAddressRequest, UnifiedSpendingKey};
use zcash_keys::{
address::Address,
keys::{ReceiverRequirement::*, UnifiedAddressRequest, UnifiedSpendingKey},
};
use zcash_protocol::consensus::Network;

use crate::{
Expand Down Expand Up @@ -139,8 +143,8 @@ mod tests {

let (addr, diversifier_index) = ufvk
.default_address(Some(UnifiedAddressRequest::unsafe_new(
false,
true,
Omit,
Require,
UA_TRANSPARENT,
)))
.unwrap();
Expand Down Expand Up @@ -168,7 +172,7 @@ mod tests {
Ok(Address::Unified(ua)) => {
assert!(!ua.has_orchard());
assert!(ua.has_sapling());
assert_eq!(ua.has_transparent(), UA_TRANSPARENT);
assert_eq!(ua.has_transparent(), UA_TRANSPARENT == Require);
}
other => panic!("Unexpected result from address decoding: {:?}", other),
}
Expand All @@ -184,9 +188,9 @@ mod tests {
Ok(Address::decode(&db_data.params, &row.get::<_, String>(0)?).unwrap())
}) {
Ok(Address::Unified(ua)) => {
assert_eq!(ua.has_orchard(), UA_ORCHARD);
assert_eq!(ua.has_orchard(), UA_ORCHARD == Require);
assert!(ua.has_sapling());
assert_eq!(ua.has_transparent(), UA_TRANSPARENT);
assert_eq!(ua.has_transparent(), UA_TRANSPARENT == Require);
}
other => panic!("Unexpected result from address decoding: {:?}", other),
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use uuid::Uuid;

use zcash_keys::{
address::Address,
keys::{UnifiedAddressRequest, UnifiedSpendingKey},
keys::{ReceiverRequirement::*, UnifiedAddressRequest, UnifiedSpendingKey},
};
use zcash_protocol::{consensus, PoolType};
use zip32::AccountId;
Expand Down Expand Up @@ -85,7 +85,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
// our second assumption above, and we report this as corrupted data.
let mut seed_is_relevant = false;

let ua_request = UnifiedAddressRequest::unsafe_new(false, true, UA_TRANSPARENT);
let ua_request = UnifiedAddressRequest::unsafe_new(Omit, Require, UA_TRANSPARENT);
let mut rows = stmt_fetch_accounts.query([])?;
while let Some(row) = rows.next()? {
// We only need to check for the presence of the seed if we have keys that
Expand Down
8 changes: 8 additions & 0 deletions zcash_keys/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,17 @@ and this library adheres to Rust's notion of
### Added
- `no-std` compatibility (`alloc` is required). A default-enabled `std` feature
flag has been added gating the `std::error::Error` usage.
- `zcash_keys::keys::ReceiverRequirement`

### Changed
- Migrated to `nonempty 0.11`
- `zcash_keys::keys::UnifiedAddressRequest` has been substantially modified;
instead of a collection of boolean flags, it is now a collection of
`ReceiverRequirement` values that describe how addresses may be constructed
in the case that keys for a particular protocol are absent or it is not
possible to generate a specific receiver at a given diversifier index.
Behavior of methods that accept a `UnifiedAddressRequest` have been modified
accordingly.

## [0.6.0] - 2024-12-16

Expand Down
Loading

0 comments on commit a250648

Please sign in to comment.