mirror of
https://github.com/logos-blockchain/logos-blockchain-pocs.git
synced 2026-04-14 14:53:53 +00:00
use btreemap for zoneid -> ledgerupdate mapping
This commit is contained in:
parent
a85b306baa
commit
5e0b2fe174
@ -50,7 +50,7 @@ impl TxRoot {
|
||||
pub struct Tx {
|
||||
pub root: TxRoot,
|
||||
pub balance: Balance,
|
||||
pub updates: Vec<LedgerUpdate>,
|
||||
pub updates: BTreeMap<ZoneId, LedgerUpdate>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
|
||||
@ -63,16 +63,16 @@ pub struct TxWitness {
|
||||
pub frontier_paths: Vec<(MMR, MMRProof)>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
// TODO: this LedgerUpdate and LedgerUpdateWitness need to be merged
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
|
||||
pub struct LedgerUpdate {
|
||||
pub zone_id: ZoneId,
|
||||
pub frontier_nodes: Vec<Root>,
|
||||
pub inputs: Vec<Nullifier>,
|
||||
pub outputs: Vec<NoteCommitment>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||
pub struct LedgerUpdateWitness {
|
||||
pub zone_id: ZoneId,
|
||||
pub frontier_nodes: Vec<Root>,
|
||||
pub inputs: Vec<Nullifier>,
|
||||
pub outputs: Vec<(NoteCommitment, Vec<u8>)>,
|
||||
@ -88,15 +88,10 @@ impl LedgerUpdateWitness {
|
||||
.collect::<Vec<_>>()
|
||||
},
|
||||
)));
|
||||
let root = merkle::root(&merkle::padded_leaves([
|
||||
input_root,
|
||||
output_root,
|
||||
self.zone_id,
|
||||
]));
|
||||
let root = merkle::root(&merkle::padded_leaves([input_root, output_root]));
|
||||
|
||||
(
|
||||
LedgerUpdate {
|
||||
zone_id: self.zone_id,
|
||||
inputs: self.inputs,
|
||||
outputs: self.outputs.into_iter().map(|(cm, _)| cm).collect(),
|
||||
frontier_nodes: self.frontier_nodes,
|
||||
@ -104,6 +99,19 @@ impl LedgerUpdateWitness {
|
||||
root,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn add_input(&mut self, nf: Nullifier, mmr: MMR) -> &mut Self {
|
||||
self.inputs.push(nf);
|
||||
self.frontier_nodes.extend(mmr.roots);
|
||||
self.frontier_nodes.sort();
|
||||
self.frontier_nodes.dedup();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_output(&mut self, cm: NoteCommitment, data: Vec<u8>) -> &mut Self {
|
||||
self.outputs.push((cm, data));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl TxWitness {
|
||||
@ -118,17 +126,19 @@ impl TxWitness {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn compute_updates(&self, inputs: &[InputDerivedFields]) -> Vec<LedgerUpdateWitness> {
|
||||
let mut updates = BTreeMap::new();
|
||||
pub fn compute_updates(
|
||||
&self,
|
||||
inputs: &[InputDerivedFields],
|
||||
) -> BTreeMap<ZoneId, LedgerUpdateWitness> {
|
||||
let mut updates: BTreeMap<ZoneId, LedgerUpdateWitness> = Default::default();
|
||||
|
||||
assert_eq!(self.inputs.len(), self.frontier_paths.len());
|
||||
for (input, (mmr, path)) in inputs.iter().zip(&self.frontier_paths) {
|
||||
let entry = updates.entry(input.zone_id).or_insert(LedgerUpdateWitness {
|
||||
zone_id: input.zone_id,
|
||||
inputs: vec![],
|
||||
outputs: vec![],
|
||||
frontier_nodes: mmr.roots.clone(),
|
||||
});
|
||||
entry.inputs.push(input.nf);
|
||||
let entry = 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);
|
||||
@ -138,17 +148,11 @@ impl TxWitness {
|
||||
assert!(output.value > 0);
|
||||
updates
|
||||
.entry(output.zone_id)
|
||||
.or_insert(LedgerUpdateWitness {
|
||||
zone_id: output.zone_id,
|
||||
inputs: vec![],
|
||||
outputs: vec![],
|
||||
frontier_nodes: vec![],
|
||||
})
|
||||
.outputs
|
||||
.push((output.note_commitment(), data.clone())); // TODO: avoid clone
|
||||
.or_default()
|
||||
.add_output(output.note_commitment(), data.clone()); // TODO: avoid clone
|
||||
}
|
||||
|
||||
updates.into_values().collect()
|
||||
updates
|
||||
}
|
||||
|
||||
pub fn mint_amounts(&self) -> Vec<MintAmount> {
|
||||
@ -232,11 +236,15 @@ impl TxWitness {
|
||||
) -> Tx {
|
||||
let mint_burn_root = Self::mint_burn_root(mints, burns);
|
||||
|
||||
let (updates, updates_roots): (Vec<_>, Vec<_>) = self
|
||||
let (updates, updates_roots): (BTreeMap<_, _>, Vec<_>) = self
|
||||
.compute_updates(inputs)
|
||||
.into_iter()
|
||||
.map(LedgerUpdateWitness::commit)
|
||||
.map(|(zone_id, update)| {
|
||||
let (update_cm, update_root) = update.commit();
|
||||
((zone_id, update_cm), merkle::node(zone_id, update_root))
|
||||
})
|
||||
.unzip();
|
||||
|
||||
let update_root = merkle::root(&merkle::padded_leaves(updates_roots));
|
||||
let root = self.root(update_root, mint_burn_root);
|
||||
let balance = self.balance(mints, burns);
|
||||
@ -251,7 +259,7 @@ impl TxWitness {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Bundle {
|
||||
pub updates: Vec<LedgerUpdate>,
|
||||
pub updates: BTreeMap<ZoneId, LedgerUpdate>,
|
||||
pub root: BundleRoot,
|
||||
}
|
||||
|
||||
@ -268,37 +276,25 @@ impl BundleWitness {
|
||||
self.txs.iter().map(|tx| tx.root.0),
|
||||
)));
|
||||
|
||||
let updates = self
|
||||
let mut updates = self
|
||||
.txs
|
||||
.into_iter()
|
||||
.fold(BTreeMap::new(), |mut updates, tx| {
|
||||
for update in tx.updates {
|
||||
let entry = updates.entry(update.zone_id).or_insert(LedgerUpdate {
|
||||
zone_id: update.zone_id,
|
||||
inputs: vec![],
|
||||
outputs: vec![],
|
||||
frontier_nodes: vec![],
|
||||
});
|
||||
|
||||
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
|
||||
})
|
||||
.into_values()
|
||||
.collect::<Vec<_>>();
|
||||
});
|
||||
|
||||
// de-dup frontier nodes
|
||||
let updates = updates
|
||||
.into_iter()
|
||||
.map(|mut update| {
|
||||
update.frontier_nodes.sort();
|
||||
update.frontier_nodes.dedup();
|
||||
update
|
||||
})
|
||||
.collect();
|
||||
updates.iter_mut().for_each(|(_, update)| {
|
||||
update.frontier_nodes.sort();
|
||||
update.frontier_nodes.dedup();
|
||||
});
|
||||
|
||||
Bundle { updates, root }
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
crust::{tx::LedgerUpdate, Bundle, NoteCommitment, Nullifier},
|
||||
crust::{BundleRoot, NoteCommitment, Nullifier},
|
||||
ds::{
|
||||
indexed::{BatchUpdateProof, NullifierTree},
|
||||
mmr::{MMRProof, MMR},
|
||||
@ -38,8 +38,8 @@ impl LedgerWitness {
|
||||
self.commitments.push(&cm.0);
|
||||
}
|
||||
|
||||
pub fn add_bundle(&mut self, bundle_root: [u8; 32]) {
|
||||
self.bundles.push(&bundle_root);
|
||||
pub fn add_bundle(&mut self, bundle_root: BundleRoot) {
|
||||
self.bundles.push(&bundle_root.0);
|
||||
}
|
||||
|
||||
pub fn assert_nfs_update(&mut self, nullifiers: &[Nullifier], proof: &BatchUpdateProof) {
|
||||
@ -77,8 +77,8 @@ impl LedgerState {
|
||||
self.nullifiers.insert_batch(nfs)
|
||||
}
|
||||
|
||||
pub fn add_bundle(&mut self, bundle_root: [u8; 32]) -> (MMR, MMRProof) {
|
||||
let proof = self.bundles.push(&bundle_root);
|
||||
pub fn add_bundle(&mut self, bundle_root: BundleRoot) -> (MMR, MMRProof) {
|
||||
let proof = self.bundles.push(&bundle_root.0);
|
||||
(self.bundles.clone(), proof)
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,8 +25,7 @@ impl ProvedLedgerTransition {
|
||||
|
||||
let zone_ledger_update = bundle
|
||||
.updates
|
||||
.iter()
|
||||
.find(|update| update.zone_id == zone_id)
|
||||
.get(&zone_id)
|
||||
.expect("why are we proving this bundle for this zone if it's not involved?");
|
||||
|
||||
let cm_root_proofs =
|
||||
@ -45,7 +44,7 @@ impl ProvedLedgerTransition {
|
||||
cm_root_proofs,
|
||||
};
|
||||
|
||||
w_bundles.push(ledger_bundle)
|
||||
w_bundles.push(ledger_bundle);
|
||||
}
|
||||
|
||||
let witness = LedgerProofPrivate {
|
||||
@ -56,13 +55,17 @@ impl ProvedLedgerTransition {
|
||||
};
|
||||
|
||||
for bundle in &witness.bundles {
|
||||
for update in &bundle.bundle.updates {
|
||||
if update.zone_id == zone_id {
|
||||
for cm in &update.outputs {
|
||||
ledger.add_commitment(cm);
|
||||
}
|
||||
}
|
||||
let update = bundle
|
||||
.bundle
|
||||
.updates
|
||||
.get(&zone_id)
|
||||
.expect("should have a bundle from the zone we are proofing for");
|
||||
|
||||
for cm in &update.outputs {
|
||||
ledger.add_commitment(cm);
|
||||
}
|
||||
|
||||
ledger.add_bundle(bundle.bundle.root);
|
||||
}
|
||||
|
||||
witness.write(&mut env);
|
||||
|
||||
@ -45,15 +45,10 @@ impl ProvedBatchUpdate {
|
||||
.zip(self.stf_proofs.iter())
|
||||
.zip(self.ledger_proofs.iter())
|
||||
{
|
||||
if ledger_proof.public().old_ledger != update.old.ledger
|
||||
|| ledger_proof.public().ledger != update.new.ledger
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if stf_proof.public.old != update.old || stf_proof.public.new != update.new {
|
||||
return false;
|
||||
}
|
||||
assert_eq!(ledger_proof.public().old_ledger, update.old.ledger);
|
||||
assert_eq!(ledger_proof.public().ledger, update.new.ledger);
|
||||
assert_eq!(stf_proof.public.old, update.old);
|
||||
assert_eq!(stf_proof.public.new, update.new);
|
||||
}
|
||||
|
||||
true
|
||||
|
||||
@ -29,38 +29,37 @@ fn main() {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let zones = Vec::from_iter(bundle.updates.iter().map(|update| update.zone_id));
|
||||
if !(zones.len() == 1 && zones[0] == id) {
|
||||
if bundle.updates.len() > 1 {
|
||||
// This is a cross zone bundle, add a sync log for it to ensure all zones
|
||||
// also approve it.
|
||||
sync_logs.push(SyncLog {
|
||||
bundle: bundle.root,
|
||||
zones,
|
||||
zones: bundle.updates.keys().copied().collect(),
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(ledger_update) = bundle
|
||||
let ledger_update = bundle
|
||||
.updates
|
||||
.into_iter()
|
||||
.find(|update| update.zone_id == id)
|
||||
{
|
||||
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))
|
||||
}
|
||||
.get(&id)
|
||||
.expect("attempting to prove a bundle that is not for this zone");
|
||||
|
||||
for cm in &ledger_update.outputs {
|
||||
ledger.add_commitment(cm);
|
||||
outputs.push(*cm);
|
||||
}
|
||||
for node in &ledger_update.frontier_nodes {
|
||||
let past_cm_root_proof = cm_root_proofs
|
||||
.get(&node.root)
|
||||
.expect("missing cm root proof");
|
||||
|
||||
nullifiers.extend(ledger_update.inputs);
|
||||
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.add_bundle(bundle.root.0);
|
||||
for cm in &ledger_update.outputs {
|
||||
ledger.add_commitment(cm);
|
||||
outputs.push(*cm);
|
||||
}
|
||||
|
||||
nullifiers.extend(ledger_update.inputs.clone());
|
||||
|
||||
ledger.add_bundle(bundle.root);
|
||||
}
|
||||
|
||||
// TODO: sort outside and check
|
||||
|
||||
Binary file not shown.
@ -1 +1 @@
|
||||
d6149899df54b0114942f4be1ec773ba771d7f6a9d4201c31a4d75038455eaf3
|
||||
8ad828fccc168801663aea5e10c8d17019f0bdbb69fa1a169400603535880fcd
|
||||
Binary file not shown.
@ -1 +1 @@
|
||||
02ed858ba11b19067319841ec824903318526d6c87c3dd1b0ac2330783d7078e
|
||||
fef663705ca009bdaa893c842d084848ddfbbf737441a801b6778125a3a5493c
|
||||
Binary file not shown.
@ -1 +1 @@
|
||||
400ac4e7c9cc351b84227e090e474c299546cce1db2f6836a8fc22b25aa4a317
|
||||
29a96bc98531b44e806051daff1be35fe84e00f4cd7f45de0213c1387184c12e
|
||||
Binary file not shown.
@ -1 +1 @@
|
||||
ec8a16b24c6ba20fe44b3758bed22da59fe7012d2dd8e5b184c1d17f7f8d2c1f
|
||||
68a7c458b6ff62901c0176a1ff9433e431d635a3a94b169af7227ac5b1681606
|
||||
Loading…
x
Reference in New Issue
Block a user