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]
}
pub type Path = Vec<PathNode>;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum PathNode {
Left([u8; 32]),
@ -66,7 +68,7 @@ pub fn path_root(leaf: [u8; 32], path: &[PathNode]) -> [u8; 32] {
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!(idx < N);

View File

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

View File

@ -3,12 +3,10 @@ use std::collections::BTreeSet;
use crate::cl::{
merkle,
mmr::{MMRProof, MMR},
NoteCommitment, Nullifier,
sparse_merkle, NoteCommitment, Nullifier,
};
use serde::{Deserialize, Serialize};
use super::sparse_merkle_tree;
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct Ledger {
cm_root: [u8; 32],
@ -31,16 +29,13 @@ impl LedgerWitness {
pub fn assert_nf_update(&mut self, nf: Nullifier, path: &[merkle::PathNode]) {
// 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
assert_eq!(
merkle::path_root(sparse_merkle_tree::ABSENT, path),
self.nf_root
);
assert_eq!(merkle::path_root(sparse_merkle::ABSENT, path), self.nf_root);
// 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] {
sparse_merkle_tree::sparse_root(&self.nullifiers)
sparse_merkle::sparse_root(&self.nullifiers)
}
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> {
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));
self.nullifiers.insert(nf.0);

View File

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

View File

@ -1,4 +1,5 @@
use crate::ptx::PtxPublic;
use cl::cl::merkle;
use cl::cl::{bundle::BundleId, Output};
use cl::zone_layer::{
ledger::{Ledger, LedgerWitness},
@ -19,7 +20,18 @@ pub struct LedgerProofPublic {
pub struct LedgerProofPrivate {
pub ledger: LedgerWitness,
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)]

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};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PtxPublic {
pub ptx: PartialTx,
pub cm_roots: Vec<[u8; 32]>,
pub cm_mmr: MMR,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PtxPrivate {
pub ptx: PartialTxWitness,
pub input_cm_paths: Vec<Vec<merkle::PathNode>>,
pub cm_roots: Vec<[u8; 32]>,
pub input_cm_paths: Vec<MMRProof>,
pub cm_mmr: MMR,
}

View File

@ -30,8 +30,9 @@ fn main() {
for bundle in bundles {
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
env::verify(
nomos_cl_risc0_proofs::BALANCE_ID,
@ -68,41 +69,42 @@ fn main() {
fn process_ptx(
mut ledger: LedgerWitness,
ptx: &PtxPublic,
ptx_witness: &LedgerPtxWitness,
zone_id: ZoneId,
roots: &[[u8; 32]],
) -> (LedgerWitness, Vec<Output>) {
// 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();
let cm_roots = &ptx.cm_roots;
let ptx = &ptx.ptx;
PtxWitness { ref ptx, ref nf_proofs } = ptx_witness;
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) {
if input.zone_id == zone_id {
assert!(roots.contains(input_cm_root));
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();
for (input, nf_proof) in ptx.ptx.inputs.iter().zip(nf_proofs) {
if input.zone_id != zone_id {
continue;
}
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 {
if output.zone_id == zone_id {
ledger.commitments.push(&output.note_comm.0);
outputs.push(*output);
if output.zone_id != zone_id {
continue;
}
ledger.commitments.push(&output.note_comm.0);
outputs.push(*output);
}
(ledger, outputs)