diff --git a/goas/atomic_asset_transfer/executor/src/lib.rs b/goas/atomic_asset_transfer/executor/src/lib.rs index 3bb8de4..7e4937f 100644 --- a/goas/atomic_asset_transfer/executor/src/lib.rs +++ b/goas/atomic_asset_transfer/executor/src/lib.rs @@ -157,7 +157,7 @@ pub fn prove_zone_stf( ledger::DeathProof::from_risc0(goas_risc0_proofs::ZONE_STATE_ID, receipt) } -pub fn prove_zone_fund_withdraw( +pub fn prove_zone_fund_constraint( in_zone_funds: cl::PartialTxInputWitness, zone_note: cl::PartialTxOutputWitness, out_zone_state: &StateWitness, @@ -214,3 +214,154 @@ pub fn prove_user_atomic_transfer(atomic_transfer: UserAtomicTransfer) -> ledger let receipt = prove_info.receipt; ledger::DeathProof::from_risc0(goas_risc0_proofs::USER_ATOMIC_TRANSFER_ID, receipt) } + +#[cfg(test)] +mod tests { + use cl::{note::unit_point, NoteWitness, NullifierNonce, OutputWitness, PartialTxWitness}; + use common::{BoundTx, Deposit, Withdraw}; + use goas_proof_statements::user_note::UserIntent; + use ledger_proof_statements::death_constraint::DeathConstraintPublic; + + use super::*; + + #[test] + pub fn test_prove_zone_stf() { + let mut rng = rand::thread_rng(); + + let zone_start = ZoneNotes::new_with_balances("ZONE", BTreeMap::from_iter([]), &mut rng); + + let bind = OutputWitness::public( + NoteWitness::basic(32, *common::ZONE_CL_FUNDS_UNIT), + cl::NullifierNonce::random(&mut rng), + ); + + let mut alice = common::new_account(&mut rng); + let alice_vk = alice.verifying_key().to_bytes(); + + let signed_deposit = SignedBoundTx::sign( + BoundTx { + tx: Tx::Deposit(Deposit { + to: alice_vk, + amount: 32, + }), + bind: bind.commit_note(), + }, + &mut alice, + ); + let signed_withdraw = SignedBoundTx::sign( + BoundTx { + tx: Tx::Withdraw(Withdraw { + from: alice_vk, + amount: 10, + }), + bind: bind.commit_note(), + }, + &mut alice, + ); + + let zone_end = zone_start + .clone() + .run([signed_deposit.bound_tx.tx, signed_withdraw.bound_tx.tx]); + + let ptx = PartialTxWitness { + inputs: vec![ + cl::InputWitness::public(bind), + zone_start.state_input_witness(), + zone_start.fund_input_witness(), + ], + outputs: vec![zone_end.state_note, zone_end.fund_note], + }; + + let txs = vec![ + (signed_deposit, ptx.input_witness(0)), + (signed_withdraw, ptx.input_witness(0)), + ]; + + let proof = prove_zone_stf( + zone_start.state.clone(), + txs, + ptx.input_witness(1), + ptx.output_witness(0), + ptx.output_witness(1), + ); + + assert!(proof.verify(DeathConstraintPublic { + nf: zone_start.state_input_witness().nullifier(), + ptx_root: ptx.commit().root(), + })) + } + + #[test] + fn test_prove_zone_fund_constraint() { + let zone = + ZoneNotes::new_with_balances("ZONE", BTreeMap::from_iter([]), &mut rand::thread_rng()); + + let ptx = PartialTxWitness { + inputs: vec![zone.fund_input_witness()], + outputs: vec![zone.state_note], + }; + + let proof = + prove_zone_fund_constraint(ptx.input_witness(0), ptx.output_witness(0), &zone.state); + + assert!(proof.verify(DeathConstraintPublic { + nf: zone.fund_input_witness().nullifier(), + ptx_root: ptx.commit().root(), + })) + } + + #[test] + fn test_prove_user_atomic_transfer() { + let mut rng = rand::thread_rng(); + + let alice = common::new_account(&mut rng); + let alice_vk = alice.verifying_key().to_bytes(); + + let mut zone_a = + ZoneNotes::new_with_balances("ZONE_A", BTreeMap::from_iter([(alice_vk, 40)]), &mut rng); + let mut zone_b = ZoneNotes::new_with_balances("ZONE_B", BTreeMap::new(), &mut rng); + + let user_intent = UserIntent { + zone_a_meta: zone_a.state.zone_metadata, + zone_b_meta: zone_b.state.zone_metadata, + withdraw: Withdraw { + from: alice_vk, + amount: 32, + }, + deposit: Deposit { + to: alice_vk, + amount: 32, + }, + }; + let user_note = cl::InputWitness::public(cl::OutputWitness::public( + NoteWitness::new(1, unit_point("INTENT"), [0u8; 32], user_intent.commit()), + NullifierNonce::random(&mut rng), + )); + + zone_a = zone_a.run([Tx::Withdraw(user_intent.withdraw)]); + zone_b = zone_b.run([Tx::Deposit(user_intent.deposit)]); + + let ptx = PartialTxWitness { + inputs: vec![user_note], + outputs: vec![zone_a.state_note, zone_b.state_note], + }; + + let user_atomic_transfer = UserAtomicTransfer { + user_note: ptx.input_witness(0), + user_intent, + zone_a: ptx.output_witness(0), + zone_b: ptx.output_witness(1), + zone_a_roots: zone_a.state.state_roots(), + zone_b_roots: zone_b.state.state_roots(), + withdraw_tx: zone_a.state.included_tx_witness(0), + deposit_tx: zone_b.state.included_tx_witness(0), + }; + + let proof = prove_user_atomic_transfer(user_atomic_transfer); + + assert!(proof.verify(DeathConstraintPublic { + nf: user_note.nullifier(), + ptx_root: ptx.commit().root(), + })) + } +} diff --git a/goas/atomic_asset_transfer/executor/tests/atomic_transfer.rs b/goas/atomic_asset_transfer/executor/tests/atomic_transfer.rs index ac66029..975831d 100644 --- a/goas/atomic_asset_transfer/executor/tests/atomic_transfer.rs +++ b/goas/atomic_asset_transfer/executor/tests/atomic_transfer.rs @@ -111,7 +111,7 @@ fn test_atomic_transfer() { ), ( zone_a_start.fund_input_witness().nullifier(), - executor::prove_zone_fund_withdraw( + executor::prove_zone_fund_constraint( atomic_transfer_ptx.input_witness(2), // input fund note atomic_transfer_ptx.output_witness(0), // output state note &zone_a_end.state, @@ -129,7 +129,7 @@ fn test_atomic_transfer() { ), ( zone_b_start.fund_input_witness().nullifier(), - executor::prove_zone_fund_withdraw( + executor::prove_zone_fund_constraint( atomic_transfer_ptx.input_witness(4), // input fund note (input #1) atomic_transfer_ptx.output_witness(2), // output state note (output #0) &zone_b_end.state, diff --git a/goas/atomic_asset_transfer/executor/tests/withdraw_ptx.rs b/goas/atomic_asset_transfer/executor/tests/withdraw_ptx.rs index ae189c4..5f099d1 100644 --- a/goas/atomic_asset_transfer/executor/tests/withdraw_ptx.rs +++ b/goas/atomic_asset_transfer/executor/tests/withdraw_ptx.rs @@ -73,7 +73,7 @@ fn test_withdrawal() { ), ( zone_start.fund_input_witness().nullifier(), - executor::prove_zone_fund_withdraw( + executor::prove_zone_fund_constraint( withdraw_ptx.input_witness(1), // input fund note (input #1) withdraw_ptx.output_witness(0), // output state note (output #0) &zone_end.state,