diff --git a/goas/atomic_asset_transfer/common/src/lib.rs b/goas/atomic_asset_transfer/common/src/lib.rs index db5f305..2eeca35 100644 --- a/goas/atomic_asset_transfer/common/src/lib.rs +++ b/goas/atomic_asset_transfer/common/src/lib.rs @@ -62,15 +62,11 @@ impl StateWitness { } pub fn withdraw(mut self, w: Withdraw) -> Self { - let Withdraw { - from, - amount, - bind: _, - } = &w; + let Withdraw { from, amount } = w; - let from_balance = self.balances.entry(*from).or_insert(0); + let from_balance = self.balances.entry(from).or_insert(0); *from_balance = from_balance - .checked_sub(*amount) + .checked_sub(amount) .expect("insufficient funds in account"); self.included_txs.push(Tx::Withdraw(w)); @@ -79,15 +75,11 @@ impl StateWitness { } pub fn deposit(mut self, d: Deposit) -> Self { - let Deposit { - to, - amount, - bind: _, - } = &d; + let Deposit { to, amount } = d; - let to_balance = self.balances.entry(*to).or_insert(0); + let to_balance = self.balances.entry(to).or_insert(0); *to_balance += to_balance - .checked_add(*amount) + .checked_add(amount) .expect("overflow in account balance"); self.included_txs.push(Tx::Deposit(d)); @@ -148,37 +140,49 @@ impl From for [u8; 32] { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub struct Withdraw { pub from: AccountId, pub amount: u64, - pub bind: PartialTxInputWitness, } impl Withdraw { - pub fn to_bytes(&self) -> [u8; 108] { - let mut bytes = [0; 108]; + pub fn to_bytes(&self) -> [u8; 12] { + let mut bytes = [0; 12]; bytes[0..4].copy_from_slice(&self.from.to_le_bytes()); bytes[4..12].copy_from_slice(&self.amount.to_le_bytes()); - bytes[12..108].copy_from_slice(&self.bind.input.commit().to_bytes()); bytes } } /// A deposit of funds into the zone -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub struct Deposit { pub to: AccountId, pub amount: u64, - pub bind: PartialTxInputWitness, } impl Deposit { - pub fn to_bytes(&self) -> [u8; 108] { - let mut bytes = [0; 108]; + pub fn to_bytes(&self) -> [u8; 12] { + let mut bytes = [0; 12]; bytes[0..4].copy_from_slice(&self.to.to_le_bytes()); bytes[4..12].copy_from_slice(&self.amount.to_le_bytes()); - bytes[12..108].copy_from_slice(&self.bind.input.commit().to_bytes()); + bytes + } +} + +/// A Tx that is executed in the zone if and only if the bind is +/// present is the same partial transaction +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct BoundTx { + pub tx: Tx, + pub bind: PartialTxInputWitness, +} + +impl BoundTx { + pub fn to_bytes(&self) -> Vec { + let mut bytes = self.tx.to_bytes(); + bytes.extend(self.bind.input.commit().to_bytes()); bytes } } diff --git a/goas/atomic_asset_transfer/executor/src/lib.rs b/goas/atomic_asset_transfer/executor/src/lib.rs index 2def1b1..c224e4c 100644 --- a/goas/atomic_asset_transfer/executor/src/lib.rs +++ b/goas/atomic_asset_transfer/executor/src/lib.rs @@ -1,9 +1,9 @@ -use common::{StateWitness, Tx}; +use common::{BoundTx, StateWitness}; use goas_proof_statements::{zone_funds::SpendFundsPrivate, zone_state::ZoneStatePrivate}; pub fn prove_zone_stf( state: StateWitness, - inputs: Vec, + inputs: Vec, zone_in: cl::PartialTxInputWitness, zone_out: cl::PartialTxOutputWitness, funds_out: cl::PartialTxOutputWitness, diff --git a/goas/atomic_asset_transfer/executor/tests/withdraw_ptx.rs b/goas/atomic_asset_transfer/executor/tests/withdraw_ptx.rs index 8da5e23..ca137b7 100644 --- a/goas/atomic_asset_transfer/executor/tests/withdraw_ptx.rs +++ b/goas/atomic_asset_transfer/executor/tests/withdraw_ptx.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; use cl::{NoteWitness, NullifierNonce, NullifierSecret}; -use common::{StateWitness, Tx, ZoneMetadata, ZONE_CL_FUNDS_UNIT}; +use common::{BoundTx, StateWitness, Tx, ZoneMetadata, ZONE_CL_FUNDS_UNIT}; use ledger::death_constraint::DeathProof; use rand_core::CryptoRngCore; @@ -75,15 +75,9 @@ fn test_withdrawal() { &mut rng, ); - let mut withdraw_ptx = cl::PartialTxWitness { - inputs: vec![zone_state_in, zone_fund_in, alice_intent], - outputs: vec![], - }; - let withdraw = common::Withdraw { from: alice, amount: 78, - bind: withdraw_ptx.input_witness(2), }; let end_state = init_state.clone().withdraw(withdraw.clone()).evolve_nonce(); @@ -113,14 +107,20 @@ fn test_withdrawal() { &mut rng, ); - withdraw_ptx.outputs = vec![zone_state_out, zone_fund_out, alice_withdrawal]; + let withdraw_ptx = cl::PartialTxWitness { + inputs: vec![zone_state_in, zone_fund_in, alice_intent], + outputs: vec![zone_state_out, zone_fund_out, alice_withdrawal], + }; let death_proofs = BTreeMap::from_iter([ ( zone_state_in.nullifier(), executor::prove_zone_stf( init_state.clone(), - vec![Tx::Withdraw(withdraw.clone())], + vec![BoundTx { + tx: Tx::Withdraw(withdraw.clone()), + bind: withdraw_ptx.input_witness(2), + }], withdraw_ptx.input_witness(0), // input state note (input #0) withdraw_ptx.output_witness(0), // output state note (output #0) withdraw_ptx.output_witness(1), // output funds note (output #1) @@ -140,8 +140,6 @@ fn test_withdrawal() { ), ]); - println!("done"); - let note_commitments = vec![ zone_state_in.note_commitment(), zone_fund_in.note_commitment(), diff --git a/goas/atomic_asset_transfer/proof_statements/src/zone_state.rs b/goas/atomic_asset_transfer/proof_statements/src/zone_state.rs index 2966b48..1b26c88 100644 --- a/goas/atomic_asset_transfer/proof_statements/src/zone_state.rs +++ b/goas/atomic_asset_transfer/proof_statements/src/zone_state.rs @@ -1,10 +1,10 @@ -use common::{StateWitness, Tx}; +use common::{BoundTx, StateWitness}; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct ZoneStatePrivate { pub state: StateWitness, - pub inputs: Vec, + pub inputs: Vec, pub zone_in: cl::PartialTxInputWitness, pub zone_out: cl::PartialTxOutputWitness, /// While the absence of birth constraints does not guarantee uniqueness of a note that can be used as diff --git a/goas/atomic_asset_transfer/risc0_proofs/zone_state/src/main.rs b/goas/atomic_asset_transfer/risc0_proofs/zone_state/src/main.rs index d913b2b..7886fbf 100644 --- a/goas/atomic_asset_transfer/risc0_proofs/zone_state/src/main.rs +++ b/goas/atomic_asset_transfer/risc0_proofs/zone_state/src/main.rs @@ -1,17 +1,30 @@ -use cl::{note::NoteWitness, nullifier::NullifierNonce, output::OutputWitness, PtxRoot}; +use cl::{ + note::NoteWitness, nullifier::NullifierNonce, output::OutputWitness, PartialTxInputWitness, + PtxRoot, +}; use common::*; use goas_proof_statements::zone_state::ZoneStatePrivate; use ledger_proof_statements::death_constraint::DeathConstraintPublic; use risc0_zkvm::guest::env; -fn withdraw(state: StateWitness, input_root: [u8; 32], withdrawal: Withdraw) -> StateWitness { - assert_eq!(input_root, withdrawal.bind.input_root()); +fn withdraw( + state: StateWitness, + input_root: [u8; 32], + withdrawal: Withdraw, + bind: PartialTxInputWitness, +) -> StateWitness { + assert_eq!(bind.input_root(), input_root); state.withdraw(withdrawal) } -fn deposit(state: StateWitness, input_root: [u8; 32], deposit: Deposit) -> StateWitness { - assert_eq!(deposit.bind.input_root(), input_root); +fn deposit( + state: StateWitness, + input_root: [u8; 32], + deposit: Deposit, + bind: PartialTxInputWitness, +) -> StateWitness { + assert_eq!(bind.input_root(), input_root); state.deposit(deposit) } @@ -87,8 +100,14 @@ fn main() { for input in inputs { state = match input { - Tx::Withdraw(w) => withdraw(state, input_root, w), - Tx::Deposit(d) => deposit(state, input_root, d), + BoundTx { + tx: Tx::Withdraw(w), + bind, + } => withdraw(state, input_root, w, bind), + BoundTx { + tx: Tx::Deposit(d), + bind, + } => deposit(state, input_root, d, bind), } }