zcash_client_sqlite: Generalise `wallet::scanning` tests
This commit is contained in:
parent
399ae762b7
commit
9d40588a50
|
@ -4,6 +4,7 @@
|
|||
|
||||
use std::{convert::Infallible, num::NonZeroU32};
|
||||
|
||||
use incrementalmerkletree::Level;
|
||||
use rusqlite::params;
|
||||
use secrecy::Secret;
|
||||
use shardtree::error::ShardTreeError;
|
||||
|
@ -29,7 +30,7 @@ use zcash_client_backend::{
|
|||
chain::CommitmentTreeRoot,
|
||||
error::Error,
|
||||
wallet::input_selection::{GreedyInputSelector, GreedyInputSelectorError},
|
||||
AccountBirthday, DecryptedTransaction, Ratio, WalletRead, WalletWrite,
|
||||
AccountBirthday, DecryptedTransaction, Ratio, WalletRead, WalletSummary, WalletWrite,
|
||||
},
|
||||
decrypt_transaction,
|
||||
fees::{fixed, standard, DustOutputPolicy},
|
||||
|
@ -87,6 +88,7 @@ pub(crate) trait ShieldedPoolTester {
|
|||
fn fvks_equal(a: &Self::Fvk, b: &Self::Fvk) -> bool;
|
||||
|
||||
fn empty_tree_leaf() -> Self::MerkleTreeHash;
|
||||
fn empty_tree_root(level: Level) -> Self::MerkleTreeHash;
|
||||
|
||||
fn put_subtree_roots<Cache>(
|
||||
st: &mut TestState<Cache>,
|
||||
|
@ -94,6 +96,8 @@ pub(crate) trait ShieldedPoolTester {
|
|||
roots: &[CommitmentTreeRoot<Self::MerkleTreeHash>],
|
||||
) -> Result<(), ShardTreeError<commitment_tree::Error>>;
|
||||
|
||||
fn next_subtree_index(s: &WalletSummary<AccountId>) -> u64;
|
||||
|
||||
fn select_spendable_notes<Cache>(
|
||||
st: &TestState<Cache>,
|
||||
account: AccountId,
|
||||
|
|
|
@ -464,7 +464,7 @@ pub(crate) fn put_received_note<T: ReceivedSaplingOutput>(
|
|||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use incrementalmerkletree::Hashable;
|
||||
use incrementalmerkletree::{Hashable, Level};
|
||||
use shardtree::error::ShardTreeError;
|
||||
use zcash_proofs::prover::LocalTxProver;
|
||||
|
||||
|
@ -486,7 +486,9 @@ pub(crate) mod tests {
|
|||
|
||||
use zcash_client_backend::{
|
||||
address::Address,
|
||||
data_api::{chain::CommitmentTreeRoot, DecryptedTransaction, WalletCommitmentTrees},
|
||||
data_api::{
|
||||
chain::CommitmentTreeRoot, DecryptedTransaction, WalletCommitmentTrees, WalletSummary,
|
||||
},
|
||||
keys::UnifiedSpendingKey,
|
||||
wallet::{Note, ReceivedNote},
|
||||
ShieldedProtocol,
|
||||
|
@ -544,6 +546,10 @@ pub(crate) mod tests {
|
|||
sapling::Node::empty_leaf()
|
||||
}
|
||||
|
||||
fn empty_tree_root(level: Level) -> Self::MerkleTreeHash {
|
||||
sapling::Node::empty_root(level)
|
||||
}
|
||||
|
||||
fn put_subtree_roots<Cache>(
|
||||
st: &mut TestState<Cache>,
|
||||
start_index: u64,
|
||||
|
@ -553,6 +559,10 @@ pub(crate) mod tests {
|
|||
.put_sapling_subtree_roots(start_index, roots)
|
||||
}
|
||||
|
||||
fn next_subtree_index(s: &WalletSummary<AccountId>) -> u64 {
|
||||
s.next_sapling_subtree_index()
|
||||
}
|
||||
|
||||
fn select_spendable_notes<Cache>(
|
||||
st: &TestState<Cache>,
|
||||
account: AccountId,
|
||||
|
|
|
@ -547,8 +547,7 @@ pub(crate) mod tests {
|
|||
use zcash_client_backend::data_api::{
|
||||
chain::CommitmentTreeRoot,
|
||||
scanning::{spanning_tree::testing::scan_range, ScanPriority},
|
||||
AccountBirthday, Ratio, WalletCommitmentTrees, WalletRead, WalletWrite,
|
||||
SAPLING_SHARD_HEIGHT,
|
||||
AccountBirthday, Ratio, WalletRead, WalletWrite, SAPLING_SHARD_HEIGHT,
|
||||
};
|
||||
use zcash_primitives::{
|
||||
block::BlockHash,
|
||||
|
@ -567,7 +566,11 @@ pub(crate) mod tests {
|
|||
};
|
||||
|
||||
#[test]
|
||||
fn scan_complete() {
|
||||
fn sapling_scan_complete() {
|
||||
scan_complete::<SaplingPoolTester>();
|
||||
}
|
||||
|
||||
fn scan_complete<T: ShieldedPoolTester>() {
|
||||
use ScanPriority::*;
|
||||
|
||||
let mut st = TestBuilder::new()
|
||||
|
@ -575,26 +578,27 @@ pub(crate) mod tests {
|
|||
.with_test_account(AccountBirthday::from_sapling_activation)
|
||||
.build();
|
||||
|
||||
let dfvk = st.test_account_sapling().unwrap();
|
||||
let dfvk = T::test_account_fvk(&st);
|
||||
let sapling_activation_height = st.sapling_activation_height();
|
||||
|
||||
assert_matches!(
|
||||
// In the following, we don't care what the root hashes are, they just need to be
|
||||
// distinct.
|
||||
st.wallet_mut().put_sapling_subtree_roots(
|
||||
T::put_subtree_roots(
|
||||
&mut st,
|
||||
0,
|
||||
&[
|
||||
CommitmentTreeRoot::from_parts(
|
||||
sapling_activation_height + 100,
|
||||
Node::empty_root(Level::from(0))
|
||||
T::empty_tree_root(Level::from(0))
|
||||
),
|
||||
CommitmentTreeRoot::from_parts(
|
||||
sapling_activation_height + 200,
|
||||
Node::empty_root(Level::from(1))
|
||||
T::empty_tree_root(Level::from(1))
|
||||
),
|
||||
CommitmentTreeRoot::from_parts(
|
||||
sapling_activation_height + 300,
|
||||
Node::empty_root(Level::from(2))
|
||||
T::empty_tree_root(Level::from(2))
|
||||
),
|
||||
]
|
||||
),
|
||||
|
@ -687,7 +691,7 @@ pub(crate) mod tests {
|
|||
st.wallet()
|
||||
.get_wallet_summary(0)
|
||||
.unwrap()
|
||||
.map(|s| s.next_sapling_subtree_index()),
|
||||
.map(|s| T::next_subtree_index(&s)),
|
||||
Some(2),
|
||||
);
|
||||
}
|
||||
|
@ -725,10 +729,14 @@ pub(crate) mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn create_account_creates_ignored_range() {
|
||||
fn sapling_create_account_creates_ignored_range() {
|
||||
create_account_creates_ignored_range::<SaplingPoolTester>();
|
||||
}
|
||||
|
||||
fn create_account_creates_ignored_range<T: ShieldedPoolTester>() {
|
||||
use ScanPriority::*;
|
||||
|
||||
let (st, _, birthday, sap_active) = test_with_canopy_birthday::<SaplingPoolTester>();
|
||||
let (st, _, birthday, sap_active) = test_with_canopy_birthday::<T>();
|
||||
let birthday_height = birthday.height().into();
|
||||
|
||||
let expected = vec![
|
||||
|
@ -784,10 +792,14 @@ pub(crate) mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn update_chain_tip_with_no_subtree_roots() {
|
||||
fn sapling_update_chain_tip_with_no_subtree_roots() {
|
||||
update_chain_tip_with_no_subtree_roots::<SaplingPoolTester>();
|
||||
}
|
||||
|
||||
fn update_chain_tip_with_no_subtree_roots<T: ShieldedPoolTester>() {
|
||||
use ScanPriority::*;
|
||||
|
||||
let (mut st, _, birthday, sap_active) = test_with_canopy_birthday::<SaplingPoolTester>();
|
||||
let (mut st, _, birthday, sap_active) = test_with_canopy_birthday::<T>();
|
||||
|
||||
// Set up the following situation:
|
||||
//
|
||||
|
@ -815,10 +827,14 @@ pub(crate) mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn update_chain_tip_when_never_scanned() {
|
||||
fn sapling_update_chain_tip_when_never_scanned() {
|
||||
update_chain_tip_when_never_scanned::<SaplingPoolTester>();
|
||||
}
|
||||
|
||||
fn update_chain_tip_when_never_scanned<T: ShieldedPoolTester>() {
|
||||
use ScanPriority::*;
|
||||
|
||||
let (mut st, _, birthday, sap_active) = test_with_canopy_birthday::<SaplingPoolTester>();
|
||||
let (mut st, _, birthday, sap_active) = test_with_canopy_birthday::<T>();
|
||||
|
||||
// Set up the following situation:
|
||||
//
|
||||
|
@ -829,16 +845,16 @@ pub(crate) mod tests {
|
|||
|
||||
// Set up some shard root history before the wallet birthday.
|
||||
let last_shard_start = birthday.height() - 1000;
|
||||
st.wallet_mut()
|
||||
.put_sapling_subtree_roots(
|
||||
0,
|
||||
&[CommitmentTreeRoot::from_parts(
|
||||
last_shard_start,
|
||||
// fake a hash, the value doesn't matter
|
||||
Node::empty_leaf(),
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
T::put_subtree_roots(
|
||||
&mut st,
|
||||
0,
|
||||
&[CommitmentTreeRoot::from_parts(
|
||||
last_shard_start,
|
||||
// fake a hash, the value doesn't matter
|
||||
T::empty_tree_leaf(),
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Update the chain tip.
|
||||
let tip_height = prior_tip_height + 500;
|
||||
|
@ -860,11 +876,15 @@ pub(crate) mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn update_chain_tip_unstable_max_scanned() {
|
||||
fn sapling_update_chain_tip_unstable_max_scanned() {
|
||||
update_chain_tip_unstable_max_scanned::<SaplingPoolTester>();
|
||||
}
|
||||
|
||||
fn update_chain_tip_unstable_max_scanned<T: ShieldedPoolTester>() {
|
||||
use ScanPriority::*;
|
||||
|
||||
// this birthday is 1234 notes into the second shard
|
||||
let (mut st, dfvk, birthday, sap_active) = test_with_canopy_birthday::<SaplingPoolTester>();
|
||||
let (mut st, dfvk, birthday, sap_active) = test_with_canopy_birthday::<T>();
|
||||
|
||||
// Set up the following situation:
|
||||
//
|
||||
|
@ -876,16 +896,16 @@ pub(crate) mod tests {
|
|||
|
||||
// Set up some shard root history before the wallet birthday.
|
||||
let initial_shard_end = birthday.height() - 1000;
|
||||
st.wallet_mut()
|
||||
.put_sapling_subtree_roots(
|
||||
0,
|
||||
&[CommitmentTreeRoot::from_parts(
|
||||
initial_shard_end,
|
||||
// fake a hash, the value doesn't matter
|
||||
Node::empty_leaf(),
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
T::put_subtree_roots(
|
||||
&mut st,
|
||||
0,
|
||||
&[CommitmentTreeRoot::from_parts(
|
||||
initial_shard_end,
|
||||
// fake a hash, the value doesn't matter
|
||||
T::empty_tree_leaf(),
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Set up prior chain state. This simulates us having imported a wallet
|
||||
// with a birthday 520 blocks below the chain tip.
|
||||
|
@ -928,16 +948,16 @@ pub(crate) mod tests {
|
|||
// Now simulate shutting down, and then restarting 90 blocks later, after a shard
|
||||
// has been completed.
|
||||
let last_shard_start = prior_tip + 70;
|
||||
st.wallet_mut()
|
||||
.put_sapling_subtree_roots(
|
||||
0,
|
||||
&[CommitmentTreeRoot::from_parts(
|
||||
last_shard_start,
|
||||
// fake a hash, the value doesn't matter
|
||||
Node::empty_leaf(),
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
T::put_subtree_roots(
|
||||
&mut st,
|
||||
0,
|
||||
&[CommitmentTreeRoot::from_parts(
|
||||
last_shard_start,
|
||||
// fake a hash, the value doesn't matter
|
||||
T::empty_tree_leaf(),
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let new_tip = last_shard_start + 20;
|
||||
st.wallet_mut().update_chain_tip(new_tip).unwrap();
|
||||
|
@ -972,10 +992,14 @@ pub(crate) mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn update_chain_tip_stable_max_scanned() {
|
||||
fn sapling_update_chain_tip_stable_max_scanned() {
|
||||
update_chain_tip_stable_max_scanned::<SaplingPoolTester>();
|
||||
}
|
||||
|
||||
fn update_chain_tip_stable_max_scanned<T: ShieldedPoolTester>() {
|
||||
use ScanPriority::*;
|
||||
|
||||
let (mut st, dfvk, birthday, sap_active) = test_with_canopy_birthday::<SaplingPoolTester>();
|
||||
let (mut st, dfvk, birthday, sap_active) = test_with_canopy_birthday::<T>();
|
||||
|
||||
// Set up the following situation:
|
||||
//
|
||||
|
@ -988,16 +1012,16 @@ pub(crate) mod tests {
|
|||
|
||||
// Set up some shard root history before the wallet birthday.
|
||||
let second_to_last_shard_start = birthday.height() - 1000;
|
||||
st.wallet_mut()
|
||||
.put_sapling_subtree_roots(
|
||||
0,
|
||||
&[CommitmentTreeRoot::from_parts(
|
||||
second_to_last_shard_start,
|
||||
// fake a hash, the value doesn't matter
|
||||
Node::empty_leaf(),
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
T::put_subtree_roots(
|
||||
&mut st,
|
||||
0,
|
||||
&[CommitmentTreeRoot::from_parts(
|
||||
second_to_last_shard_start,
|
||||
// fake a hash, the value doesn't matter
|
||||
T::empty_tree_leaf(),
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// We have scan ranges and a subtree, but have scanned no blocks.
|
||||
let summary = st.get_wallet_summary(1);
|
||||
|
@ -1032,10 +1056,7 @@ pub(crate) mod tests {
|
|||
// We have scanned a block, so we now have a starting tree position, 500 blocks above the
|
||||
// wallet birthday but before the end of the shard.
|
||||
let summary = st.get_wallet_summary(1);
|
||||
assert_eq!(
|
||||
summary.as_ref().map(|s| s.next_sapling_subtree_index()),
|
||||
Some(0),
|
||||
);
|
||||
assert_eq!(summary.as_ref().map(|s| T::next_subtree_index(s)), Some(0),);
|
||||
assert_eq!(
|
||||
summary.and_then(|s| s.scan_progress()),
|
||||
Some(Ratio::new(1, 0x1 << SAPLING_SHARD_HEIGHT))
|
||||
|
@ -1044,16 +1065,16 @@ pub(crate) mod tests {
|
|||
// Now simulate shutting down, and then restarting 70 blocks later, after a shard
|
||||
// has been completed.
|
||||
let last_shard_start = prior_tip + 50;
|
||||
st.wallet_mut()
|
||||
.put_sapling_subtree_roots(
|
||||
0,
|
||||
&[CommitmentTreeRoot::from_parts(
|
||||
last_shard_start,
|
||||
// fake a hash, the value doesn't matter
|
||||
Node::empty_leaf(),
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
T::put_subtree_roots(
|
||||
&mut st,
|
||||
0,
|
||||
&[CommitmentTreeRoot::from_parts(
|
||||
last_shard_start,
|
||||
// fake a hash, the value doesn't matter
|
||||
T::empty_tree_leaf(),
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let new_tip = last_shard_start + 20;
|
||||
st.wallet_mut().update_chain_tip(new_tip).unwrap();
|
||||
|
|
Loading…
Reference in New Issue