From 669401271cc27ccf252bcec0c364e75823bc3ada Mon Sep 17 00:00:00 2001 From: Giacomo Pasini Date: Mon, 17 Mar 2025 10:45:57 +0100 Subject: [PATCH] Process ledger updates in batches to allow usage of notes in the same bundle --- emmarin/cl/cl/src/crust/tx.rs | 25 ++++----------- emmarin/cl/ledger/src/ledger.rs | 30 +++++++++-------- .../cl/ledger_risc0_proof/src/bin/ledger.rs | 32 +++++++++++-------- 3 files changed, 40 insertions(+), 47 deletions(-) diff --git a/emmarin/cl/cl/src/crust/tx.rs b/emmarin/cl/cl/src/crust/tx.rs index 274ae30..f4458ce 100644 --- a/emmarin/cl/cl/src/crust/tx.rs +++ b/emmarin/cl/cl/src/crust/tx.rs @@ -142,14 +142,11 @@ impl TxWitness { self.frontier_paths.len() ); for (input, (mmr, path)) in inputs.iter().zip(&self.frontier_paths) { - let entry = updates + assert!(mmr.verify_proof(&input.cm.0, path)); + updates .entry(input.zone_id) .or_default() .add_input(input.nf, mmr.clone()); - - assert!(mmr.verify_proof(&input.cm.0, path)); - // ensure a single MMR per zone per tx - assert_eq!(&mmr.roots, &entry.frontier_nodes); } for (output, data) in &self.outputs { @@ -264,7 +261,7 @@ impl TxWitness { #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Bundle { - pub updates: BTreeMap, + pub updates: BTreeMap>, pub root: BundleRoot, } @@ -285,26 +282,16 @@ impl BundleWitness { let root = self.root(); - let mut updates = self + let updates = self .txs .into_iter() - .fold(BTreeMap::new(), |mut updates, tx| { + .fold(>>::new(), |mut updates, tx| { for (zone_id, update) in tx.updates { - let entry: &mut LedgerUpdate = updates.entry(zone_id).or_default(); - entry.inputs.extend(update.inputs); - entry.outputs.extend(update.outputs); - entry.frontier_nodes.extend(update.frontier_nodes); // TODO: maybe merge? + updates.entry(zone_id).or_default().push(update); } - updates }); - // de-dup frontier nodes - updates.iter_mut().for_each(|(_, update)| { - update.frontier_nodes.sort(); - update.frontier_nodes.dedup(); - }); - Bundle { updates, root } } } diff --git a/emmarin/cl/ledger/src/ledger.rs b/emmarin/cl/ledger/src/ledger.rs index 296300d..4ec1b3d 100644 --- a/emmarin/cl/ledger/src/ledger.rs +++ b/emmarin/cl/ledger/src/ledger.rs @@ -23,21 +23,21 @@ impl ProvedLedgerTransition { let bundle = proved_bundle.public(); - let zone_ledger_update = bundle + let zone_ledger_updates = bundle .updates .get(&zone_id) .expect("why are we proving this bundle for this zone if it's not involved?"); - let cm_root_proofs = - BTreeMap::from_iter(zone_ledger_update.frontier_nodes.iter().map(|root| { - // We make the simplifying assumption that bundle proofs - // are done w.r.t. the latest MMR (hence, empty merkle proofs) - // - // We can remove this assumption by tracking old MMR roots in the LedgerState - (root.root, vec![]) - })); - - nullifiers.extend(zone_ledger_update.inputs.clone()); + let mut cm_root_proofs = BTreeMap::new(); + for zone_ledger_update in zone_ledger_updates { + cm_root_proofs.extend( + zone_ledger_update + .frontier_nodes + .iter() + .map(|root| (root.root, vec![])), + ); + nullifiers.extend(zone_ledger_update.inputs.clone()); + } let ledger_bundle = LedgerBundleWitness { bundle, @@ -55,14 +55,16 @@ impl ProvedLedgerTransition { }; for bundle in &witness.bundles { - let update = bundle + let updates = bundle .bundle .updates .get(&zone_id) .expect("should have a bundle from the zone we are proofing for"); - for (cm, _data) in &update.outputs { - ledger.add_commitment(cm); + for update in updates { + for (cm, _data) in &update.outputs { + ledger.add_commitment(cm); + } } ledger.add_bundle(bundle.bundle.root); diff --git a/emmarin/cl/ledger_risc0_proof/src/bin/ledger.rs b/emmarin/cl/ledger_risc0_proof/src/bin/ledger.rs index 42b1068..9898d8d 100644 --- a/emmarin/cl/ledger_risc0_proof/src/bin/ledger.rs +++ b/emmarin/cl/ledger_risc0_proof/src/bin/ledger.rs @@ -38,27 +38,31 @@ fn main() { }); } - let ledger_update = bundle + let ledger_updates = bundle .updates .get(&id) .expect("attempting to prove a bundle that is not for this zone"); - for node in &ledger_update.frontier_nodes { - let past_cm_root_proof = cm_root_proofs - .get(&node.root) - .expect("missing cm root proof"); + for ledger_update in ledger_updates { + for node in &ledger_update.frontier_nodes { + let past_cm_root_proof = cm_root_proofs + .get(&node.root) + .expect("missing cm root proof"); - let expected_current_cm_root = merkle::path_root(node.root, past_cm_root_proof); - assert!(old_ledger.valid_cm_root(expected_current_cm_root)) + let expected_current_cm_root = merkle::path_root(node.root, past_cm_root_proof); + assert!( + old_ledger.valid_cm_root(expected_current_cm_root) + || ledger.valid_cm_root(expected_current_cm_root) + ); + } + + for (cm, _data) in &ledger_update.outputs { + ledger.add_commitment(cm); + outputs.push(*cm); + } + nullifiers.extend(ledger_update.inputs.clone()); } - for (cm, _data) in &ledger_update.outputs { - ledger.add_commitment(cm); - outputs.push(*cm); - } - - nullifiers.extend(ledger_update.inputs.clone()); - ledger.add_bundle(bundle.root); }