zcash_client_backend: Remove account from `UnifiedFullViewingKey`

The account number is not stored in the ZIP 316 UFVK encoding, and in
general won't necessarily be known (e.g. if a UFVK is being imported
into a wallet).

`zcash_client_sqlite::wallet::init::init_accounts_table` reverts to its
previous behaviour of requiring the provided `&[UnifiedFullViewingKey]`
to be indexed by account number.
This commit is contained in:
Jack Grigg 2022-06-14 01:56:46 +00:00
parent 1ce289e568
commit d8b860207d
5 changed files with 24 additions and 62 deletions

View File

@ -107,7 +107,6 @@ impl UnifiedSpendingKey {
pub fn to_unified_full_viewing_key(&self) -> UnifiedFullViewingKey {
UnifiedFullViewingKey {
account: self.account,
#[cfg(feature = "transparent-inputs")]
transparent: Some(self.transparent.to_account_pubkey()),
sapling: Some(sapling::ExtendedFullViewingKey::from(&self.sapling)),
@ -137,7 +136,6 @@ impl UnifiedSpendingKey {
#[derive(Clone, Debug)]
#[doc(hidden)]
pub struct UnifiedFullViewingKey {
account: AccountId,
#[cfg(feature = "transparent-inputs")]
transparent: Option<legacy::AccountPubKey>,
// TODO: This type is invalid for a UFVK; create a `sapling::DiversifiableFullViewingKey`
@ -149,7 +147,6 @@ pub struct UnifiedFullViewingKey {
impl UnifiedFullViewingKey {
/// Construct a new unified full viewing key, if the required components are present.
pub fn new(
account: AccountId,
#[cfg(feature = "transparent-inputs")] transparent: Option<legacy::AccountPubKey>,
sapling: Option<sapling::ExtendedFullViewingKey>,
) -> Option<UnifiedFullViewingKey> {
@ -157,7 +154,6 @@ impl UnifiedFullViewingKey {
None
} else {
Some(UnifiedFullViewingKey {
account,
#[cfg(feature = "transparent-inputs")]
transparent,
sapling,
@ -167,11 +163,7 @@ impl UnifiedFullViewingKey {
/// Attempts to decode the given string as an encoding of a `UnifiedFullViewingKey`
/// for the given network.
pub fn decode<P: consensus::Parameters>(
params: &P,
encoding: &str,
account: AccountId,
) -> Result<Self, String> {
pub fn decode<P: consensus::Parameters>(params: &P, encoding: &str) -> Result<Self, String> {
encoding
.strip_prefix("DONOTUSEUFVK")
.and_then(|data| hex::decode(data).ok())
@ -199,7 +191,6 @@ impl UnifiedFullViewingKey {
};
Some(Self {
account,
#[cfg(feature = "transparent-inputs")]
transparent,
sapling,
@ -227,12 +218,6 @@ impl UnifiedFullViewingKey {
format!("DONOTUSEUFVK{}", hex::encode(&ufvk))
}
/// Returns the ZIP32 account identifier to which all component
/// keys are related.
pub fn account(&self) -> AccountId {
self.account
}
/// Returns the transparent component of the unified key at the
/// BIP44 path `m/44'/<coin_type>'/<account>'`.
#[cfg(feature = "transparent-inputs")]
@ -370,7 +355,6 @@ mod tests {
let transparent = { None };
let ufvk = UnifiedFullViewingKey::new(
account,
#[cfg(feature = "transparent-inputs")]
transparent,
sapling,
@ -378,8 +362,7 @@ mod tests {
.unwrap();
let encoding = ufvk.encode(&MAIN_NETWORK);
let decoded = UnifiedFullViewingKey::decode(&MAIN_NETWORK, &encoding, account).unwrap();
assert_eq!(decoded.account, ufvk.account);
let decoded = UnifiedFullViewingKey::decode(&MAIN_NETWORK, &encoding).unwrap();
#[cfg(feature = "transparent-inputs")]
assert_eq!(
decoded.transparent.map(|t| t.serialize()),

View File

@ -802,7 +802,6 @@ mod tests {
let taddr = None;
let ufvk = UnifiedFullViewingKey::new(
account,
#[cfg(feature = "transparent-inputs")]
tkey,
Some(extfvk.clone()),

View File

@ -208,7 +208,7 @@ pub(crate) fn get_unified_full_viewing_keys<P: consensus::Parameters>(
let acct: u32 = row.get(0)?;
let account = AccountId::from(acct);
let ufvk_str: String = row.get(1)?;
let ufvk = UnifiedFullViewingKey::decode(&wdb.params, &ufvk_str, account)
let ufvk = UnifiedFullViewingKey::decode(&wdb.params, &ufvk_str)
.map_err(SqliteClientError::CorruptedData);
Ok((account, ufvk))
@ -240,7 +240,7 @@ pub fn is_valid_account_extfvk<P: consensus::Parameters>(
.prepare("SELECT ufvk FROM accounts WHERE account = ?")?
.query_row(&[u32::from(account).to_sql()?], |row| {
row.get(0).map(|ufvk_str: String| {
UnifiedFullViewingKey::decode(&wdb.params, &ufvk_str, account)
UnifiedFullViewingKey::decode(&wdb.params, &ufvk_str)
.map_err(SqliteClientError::CorruptedData)
})
})

View File

@ -180,7 +180,7 @@ pub fn init_wallet_db<P>(wdb: &WalletDb<P>) -> Result<(), rusqlite::Error> {
/// let account = AccountId::from(0);
/// let extsk = sapling::spending_key(&seed, Network::TestNetwork.coin_type(), account);
/// let extfvk = ExtendedFullViewingKey::from(&extsk);
/// let ufvk = UnifiedFullViewingKey::new(account, None, Some(extfvk)).unwrap();
/// let ufvk = UnifiedFullViewingKey::new(None, Some(extfvk)).unwrap();
/// init_accounts_table(&db_data, &[ufvk]).unwrap();
/// # }
/// ```
@ -199,7 +199,7 @@ pub fn init_accounts_table<P: consensus::Parameters>(
// Insert accounts atomically
wdb.conn.execute("BEGIN IMMEDIATE", NO_PARAMS)?;
for key in keys.iter() {
for (account, key) in (0u32..).zip(keys) {
let ufvk_str: String = key.encode(&wdb.params);
let address_str: String = key.default_address().0.encode(&wdb.params);
#[cfg(feature = "transparent-inputs")]
@ -214,12 +214,7 @@ pub fn init_accounts_table<P: consensus::Parameters>(
wdb.conn.execute(
"INSERT INTO accounts (account, ufvk, address, transparent_address)
VALUES (?, ?, ?, ?)",
params![
u32::from(key.account()),
ufvk_str,
address_str,
taddress_str,
],
params![account, ufvk_str, address_str, taddress_str],
)?;
}
wdb.conn.execute("COMMIT", NO_PARAMS)?;
@ -328,7 +323,6 @@ mod tests {
#[cfg(feature = "transparent-inputs")]
let ufvk = UnifiedFullViewingKey::new(
account,
Some(
transparent::AccountPrivKey::from_seed(&network(), &seed, account)
.unwrap()
@ -339,7 +333,7 @@ mod tests {
.unwrap();
#[cfg(not(feature = "transparent-inputs"))]
let ufvk = UnifiedFullViewingKey::new(account, Some(extfvk)).unwrap();
let ufvk = UnifiedFullViewingKey::new(Some(extfvk)).unwrap();
init_accounts_table(&db_data, &[ufvk.clone()]).unwrap();

View File

@ -219,24 +219,14 @@ mod tests {
transparent::AccountPrivKey::from_seed(&network(), &[1u8; 32], AccountId::from(1))
.unwrap();
[
UnifiedFullViewingKey::new(
AccountId::from(0),
Some(tsk0.to_account_pubkey()),
Some(extfvk0),
)
.unwrap(),
UnifiedFullViewingKey::new(
AccountId::from(1),
Some(tsk1.to_account_pubkey()),
Some(extfvk1),
)
.unwrap(),
UnifiedFullViewingKey::new(Some(tsk0.to_account_pubkey()), Some(extfvk0)).unwrap(),
UnifiedFullViewingKey::new(Some(tsk1.to_account_pubkey()), Some(extfvk1)).unwrap(),
]
};
#[cfg(not(feature = "transparent-inputs"))]
let ufvks = [
UnifiedFullViewingKey::new(AccountId::from(0), Some(extfvk0)).unwrap(),
UnifiedFullViewingKey::new(AccountId::from(1), Some(extfvk1)).unwrap(),
UnifiedFullViewingKey::new(Some(extfvk0)).unwrap(),
UnifiedFullViewingKey::new(Some(extfvk1)).unwrap(),
];
init_accounts_table(&db_data, &ufvks).unwrap();
@ -288,9 +278,9 @@ mod tests {
let extfvk = ExtendedFullViewingKey::from(&extsk);
#[cfg(feature = "transparent-inputs")]
let ufvk = UnifiedFullViewingKey::new(AccountId::from(0), None, Some(extfvk)).unwrap();
let ufvk = UnifiedFullViewingKey::new(None, Some(extfvk)).unwrap();
#[cfg(not(feature = "transparent-inputs"))]
let ufvk = UnifiedFullViewingKey::new(AccountId::from(0), Some(extfvk)).unwrap();
let ufvk = UnifiedFullViewingKey::new(Some(extfvk)).unwrap();
init_accounts_table(&db_data, &[ufvk]).unwrap();
let to = extsk.default_address().1.into();
@ -331,9 +321,9 @@ mod tests {
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId::from(0));
let extfvk = ExtendedFullViewingKey::from(&extsk);
#[cfg(feature = "transparent-inputs")]
let ufvk = UnifiedFullViewingKey::new(AccountId::from(0), None, Some(extfvk)).unwrap();
let ufvk = UnifiedFullViewingKey::new(None, Some(extfvk)).unwrap();
#[cfg(not(feature = "transparent-inputs"))]
let ufvk = UnifiedFullViewingKey::new(AccountId::from(0), Some(extfvk)).unwrap();
let ufvk = UnifiedFullViewingKey::new(Some(extfvk)).unwrap();
init_accounts_table(&db_data, &[ufvk]).unwrap();
let to = extsk.default_address().1.into();
@ -379,10 +369,9 @@ mod tests {
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId::from(0));
let extfvk = ExtendedFullViewingKey::from(&extsk);
#[cfg(feature = "transparent-inputs")]
let ufvk =
UnifiedFullViewingKey::new(AccountId::from(0), None, Some(extfvk.clone())).unwrap();
let ufvk = UnifiedFullViewingKey::new(None, Some(extfvk.clone())).unwrap();
#[cfg(not(feature = "transparent-inputs"))]
let ufvk = UnifiedFullViewingKey::new(AccountId::from(0), Some(extfvk.clone())).unwrap();
let ufvk = UnifiedFullViewingKey::new(Some(extfvk.clone())).unwrap();
init_accounts_table(&db_data, &[ufvk]).unwrap();
// Add funds to the wallet in a single note
@ -523,10 +512,9 @@ mod tests {
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId::from(0));
let extfvk = ExtendedFullViewingKey::from(&extsk);
#[cfg(feature = "transparent-inputs")]
let ufvk =
UnifiedFullViewingKey::new(AccountId::from(0), None, Some(extfvk.clone())).unwrap();
let ufvk = UnifiedFullViewingKey::new(None, Some(extfvk.clone())).unwrap();
#[cfg(not(feature = "transparent-inputs"))]
let ufvk = UnifiedFullViewingKey::new(AccountId::from(0), Some(extfvk.clone())).unwrap();
let ufvk = UnifiedFullViewingKey::new(Some(extfvk.clone())).unwrap();
init_accounts_table(&db_data, &[ufvk]).unwrap();
// Add funds to the wallet in a single note
@ -653,10 +641,9 @@ mod tests {
let extsk = sapling::spending_key(&[0u8; 32], network.coin_type(), AccountId::from(0));
let extfvk = ExtendedFullViewingKey::from(&extsk);
#[cfg(feature = "transparent-inputs")]
let ufvk =
UnifiedFullViewingKey::new(AccountId::from(0), None, Some(extfvk.clone())).unwrap();
let ufvk = UnifiedFullViewingKey::new(None, Some(extfvk.clone())).unwrap();
#[cfg(not(feature = "transparent-inputs"))]
let ufvk = UnifiedFullViewingKey::new(AccountId::from(0), Some(extfvk.clone())).unwrap();
let ufvk = UnifiedFullViewingKey::new(Some(extfvk.clone())).unwrap();
init_accounts_table(&db_data, &[ufvk]).unwrap();
// Add funds to the wallet in a single note
@ -764,10 +751,9 @@ mod tests {
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId::from(0));
let extfvk = ExtendedFullViewingKey::from(&extsk);
#[cfg(feature = "transparent-inputs")]
let ufvk =
UnifiedFullViewingKey::new(AccountId::from(0), None, Some(extfvk.clone())).unwrap();
let ufvk = UnifiedFullViewingKey::new(None, Some(extfvk.clone())).unwrap();
#[cfg(not(feature = "transparent-inputs"))]
let ufvk = UnifiedFullViewingKey::new(AccountId::from(0), Some(extfvk.clone())).unwrap();
let ufvk = UnifiedFullViewingKey::new(Some(extfvk.clone())).unwrap();
init_accounts_table(&db_data, &[ufvk]).unwrap();
// Add funds to the wallet in a single note