Extract get_extended_full_viewing_keys function.
This required a bit of generalization of the data_api error types.
This commit is contained in:
parent
3eec6f8faa
commit
d16c74725e
|
@ -26,15 +26,16 @@ pub const ANCHOR_OFFSET: u32 = 10;
|
|||
///
|
||||
/// This function does not mutate either of the databases.
|
||||
pub fn validate_combined_chain<
|
||||
E,
|
||||
E0,
|
||||
E: From<Error<E0>>,
|
||||
P: consensus::Parameters,
|
||||
C: CacheOps<Error = Error<E>>,
|
||||
D: DBOps<Error = Error<E>>,
|
||||
C: CacheOps<Error = E>,
|
||||
D: DBOps<Error = E>,
|
||||
>(
|
||||
parameters: &P,
|
||||
cache: &C,
|
||||
data: &D,
|
||||
) -> Result<(), Error<E>> {
|
||||
) -> Result<(), E> {
|
||||
let sapling_activation_height = parameters
|
||||
.activation_height(NetworkUpgrade::Sapling)
|
||||
.ok_or(Error::SaplingNotActive)?;
|
||||
|
@ -49,12 +50,12 @@ pub fn validate_combined_chain<
|
|||
let from_height = data_max_height.unwrap_or(sapling_activation_height - 1);
|
||||
let cached_hash_opt = cache.validate_chain(from_height, |top_block, next_block| {
|
||||
if next_block.height() != top_block.height() - 1 {
|
||||
Err(ChainInvalid::block_height_mismatch(
|
||||
top_block.height() - 1,
|
||||
next_block.height(),
|
||||
))
|
||||
Err(
|
||||
ChainInvalid::block_height_mismatch(top_block.height() - 1, next_block.height())
|
||||
.into(),
|
||||
)
|
||||
} else if next_block.hash() != top_block.prev_hash() {
|
||||
Err(ChainInvalid::prev_hash_mismatch(next_block.height()))
|
||||
Err(ChainInvalid::prev_hash_mismatch(next_block.height()).into())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -66,12 +67,13 @@ pub fn validate_combined_chain<
|
|||
if cached_hash == data_scan_max_hash {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ChainInvalid::prev_hash_mismatch::<E>(h))
|
||||
Err(ChainInvalid::prev_hash_mismatch(h).into())
|
||||
}
|
||||
}
|
||||
None => Err(Error::CorruptedData(
|
||||
"No block hash available for block at maximum chain height.",
|
||||
)),
|
||||
)
|
||||
.into()),
|
||||
},
|
||||
_ => {
|
||||
// No cached blocks are present, or the max data height is absent, this is fine.
|
||||
|
@ -82,9 +84,9 @@ pub fn validate_combined_chain<
|
|||
|
||||
/// Determines the target height for a transaction, and the height from which to
|
||||
/// select anchors, based on the current synchronised block chain.
|
||||
pub fn get_target_and_anchor_heights<E, D: DBOps<Error = Error<E>>>(
|
||||
pub fn get_target_and_anchor_heights<E0, E: From<Error<E0>>, D: DBOps<Error = E>>(
|
||||
data: &D,
|
||||
) -> Result<(BlockHeight, BlockHeight), Error<E>> {
|
||||
) -> Result<(BlockHeight, BlockHeight), E> {
|
||||
data.block_height_extrema().and_then(|heights| {
|
||||
match heights {
|
||||
Some((min_height, max_height)) => {
|
||||
|
@ -99,7 +101,7 @@ pub fn get_target_and_anchor_heights<E, D: DBOps<Error = Error<E>>>(
|
|||
|
||||
Ok((target_height, anchor_height))
|
||||
}
|
||||
None => Err(Error::ScanRequired),
|
||||
None => Err(Error::ScanRequired.into()),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@ pub mod error;
|
|||
|
||||
pub trait DBOps {
|
||||
type Error;
|
||||
type Account;
|
||||
type AccountId;
|
||||
type NoteId;
|
||||
// type TxRef; // Backend-specific transaction handle
|
||||
// type NoteRef; // Backend-specific note identifier`
|
||||
|
||||
|
@ -48,17 +49,23 @@ pub trait DBOps {
|
|||
fn get_address<P: consensus::Parameters>(
|
||||
&self,
|
||||
params: &P,
|
||||
account: Self::Account,
|
||||
account: Self::AccountId,
|
||||
) -> Result<Option<PaymentAddress>, Self::Error>;
|
||||
|
||||
fn get_balance(&self, account: Self::Account) -> Result<Amount, Self::Error>;
|
||||
fn get_balance(&self, account: Self::AccountId) -> Result<Amount, Self::Error>;
|
||||
|
||||
fn get_verified_balance(&self, account: Self::Account) -> Result<Amount, Self::Error>;
|
||||
fn get_verified_balance(&self, account: Self::AccountId) -> Result<Amount, Self::Error>;
|
||||
|
||||
fn get_received_memo_as_utf8(
|
||||
&self,
|
||||
id_note: Self::NoteId,
|
||||
) -> Result<Option<String>, Self::Error>;
|
||||
|
||||
fn get_extended_full_viewing_keys<P: consensus::Parameters>(
|
||||
&self,
|
||||
params: &P,
|
||||
) -> Result<Vec<ExtendedFullViewingKey>, Self::Error>;
|
||||
|
||||
// fn get_received_memo_as_utf8(id_note: i64) -> Result<Option<String>, Self::Error>;
|
||||
//
|
||||
// fn get_extended_full_viewing_keys() -> Result<Box<dyn Iterator<Item = ExtendedFullViewingKey>>, Self::Error>;
|
||||
//
|
||||
// fn get_commitment_tree(block_height: BlockHeight) -> Result<Option<CommitmentTree<Node>>, Self::Error>;
|
||||
//
|
||||
// fn get_witnesses(block_height: BlockHeight) -> Result<Box<dyn Iterator<Item = IncrementalWitness<Node>>>, Self::Error>;
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
//! // Given that we assume the server always gives us correct-at-the-time blocks, any
|
||||
//! // errors are in the blocks we have previously cached or scanned.
|
||||
//! if let Err(e) = validate_combined_chain(&network, &db_cache, &db_data) {
|
||||
//! match e {
|
||||
//! match e.0 {
|
||||
//! Error::InvalidChain(upper_bound, _) => {
|
||||
//! // a) Pick a height to rewind to.
|
||||
//! //
|
||||
|
@ -96,7 +96,7 @@ pub fn validate_chain<F>(
|
|||
validate: F,
|
||||
) -> Result<Option<BlockHash>, SqliteClientError>
|
||||
where
|
||||
F: Fn(&CompactBlock, &CompactBlock) -> Result<(), Error<rusqlite::Error>>,
|
||||
F: Fn(&CompactBlock, &CompactBlock) -> Result<(), SqliteClientError>,
|
||||
{
|
||||
let mut stmt_blocks = conn
|
||||
.0
|
||||
|
@ -252,7 +252,7 @@ mod tests {
|
|||
query::get_balance,
|
||||
scan::scan_cached_blocks,
|
||||
tests::{self, fake_compact_block, insert_into_cache, sapling_activation_height},
|
||||
Account, CacheConnection, DataConnection,
|
||||
AccountId, CacheConnection, DataConnection,
|
||||
};
|
||||
|
||||
use super::rewind_to_height;
|
||||
|
@ -366,7 +366,7 @@ mod tests {
|
|||
insert_into_cache(&db_cache, &cb4);
|
||||
|
||||
// Data+cache chain should be invalid at the data/cache boundary
|
||||
match validate_combined_chain(&tests::network(), &db_cache, &db_data) {
|
||||
match validate_combined_chain(&tests::network(), &db_cache, &db_data).map_err(|e| e.0) {
|
||||
Err(Error::InvalidChain(upper_bound, _)) => {
|
||||
assert_eq!(upper_bound, sapling_activation_height() + 1)
|
||||
}
|
||||
|
@ -428,7 +428,7 @@ mod tests {
|
|||
insert_into_cache(&db_cache, &cb4);
|
||||
|
||||
// Data+cache chain should be invalid inside the cache
|
||||
match validate_combined_chain(&tests::network(), &db_cache, &db_data) {
|
||||
match validate_combined_chain(&tests::network(), &db_cache, &db_data).map_err(|e| e.0) {
|
||||
Err(Error::InvalidChain(upper_bound, _)) => {
|
||||
assert_eq!(upper_bound, sapling_activation_height() + 2)
|
||||
}
|
||||
|
@ -452,7 +452,7 @@ mod tests {
|
|||
init_accounts_table(&db_data, &tests::network(), &[extfvk.clone()]).unwrap();
|
||||
|
||||
// Account balance should be zero
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), Amount::zero());
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), Amount::zero());
|
||||
|
||||
// Create fake CompactBlocks sending value to the address
|
||||
let value = Amount::from_u64(5).unwrap();
|
||||
|
@ -473,24 +473,24 @@ mod tests {
|
|||
scan_cached_blocks(&tests::network(), &db_cache, &db_data, None).unwrap();
|
||||
|
||||
// Account balance should reflect both received notes
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), value + value2);
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value + value2);
|
||||
|
||||
// "Rewind" to height of last scanned block
|
||||
rewind_to_height(&db_data, &tests::network(), sapling_activation_height() + 1).unwrap();
|
||||
|
||||
// Account balance should be unaltered
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), value + value2);
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value + value2);
|
||||
|
||||
// Rewind so that one block is dropped
|
||||
rewind_to_height(&db_data, &tests::network(), sapling_activation_height()).unwrap();
|
||||
|
||||
// Account balance should only contain the first received note
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), value);
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value);
|
||||
|
||||
// Scan the cache again
|
||||
scan_cached_blocks(&tests::network(), &db_cache, &db_data, None).unwrap();
|
||||
|
||||
// Account balance should again reflect both received notes
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), value + value2);
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value + value2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -272,7 +272,7 @@ mod tests {
|
|||
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
|
||||
};
|
||||
|
||||
use crate::{query::get_address, tests, Account, DataConnection};
|
||||
use crate::{query::get_address, tests, AccountId, DataConnection};
|
||||
|
||||
use super::{init_accounts_table, init_blocks_table, init_data_database};
|
||||
|
||||
|
@ -336,7 +336,7 @@ mod tests {
|
|||
init_accounts_table(&db_data, &tests::network(), &extfvks).unwrap();
|
||||
|
||||
// The account's address should be in the data DB
|
||||
let pa = get_address(&db_data, &tests::network(), Account(0)).unwrap();
|
||||
let pa = get_address(&db_data, &tests::network(), AccountId(0)).unwrap();
|
||||
assert_eq!(pa.unwrap(), extsk.default_address().unwrap().1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,11 +36,13 @@ use zcash_primitives::{
|
|||
};
|
||||
|
||||
use zcash_client_backend::{
|
||||
data_api::{error::Error, CacheOps, DBOps},
|
||||
data_api::{CacheOps, DBOps},
|
||||
encoding::encode_payment_address,
|
||||
proto::compact_formats::CompactBlock,
|
||||
};
|
||||
|
||||
use crate::error::SqliteClientError;
|
||||
|
||||
pub mod chain;
|
||||
pub mod error;
|
||||
pub mod init;
|
||||
|
@ -48,7 +50,8 @@ pub mod query;
|
|||
pub mod scan;
|
||||
pub mod transact;
|
||||
|
||||
pub struct Account(pub u32);
|
||||
pub struct AccountId(pub u32);
|
||||
pub struct NoteId(pub i64);
|
||||
|
||||
pub struct DataConnection(Connection);
|
||||
|
||||
|
@ -59,11 +62,12 @@ impl DataConnection {
|
|||
}
|
||||
|
||||
impl DBOps for DataConnection {
|
||||
type Error = Error<rusqlite::Error>;
|
||||
type Account = Account;
|
||||
type Error = SqliteClientError;
|
||||
type AccountId = AccountId;
|
||||
type NoteId = NoteId;
|
||||
|
||||
fn init_db(&self) -> Result<(), Self::Error> {
|
||||
init::init_data_database(self).map_err(Error::Database)
|
||||
init::init_data_database(self).map_err(SqliteClientError::from)
|
||||
}
|
||||
|
||||
fn init_account_storage<P: consensus::Parameters>(
|
||||
|
@ -71,7 +75,7 @@ impl DBOps for DataConnection {
|
|||
params: &P,
|
||||
extfvks: &[ExtendedFullViewingKey],
|
||||
) -> Result<(), Self::Error> {
|
||||
init::init_accounts_table(self, params, extfvks).map_err(|e| e.0)
|
||||
init::init_accounts_table(self, params, extfvks)
|
||||
}
|
||||
|
||||
fn init_block_storage(
|
||||
|
@ -81,15 +85,15 @@ impl DBOps for DataConnection {
|
|||
time: u32,
|
||||
sapling_tree: &[u8],
|
||||
) -> Result<(), Self::Error> {
|
||||
init::init_blocks_table(self, height, hash, time, sapling_tree).map_err(|e| e.0)
|
||||
init::init_blocks_table(self, height, hash, time, sapling_tree)
|
||||
}
|
||||
|
||||
fn block_height_extrema(&self) -> Result<Option<(BlockHeight, BlockHeight)>, Self::Error> {
|
||||
chain::block_height_extrema(self).map_err(Error::Database)
|
||||
chain::block_height_extrema(self).map_err(SqliteClientError::from)
|
||||
}
|
||||
|
||||
fn get_block_hash(&self, block_height: BlockHeight) -> Result<Option<BlockHash>, Self::Error> {
|
||||
chain::get_block_hash(self, block_height).map_err(Error::Database)
|
||||
chain::get_block_hash(self, block_height).map_err(SqliteClientError::from)
|
||||
}
|
||||
|
||||
fn rewind_to_height<P: consensus::Parameters>(
|
||||
|
@ -97,23 +101,37 @@ impl DBOps for DataConnection {
|
|||
parameters: &P,
|
||||
block_height: BlockHeight,
|
||||
) -> Result<(), Self::Error> {
|
||||
chain::rewind_to_height(self, parameters, block_height).map_err(|e| e.0)
|
||||
chain::rewind_to_height(self, parameters, block_height)
|
||||
}
|
||||
|
||||
fn get_address<P: consensus::Parameters>(
|
||||
&self,
|
||||
params: &P,
|
||||
account: Self::Account,
|
||||
account: Self::AccountId,
|
||||
) -> Result<Option<PaymentAddress>, Self::Error> {
|
||||
query::get_address(self, params, account).map_err(|e| e.0)
|
||||
query::get_address(self, params, account)
|
||||
}
|
||||
|
||||
fn get_balance(&self, account: Account) -> Result<Amount, Self::Error> {
|
||||
query::get_balance(self, account).map_err(|e| e.0)
|
||||
fn get_balance(&self, account: Self::AccountId) -> Result<Amount, Self::Error> {
|
||||
query::get_balance(self, account)
|
||||
}
|
||||
|
||||
fn get_verified_balance(&self, account: Self::Account) -> Result<Amount, Self::Error> {
|
||||
query::get_verified_balance(self, account).map_err(|e| e.0)
|
||||
fn get_verified_balance(&self, account: Self::AccountId) -> Result<Amount, Self::Error> {
|
||||
query::get_verified_balance(self, account)
|
||||
}
|
||||
|
||||
fn get_received_memo_as_utf8(
|
||||
&self,
|
||||
id_note: Self::NoteId,
|
||||
) -> Result<Option<String>, Self::Error> {
|
||||
query::get_received_memo_as_utf8(self, id_note)
|
||||
}
|
||||
|
||||
fn get_extended_full_viewing_keys<P: consensus::Parameters>(
|
||||
&self,
|
||||
params: &P,
|
||||
) -> Result<Vec<ExtendedFullViewingKey>, Self::Error> {
|
||||
query::get_extended_full_viewing_keys(self, params)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,10 +144,10 @@ impl CacheConnection {
|
|||
}
|
||||
|
||||
impl CacheOps for CacheConnection {
|
||||
type Error = Error<rusqlite::Error>;
|
||||
type Error = SqliteClientError;
|
||||
|
||||
fn init_cache(&self) -> Result<(), Self::Error> {
|
||||
init::init_cache_database(self).map_err(Error::Database)
|
||||
init::init_cache_database(self).map_err(SqliteClientError::from)
|
||||
}
|
||||
|
||||
fn validate_chain<F>(
|
||||
|
@ -140,7 +158,7 @@ impl CacheOps for CacheConnection {
|
|||
where
|
||||
F: Fn(&CompactBlock, &CompactBlock) -> Result<(), Self::Error>,
|
||||
{
|
||||
chain::validate_chain(self, from_height, validate).map_err(|s| s.0)
|
||||
chain::validate_chain(self, from_height, validate)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
//! Functions for querying information in the data database.
|
||||
|
||||
use rusqlite::NO_PARAMS;
|
||||
|
||||
use zcash_primitives::{
|
||||
consensus::{self},
|
||||
note_encryption::Memo,
|
||||
primitives::PaymentAddress,
|
||||
transaction::components::Amount,
|
||||
zip32::ExtendedFullViewingKey,
|
||||
};
|
||||
|
||||
use zcash_client_backend::{
|
||||
data_api::{chain::get_target_and_anchor_heights, error::Error},
|
||||
encoding::decode_payment_address,
|
||||
encoding::{decode_extended_full_viewing_key, decode_payment_address},
|
||||
};
|
||||
|
||||
use crate::{error::SqliteClientError, Account, DataConnection};
|
||||
use crate::{error::SqliteClientError, AccountId, DataConnection, NoteId};
|
||||
|
||||
/// Returns the address for the account.
|
||||
///
|
||||
|
@ -24,19 +27,19 @@ use crate::{error::SqliteClientError, Account, DataConnection};
|
|||
/// consensus::{self, Network},
|
||||
/// };
|
||||
/// use zcash_client_sqlite::{
|
||||
/// Account,
|
||||
/// AccountId,
|
||||
/// DataConnection,
|
||||
/// query::get_address,
|
||||
/// };
|
||||
///
|
||||
/// let data_file = NamedTempFile::new().unwrap();
|
||||
/// let db = DataConnection::for_path(data_file).unwrap();
|
||||
/// let addr = get_address(&db, &Network::TestNetwork, Account(0));
|
||||
/// let addr = get_address(&db, &Network::TestNetwork, AccountId(0));
|
||||
/// ```
|
||||
pub fn get_address<P: consensus::Parameters>(
|
||||
data: &DataConnection,
|
||||
params: &P,
|
||||
account: Account,
|
||||
account: AccountId,
|
||||
) -> Result<Option<PaymentAddress>, SqliteClientError> {
|
||||
let addr: String = data.0.query_row(
|
||||
"SELECT address FROM accounts
|
||||
|
@ -62,16 +65,16 @@ pub fn get_address<P: consensus::Parameters>(
|
|||
/// ```
|
||||
/// use tempfile::NamedTempFile;
|
||||
/// use zcash_client_sqlite::{
|
||||
/// Account,
|
||||
/// AccountId,
|
||||
/// DataConnection,
|
||||
/// query::get_balance,
|
||||
/// };
|
||||
///
|
||||
/// let data_file = NamedTempFile::new().unwrap();
|
||||
/// let db = DataConnection::for_path(data_file).unwrap();
|
||||
/// let addr = get_balance(&db, Account(0));
|
||||
/// let addr = get_balance(&db, AccountId(0));
|
||||
/// ```
|
||||
pub fn get_balance(data: &DataConnection, account: Account) -> Result<Amount, SqliteClientError> {
|
||||
pub fn get_balance(data: &DataConnection, account: AccountId) -> Result<Amount, SqliteClientError> {
|
||||
let balance = data.0.query_row(
|
||||
"SELECT SUM(value) FROM received_notes
|
||||
INNER JOIN transactions ON transactions.id_tx = received_notes.tx
|
||||
|
@ -96,18 +99,18 @@ pub fn get_balance(data: &DataConnection, account: Account) -> Result<Amount, Sq
|
|||
/// ```
|
||||
/// use tempfile::NamedTempFile;
|
||||
/// use zcash_client_sqlite::{
|
||||
/// Account,
|
||||
/// AccountId,
|
||||
/// DataConnection,
|
||||
/// query::get_verified_balance,
|
||||
/// };
|
||||
///
|
||||
/// let data_file = NamedTempFile::new().unwrap();
|
||||
/// let db = DataConnection::for_path(data_file).unwrap();
|
||||
/// let addr = get_verified_balance(&db, Account(0));
|
||||
/// let addr = get_verified_balance(&db, AccountId(0));
|
||||
/// ```
|
||||
pub fn get_verified_balance(
|
||||
data: &DataConnection,
|
||||
account: Account,
|
||||
account: AccountId,
|
||||
) -> Result<Amount, SqliteClientError> {
|
||||
let (_, anchor_height) = get_target_and_anchor_heights(data)?;
|
||||
|
||||
|
@ -137,22 +140,23 @@ pub fn get_verified_balance(
|
|||
/// ```
|
||||
/// use tempfile::NamedTempFile;
|
||||
/// use zcash_client_sqlite::{
|
||||
/// NoteId,
|
||||
/// DataConnection,
|
||||
/// query::get_received_memo_as_utf8,
|
||||
/// };
|
||||
///
|
||||
/// let data_file = NamedTempFile::new().unwrap();
|
||||
/// let db = DataConnection::for_path(data_file).unwrap();
|
||||
/// let memo = get_received_memo_as_utf8(&db, 27);
|
||||
/// let memo = get_received_memo_as_utf8(&db, NoteId(27));
|
||||
/// ```
|
||||
pub fn get_received_memo_as_utf8(
|
||||
data: &DataConnection,
|
||||
id_note: i64,
|
||||
id_note: NoteId,
|
||||
) -> Result<Option<String>, SqliteClientError> {
|
||||
let memo: Vec<_> = data.0.query_row(
|
||||
"SELECT memo FROM received_notes
|
||||
WHERE id_note = ?",
|
||||
&[id_note],
|
||||
&[id_note.0],
|
||||
|row| row.get(0),
|
||||
)?;
|
||||
|
||||
|
@ -176,22 +180,23 @@ pub fn get_received_memo_as_utf8(
|
|||
/// ```
|
||||
/// use tempfile::NamedTempFile;
|
||||
/// use zcash_client_sqlite::{
|
||||
/// NoteId,
|
||||
/// DataConnection,
|
||||
/// query::get_sent_memo_as_utf8,
|
||||
/// };
|
||||
///
|
||||
/// let data_file = NamedTempFile::new().unwrap();
|
||||
/// let db = DataConnection::for_path(data_file).unwrap();
|
||||
/// let memo = get_sent_memo_as_utf8(&db, 12);
|
||||
/// let memo = get_sent_memo_as_utf8(&db, NoteId(12));
|
||||
/// ```
|
||||
pub fn get_sent_memo_as_utf8(
|
||||
data: &DataConnection,
|
||||
id_note: i64,
|
||||
id_note: NoteId,
|
||||
) -> Result<Option<String>, SqliteClientError> {
|
||||
let memo: Vec<_> = data.0.query_row(
|
||||
"SELECT memo FROM sent_notes
|
||||
WHERE id_note = ?",
|
||||
&[id_note],
|
||||
&[id_note.0],
|
||||
|row| row.get(0),
|
||||
)?;
|
||||
|
||||
|
@ -205,6 +210,32 @@ pub fn get_sent_memo_as_utf8(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_extended_full_viewing_keys<P: consensus::Parameters>(
|
||||
data: &DataConnection,
|
||||
params: &P,
|
||||
) -> Result<Vec<ExtendedFullViewingKey>, SqliteClientError> {
|
||||
// Fetch the ExtendedFullViewingKeys we are tracking
|
||||
let mut stmt_fetch_accounts = data
|
||||
.0
|
||||
.prepare("SELECT extfvk FROM accounts ORDER BY account ASC")?;
|
||||
|
||||
let rows = stmt_fetch_accounts
|
||||
.query_map(NO_PARAMS, |row| {
|
||||
row.get(0).map(|extfvk: String| {
|
||||
decode_extended_full_viewing_key(
|
||||
params.hrp_sapling_extended_full_viewing_key(),
|
||||
&extfvk,
|
||||
)
|
||||
.map_err(|e| Error::Bech32(e))
|
||||
.and_then(|k| k.ok_or(Error::IncorrectHRPExtFVK))
|
||||
.map_err(SqliteClientError)
|
||||
})
|
||||
})
|
||||
.map_err(|e| SqliteClientError(Error::Database(e)))?;
|
||||
|
||||
rows.collect::<Result<Result<_, _>, _>>()?
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rusqlite::Connection;
|
||||
|
@ -219,7 +250,7 @@ mod tests {
|
|||
|
||||
use crate::{
|
||||
init::{init_accounts_table, init_data_database},
|
||||
tests, Account, DataConnection,
|
||||
tests, AccountId, DataConnection,
|
||||
};
|
||||
|
||||
use super::{get_address, get_balance, get_verified_balance};
|
||||
|
@ -236,17 +267,17 @@ mod tests {
|
|||
init_accounts_table(&db_data, &tests::network(), &extfvks).unwrap();
|
||||
|
||||
// The account should be empty
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), Amount::zero());
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), Amount::zero());
|
||||
|
||||
// The account should have no verified balance, as we haven't scanned any blocks
|
||||
let e = get_verified_balance(&db_data, Account(0)).unwrap_err();
|
||||
let e = get_verified_balance(&db_data, AccountId(0)).unwrap_err();
|
||||
match e.0 {
|
||||
Error::ScanRequired => (),
|
||||
_ => panic!("Unexpected error: {:?}", e),
|
||||
}
|
||||
|
||||
// An invalid account has zero balance
|
||||
assert!(get_address(&db_data, &tests::network(), Account(1)).is_err());
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), Amount::zero());
|
||||
assert!(get_address(&db_data, &tests::network(), AccountId(1)).is_err());
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), Amount::zero());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -585,7 +585,7 @@ mod tests {
|
|||
self, fake_compact_block, fake_compact_block_spending, insert_into_cache,
|
||||
sapling_activation_height,
|
||||
},
|
||||
Account, CacheConnection, DataConnection,
|
||||
AccountId, CacheConnection, DataConnection,
|
||||
};
|
||||
|
||||
use super::scan_cached_blocks;
|
||||
|
@ -615,7 +615,7 @@ mod tests {
|
|||
);
|
||||
insert_into_cache(&db_cache, &cb1);
|
||||
scan_cached_blocks(&tests::network(), &db_cache, &db_data, None).unwrap();
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), value);
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value);
|
||||
|
||||
// We cannot scan a block of height SAPLING_ACTIVATION_HEIGHT + 2 next
|
||||
let (cb2, _) = fake_compact_block(
|
||||
|
@ -654,7 +654,7 @@ mod tests {
|
|||
insert_into_cache(&db_cache, &cb2);
|
||||
scan_cached_blocks(&tests::network(), &db_cache, &db_data, None).unwrap();
|
||||
assert_eq!(
|
||||
get_balance(&db_data, Account(0)).unwrap(),
|
||||
get_balance(&db_data, AccountId(0)).unwrap(),
|
||||
Amount::from_u64(150_000).unwrap()
|
||||
);
|
||||
}
|
||||
|
@ -675,7 +675,7 @@ mod tests {
|
|||
init_accounts_table(&db_data, &tests::network(), &[extfvk.clone()]).unwrap();
|
||||
|
||||
// Account balance should be zero
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), Amount::zero());
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), Amount::zero());
|
||||
|
||||
// Create a fake CompactBlock sending value to the address
|
||||
let value = Amount::from_u64(5).unwrap();
|
||||
|
@ -691,7 +691,7 @@ mod tests {
|
|||
scan_cached_blocks(&tests::network(), &db_cache, &db_data, None).unwrap();
|
||||
|
||||
// Account balance should reflect the received note
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), value);
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value);
|
||||
|
||||
// Create a second fake CompactBlock sending more value to the address
|
||||
let value2 = Amount::from_u64(7).unwrap();
|
||||
|
@ -703,7 +703,7 @@ mod tests {
|
|||
scan_cached_blocks(&tests::network(), &db_cache, &db_data, None).unwrap();
|
||||
|
||||
// Account balance should reflect both received notes
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), value + value2);
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value + value2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -722,7 +722,7 @@ mod tests {
|
|||
init_accounts_table(&db_data, &tests::network(), &[extfvk.clone()]).unwrap();
|
||||
|
||||
// Account balance should be zero
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), Amount::zero());
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), Amount::zero());
|
||||
|
||||
// Create a fake CompactBlock sending value to the address
|
||||
let value = Amount::from_u64(5).unwrap();
|
||||
|
@ -738,7 +738,7 @@ mod tests {
|
|||
scan_cached_blocks(&tests::network(), &db_cache, &db_data, None).unwrap();
|
||||
|
||||
// Account balance should reflect the received note
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), value);
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value);
|
||||
|
||||
// Create a second fake CompactBlock spending value from the address
|
||||
let extsk2 = ExtendedSpendingKey::master(&[0]);
|
||||
|
@ -760,6 +760,6 @@ mod tests {
|
|||
scan_cached_blocks(&tests::network(), &db_cache, &db_data, None).unwrap();
|
||||
|
||||
// Account balance should equal the change
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), value - value2);
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value - value2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -391,7 +391,7 @@ mod tests {
|
|||
query::{get_balance, get_verified_balance},
|
||||
scan::scan_cached_blocks,
|
||||
tests::{self, fake_compact_block, insert_into_cache, sapling_activation_height},
|
||||
Account, CacheConnection, DataConnection,
|
||||
AccountId, CacheConnection, DataConnection,
|
||||
};
|
||||
|
||||
use super::{create_to_address, OvkPolicy};
|
||||
|
@ -503,7 +503,7 @@ mod tests {
|
|||
let to = extsk.default_address().unwrap().1.into();
|
||||
|
||||
// Account balance should be zero
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), Amount::zero());
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), Amount::zero());
|
||||
|
||||
// We cannot spend anything
|
||||
match create_to_address(
|
||||
|
@ -552,8 +552,8 @@ mod tests {
|
|||
scan_cached_blocks(&tests::network(), &db_cache, &db_data, None).unwrap();
|
||||
|
||||
// Verified balance matches total balance
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), value);
|
||||
assert_eq!(get_verified_balance(&db_data, Account(0)).unwrap(), value);
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value);
|
||||
assert_eq!(get_verified_balance(&db_data, AccountId(0)).unwrap(), value);
|
||||
|
||||
// Add more funds to the wallet in a second note
|
||||
let (cb, _) = fake_compact_block(
|
||||
|
@ -566,8 +566,8 @@ mod tests {
|
|||
scan_cached_blocks(&tests::network(), &db_cache, &db_data, None).unwrap();
|
||||
|
||||
// Verified balance does not include the second note
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), value + value);
|
||||
assert_eq!(get_verified_balance(&db_data, Account(0)).unwrap(), value);
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value + value);
|
||||
assert_eq!(get_verified_balance(&db_data, AccountId(0)).unwrap(), value);
|
||||
|
||||
// Spend fails because there are insufficient verified notes
|
||||
let extsk2 = ExtendedSpendingKey::master(&[]);
|
||||
|
@ -672,7 +672,7 @@ mod tests {
|
|||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
scan_cached_blocks(&tests::network(), &db_cache, &db_data, None).unwrap();
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), value);
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value);
|
||||
|
||||
// Send some of the funds to another address
|
||||
let extsk2 = ExtendedSpendingKey::master(&[]);
|
||||
|
@ -791,8 +791,8 @@ mod tests {
|
|||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
scan_cached_blocks(&network, &db_cache, &db_data, None).unwrap();
|
||||
assert_eq!(get_balance(&db_data, Account(0)).unwrap(), value);
|
||||
scan_cached_blocks(&tests::network(), &db_cache, &db_data, None).unwrap();
|
||||
assert_eq!(get_balance(&db_data, AccountId(0)).unwrap(), value);
|
||||
|
||||
let extsk2 = ExtendedSpendingKey::master(&[]);
|
||||
let addr2 = extsk2.default_address().unwrap().1;
|
||||
|
|
Loading…
Reference in New Issue