use zcash_primitives::transaction::fees::zip317::MARGINAL_FEE;
use zcash_protocol::value::Zatoshis;
use zcash_protocol::{PoolType, ShieldedPool};
use crate::perspective::value_transfer::{
SelfSendValueTransfer, SentValueTransfer, ValueTransferKind,
};
use crate::testutils::chain_generics::conduct_chain::ConductChain;
use crate::testutils::chain_generics::with_assertions;
use crate::testutils::fee_tables;
use crate::testutils::lightclient::get_base_address;
use crate::testutils::timed;
use crate::testutils::timestamped_test_log;
pub async fn create_various_value_transfers<CC>()
where
CC: ConductChain,
{
let mut environment = CC::setup().await;
let mut sender = environment.fund_client_orchard(250_000).await;
let sender_orchard_addr =
get_base_address(&sender, PoolType::Shielded(ShieldedPool::Orchard)).await;
let sender_sapling_addr =
get_base_address(&sender, PoolType::Shielded(ShieldedPool::Sapling)).await;
let sender_taddr = get_base_address(&sender, PoolType::Transparent).await;
let send_value_for_recipient = 23_000;
let send_value_self = 17_000;
tracing::info!("client is ready to send");
let mut recipient = environment.create_client().await;
tracing::debug!("TEST 1");
with_assertions::assure_propose_send_bump_sync_all_recipients(
&mut environment,
&mut sender,
vec![
(
&get_base_address(&recipient, PoolType::Shielded(ShieldedPool::Orchard)).await,
send_value_for_recipient,
Some("Orchard sender to recipient"),
),
(
&sender_sapling_addr,
send_value_self,
Some("Orchard sender to self"),
),
(&sender_taddr, send_value_self, None),
],
vec![&mut recipient],
false,
)
.await
.unwrap();
assert_eq!(sender.value_transfers(true).await.unwrap().len(), 3);
assert!(
sender
.value_transfers(false)
.await
.unwrap()
.iter()
.any(|vt| { vt.kind == ValueTransferKind::Received })
);
assert!(
sender
.value_transfers(false)
.await
.unwrap()
.iter()
.any(|vt| { vt.kind == ValueTransferKind::Sent(SentValueTransfer::Send) })
);
assert!(
sender
.value_transfers(false)
.await
.unwrap()
.iter()
.any(|vt| {
vt.kind
== ValueTransferKind::Sent(SentValueTransfer::SendToSelf(
SelfSendValueTransfer::MemoToSelf,
))
})
);
assert_eq!(recipient.value_transfers(true).await.unwrap().len(), 1);
tracing::debug!("TEST 2");
with_assertions::assure_propose_send_bump_sync_all_recipients(
&mut environment,
&mut sender,
vec![(&sender_orchard_addr, send_value_self, None)],
vec![],
false,
)
.await
.unwrap();
assert_eq!(sender.value_transfers(true).await.unwrap().len(), 4);
assert_eq!(
sender.value_transfers(true).await.unwrap()[0].kind,
ValueTransferKind::Sent(SentValueTransfer::SendToSelf(SelfSendValueTransfer::Basic))
);
with_assertions::assure_propose_shield_bump_sync(&mut environment, &mut sender, false)
.await
.unwrap();
assert_eq!(sender.value_transfers(true).await.unwrap().len(), 5);
assert_eq!(
sender.value_transfers(true).await.unwrap()[0].kind,
ValueTransferKind::Sent(SentValueTransfer::SendToSelf(SelfSendValueTransfer::Shield))
);
}
pub async fn send_shield_cycle<CC>(n: u64)
where
CC: ConductChain,
{
let (mut environment, ()) = tokio::join!(
timed("send_shield_cycle::setup", CC::setup()),
timed(
"send_shield_cycle::warm_orchard_proving_key",
crate::testutils::warm_orchard_proving_key(),
),
);
let primary_fund = 1_000_000;
let mut primary = timed(
"send_shield_cycle::fund_client_orchard",
environment.fund_client_orchard(primary_fund),
)
.await;
let mut secondary = timed(
"send_shield_cycle::create_secondary_client",
environment.create_client(),
)
.await;
let secondary_taddr = timed(
"send_shield_cycle::get_secondary_taddr",
get_base_address(&secondary, PoolType::Transparent),
)
.await;
for cycle in 0..n {
timed(
format!("send_shield_cycle::cycle[{cycle}]").as_str(),
async {
let (recorded_fee, recorded_value, recorded_change) = timed(
format!("send_shield_cycle::cycle[{cycle}]::send_to_transparent").as_str(),
with_assertions::assure_propose_send_bump_sync_all_recipients(
&mut environment,
&mut primary,
vec![
(&secondary_taddr, 100_000, None),
(&secondary_taddr, 4_000, None),
],
vec![&mut secondary],
false,
),
)
.await
.unwrap();
assert_eq!(
(recorded_fee, recorded_value, recorded_change),
(
Option::unwrap(MARGINAL_FEE * 4_u64),
recorded_value,
recorded_change
)
);
let (recorded_fee, recorded_value) = timed(
format!("send_shield_cycle::cycle[{cycle}]::shield").as_str(),
with_assertions::assure_propose_shield_bump_sync(
&mut environment,
&mut secondary,
false,
),
)
.await
.unwrap();
assert_eq!(
(recorded_fee, recorded_value),
(
Option::unwrap(MARGINAL_FEE * 3_u64),
Option::unwrap(Zatoshis::from_u64(100_000).unwrap() - recorded_fee)
)
);
let primary_orchard_addr = timed(
format!("send_shield_cycle::cycle[{cycle}]::get_primary_orchard_addr").as_str(),
get_base_address(&primary, PoolType::Shielded(ShieldedPool::Orchard)),
)
.await;
let (recorded_fee, recorded_value, recorded_change) = timed(
format!("send_shield_cycle::cycle[{cycle}]::send_back_to_orchard").as_str(),
with_assertions::assure_propose_send_bump_sync_all_recipients(
&mut environment,
&mut secondary,
vec![(&primary_orchard_addr, 50_000, None)],
vec![&mut primary],
false,
),
)
.await
.unwrap();
assert_eq!(
(recorded_fee, recorded_value, recorded_change),
(
Option::unwrap(MARGINAL_FEE * 2_u64),
Zatoshis::from_u64(50_000).unwrap(),
recorded_change
)
);
},
)
.await;
}
}
pub async fn any_source_sends_to_any_receiver<CC>(
shpool: ShieldedPool,
pool: PoolType,
receiver_value: u64,
change: u64,
test_mempool: bool,
) where
CC: ConductChain,
{
timestamped_test_log(format!("starting a {shpool:?} to {pool} test").as_str());
let mut environment = CC::setup().await;
for _ in 0..5 {
environment.increase_chain_height().await;
}
let mut primary = environment.create_faucet().await;
let mut secondary = environment.create_client().await;
let mut tertiary = environment.create_client().await;
let expected_fee = fee_tables::one_to_one(Some(shpool), pool, true);
with_assertions::assure_propose_send_bump_sync_all_recipients(
&mut environment,
&mut primary,
vec![(
&get_base_address(&secondary, PoolType::Shielded(shpool)).await,
receiver_value + change + expected_fee,
None,
)],
vec![&mut secondary],
test_mempool,
)
.await
.unwrap();
let (recorded_fee, recorded_value, recorded_change) =
with_assertions::assure_propose_send_bump_sync_all_recipients(
&mut environment,
&mut secondary,
vec![(
&get_base_address(&tertiary, pool).await,
receiver_value,
None,
)],
vec![&mut tertiary],
test_mempool,
)
.await
.unwrap();
assert_eq!(
(recorded_fee, recorded_value, recorded_change),
(
Zatoshis::from_u64(expected_fee).unwrap(),
Zatoshis::from_u64(receiver_value).unwrap(),
Zatoshis::from_u64(change).unwrap()
)
);
}