Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assertions 400: expected fee #1131

Merged
merged 17 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions zingo-testutils/src/assertions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ use zingolib::{lightclient::LightClient, wallet::notes::query::OutputQuery};

/// currently only checks if the fee matches
/// this currently fails for any broadcast but not confirmed transaction: it seems like get_transaction_fee does not recognize pending spends
/// returns the total fee for the transfer
pub async fn assert_send_outputs_match_sender<NoteId>(
client: &LightClient,
proposal: &Proposal<zcash_primitives::transaction::fees::zip317::FeeRule, NoteId>,
txids: &NonEmpty<TxId>,
) {
) -> u64 {
let records = &client
.wallet
.transaction_context
Expand All @@ -22,20 +23,21 @@ pub async fn assert_send_outputs_match_sender<NoteId>(
.transaction_records_by_id;

assert_eq!(proposal.steps().len(), txids.len());
let mut total_fee = 0;
for (i, step) in proposal.steps().iter().enumerate() {
let record = records.get(&txids[i]).expect("sender must recognize txid");
// does this record match this step?
// may fail in uncertain ways if used on a transaction we dont have an OutgoingViewingKey for
assert_eq!(
records.calculate_transaction_fee(record).unwrap(),
step.balance().fee_required().into_u64()
);
let recorded_fee = records.calculate_transaction_fee(record).unwrap();
assert_eq!(recorded_fee, step.balance().fee_required().into_u64());

total_fee += recorded_fee;
}
total_fee
}

/// currently only checks if the fee matches
/// this currently fails for any broadcast but not confirmed transaction: it seems like get_transaction_fee does not recognize pending spends
pub async fn assert_send_outputs_match_receiver<NoteId>(
/// currently only checks if the received total matches
pub async fn assert_send_outputs_match_recipient<NoteId>(
client: &LightClient,
proposal: &Proposal<zcash_primitives::transaction::fees::zip317::FeeRule, NoteId>,
txids: &NonEmpty<TxId>,
Expand All @@ -52,11 +54,9 @@ pub async fn assert_send_outputs_match_receiver<NoteId>(
for (i, step) in proposal.steps().iter().enumerate() {
let record = records.get(&txids[i]).expect("sender must recognize txid");

let mut sum_received = 0;
for payment in step.transaction_request().payments().values() {
sum_received += payment.amount.into_u64();
}

assert_eq!(sum_received, record.query_sum_value(OutputQuery::any()));
assert_eq!(
record.query_sum_value(OutputQuery::any()),
step.transaction_request().total().unwrap().into_u64()
);
}
}
89 changes: 43 additions & 46 deletions zingo-testutils/src/chain_generic_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,22 @@ pub mod fixtures {

let expected_fee = MARGINAL_FEE.into_u64()
* match pooltype {
// contribution_transparent = 1
// 1 transfer
// contribution_orchard = 2
// 1 input
// 1 dummy output
Transparent => 3,
// contribution_sapling = 2
// 1 output
// 1 dummy input
// contribution_orchard = 2
// 1 input
// 1 dummy output
Shielded(Sapling) => 4,
// contribution_orchard = 2
// 1 input
// 1 output
Shielded(Orchard) => 2,
};
fluidvanadium marked this conversation as resolved.
Show resolved Hide resolved

Expand All @@ -103,29 +117,15 @@ pub mod fixtures {

println!("recipient ready");

with_assertions::propose_send_bump_sync_recipient(
let recorded_fee = with_assertions::propose_send_bump_sync_recipient(
&mut environment,
&sender,
&recipient,
vec![(pooltype, send_value)],
)
.await;

recipient.do_sync(false).await.unwrap();

assert_eq!(
recipient
.query_sum_value(OutputQuery {
spend_status: OutputSpendStatusQuery {
unspent: true,
pending_spent: false,
spent: false,
},
pools: OutputPoolQuery::one_pool(pooltype),
})
.await,
send_value
);
assert_eq!(expected_fee, recorded_fee);
}

/// sends back and forth several times, including sends to transparent
Expand All @@ -134,41 +134,38 @@ pub mod fixtures {
CC: ConductChain,
{
let mut environment = CC::setup().await;
let mut primary_fund = 1_000_000;
let mut secondary_fund = 0u64;
let primary_fund = 1_000_000;
let primary = environment.fund_client_orchard(primary_fund).await;

let secondary = environment.create_client().await;

fn per_cycle_primary_debit(start: u64) -> u64 {
start - 65_000u64
}
fn per_cycle_secondary_credit(start: u64) -> u64 {
start + 25_000u64
}
for _ in 0..n {
with_assertions::propose_send_bump_sync_recipient(
&mut environment,
&primary,
&secondary,
vec![(Transparent, 100_000)],
)
.await;

with_assertions::propose_shield_bump_sync(&mut environment, &secondary).await;

with_assertions::propose_send_bump_sync_recipient(
&mut environment,
&secondary,
&primary,
vec![(Shielded(Orchard), 50_000)],
)
.await;

primary_fund = per_cycle_primary_debit(primary_fund);
secondary_fund = per_cycle_secondary_credit(secondary_fund);
check_client_balances!(primary, o: primary_fund s: 0 t: 0);
check_client_balances!(secondary, o: secondary_fund s: 0 t: 0);
assert_eq!(
with_assertions::propose_send_bump_sync_recipient(
&mut environment,
&primary,
&secondary,
vec![(Transparent, 100_000), (Transparent, 4_000)],
)
.await,
MARGINAL_FEE.into_u64() * 4
);

assert_eq!(
with_assertions::propose_shield_bump_sync(&mut environment, &secondary).await,
MARGINAL_FEE.into_u64() * 3
);

assert_eq!(
with_assertions::propose_send_bump_sync_recipient(
&mut environment,
&secondary,
&primary,
vec![(Shielded(Orchard), 50_000)],
)
.await,
MARGINAL_FEE.into_u64() * 2
);
}
}

Expand Down
25 changes: 15 additions & 10 deletions zingo-testutils/src/lightclient/with_assertions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@ use zcash_client_backend::PoolType;
use zingolib::lightclient::LightClient;

use crate::{
assertions::{assert_send_outputs_match_receiver, assert_send_outputs_match_sender},
assertions::{assert_send_outputs_match_recipient, assert_send_outputs_match_sender},
chain_generic_tests::conduct_chain::ConductChain,
lightclient::{from_inputs, get_base_address},
};

/// a test-only generic version of send that includes assertions that the proposal was fulfilled
/// NOTICE this function bumps the chain and syncs the client
/// only compatible with zip317
/// returns the total fee for the transfer
pub async fn propose_send_bump_sync<CC>(
environment: &mut CC,
client: &LightClient,
raw_receivers: Vec<(&str, u64, Option<&str>)>,
) where
) -> u64
where
CC: ConductChain,
{
let proposal = from_inputs::propose(client, raw_receivers).await.unwrap();
Expand All @@ -29,19 +31,21 @@ pub async fn propose_send_bump_sync<CC>(

client.do_sync(false).await.unwrap();

assert_send_outputs_match_sender(client, &proposal, &txids).await;
assert_send_outputs_match_sender(client, &proposal, &txids).await
}

/// this version assumes a single recipient and measures that the recipient also recieved the expected balances
/// test-only generic
/// NOTICE this function bumps the chain and syncs the client
/// only compatible with zip317
/// returns the total fee for the transfer
pub async fn propose_send_bump_sync_recipient<CC>(
environment: &mut CC,
sender: &LightClient,
recipient: &LightClient,
sends: Vec<(PoolType, u64)>,
) where
) -> u64
where
CC: ConductChain,
{
let mut subraw_receivers = vec![];
Expand All @@ -63,17 +67,18 @@ pub async fn propose_send_bump_sync_recipient<CC>(

environment.bump_chain().await;

sender.do_sync(false).await.unwrap();
assert_send_outputs_match_sender(sender, &proposal, &txids).await;

recipient.do_sync(false).await.unwrap();
assert_send_outputs_match_receiver(recipient, &proposal, &txids).await;
assert_send_outputs_match_recipient(recipient, &proposal, &txids).await;

sender.do_sync(false).await.unwrap();
assert_send_outputs_match_sender(sender, &proposal, &txids).await
}

/// a test-only generic version of shield that includes assertions that the proposal was fulfilled
/// NOTICE this function bumps the chain and syncs the client
/// only compatible with zip317
pub async fn propose_shield_bump_sync<CC>(environment: &mut CC, client: &LightClient)
/// returns the total fee for the transfer
pub async fn propose_shield_bump_sync<CC>(environment: &mut CC, client: &LightClient) -> u64
where
CC: ConductChain,
{
Expand All @@ -87,5 +92,5 @@ where

client.do_sync(false).await.unwrap();

assert_send_outputs_match_sender(client, &proposal, &txids).await;
assert_send_outputs_match_sender(client, &proposal, &txids).await
}
Loading