wip: integrating new ledger into proofs

This commit is contained in:
David Rusu 2024-12-06 12:58:00 +04:00
parent 53aa3b75c0
commit aa57295f4b
7 changed files with 56 additions and 41 deletions

View File

@ -43,6 +43,8 @@ pub fn root<const N: usize>(elements: [[u8; 32]; N]) -> [u8; 32] {
nodes[0] nodes[0]
} }
pub type Path = Vec<PathNode>;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum PathNode { pub enum PathNode {
Left([u8; 32]), Left([u8; 32]),
@ -66,7 +68,7 @@ pub fn path_root(leaf: [u8; 32], path: &[PathNode]) -> [u8; 32] {
computed_hash computed_hash
} }
pub fn path<const N: usize>(leaves: [[u8; 32]; N], idx: usize) -> Vec<PathNode> { pub fn path<const N: usize>(leaves: [[u8; 32]; N], idx: usize) -> Path {
assert!(N.is_power_of_two()); assert!(N.is_power_of_two());
assert!(idx < N); assert!(idx < N);

View File

@ -9,6 +9,7 @@ pub mod note;
pub mod nullifier; pub mod nullifier;
pub mod output; pub mod output;
pub mod partial_tx; pub mod partial_tx;
pub mod sparse_merkle;
pub use balance::{Balance, BalanceWitness}; pub use balance::{Balance, BalanceWitness};
pub use bundle::Bundle; pub use bundle::Bundle;

View File

@ -3,12 +3,10 @@ use std::collections::BTreeSet;
use crate::cl::{ use crate::cl::{
merkle, merkle,
mmr::{MMRProof, MMR}, mmr::{MMRProof, MMR},
NoteCommitment, Nullifier, sparse_merkle, NoteCommitment, Nullifier,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::sparse_merkle_tree;
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct Ledger { pub struct Ledger {
cm_root: [u8; 32], cm_root: [u8; 32],
@ -31,16 +29,13 @@ impl LedgerWitness {
pub fn assert_nf_update(&mut self, nf: Nullifier, path: &[merkle::PathNode]) { pub fn assert_nf_update(&mut self, nf: Nullifier, path: &[merkle::PathNode]) {
// verify that the path corresponds to the nullifier // verify that the path corresponds to the nullifier
assert_eq!(sparse_merkle_tree::path_key(path), nf.0); assert_eq!(sparse_merkle::path_key(path), nf.0);
// verify that the nullifier was not already present // verify that the nullifier was not already present
assert_eq!( assert_eq!(merkle::path_root(sparse_merkle::ABSENT, path), self.nf_root);
merkle::path_root(sparse_merkle_tree::ABSENT, path),
self.nf_root
);
// update the nullifer root with the nullifier inserted into the tree // update the nullifer root with the nullifier inserted into the tree
self.nf_root = merkle::path_root(sparse_merkle_tree::PRESENT, path); self.nf_root = merkle::path_root(sparse_merkle::PRESENT, path);
} }
} }
@ -58,7 +53,7 @@ impl LedgerState {
} }
pub fn nf_root(&self) -> [u8; 32] { pub fn nf_root(&self) -> [u8; 32] {
sparse_merkle_tree::sparse_root(&self.nullifiers) sparse_merkle::sparse_root(&self.nullifiers)
} }
pub fn add_commitment(&mut self, cm: NoteCommitment) -> MMRProof { pub fn add_commitment(&mut self, cm: NoteCommitment) -> MMRProof {
@ -66,7 +61,7 @@ impl LedgerState {
} }
pub fn add_nullifier(&mut self, nf: Nullifier) -> Vec<merkle::PathNode> { pub fn add_nullifier(&mut self, nf: Nullifier) -> Vec<merkle::PathNode> {
let path = sparse_merkle_tree::sparse_path(nf.0, &self.nullifiers); let path = sparse_merkle::sparse_path(nf.0, &self.nullifiers);
assert!(!self.nullifiers.contains(&nf.0)); assert!(!self.nullifiers.contains(&nf.0));
self.nullifiers.insert(nf.0); self.nullifiers.insert(nf.0);

View File

@ -1,4 +1,3 @@
pub mod ledger; pub mod ledger;
pub mod notes; pub mod notes;
pub mod sparse_merkle_tree;
pub mod tx; pub mod tx;

View File

@ -1,4 +1,5 @@
use crate::ptx::PtxPublic; use crate::ptx::PtxPublic;
use cl::cl::merkle;
use cl::cl::{bundle::BundleId, Output}; use cl::cl::{bundle::BundleId, Output};
use cl::zone_layer::{ use cl::zone_layer::{
ledger::{Ledger, LedgerWitness}, ledger::{Ledger, LedgerWitness},
@ -19,7 +20,18 @@ pub struct LedgerProofPublic {
pub struct LedgerProofPrivate { pub struct LedgerProofPrivate {
pub ledger: LedgerWitness, pub ledger: LedgerWitness,
pub id: ZoneId, pub id: ZoneId,
pub bundles: Vec<Vec<PtxPublic>>, pub bundles: Vec<LedgerBundleWitness>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct LedgerBundleWitness {
pub partials: Vec<LedgerPtxWitness>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct LedgerPtxWitness {
pub ptx: PtxPublic,
pub nf_proofs: Vec<merkle::Path>,
} }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]

View File

@ -1,15 +1,19 @@
use cl::cl::{merkle, PartialTx, PartialTxWitness}; use cl::cl::{
merkle,
mmr::{MMRProof, MMR},
PartialTx, PartialTxWitness,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PtxPublic { pub struct PtxPublic {
pub ptx: PartialTx, pub ptx: PartialTx,
pub cm_roots: Vec<[u8; 32]>, pub cm_mmr: MMR,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PtxPrivate { pub struct PtxPrivate {
pub ptx: PartialTxWitness, pub ptx: PartialTxWitness,
pub input_cm_paths: Vec<Vec<merkle::PathNode>>, pub input_cm_paths: Vec<MMRProof>,
pub cm_roots: Vec<[u8; 32]>, pub cm_mmr: MMR,
} }

View File

@ -30,8 +30,9 @@ fn main() {
for bundle in bundles { for bundle in bundles {
let balance_public = BalancePublic { let balance_public = BalancePublic {
balances: bundle.iter().map(|ptx| ptx.ptx.balance).collect::<Vec<_>>(), balances: bundle.partials.iter().map(|bundle_ptx| bundle_ptx.ptx.ptx.balance).collect::<Vec<_>>(),
}; };
// verify bundle is balanced // verify bundle is balanced
env::verify( env::verify(
nomos_cl_risc0_proofs::BALANCE_ID, nomos_cl_risc0_proofs::BALANCE_ID,
@ -68,41 +69,42 @@ fn main() {
fn process_ptx( fn process_ptx(
mut ledger: LedgerWitness, mut ledger: LedgerWitness,
ptx: &PtxPublic, ptx_witness: &LedgerPtxWitness,
zone_id: ZoneId, zone_id: ZoneId,
roots: &[[u8; 32]], roots: &[[u8; 32]],
) -> (LedgerWitness, Vec<Output>) { ) -> (LedgerWitness, Vec<Output>) {
// always verify the ptx to ensure outputs were derived with the correct zone id // 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(); env::verify(nomos_cl_risc0_proofs::PTX_ID, &serde::to_vec(&ptx).unwrap()).unwrap();
let cm_roots = &ptx.cm_roots; PtxWitness { ref ptx, ref nf_proofs } = ptx_witness;
let ptx = &ptx.ptx;
let mut outputs = vec![]; assert_eq!(ptx.cm_mmr, roots); // we force commitment proofs w.r.t. latest MMR
assert_eq!(ptx.ptx.inputs.len(), nf_proofs.len());
for (input, input_cm_root) in ptx.inputs.iter().zip(cm_roots) { for (input, nf_proof) in ptx.ptx.inputs.iter().zip(nf_proofs) {
if input.zone_id == zone_id { if input.zone_id != zone_id {
assert!(roots.contains(input_cm_root)); continue;
assert!(!ledger.nullifiers.contains(&input.nullifier));
ledger.nullifiers.push(input.nullifier);
env::verify(
input.constraint.0,
&serde::to_vec(&ConstraintPublic {
ptx_root: ptx.root(),
nf: input.nullifier,
})
.unwrap(),
)
.unwrap();
} }
ledger.assert_nf_update(input.nullifier, nf_proof);
env::verify(
input.constraint.0,
&serde::to_vec(&ConstraintPublic {
ptx_root: ptx.root(),
nf: input.nullifier,
}).unwrap(),
).unwrap();
} }
let mut outputs = vec![];
for output in &ptx.outputs { for output in &ptx.outputs {
if output.zone_id == zone_id { if output.zone_id != zone_id {
ledger.commitments.push(&output.note_comm.0); continue;
outputs.push(*output);
} }
ledger.commitments.push(&output.note_comm.0);
outputs.push(*output);
} }
(ledger, outputs) (ledger, outputs)