diff --git a/emmarin/apps/swapvm/app/src/lib.rs b/emmarin/apps/swapvm/app/src/lib.rs index 56a00a6..c5bf27c 100644 --- a/emmarin/apps/swapvm/app/src/lib.rs +++ b/emmarin/apps/swapvm/app/src/lib.rs @@ -165,13 +165,13 @@ impl ZoneData { /// Check no pool notes are used in this tx pub fn validate_no_pools(&self, tx: &Tx) -> bool { - let Some(update) = tx.updates.get(&self.zone_id) else { + let Some(zone_update) = tx.updates.get(&self.zone_id) else { // this tx is not involving this zone, therefore it is - // guaranteed to have no pool notes + // guaranteed to not consume pool notes return true; }; - update.inputs.iter().all(|nf| !self.nfs.contains(nf)) + self.nfs.iter().all(|nf| !zone_update.has_input(nf)) } pub fn validate_op(&self, op: &ZoneOp) -> bool { @@ -193,7 +193,7 @@ impl ZoneData { return; }; // check all previous nullifiers are used - assert!(self.nfs.iter().all(|nf| zone_update.inputs.contains(nf))); + assert!(self.nfs.iter().all(|nf| zone_update.has_input(nf))); self.nfs.clear(); // check the exepected pool balances are reflected in the tx outputs @@ -205,10 +205,7 @@ impl ZoneData { let value = expected_pool_balances.get(&output.unit).unwrap(); assert_eq!(note.value, *value); - assert!(zone_update - .outputs - .find(|(cm, _data)| cm == &output.note_commitment()) - .is_some()); + assert!(zone_update.has_output(&output.note_commitment())); self.nfs.insert(note.nullifier()); } } @@ -220,10 +217,7 @@ impl ZoneData { for shares in &self.shares_to_mint { let output = shares.to_output(self.zone_id); - assert!(zone_update - .outputs - .find(|(cm, _data)| cm == &output.note_commitment()) - .is_some()); + assert!(zone_update.has_output(&output.note_commitment())); } } @@ -233,10 +227,7 @@ impl ZoneData { }; for shares in &self.shares_to_redeem { - assert!(zone_update - .outputs - .find(|(cm, _data)| cm == &shares.note_commitment()) - .is_some()); + assert!(zone_update.has_output(&shares.note_commitment())); } // TODO: chech shares have been burned diff --git a/emmarin/apps/swapvm/stf/host/src/lib.rs b/emmarin/apps/swapvm/stf/host/src/lib.rs index 402bbfd..6beff11 100644 --- a/emmarin/apps/swapvm/stf/host/src/lib.rs +++ b/emmarin/apps/swapvm/stf/host/src/lib.rs @@ -1,4 +1,5 @@ use app::{StateUpdate, ZoneOp}; +use cl::crust::BundleWitness; use cl::mantle::{ledger::Ledger, zone::ZoneData}; use ledger_proof_statements::ledger::SyncLog; use methods::{STF_ELF, STF_ID}; @@ -11,6 +12,7 @@ pub struct StfPrivate { pub sync_logs: Vec, pub ops: Vec, pub update_tx: StateUpdate, + pub bundles: BundleWitness, } impl StfPrivate { diff --git a/emmarin/apps/swapvm/stf/methods/guest/Cargo.toml b/emmarin/apps/swapvm/stf/methods/guest/Cargo.toml index befd76c..69cb408 100644 --- a/emmarin/apps/swapvm/stf/methods/guest/Cargo.toml +++ b/emmarin/apps/swapvm/stf/methods/guest/Cargo.toml @@ -10,4 +10,4 @@ risc0-zkvm = { version = "1.2.0", default-features = false, features = ['std'] } app = { path = "../../../app" } ledger_proof_statements = { path = "../../../../../cl/ledger_proof_statements" } cl = { path = "../../../../../cl/cl" } -ledger_validity_proof = { path = "../../../../../cl/ledger_validity_proof" } \ No newline at end of file +ledger_risc0_proof = { path = "../../../../../cl/ledger_risc0_proof" } \ No newline at end of file diff --git a/emmarin/cl/cl/src/crust/balance.rs b/emmarin/cl/cl/src/crust/balance.rs index 52cf97e..8de4ac6 100644 --- a/emmarin/cl/cl/src/crust/balance.rs +++ b/emmarin/cl/cl/src/crust/balance.rs @@ -33,24 +33,32 @@ pub struct UnitBalance { } impl UnitBalance { - pub fn is_zero(&self) -> bool { - self.pos == self.neg - } - - pub fn pos(unit: Unit, value: u64) -> Self { + pub fn zero(unit: Unit) -> Self { Self { unit, - pos: value, + pos: 0, neg: 0, } } - pub fn neg(unit: Unit, value: u64) -> Self { - Self { - unit, - pos: 0, - neg: value, - } + pub fn pos(unit: Unit, pos: u64) -> Self { + Self { unit, pos, neg: 0 } + } + + pub fn neg(unit: Unit, neg: u64) -> Self { + Self { unit, pos: 0, neg } + } + + pub fn is_zero(&self) -> bool { + self.pos == self.neg + } + + pub fn is_neg(&self) -> bool { + self.neg > self.pos + } + + pub fn is_pos(&self) -> bool { + self.pos > self.neg } } @@ -65,6 +73,14 @@ impl Balance { } } + pub fn unit_balance(&self, unit: Unit) -> UnitBalance { + self.balances + .iter() + .find(|b| b.unit == unit) + .cloned() + .unwrap_or_else(|| UnitBalance::zero(unit)) + } + pub fn insert_positive(&mut self, unit: Unit, value: Value) { for unit_bal in self.balances.iter_mut() { if unit_bal.unit == unit { diff --git a/emmarin/cl/cl/src/crust/tx.rs b/emmarin/cl/cl/src/crust/tx.rs index b4ea963..c8904c5 100644 --- a/emmarin/cl/cl/src/crust/tx.rs +++ b/emmarin/cl/cl/src/crust/tx.rs @@ -96,6 +96,14 @@ impl LedgerUpdate { self.outputs.push((cm, data)); self } + + pub fn has_input(&self, nf: &Nullifier) -> bool { + self.inputs.contains(nf) + } + + pub fn has_output(&self, cm: &NoteCommitment) -> bool { + self.outputs.iter().any(|(out_cm, _data)| out_cm == cm) + } } impl TxWitness { @@ -247,12 +255,16 @@ pub struct BundleWitness { } impl BundleWitness { + pub fn root(&self) -> BundleRoot { + BundleRoot(merkle::root(&merkle::padded_leaves( + self.txs.iter().map(|tx| tx.root.0), + ))) + } + pub fn commit(self) -> Bundle { assert!(Balance::combine(self.txs.iter().map(|tx| &tx.balance)).is_zero()); - let root = BundleRoot(merkle::root(&merkle::padded_leaves( - self.txs.iter().map(|tx| tx.root.0), - ))); + let root = self.root(); let mut updates = self .txs