Process ledger updates in batches to allow usage of notes in the same bundle

This commit is contained in:
Giacomo Pasini 2025-03-17 10:45:57 +01:00
parent 21bf72c6f4
commit 669401271c
No known key found for this signature in database
GPG Key ID: FC08489D2D895D4B
3 changed files with 40 additions and 47 deletions

View File

@ -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<ZoneId, LedgerUpdate>,
pub updates: BTreeMap<ZoneId, Vec<LedgerUpdate>>,
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(<BTreeMap<_, Vec<_>>>::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 }
}
}

View File

@ -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);

View File

@ -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);
}