Skip to content

Commit

Permalink
zcash_client_sqlite: Add a failing test of cross-pool transfer
Browse files Browse the repository at this point in the history
  • Loading branch information
nuttycom committed Mar 11, 2024
1 parent 52257f3 commit b32d449
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 7 deletions.
23 changes: 19 additions & 4 deletions zcash_client_backend/src/data_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ use {
zcash_primitives::{legacy::TransparentAddress, transaction::components::OutPoint},
};

#[cfg(feature = "test-dependencies")]
use zcash_primitives::consensus::NetworkUpgrade;

pub mod chain;
pub mod error;
pub mod scanning;
Expand Down Expand Up @@ -1172,19 +1175,31 @@ impl AccountBirthday {
/// # Panics
///
/// Panics if the Sapling activation height is not set.
pub fn from_sapling_activation<P: zcash_primitives::consensus::Parameters>(
pub fn from_activation<P: zcash_primitives::consensus::Parameters>(
params: &P,
network_upgrade: NetworkUpgrade,
) -> AccountBirthday {
use zcash_primitives::consensus::NetworkUpgrade;

AccountBirthday::from_parts(
params.activation_height(NetworkUpgrade::Sapling).unwrap(),
params.activation_height(network_upgrade).unwrap(),
Frontier::empty(),
#[cfg(feature = "orchard")]
Frontier::empty(),
None,
)
}

#[cfg(feature = "test-dependencies")]
/// Constructs a new [`AccountBirthday`] at Sapling activation, with no
/// "recover until" height.
///
/// # Panics
///
/// Panics if the Sapling activation height is not set.
pub fn from_sapling_activation<P: zcash_primitives::consensus::Parameters>(
params: &P,
) -> AccountBirthday {
Self::from_activation(params, NetworkUpgrade::Sapling)
}
}

/// This trait encapsulates the write capabilities required to update stored
Expand Down
4 changes: 2 additions & 2 deletions zcash_client_sqlite/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -960,9 +960,9 @@ impl<P: consensus::Parameters> WalletWrite for WalletDb<rusqlite::Connection, P>
)?;
}
}
if let Some(bundle) = sent_tx.tx().orchard_bundle() {
if let Some(_bundle) = sent_tx.tx().orchard_bundle() {
#[cfg(feature = "orchard")]
for action in bundle.actions() {
for action in _bundle.actions() {
wallet::orchard::mark_orchard_note_spent(
wdb.conn.0,
tx_ref,
Expand Down
85 changes: 84 additions & 1 deletion zcash_client_sqlite/src/testing/pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use secrecy::Secret;
use shardtree::error::ShardTreeError;
use zcash_primitives::{
block::BlockHash,
consensus::BranchId,
consensus::{BranchId, NetworkUpgrade},
legacy::TransparentAddress,
memo::{Memo, MemoBytes},
transaction::{
Expand Down Expand Up @@ -1400,6 +1400,89 @@ pub(crate) fn checkpoint_gaps<T: ShieldedPoolTester>() {
);
}

#[cfg(feature = "orchard")]
pub(crate) fn cross_pool_exchange<P0: ShieldedPoolTester, P1: ShieldedPoolTester>() {
let mut st = TestBuilder::new()
.with_block_cache()
.with_test_account(|params| AccountBirthday::from_activation(params, NetworkUpgrade::Nu5))
.build();

let (account, usk, birthday) = st.test_account().unwrap();

let p0_fvk = P0::test_account_fvk(&st);

let p1_fvk = P1::test_account_fvk(&st);
let p1_to = P1::fvk_default_address(&p1_fvk);

let value = NonNegativeAmount::const_from_u64(300000);
st.generate_next_block(&p0_fvk, AddressType::DefaultExternal, value);
st.generate_next_block(&p1_fvk, AddressType::DefaultExternal, value);
st.scan_cached_blocks(birthday.height(), 2);

let initial_balance = NonNegativeAmount::const_from_u64(600000);
assert_eq!(st.get_total_balance(account), initial_balance);
assert_eq!(st.get_spendable_balance(account, 1), initial_balance);

let p0_to_p1 = zip321::TransactionRequest::new(vec![Payment {
recipient_address: p1_to,
amount: NonNegativeAmount::const_from_u64(200000),
memo: None,
label: None,
message: None,
other_params: vec![],
}])
.unwrap();

let fee_rule = StandardFeeRule::Zip317;
let input_selector = GreedyInputSelector::new(
standard::SingleOutputChangeStrategy::new(fee_rule, None, P1::SHIELDED_PROTOCOL),
DustOutputPolicy::default(),
);
let proposal0 = st
.propose_transfer(
account,
&input_selector,
p0_to_p1,
NonZeroU32::new(1).unwrap(),
)
.unwrap();

let _min_target_height = proposal0.min_target_height();
let step0 = &proposal0.steps().head;

let proposed_change = step0.balance().proposed_change();
assert_eq!(proposed_change.len(), 1);
let change_output = proposed_change.get(0).unwrap();
// Since this is a cross-pool transfer, change will be sent to the preferred pool.
assert_eq!(
change_output.output_pool(),
std::cmp::max(ShieldedProtocol::Sapling, ShieldedProtocol::Orchard)
);
assert_eq!(
change_output.value(),
NonNegativeAmount::const_from_u64(80000)
);

let expected_fee = NonNegativeAmount::const_from_u64(20000);
assert_eq!(step0.balance().fee_required(), expected_fee);

let create_proposed_result =
st.create_proposed_transactions::<Infallible, _>(&usk, OvkPolicy::Sender, &proposal0);
assert_matches!(&create_proposed_result, Ok(txids) if txids.len() == 1);

let (h, _) = st.generate_next_block_including(create_proposed_result.unwrap()[0]);
st.scan_cached_blocks(h, 1);

assert_eq!(
st.get_total_balance(account),
(initial_balance - expected_fee).unwrap()
);
assert_eq!(
st.get_spendable_balance(account, 1),
(initial_balance - expected_fee).unwrap()
);
}

pub(crate) fn valid_chain_states<T: ShieldedPoolTester>() {
let mut st = TestBuilder::new()
.with_block_cache()
Expand Down
7 changes: 7 additions & 0 deletions zcash_client_sqlite/src/wallet/orchard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,4 +599,11 @@ pub(crate) mod tests {
fn scan_cached_blocks_detects_spends_out_of_order() {
testing::pool::scan_cached_blocks_detects_spends_out_of_order::<OrchardPoolTester>()
}

#[test]
fn cross_pool_exchange() {
use crate::wallet::sapling::tests::SaplingPoolTester;

testing::pool::cross_pool_exchange::<OrchardPoolTester, SaplingPoolTester>()
}
}
8 changes: 8 additions & 0 deletions zcash_client_sqlite/src/wallet/sapling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,4 +602,12 @@ pub(crate) mod tests {
fn scan_cached_blocks_detects_spends_out_of_order() {
testing::pool::scan_cached_blocks_detects_spends_out_of_order::<SaplingPoolTester>()
}

#[test]
#[cfg(feature = "orchard")]
fn cross_pool_exchange() {
use crate::wallet::orchard::tests::OrchardPoolTester;

testing::pool::cross_pool_exchange::<SaplingPoolTester, OrchardPoolTester>()
}
}

0 comments on commit b32d449

Please sign in to comment.