zcash_client_sqlite: Do not require a transparent key for migrations.

The `reserve_until` method for generating ephemeral addresses is used in
database migrations, but it makes no sense to use this in the case that
the UFVK for an account contains no transparent component; such accounts
can never be used to make ZIP 320 spends.
This commit is contained in:
Kris Nuttycombe 2024-08-30 16:47:09 -06:00
parent a7329323aa
commit 5ad432ad6e
1 changed files with 39 additions and 38 deletions

View File

@ -113,7 +113,7 @@ pub(crate) fn get_ephemeral_ivk<P: consensus::Parameters>(
conn: &rusqlite::Connection, conn: &rusqlite::Connection,
params: &P, params: &P,
account_id: AccountId, account_id: AccountId,
) -> Result<EphemeralIvk, SqliteClientError> { ) -> Result<Option<EphemeralIvk>, SqliteClientError> {
let ufvk = conn let ufvk = conn
.query_row( .query_row(
"SELECT ufvk FROM accounts WHERE id = :account_id", "SELECT ufvk FROM accounts WHERE id = :account_id",
@ -133,8 +133,8 @@ pub(crate) fn get_ephemeral_ivk<P: consensus::Parameters>(
let eivk = ufvk let eivk = ufvk
.as_ref() .as_ref()
.and_then(|ufvk| ufvk.transparent()) .and_then(|ufvk| ufvk.transparent())
.ok_or(SqliteClientError::UnknownZip32Derivation)? .map(|t| t.derive_ephemeral_ivk())
.derive_ephemeral_ivk()?; .transpose()?;
Ok(eivk) Ok(eivk)
} }
@ -265,11 +265,11 @@ pub(crate) fn init_account<P: consensus::Parameters>(
reserve_until(conn, params, account_id, 0) reserve_until(conn, params, account_id, 0)
} }
/// Extend the range of stored addresses in an account if necessary so that the /// Extend the range of stored addresses in an account if necessary so that the index of the next
/// index of the next address to reserve will be *at least* `next_to_reserve`. /// address to reserve will be *at least* `next_to_reserve`. If no transparent key exists for the
/// If it would already have been at least `next_to_reserve`, then do nothing. /// given account or it would already have been at least `next_to_reserve`, then do nothing.
/// ///
/// Note that this is called from db migration code. /// Note that this is called from database migration code.
/// ///
/// # Panics /// # Panics
/// ///
@ -282,14 +282,13 @@ fn reserve_until<P: consensus::Parameters>(
) -> Result<(), SqliteClientError> { ) -> Result<(), SqliteClientError> {
assert!(next_to_reserve <= 1 << 31); assert!(next_to_reserve <= 1 << 31);
if let Some(ephemeral_ivk) = get_ephemeral_ivk(conn, params, account_id)? {
let first_unstored = first_unstored_index(conn, account_id)?; let first_unstored = first_unstored_index(conn, account_id)?;
let range_to_store = first_unstored..(next_to_reserve.checked_add(GAP_LIMIT).unwrap()); let range_to_store = first_unstored..(next_to_reserve.checked_add(GAP_LIMIT).unwrap());
if range_to_store.is_empty() { if range_to_store.is_empty() {
return Ok(()); return Ok(());
} }
let ephemeral_ivk = get_ephemeral_ivk(conn, params, account_id)?;
// used_in_tx and seen_in_tx are initially NULL // used_in_tx and seen_in_tx are initially NULL
let mut stmt_insert_ephemeral_address = conn.prepare_cached( let mut stmt_insert_ephemeral_address = conn.prepare_cached(
"INSERT INTO ephemeral_addresses (account_id, address_index, address) "INSERT INTO ephemeral_addresses (account_id, address_index, address)
@ -315,6 +314,8 @@ fn reserve_until<P: consensus::Parameters>(
":address": address_str_opt, ":address": address_str_opt,
])?; ])?;
} }
}
Ok(()) Ok(())
} }