use core::num::NonZeroU32;
use crate::{
SAPLING_TABLES_PREFIX,
error::SqliteClientError,
testing::{BlockCache, db::TestDbFactory},
};
use zcash_client_backend::data_api::{
WalletWrite,
anchor_retention::AnchorRetentionInterval,
chain::{ChainState, error::Error},
testing::{
AddressType,
pool::{InputTrust, ShieldedPoolTester, dsl::TestDsl},
sapling::SaplingPoolTester,
},
};
#[cfg(feature = "transparent-inputs")]
use rusqlite::named_params;
use zcash_protocol::{
consensus::{NetworkUpgrade, Parameters},
value::Zatoshis,
};
#[cfg(feature = "orchard")]
use {
crate::ORCHARD_TABLES_PREFIX,
zcash_client_backend::data_api::testing::orchard::OrchardPoolTester,
zcash_protocol::ShieldedPool,
};
pub(crate) trait ShieldedPoolPersistence {
const TABLES_PREFIX: &'static str;
}
impl ShieldedPoolPersistence for SaplingPoolTester {
const TABLES_PREFIX: &'static str = SAPLING_TABLES_PREFIX;
}
#[cfg(feature = "orchard")]
impl ShieldedPoolPersistence for OrchardPoolTester {
const TABLES_PREFIX: &'static str = ORCHARD_TABLES_PREFIX;
}
pub(crate) fn send_single_step_proposed_transfer<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::send_single_step_proposed_transfer::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn scan_full_block_detects_outputs<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::scan_full_block_detects_outputs::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn spend_max_spendable_single_step_proposed_transfer<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::spend_max_spendable_single_step_proposed_transfer::<
T,
>(TestDbFactory::default(), BlockCache::new())
}
pub(crate) fn spend_everything_single_step_proposed_transfer<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::spend_everything_single_step_proposed_transfer::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "orchard")]
pub(crate) fn send_max_spends_inputs_across_pools<
P0: ShieldedPoolTester,
P1: ShieldedPoolTester,
>() {
zcash_client_backend::data_api::testing::pool::send_max_spends_inputs_across_pools::<P0, P1>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "transparent-inputs")]
pub(crate) fn send_max_fee_overflow_is_an_error<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::send_max_fee_overflow_is_an_error::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(not(feature = "transparent-inputs"))]
pub(crate) fn send_max_to_tex_fails_without_transparent_inputs<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::send_max_to_tex_fails_without_transparent_inputs::<
T,
>(TestDbFactory::default(), BlockCache::new())
}
#[cfg(feature = "transparent-inputs")]
pub(crate) fn send_max_spendable_to_transparent<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::send_max_spendable_to_transparent::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "transparent-inputs")]
pub(crate) fn fails_to_send_max_to_transparent_with_memo<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::fails_to_send_max_spendable_to_transparent_with_memo::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(not(feature = "orchard"))]
pub(crate) fn send_max_delivers_via_sapling_when_orchard_is_unavailable<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::send_max_delivers_via_sapling_when_orchard_is_unavailable::<
T,
>(TestDbFactory::default(), BlockCache::new())
}
#[cfg(not(feature = "orchard"))]
pub(crate) fn send_max_to_orchard_only_ua_fails_without_orchard<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::send_max_to_orchard_only_ua_fails_without_orchard::<
T,
>(TestDbFactory::default(), BlockCache::new())
}
pub(crate) fn send_max_fails_when_balance_is_consumed_by_fees<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::send_max_fails_when_balance_is_consumed_by_fees::<
T,
>(TestDbFactory::default(), BlockCache::new())
}
pub(crate) fn send_max_proposal_fails_when_unconfirmed_funds_present<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::spend_everything_proposal_fails_when_unconfirmed_funds_present::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "transparent-inputs")]
pub(crate) fn spend_everything_multi_step_many_notes_proposed_transfer<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::spend_everything_multi_step_many_notes_proposed_transfer::<
T,
_,
>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "transparent-inputs")]
pub(crate) fn spend_everything_multi_step_with_marginal_notes_proposed_transfer<
T: ShieldedPoolTester,
>() {
zcash_client_backend::data_api::testing::pool::spend_everything_multi_step_with_marginal_notes_proposed_transfer::<
T,
_,
>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "transparent-inputs")]
pub(crate) fn spend_everything_multi_step_single_note_proposed_transfer<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::spend_everything_multi_step_single_note_proposed_transfer::<
T,
_,
>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn send_with_multiple_change_outputs<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::send_with_multiple_change_outputs::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "transparent-inputs")]
pub(crate) fn send_multi_step_proposed_transfer<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::send_multi_step_proposed_transfer::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
|e, _, expected_bad_index| {
matches!(
e,
crate::error::SqliteClientError::ReachedGapLimit(_, bad_index)
if bad_index == &expected_bad_index)
},
)
}
pub(crate) fn spend_all_funds_single_step_proposed_transfer<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::spend_all_funds_single_step_proposed_transfer::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "transparent-inputs")]
pub(crate) fn spend_all_funds_multi_step_proposed_transfer<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::spend_all_funds_multi_step_proposed_transfer::<
T,
_,
>(TestDbFactory::default(), BlockCache::new())
}
#[cfg(feature = "transparent-inputs")]
pub(crate) fn proposal_fails_if_not_all_ephemeral_outputs_consumed<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::proposal_fails_if_not_all_ephemeral_outputs_consumed::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn create_to_address_fails_on_incorrect_usk<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::create_to_address_fails_on_incorrect_usk::<T, _>(
TestDbFactory::default(),
)
}
pub(crate) fn proposal_fails_with_no_blocks<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::proposal_fails_with_no_blocks::<T, _>(
TestDbFactory::default(),
)
}
pub(crate) fn spend_fails_on_unverified_notes<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::spend_fails_on_unverified_notes::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn ovk_policy_prevents_recovery_from_chain<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::ovk_policy_prevents_recovery_from_chain::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn spend_succeeds_to_t_addr_zero_change<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::spend_succeeds_to_t_addr_zero_change::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn change_note_spends_succeed<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::change_note_spends_succeed::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn account_deletion<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::account_deletion::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn account_deletion_with_internal_transfer<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::account_deletion_with_internal_transfer::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn external_address_change_spends_detected_in_restore_from_seed<
T: ShieldedPoolTester,
>() {
zcash_client_backend::data_api::testing::pool::external_address_change_spends_detected_in_restore_from_seed::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[allow(dead_code)]
pub(crate) fn zip317_spend<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::zip317_spend::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "transparent-inputs")]
pub(crate) fn shield_transparent<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::shield_transparent::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[allow(dead_code)]
pub(crate) fn birthday_in_anchor_shard<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::birthday_in_anchor_shard::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn checkpoint_gaps<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::checkpoint_gaps::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn anchor_checkpoints_retained_across_deep_scan<T: ShieldedPoolTester>() {
for interval in [
AnchorRetentionInterval::ZIP_318,
AnchorRetentionInterval::custom(NonZeroU32::new(12).expect("nonzero")),
] {
zcash_client_backend::data_api::testing::pool::anchor_checkpoints_retained_across_deep_scan::<
T,
_,
>(TestDbFactory::default(), BlockCache::new(), interval)
}
}
pub(crate) fn oldest_note_is_selected_first<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::oldest_note_is_selected_first::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "orchard")]
pub(crate) fn empty_boundary_blocks_are_checkpointed_and_retained<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::empty_boundary_blocks_are_checkpointed_and_retained::<
T,
_,
>(
TestDbFactory::default(),
BlockCache::new(),
AnchorRetentionInterval::custom(NonZeroU32::new(7).expect("nonzero")),
)
}
#[cfg(feature = "orchard")]
pub(crate) fn canonical_crossing_is_bucketed_and_unpadded() {
zcash_client_backend::data_api::testing::pool::canonical_crossing_is_bucketed_and_unpadded(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "orchard")]
pub(crate) fn canonical_crossing_builds_at_empty_boundary_block() {
zcash_client_backend::data_api::testing::pool::canonical_crossing_builds_at_empty_boundary_block(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "orchard")]
pub(crate) fn canonical_crossing_abandoned_without_anchor_checkpoint() {
zcash_client_backend::data_api::testing::pool::canonical_crossing_abandoned_without_anchor_checkpoint(
TestDbFactory::default(),
BlockCache::new(),
|st, height| {
let conn = st.wallet().conn();
for table in [
"sapling_tree_checkpoints",
"orchard_tree_checkpoints",
"ironwood_tree_checkpoints",
"sapling_tree_retained_checkpoints",
"orchard_tree_retained_checkpoints",
"ironwood_tree_retained_checkpoints",
] {
conn.execute(
&format!("DELETE FROM {table} WHERE checkpoint_id = :height"),
rusqlite::named_params![":height": u32::from(height)],
)
.expect("checkpoint records can be deleted");
}
},
)
}
#[cfg(feature = "orchard")]
pub(crate) fn canonical_crossing_prefers_single_note() {
zcash_client_backend::data_api::testing::pool::canonical_crossing_prefers_single_note(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "orchard")]
pub(crate) fn multi_note_crossing_is_not_bucketed() {
zcash_client_backend::data_api::testing::pool::multi_note_crossing_is_not_bucketed(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "orchard")]
pub(crate) fn self_migration_keeps_spending_orchard() {
zcash_client_backend::data_api::testing::pool::self_migration_keeps_spending_orchard(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "orchard")]
pub(crate) fn pool_crossing_required<P0: ShieldedPoolTester, P1: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::pool_crossing_required::<P0, P1>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "orchard")]
pub(crate) fn fully_funded_fully_private<P0: ShieldedPoolTester, P1: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::fully_funded_fully_private::<P0, P1>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(all(feature = "orchard", feature = "transparent-inputs"))]
pub(crate) fn fully_funded_send_to_t<P0: ShieldedPoolTester, P1: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::fully_funded_send_to_t::<P0, P1>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "orchard")]
pub(crate) fn multi_pool_checkpoint<P0: ShieldedPoolTester, P1: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::multi_pool_checkpoint::<P0, P1>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "orchard")]
pub(crate) fn multi_pool_checkpoints_with_pruning<
P0: ShieldedPoolTester,
P1: ShieldedPoolTester,
>() {
zcash_client_backend::data_api::testing::pool::multi_pool_checkpoints_with_pruning::<P0, P1>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn valid_chain_states<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::valid_chain_states::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[allow(dead_code)]
pub(crate) fn invalid_chain_cache_disconnected<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::invalid_chain_cache_disconnected::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn data_db_truncation<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::data_db_truncation::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn truncate_to_chain_state<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::truncate_to_chain_state::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn truncate_to_chain_state_below_birthday<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::truncate_to_chain_state_below_birthday::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn truncate_to_chain_state_above_scanned<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::truncate_to_chain_state_above_scanned::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn truncate_to_chain_state_commitment_tree_error<T: ShieldedPoolTester>() {
const PRUNING_DEPTH: u32 = 100;
let mut wallet_a =
TestDsl::with_sapling_birthday_account(TestDbFactory::default(), BlockCache::new())
.build::<T>();
let activation = wallet_a
.network()
.activation_height(NetworkUpgrade::Sapling)
.unwrap();
let account_fvk_a = T::test_account_fvk(&wallet_a);
let fvk_a = T::sk_to_fvk(&T::sk(&[1u8; 32]));
let initial_blocks = 8u32;
wallet_a.generate_next_block(
&account_fvk_a,
AddressType::DefaultExternal,
Zatoshis::const_from_u64(10_000),
);
for _ in 1..initial_blocks {
wallet_a.generate_next_block(
&fvk_a,
AddressType::DefaultExternal,
Zatoshis::const_from_u64(10_000),
);
}
wallet_a.scan_cached_blocks(activation, initial_blocks as usize);
let capture_height = activation + initial_blocks - 1;
let captured = wallet_a
.latest_cached_block()
.expect("should have cached blocks")
.chain_state()
.clone();
assert_eq!(captured.block_height(), capture_height);
let extra_blocks = PRUNING_DEPTH + 10;
for _ in 0..extra_blocks {
wallet_a.generate_next_block(
&fvk_a,
AddressType::DefaultExternal,
Zatoshis::const_from_u64(5_000),
);
}
wallet_a.scan_cached_blocks(capture_height + 1, extra_blocks as usize);
let mut wallet_b =
TestDsl::with_sapling_birthday_account(TestDbFactory::default(), BlockCache::new())
.build::<T>();
let fvk_b = T::sk_to_fvk(&T::sk(&[2u8; 32]));
for _ in 0..initial_blocks {
wallet_b.generate_next_block(
&fvk_b,
AddressType::DefaultExternal,
Zatoshis::const_from_u64(7_000),
);
}
wallet_b.scan_cached_blocks(activation, initial_blocks as usize);
let foreign = wallet_b
.latest_cached_block()
.expect("should have cached blocks")
.chain_state()
.clone();
assert_eq!(foreign.block_height(), capture_height);
#[cfg(feature = "orchard")]
let ironwood_initial_tree = incrementalmerkletree::frontier::Frontier::empty();
#[cfg(feature = "orchard")]
let bad_chain_state = match T::SHIELDED_PROTOCOL {
ShieldedPool::Sapling => ChainState::new(
capture_height,
captured.block_hash(),
foreign.final_sapling_tree().clone(),
captured.final_orchard_tree().clone(),
ironwood_initial_tree,
),
ShieldedPool::Orchard => ChainState::new(
capture_height,
captured.block_hash(),
captured.final_sapling_tree().clone(),
foreign.final_orchard_tree().clone(),
ironwood_initial_tree,
),
ShieldedPool::Ironwood => ChainState::new(
capture_height,
captured.block_hash(),
captured.final_sapling_tree().clone(),
captured.final_orchard_tree().clone(),
foreign.final_ironwood_tree().clone(),
),
};
#[cfg(not(feature = "orchard"))]
let bad_chain_state = ChainState::new(
capture_height,
captured.block_hash(),
foreign.final_sapling_tree().clone(),
);
match wallet_a
.wallet_mut()
.truncate_to_chain_state(bad_chain_state)
{
Err(SqliteClientError::TruncateCommitmentTree { pool, height, .. }) => {
assert_eq!(pool, T::SHIELDED_PROTOCOL);
assert_eq!(height, capture_height);
}
other => panic!("expected TruncateCommitmentTree error, got {other:?}"),
}
}
pub(crate) fn put_blocks_commitment_tree_error<T: ShieldedPoolTester>() {
let mut wallet_a =
TestDsl::with_sapling_birthday_account(TestDbFactory::default(), BlockCache::new())
.build::<T>();
let activation = wallet_a
.network()
.activation_height(NetworkUpgrade::Sapling)
.unwrap();
let fvk_a = T::sk_to_fvk(&T::sk(&[1u8; 32]));
let initial_blocks = 8u32;
for _ in 0..initial_blocks {
wallet_a.generate_next_block(
&fvk_a,
AddressType::DefaultExternal,
Zatoshis::const_from_u64(10_000),
);
}
wallet_a.scan_cached_blocks(activation, initial_blocks as usize);
let from_height = activation + initial_blocks;
let captured = wallet_a
.latest_cached_block()
.expect("should have cached blocks")
.chain_state()
.clone();
assert_eq!(captured.block_height(), from_height - 1);
let scan_blocks = 3u32;
for _ in 0..scan_blocks {
wallet_a.generate_next_block(
&fvk_a,
AddressType::DefaultExternal,
Zatoshis::const_from_u64(5_000),
);
}
let mut wallet_b =
TestDsl::with_sapling_birthday_account(TestDbFactory::default(), BlockCache::new())
.build::<T>();
let fvk_b = T::sk_to_fvk(&T::sk(&[2u8; 32]));
for _ in 0..initial_blocks {
wallet_b.generate_next_block(
&fvk_b,
AddressType::DefaultExternal,
Zatoshis::const_from_u64(7_000),
);
}
wallet_b.scan_cached_blocks(activation, initial_blocks as usize);
let foreign = wallet_b
.latest_cached_block()
.expect("should have cached blocks")
.chain_state()
.clone();
assert_eq!(foreign.block_height(), from_height - 1);
#[cfg(feature = "orchard")]
let ironwood_initial_tree = incrementalmerkletree::frontier::Frontier::empty();
#[cfg(feature = "orchard")]
let bad_from_state = match T::SHIELDED_PROTOCOL {
ShieldedPool::Sapling => ChainState::new(
from_height - 1,
captured.block_hash(),
foreign.final_sapling_tree().clone(),
captured.final_orchard_tree().clone(),
ironwood_initial_tree,
),
ShieldedPool::Orchard => ChainState::new(
from_height - 1,
captured.block_hash(),
captured.final_sapling_tree().clone(),
foreign.final_orchard_tree().clone(),
ironwood_initial_tree,
),
ShieldedPool::Ironwood => ChainState::new(
from_height - 1,
captured.block_hash(),
captured.final_sapling_tree().clone(),
captured.final_orchard_tree().clone(),
foreign.final_ironwood_tree().clone(),
),
};
#[cfg(not(feature = "orchard"))]
let bad_from_state = ChainState::new(
from_height - 1,
captured.block_hash(),
foreign.final_sapling_tree().clone(),
);
match wallet_a.try_scan_cached_blocks_with_state(
from_height,
&bad_from_state,
scan_blocks as usize,
) {
Err(Error::Wallet(SqliteClientError::PutBlocksCommitmentTree {
pool,
block_range,
..
})) => {
assert_eq!(pool, T::SHIELDED_PROTOCOL);
assert_eq!(block_range, (from_height - 1)..(from_height + scan_blocks));
}
other => panic!("expected PutBlocksCommitmentTree error, got {other:?}"),
}
}
pub(crate) fn rewind_to_chain_state_deep<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::rewind_to_chain_state_deep::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn rewind_to_chain_state_shallow<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::rewind_to_chain_state_shallow::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn rewind_after_non_contiguous_scan<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::rewind_after_non_contiguous_scan::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "expensive-tests")]
pub(crate) fn stabilized_note_spendable_after_deep_rewind<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::stabilized_note_spendable_after_deep_rewind::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "expensive-tests")]
pub(crate) fn newly_discovered_notes_become_stabilized<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::newly_discovered_notes_become_stabilized::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn reorg_to_checkpoint<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::reorg_to_checkpoint::<T, _, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn scan_cached_blocks_allows_blocks_out_of_order<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::scan_cached_blocks_allows_blocks_out_of_order::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn scan_cached_blocks_finds_received_notes<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::scan_cached_blocks_finds_received_notes::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn scan_cached_blocks_finds_change_notes<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::scan_cached_blocks_finds_change_notes::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
pub(crate) fn scan_cached_blocks_detects_spends_out_of_order<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::scan_cached_blocks_detects_spends_out_of_order::<
T,
_,
>(TestDbFactory::default(), BlockCache::new())
}
pub(crate) fn metadata_queries_exclude_unwanted_notes<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::metadata_queries_exclude_unwanted_notes::<T, _, _>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(feature = "pczt-tests")]
pub(crate) fn pczt_single_step<P0: ShieldedPoolTester, P1: ShieldedPoolTester>(
pin_expiry_above_target: Option<u32>,
) {
zcash_client_backend::data_api::testing::pool::pczt_single_step::<P0, P1, _>(
TestDbFactory::default(),
BlockCache::new(),
pin_expiry_above_target,
)
}
#[cfg(feature = "transparent-inputs")]
pub(crate) fn wallet_recovery_computes_fees<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::wallet_recovery_computes_fees::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
|db, txid| {
db.db_mut().conn.execute(
"UPDATE transactions
SET fee = NULL
WHERE txid = :txid",
named_params! {
":txid": txid.as_ref(),
},
)?;
Ok(())
},
)
}
pub(crate) fn can_spend_inputs_by_confirmations_policy<T: ShieldedPoolTester>() {
for trust in [
InputTrust::Internal,
InputTrust::ExternalUntrusted,
InputTrust::ExternalTrusted,
] {
zcash_client_backend::data_api::testing::pool::zip_315_confirmations_test_steps::<T>(
TestDbFactory::default(),
BlockCache::new(),
trust,
);
}
}
pub(crate) fn receive_two_notes_with_same_value<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::receive_two_notes_with_same_value::<T>(
TestDbFactory::default(),
BlockCache::new(),
)
}
#[cfg(all(feature = "pczt-tests", feature = "transparent-inputs"))]
pub(crate) fn immature_coinbase_outputs_are_excluded_from_note_selection<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::immature_coinbase_outputs_are_excluded_from_note_selection::<T>(
TestDbFactory::default(),
BlockCache::new(),
);
}
#[cfg(all(feature = "pczt-tests", feature = "transparent-inputs"))]
pub(crate) fn coinbase_only_filtering<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::coinbase_only_filtering::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
);
}
#[cfg(all(feature = "pczt-tests", feature = "transparent-inputs"))]
pub(crate) fn propose_shielding_coinbase_succeeds<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::propose_shielding_coinbase_succeeds::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
);
}
#[cfg(all(feature = "pczt-tests", feature = "transparent-inputs"))]
pub(crate) fn proposal_without_confirmations_policy_builds<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::proposal_without_confirmations_policy_builds::<
T,
_,
>(TestDbFactory::default(), BlockCache::new());
}
#[cfg(all(feature = "pczt-tests", feature = "transparent-inputs"))]
pub(crate) fn propose_shielding_coinbase_transparent_recipient_rejected<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::propose_shielding_coinbase_transparent_recipient_rejected::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
);
}
#[cfg(all(feature = "pczt-tests", feature = "transparent-inputs"))]
pub(crate) fn propose_shielding_coinbase_with_memo_succeeds<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::propose_shielding_coinbase_with_memo_succeeds::<
T,
_,
>(TestDbFactory::default(), BlockCache::new());
}
#[cfg(all(feature = "pczt-tests", feature = "transparent-inputs"))]
pub(crate) fn propose_shielding_coinbase_with_limit_truncates_inputs<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::propose_shielding_coinbase_with_limit_truncates_inputs::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
);
}
#[cfg(all(feature = "pczt-tests", feature = "transparent-inputs"))]
pub(crate) fn propose_shielding_coinbase_with_zero_limit_insufficient_funds<
T: ShieldedPoolTester,
>() {
zcash_client_backend::data_api::testing::pool::propose_shielding_coinbase_with_zero_limit_insufficient_funds::<T, _>(
TestDbFactory::default(),
BlockCache::new(),
);
}
#[cfg(all(feature = "pczt-tests", feature = "transparent-inputs"))]
pub(crate) fn propose_and_build_shielding_coinbase_succeeds<T: ShieldedPoolTester>() {
zcash_client_backend::data_api::testing::pool::propose_and_build_shielding_coinbase_succeeds::<
T,
_,
>(TestDbFactory::default(), BlockCache::new());
}
#[cfg(all(
feature = "orchard",
feature = "pczt-tests",
feature = "transparent-inputs"
))]
pub(crate) fn shielding_coinbase_to_orchard_receiver_delivers_via_ironwood() {
zcash_client_backend::data_api::testing::pool::shielding_coinbase_to_orchard_receiver_delivers_via_ironwood(
TestDbFactory::default(),
BlockCache::new(),
);
}
#[cfg(feature = "orchard")]
pub(crate) fn orchard_to_ironwood_payment_reports_net_value_delta() {
zcash_client_backend::data_api::testing::pool::orchard_to_ironwood_payment_reports_net_value_delta(
TestDbFactory::default(),
BlockCache::new(),
);
}
#[cfg(feature = "orchard")]
pub(crate) fn orchard_to_ironwood_self_migration_reports_fee_only_delta() {
zcash_client_backend::data_api::testing::pool::orchard_to_ironwood_self_migration_reports_fee_only_delta(
TestDbFactory::default(),
BlockCache::new(),
);
}
#[cfg(feature = "orchard")]
pub(crate) fn propose_v5_payment_to_orchard_receiver_is_rejected() {
zcash_client_backend::data_api::testing::pool::propose_v5_payment_to_orchard_receiver_is_rejected(
TestDbFactory::default(),
BlockCache::new(),
);
}
#[cfg(all(feature = "orchard", feature = "pczt-tests"))]
pub(crate) fn create_pczt_supports_ironwood_output() {
zcash_client_backend::data_api::testing::pool::create_pczt_supports_ironwood_output(
TestDbFactory::default(),
BlockCache::new(),
);
}
#[cfg(feature = "orchard")]
pub(crate) fn proposal_records_and_serializes_proposed_version() {
zcash_client_backend::data_api::testing::pool::proposal_records_and_serializes_proposed_version(
TestDbFactory::default(),
BlockCache::new(),
);
}