zcash_client_backend: Expose the kind of an `Account`
This commit is contained in:
parent
bc6aa955ff
commit
65093487c3
|
@ -16,6 +16,7 @@ and this library adheres to Rust's notion of
|
|||
- `Account`
|
||||
- `AccountBalance::with_orchard_balance_mut`
|
||||
- `AccountBirthday::orchard_frontier`
|
||||
- `AccountKind`
|
||||
- `BlockMetadata::orchard_tree_size`
|
||||
- `DecryptedTransaction::{new, tx(), orchard_outputs()}`
|
||||
- `ScannedBlock::orchard`
|
||||
|
|
|
@ -315,12 +315,32 @@ impl AccountBalance {
|
|||
}
|
||||
}
|
||||
|
||||
/// The kinds of accounts supported by `zcash_client_backend`.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum AccountKind {
|
||||
/// An account derived from a known seed.
|
||||
Derived {
|
||||
seed_fingerprint: HdSeedFingerprint,
|
||||
account_index: zip32::AccountId,
|
||||
},
|
||||
|
||||
/// An account imported from a viewing key.
|
||||
Imported,
|
||||
}
|
||||
|
||||
/// A set of capabilities that a client account must provide.
|
||||
pub trait Account<AccountId: Copy> {
|
||||
/// Returns the unique identifier for the account.
|
||||
fn id(&self) -> AccountId;
|
||||
|
||||
/// Returns whether this account is derived or imported, and the derivation parameters
|
||||
/// if applicable.
|
||||
fn kind(&self) -> AccountKind;
|
||||
|
||||
/// Returns the UFVK that the wallet backend has stored for the account, if any.
|
||||
///
|
||||
/// Accounts for which this returns `None` cannot be used in wallet contexts, because
|
||||
/// they are unable to maintain an accurate balance.
|
||||
fn ufvk(&self) -> Option<&UnifiedFullViewingKey>;
|
||||
}
|
||||
|
||||
|
@ -329,6 +349,10 @@ impl<A: Copy> Account<A> for (A, UnifiedFullViewingKey) {
|
|||
self.0
|
||||
}
|
||||
|
||||
fn kind(&self) -> AccountKind {
|
||||
AccountKind::Imported
|
||||
}
|
||||
|
||||
fn ufvk(&self) -> Option<&UnifiedFullViewingKey> {
|
||||
Some(&self.1)
|
||||
}
|
||||
|
@ -339,6 +363,10 @@ impl<A: Copy> Account<A> for (A, Option<UnifiedFullViewingKey>) {
|
|||
self.0
|
||||
}
|
||||
|
||||
fn kind(&self) -> AccountKind {
|
||||
AccountKind::Imported
|
||||
}
|
||||
|
||||
fn ufvk(&self) -> Option<&UnifiedFullViewingKey> {
|
||||
self.1.as_ref()
|
||||
}
|
||||
|
|
|
@ -60,9 +60,9 @@ use zcash_client_backend::{
|
|||
self,
|
||||
chain::{BlockSource, ChainState, CommitmentTreeRoot},
|
||||
scanning::{ScanPriority, ScanRange},
|
||||
AccountBirthday, BlockMetadata, DecryptedTransaction, InputSource, NullifierQuery,
|
||||
ScannedBlock, SentTransaction, WalletCommitmentTrees, WalletRead, WalletSummary,
|
||||
WalletWrite, SAPLING_SHARD_HEIGHT,
|
||||
Account, AccountBirthday, AccountKind, BlockMetadata, DecryptedTransaction, InputSource,
|
||||
NullifierQuery, ScannedBlock, SentTransaction, WalletCommitmentTrees, WalletRead,
|
||||
WalletSummary, WalletWrite, SAPLING_SHARD_HEIGHT,
|
||||
},
|
||||
keys::{
|
||||
AddressGenerationError, UnifiedAddressRequest, UnifiedFullViewingKey, UnifiedSpendingKey,
|
||||
|
@ -100,7 +100,7 @@ pub mod error;
|
|||
pub mod wallet;
|
||||
use wallet::{
|
||||
commitment_tree::{self, put_shard_roots},
|
||||
AccountType, SubtreeScanProgress,
|
||||
SubtreeScanProgress,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -307,10 +307,10 @@ impl<C: Borrow<rusqlite::Connection>, P: consensus::Parameters> WalletRead for W
|
|||
seed: &SecretVec<u8>,
|
||||
) -> Result<bool, Self::Error> {
|
||||
if let Some(account) = wallet::get_account(self, account_id)? {
|
||||
if let AccountType::Derived {
|
||||
if let AccountKind::Derived {
|
||||
seed_fingerprint,
|
||||
account_index,
|
||||
} = account.kind
|
||||
} = account.kind()
|
||||
{
|
||||
let seed_fingerprint_match = HdSeedFingerprint::from_seed(seed) == seed_fingerprint;
|
||||
|
||||
|
@ -507,7 +507,7 @@ impl<P: consensus::Parameters> WalletWrite for WalletDb<rusqlite::Connection, P>
|
|||
let account_id = wallet::add_account(
|
||||
wdb.conn.0,
|
||||
&wdb.params,
|
||||
AccountType::Derived {
|
||||
AccountKind::Derived {
|
||||
seed_fingerprint,
|
||||
account_index,
|
||||
},
|
||||
|
|
|
@ -81,7 +81,7 @@ use zcash_client_backend::{
|
|||
address::{Address, UnifiedAddress},
|
||||
data_api::{
|
||||
scanning::{ScanPriority, ScanRange},
|
||||
AccountBalance, AccountBirthday, BlockMetadata, Ratio, SentTransactionOutput,
|
||||
AccountBalance, AccountBirthday, AccountKind, BlockMetadata, Ratio, SentTransactionOutput,
|
||||
WalletSummary, SAPLING_SHARD_HEIGHT,
|
||||
},
|
||||
encoding::AddressCodec,
|
||||
|
@ -138,27 +138,13 @@ pub(crate) mod scanning;
|
|||
|
||||
pub(crate) const BLOCK_SAPLING_FRONTIER_ABSENT: &[u8] = &[0x0];
|
||||
|
||||
/// This tracks the allowed values of the `account_type` column of the `accounts` table
|
||||
/// and should not be made public.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub(crate) enum AccountType {
|
||||
/// An account derived from a known seed.
|
||||
Derived {
|
||||
seed_fingerprint: HdSeedFingerprint,
|
||||
account_index: zip32::AccountId,
|
||||
},
|
||||
|
||||
/// An account imported from a viewing key.
|
||||
Imported,
|
||||
}
|
||||
|
||||
fn parse_account_kind(
|
||||
account_type: u32,
|
||||
hd_seed_fingerprint: Option<[u8; 32]>,
|
||||
hd_account_index: Option<u32>,
|
||||
) -> Result<AccountType, SqliteClientError> {
|
||||
) -> Result<AccountKind, SqliteClientError> {
|
||||
match (account_type, hd_seed_fingerprint, hd_account_index) {
|
||||
(0, Some(seed_fp), Some(account_index)) => Ok(AccountType::Derived {
|
||||
(0, Some(seed_fp), Some(account_index)) => Ok(AccountKind::Derived {
|
||||
seed_fingerprint: HdSeedFingerprint::from_bytes(seed_fp),
|
||||
account_index: zip32::AccountId::try_from(account_index).map_err(|_| {
|
||||
SqliteClientError::CorruptedData(
|
||||
|
@ -166,7 +152,7 @@ fn parse_account_kind(
|
|||
)
|
||||
})?,
|
||||
}),
|
||||
(1, None, None) => Ok(AccountType::Imported),
|
||||
(1, None, None) => Ok(AccountKind::Imported),
|
||||
(0, None, None) | (1, Some(_), Some(_)) => Err(SqliteClientError::CorruptedData(
|
||||
"Wallet DB account_type constraint violated".to_string(),
|
||||
)),
|
||||
|
@ -176,10 +162,10 @@ fn parse_account_kind(
|
|||
}
|
||||
}
|
||||
|
||||
fn account_kind_code(value: AccountType) -> u32 {
|
||||
fn account_kind_code(value: AccountKind) -> u32 {
|
||||
match value {
|
||||
AccountType::Derived { .. } => 0,
|
||||
AccountType::Imported => 1,
|
||||
AccountKind::Derived { .. } => 0,
|
||||
AccountKind::Imported => 1,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,7 +189,7 @@ pub(crate) enum ViewingKey {
|
|||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct Account {
|
||||
account_id: AccountId,
|
||||
pub(crate) kind: AccountType,
|
||||
kind: AccountKind,
|
||||
viewing_key: ViewingKey,
|
||||
}
|
||||
|
||||
|
@ -229,6 +215,10 @@ impl zcash_client_backend::data_api::Account<AccountId> for Account {
|
|||
self.account_id
|
||||
}
|
||||
|
||||
fn kind(&self) -> AccountKind {
|
||||
self.kind
|
||||
}
|
||||
|
||||
fn ufvk(&self) -> Option<&UnifiedFullViewingKey> {
|
||||
self.viewing_key.ufvk()
|
||||
}
|
||||
|
@ -333,16 +323,16 @@ pub(crate) fn ufvk_to_uivk<P: consensus::Parameters>(
|
|||
pub(crate) fn add_account<P: consensus::Parameters>(
|
||||
conn: &rusqlite::Transaction,
|
||||
params: &P,
|
||||
kind: AccountType,
|
||||
kind: AccountKind,
|
||||
viewing_key: ViewingKey,
|
||||
birthday: AccountBirthday,
|
||||
) -> Result<AccountId, SqliteClientError> {
|
||||
let (hd_seed_fingerprint, hd_account_index) = match kind {
|
||||
AccountType::Derived {
|
||||
AccountKind::Derived {
|
||||
seed_fingerprint,
|
||||
account_index,
|
||||
} => (Some(seed_fingerprint), Some(account_index)),
|
||||
AccountType::Imported => (None, None),
|
||||
AccountKind::Imported => (None, None),
|
||||
};
|
||||
|
||||
let orchard_item = viewing_key
|
||||
|
@ -2695,12 +2685,12 @@ mod tests {
|
|||
use std::num::NonZeroU32;
|
||||
|
||||
use sapling::zip32::ExtendedSpendingKey;
|
||||
use zcash_client_backend::data_api::{AccountBirthday, WalletRead};
|
||||
use zcash_client_backend::data_api::{AccountBirthday, AccountKind, WalletRead};
|
||||
use zcash_primitives::{block::BlockHash, transaction::components::amount::NonNegativeAmount};
|
||||
|
||||
use crate::{
|
||||
testing::{AddressType, BlockCache, TestBuilder, TestState},
|
||||
wallet::{get_account, AccountType},
|
||||
wallet::get_account,
|
||||
AccountId,
|
||||
};
|
||||
|
||||
|
@ -2853,7 +2843,7 @@ mod tests {
|
|||
let expected_account_index = zip32::AccountId::try_from(0).unwrap();
|
||||
assert_matches!(
|
||||
account_parameters.kind,
|
||||
AccountType::Derived{account_index, ..} if account_index == expected_account_index
|
||||
AccountKind::Derived{account_index, ..} if account_index == expected_account_index
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1282,9 +1282,9 @@ mod tests {
|
|||
#[test]
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
fn account_produces_expected_ua_sequence() {
|
||||
use zcash_client_backend::data_api::AccountBirthday;
|
||||
use zcash_client_backend::data_api::{AccountBirthday, AccountKind};
|
||||
|
||||
use crate::wallet::{get_account, AccountType};
|
||||
use crate::wallet::get_account;
|
||||
|
||||
let network = Network::MainNetwork;
|
||||
let data_file = NamedTempFile::new().unwrap();
|
||||
|
@ -1303,7 +1303,7 @@ mod tests {
|
|||
get_account(&db_data, account_id),
|
||||
Ok(Some(account)) if matches!(
|
||||
account.kind,
|
||||
AccountType::Derived{account_index, ..} if account_index == zip32::AccountId::ZERO,
|
||||
AccountKind::Derived{account_index, ..} if account_index == zip32::AccountId::ZERO,
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use std::{collections::HashSet, rc::Rc};
|
||||
|
||||
use crate::wallet::{account_kind_code, init::WalletMigrationError, ufvk_to_uivk, AccountType};
|
||||
use crate::wallet::{account_kind_code, init::WalletMigrationError, ufvk_to_uivk};
|
||||
use rusqlite::{named_params, Transaction};
|
||||
use schemer_rusqlite::RusqliteMigration;
|
||||
use secrecy::{ExposeSecret, SecretVec};
|
||||
use uuid::Uuid;
|
||||
use zcash_client_backend::keys::UnifiedSpendingKey;
|
||||
use zcash_client_backend::{data_api::AccountKind, keys::UnifiedSpendingKey};
|
||||
use zcash_keys::keys::{HdSeedFingerprint, UnifiedFullViewingKey};
|
||||
use zcash_primitives::consensus;
|
||||
|
||||
|
@ -44,11 +44,11 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
|
|||
type Error = WalletMigrationError;
|
||||
|
||||
fn up(&self, transaction: &Transaction) -> Result<(), WalletMigrationError> {
|
||||
let account_type_derived = account_kind_code(AccountType::Derived {
|
||||
let account_type_derived = account_kind_code(AccountKind::Derived {
|
||||
seed_fingerprint: HdSeedFingerprint::from_bytes([0; 32]),
|
||||
account_index: zip32::AccountId::ZERO,
|
||||
});
|
||||
let account_type_imported = account_kind_code(AccountType::Imported);
|
||||
let account_type_imported = account_kind_code(AccountKind::Imported);
|
||||
transaction.execute_batch(
|
||||
&format!(r#"
|
||||
PRAGMA foreign_keys = OFF;
|
||||
|
|
Loading…
Reference in New Issue