diff --git a/emmarin/cl/cl/src/cl/mmr.rs b/emmarin/cl/cl/src/cl/mmr.rs index 153e930..0a11847 100644 --- a/emmarin/cl/cl/src/cl/mmr.rs +++ b/emmarin/cl/cl/src/cl/mmr.rs @@ -18,6 +18,13 @@ pub struct MMRProof { pub path: Vec, } +impl MMRProof { + pub fn root(&self, elem: &[u8]) -> [u8; 32] { + let leaf = merkle::leaf(elem); + merkle::path_root(leaf, &self.path) + } +} + impl MMR { pub fn new() -> Self { Self::default() @@ -52,8 +59,7 @@ impl MMR { pub fn verify_proof(&self, elem: &[u8], proof: &MMRProof) -> bool { let path_len = proof.path.len(); - let leaf = merkle::leaf(elem); - let root = merkle::path_root(leaf, &proof.path); + let root = proof.root(elem); for mmr_root in self.roots.iter() { if mmr_root.height == (path_len + 1) as u8 { diff --git a/emmarin/cl/cl/src/zone_layer/ledger.rs b/emmarin/cl/cl/src/zone_layer/ledger.rs index eca60e6..e01d49d 100644 --- a/emmarin/cl/cl/src/zone_layer/ledger.rs +++ b/emmarin/cl/cl/src/zone_layer/ledger.rs @@ -39,10 +39,10 @@ impl LedgerWitness { } } -#[derive(Default, Clone)] +#[derive(Debug, Default, Clone)] pub struct LedgerState { - commitments: MMR, - nullifiers: BTreeSet<[u8; 32]>, + pub commitments: MMR, + pub nullifiers: BTreeSet<[u8; 32]>, } impl LedgerState { @@ -53,10 +53,6 @@ impl LedgerState { } } - pub fn cm_mmr(&self) -> MMR { - self.commitments.clone() - } - pub fn nf_root(&self) -> [u8; 32] { sparse_merkle::sparse_root(&self.nullifiers) } diff --git a/emmarin/cl/ledger/src/partial_tx.rs b/emmarin/cl/ledger/src/partial_tx.rs index 2cb007d..d4e8b91 100644 --- a/emmarin/cl/ledger/src/partial_tx.rs +++ b/emmarin/cl/ledger/src/partial_tx.rs @@ -15,13 +15,11 @@ pub struct ProvedPartialTx { impl ProvedPartialTx { pub fn prove( ptx_witness: PartialTxWitness, - input_cm_paths: Vec, - cm_mmr: MMR, + input_cm_proofs: Vec<(MMR, MMRProof)>, ) -> Result { let ptx_private = PtxPrivate { ptx: ptx_witness, - input_cm_paths, - cm_mmr: cm_mmr.clone(), + input_cm_proofs, }; let env = risc0_zkvm::ExecutorEnv::builder() diff --git a/emmarin/cl/ledger/src/zone_update.rs b/emmarin/cl/ledger/src/zone_update.rs index 7aa1341..988945b 100644 --- a/emmarin/cl/ledger/src/zone_update.rs +++ b/emmarin/cl/ledger/src/zone_update.rs @@ -27,7 +27,6 @@ impl ProvedUpdateBundle { } } - println!("{:?} | {:?}", expected_zones, actual_zones); for (bundle, expected) in expected_zones.iter() { if let Some(actual) = actual_zones.get(bundle) { if actual != expected { diff --git a/emmarin/cl/ledger/tests/simple_transfer.rs b/emmarin/cl/ledger/tests/simple_transfer.rs index cf6f967..3134274 100644 --- a/emmarin/cl/ledger/tests/simple_transfer.rs +++ b/emmarin/cl/ledger/tests/simple_transfer.rs @@ -1,7 +1,10 @@ use cl::{ cl::{ - balance::Unit, mmr::MMRProof, note::derive_unit, BalanceWitness, InputWitness, NoteWitness, - NullifierCommitment, NullifierSecret, OutputWitness, PartialTxWitness, + balance::Unit, + mmr::{MMRProof, MMR}, + note::derive_unit, + BalanceWitness, InputWitness, NoteWitness, NullifierCommitment, NullifierSecret, + OutputWitness, PartialTxWitness, }, zone_layer::{ ledger::LedgerState, @@ -48,7 +51,7 @@ fn receive_utxo(note: NoteWitness, nf_pk: NullifierCommitment, zone_id: ZoneId) fn cross_transfer_transition( input: InputWitness, - input_path: MMRProof, + input_proof: (MMR, MMRProof), to: User, amount: u64, zone_a: ZoneId, @@ -74,8 +77,7 @@ fn cross_transfer_transition( outputs: vec![transfer, change], balance_blinding: BalanceWitness::random_blinding(&mut rng), }; - let proved_ptx = - ProvedPartialTx::prove(ptx_witness.clone(), vec![input_path], ledger_a.cm_mmr()).unwrap(); + let proved_ptx = ProvedPartialTx::prove(ptx_witness.clone(), vec![input_proof]).unwrap(); let balance = ProvedBalance::prove(&BalancePrivate { balances: vec![ptx_witness.balance()], @@ -141,7 +143,8 @@ fn zone_update_cross() { let alice_input = InputWitness::from_output(utxo, alice.sk()); let mut ledger_a = LedgerState::default(); - let input_cm_path = ledger_a.add_commitment(utxo.commit_note()); + let alice_cm_path = ledger_a.add_commitment(utxo.commit_note()); + let alice_cm_proof = (ledger_a.commitments.clone(), alice_cm_path); let ledger_b = LedgerState::default(); @@ -160,7 +163,7 @@ fn zone_update_cross() { let (ledger_a_transition, ledger_b_transition) = cross_transfer_transition( alice_input, - input_cm_path, + alice_cm_proof, bob, 8, zone_a_id, diff --git a/emmarin/cl/ledger_proof_statements/src/ptx.rs b/emmarin/cl/ledger_proof_statements/src/ptx.rs index 6f25761..425675f 100644 --- a/emmarin/cl/ledger_proof_statements/src/ptx.rs +++ b/emmarin/cl/ledger_proof_statements/src/ptx.rs @@ -7,12 +7,11 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct PtxPublic { pub ptx: PartialTx, - pub cm_mmr: MMR, + pub cm_mmr: Vec, } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct PtxPrivate { pub ptx: PartialTxWitness, - pub input_cm_proofs: Vec, - pub cm_mmr: MMR, + pub input_cm_proofs: Vec<(MMR, MMRProof)>, } diff --git a/emmarin/cl/ledger_validity_proof/ledger/src/main.rs b/emmarin/cl/ledger_validity_proof/ledger/src/main.rs index 9f9ab02..215f243 100644 --- a/emmarin/cl/ledger_validity_proof/ledger/src/main.rs +++ b/emmarin/cl/ledger_validity_proof/ledger/src/main.rs @@ -5,8 +5,7 @@ use cl::{ use ledger_proof_statements::{ balance::BalancePublic, constraint::ConstraintPublic, - ledger::{CrossZoneBundle, LedgerProofPrivate, LedgerProofPublic}, - ptx::PtxPublic, + ledger::{CrossZoneBundle, LedgerProofPrivate, LedgerProofPublic, LedgerPtxWitness}, }; use risc0_zkvm::{guest::env, serde}; @@ -21,13 +20,6 @@ fn main() { let mut cross_bundles = vec![]; let mut outputs = vec![]; - let roots = ledger - .commitments - .roots - .iter() - .map(|r| r.root) - .collect::>(); - for bundle in bundles { let balance_public = BalancePublic { balances: bundle.partials.iter().map(|bundle_ptx| bundle_ptx.ptx.ptx.balance).collect::>(), @@ -40,14 +32,13 @@ fn main() { ) .unwrap(); - for ptx in &bundle { - let (new_ledger, ptx_outputs) = process_ptx(ledger, ptx, id, &roots); - ledger = new_ledger; + for ptx in &bundle.partials { + let ptx_outputs = process_ptx(&mut ledger, ptx, id); outputs.extend(ptx_outputs); } let bundle = Bundle { - partials: bundle.into_iter().map(|ptx| ptx.ptx).collect(), + partials: bundle.partials.into_iter().map(|ptx_witness| ptx_witness.ptx.ptx).collect(), }; let zones = bundle.zones(); if zones.len() > 1 { @@ -68,37 +59,40 @@ fn main() { } fn process_ptx( - mut ledger: LedgerWitness, + ledger: &mut LedgerWitness, ptx_witness: &LedgerPtxWitness, zone_id: ZoneId, - roots: &[[u8; 32]], -) -> (LedgerWitness, Vec) { +) -> Vec { + let ptx = &ptx_witness.ptx; + let nf_proofs = &ptx_witness.nf_proofs; + // always verify the ptx to ensure outputs were derived with the correct zone id env::verify(nomos_cl_risc0_proofs::PTX_ID, &serde::to_vec(&ptx).unwrap()).unwrap(); - PtxWitness { ref ptx, ref nf_proofs } = ptx_witness; - - assert_eq!(ptx.cm_mmr, roots); // we force commitment proofs w.r.t. latest MMR + assert_eq!(ptx.ptx.inputs.len(), nf_proofs.len()); + assert_eq!(ptx.ptx.inputs.len(), ptx.cm_mmr.len()); - for (input, nf_proof) in ptx.ptx.inputs.iter().zip(nf_proofs) { + for ((input, nf_proof), cm_mmr) in ptx.ptx.inputs.iter().zip(nf_proofs).zip(ptx.cm_mmr.iter()) { if input.zone_id != zone_id { continue; } + + assert_eq!(cm_mmr, &ledger.commitments); // we force commitment proofs w.r.t. latest MMR ledger.assert_nf_update(input.nullifier, nf_proof); env::verify( input.constraint.0, &serde::to_vec(&ConstraintPublic { - ptx_root: ptx.root(), + ptx_root: ptx.ptx.root(), nf: input.nullifier, }).unwrap(), ).unwrap(); } let mut outputs = vec![]; - for output in &ptx.outputs { + for output in &ptx.ptx.outputs { if output.zone_id != zone_id { continue; } @@ -107,5 +101,5 @@ fn process_ptx( outputs.push(*output); } - (ledger, outputs) + outputs } diff --git a/emmarin/cl/risc0_proofs/ptx/src/main.rs b/emmarin/cl/risc0_proofs/ptx/src/main.rs index 2ab181a..b03995b 100644 --- a/emmarin/cl/risc0_proofs/ptx/src/main.rs +++ b/emmarin/cl/risc0_proofs/ptx/src/main.rs @@ -6,13 +6,14 @@ fn main() { let PtxPrivate { ptx, input_cm_proofs, - cm_mmr, } = env::read(); assert_eq!(ptx.inputs.len(), input_cm_proofs.len()); - for (input, cm_mmr_proof) in ptx.inputs.iter().zip(input_cm_proofs) { + let mut cm_mmr = Vec::new(); + for (input, (mmr, mmr_proof)) in ptx.inputs.iter().zip(input_cm_proofs) { let note_cm = input.note_commitment(); - assert!(cm_mmr.verify_proof(¬e_cm.0, &cm_mmr_proof)); + assert!(mmr.verify_proof(¬e_cm.0, &mmr_proof)); + cm_mmr.push(mmr); } for output in ptx.outputs.iter() {