add zone layer txs

This commit is contained in:
Giacomo Pasini 2024-11-20 18:19:36 +01:00
parent afd9bafb79
commit a940705b01
No known key found for this signature in database
GPG Key ID: FC08489D2D895D4B
15 changed files with 259 additions and 91 deletions

View File

@ -6,7 +6,7 @@ use crate::cl::{
NullifierSecret,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize)]
pub struct Output {
pub note_comm: NoteCommitment,
}

View File

@ -1,5 +1,5 @@
use crate::zone_layer::ZoneId;
use crate::cl::{PartialTx, PartialTxWitness};
use crate::zone_layer::notes::ZoneId;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]

View File

@ -0,0 +1,55 @@
use crate::cl::{merkle, NoteCommitment, Nullifier};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct Ledger {
cm_root: [u8; 32],
nf_root: [u8; 32],
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct LedgerWitness {
pub commitments: Vec<NoteCommitment>,
pub nullifiers: Vec<Nullifier>,
}
const MAX_COMM: usize = 256;
const MAX_NULL: usize = 256;
impl LedgerWitness {
pub fn commit(&self) -> Ledger {
Ledger {
cm_root: self.cm_root(),
nf_root: self.nf_root(),
}
}
pub fn nf_root(&self) -> [u8; 32] {
let bytes = self
.nullifiers
.iter()
.map(|i| i.as_bytes().to_vec())
.collect::<Vec<_>>();
merkle::root(merkle::padded_leaves::<MAX_NULL>(&bytes))
}
pub fn cm_root(&self) -> [u8; 32] {
let bytes = self
.commitments
.iter()
.map(|i| i.as_bytes().to_vec())
.collect::<Vec<_>>();
merkle::root(merkle::padded_leaves::<MAX_COMM>(&bytes))
}
pub fn cm_path(&self, cm: &NoteCommitment) -> Option<Vec<merkle::PathNode>> {
let bytes = self
.commitments
.iter()
.map(|i| i.as_bytes().to_vec())
.collect::<Vec<_>>();
let leaves = merkle::padded_leaves::<MAX_COMM>(&bytes);
let idx = self.commitments.iter().position(|c| c == cm)?;
Some(merkle::path(leaves, idx))
}
}

View File

@ -1,66 +1,3 @@
use crate::cl::{merkle, Constraint, NoteCommitment, Nullifier};
use serde::{Deserialize, Serialize};
pub struct ZoneNote {
pub stf: Constraint,
pub state: State,
pub ledger: Ledger,
pub id: [u8; 32],
}
pub type State = [u8; 32];
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Ledger {
cm_root: [u8; 32],
nf_root: [u8; 32],
}
pub type ZoneId = [u8; 32];
pub struct StateWitness;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct LedgerWitness {
pub commitments: Vec<NoteCommitment>,
pub nullifiers: Vec<Nullifier>,
}
const MAX_COMM: usize = 256;
const MAX_NULL: usize = 256;
impl LedgerWitness {
pub fn commit(&self) -> Ledger {
Ledger {
cm_root: self.cm_root(),
nf_root: self.nf_root(),
}
}
pub fn nf_root(&self) -> [u8; 32] {
let bytes = self
.nullifiers
.iter()
.map(|i| i.as_bytes().to_vec())
.collect::<Vec<_>>();
merkle::root(merkle::padded_leaves::<MAX_NULL>(&bytes))
}
pub fn cm_root(&self) -> [u8; 32] {
let bytes = self
.commitments
.iter()
.map(|i| i.as_bytes().to_vec())
.collect::<Vec<_>>();
merkle::root(merkle::padded_leaves::<MAX_COMM>(&bytes))
}
pub fn cm_path(&self, cm: &NoteCommitment) -> Option<Vec<merkle::PathNode>> {
let bytes = self
.commitments
.iter()
.map(|i| i.as_bytes().to_vec())
.collect::<Vec<_>>();
let leaves = merkle::padded_leaves::<MAX_COMM>(&bytes);
let idx = self.commitments.iter().position(|c| c == cm)?;
Some(merkle::path(leaves, idx))
}
}
pub mod ledger;
pub mod notes;
pub mod tx;

View File

@ -0,0 +1,14 @@
use super::ledger::Ledger;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct ZoneNote {
pub stf: Stf,
pub state: State,
pub ledger: Ledger,
pub id: [u8; 32],
}
pub type Stf = [u8; 32];
pub type ZoneId = [u8; 32];
pub type State = [u8; 32];

View File

@ -0,0 +1,24 @@
use super::notes::ZoneNote;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UpdateBundle {
pub updates: Vec<ZoneUpdate>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ZoneUpdate {
pub old: ZoneNote,
pub new: ZoneNote,
}
impl ZoneUpdate {
pub fn new(old: ZoneNote, new: ZoneNote) -> Self {
assert_eq!(old.id, new.id);
Self { old, new }
}
pub fn well_formed(&self) -> bool {
self.old.id == self.new.id
}
}

View File

@ -7,7 +7,7 @@ use crate::{
pact::ProvedPact,
partial_tx::ProvedPartialTx,
};
use cl::zone_layer::{LedgerWitness, ZoneId};
use cl::zone_layer::{ledger::LedgerWitness, notes::ZoneId};
pub struct ProvedLedgerTransition {
pub public: LedgerProofPublic,
@ -101,26 +101,7 @@ impl ProvedLedgerTransition {
})
}
pub fn public(&self) -> Result<LedgerProofPublic> {
Ok(self.risc0_receipt.journal.decode()?)
}
pub fn verify(&self) -> bool {
// let Ok(proved_ptx_inputs) = self.public() else {
// return false;
// };
// let expected_ptx_inputs = PtxPublic {
// ptx: self.ptx.clone(),
// cm_root: self.cm_root,
// from: self.from,
// to: self.to,
// };
// if expected_ptx_inputs != proved_ptx_inputs {
// return false;
// }
// let ptx_root = self.ptx.root();
self.risc0_receipt
.verify(ledger_validity_proof::LEDGER_ID)
.is_ok()

View File

@ -4,5 +4,7 @@ pub mod error;
pub mod ledger;
pub mod pact;
pub mod partial_tx;
pub mod stf;
pub mod zone_update;
pub use constraint::ConstraintProof;

View File

@ -2,7 +2,7 @@ use ledger_proof_statements::ptx::{PtxPrivate, PtxPublic};
use crate::error::{Error, Result};
use cl::cl::{merkle, PartialTx, PartialTxWitness};
use cl::zone_layer::ZoneId;
use cl::zone_layer::notes::ZoneId;
pub struct ProvedPartialTx {
pub ptx: PartialTx,

View File

@ -0,0 +1,33 @@
use cl::zone_layer::notes::Stf;
use ledger_proof_statements::stf::StfPublic;
#[derive(Debug, Clone)]
pub struct StfProof {
pub risc0_id: [u32; 8],
pub public: StfPublic,
pub risc0_receipt: risc0_zkvm::Receipt,
}
pub fn risc0_constraint(risc0_id: [u32; 8]) -> Stf {
// TODO: hash
unsafe { core::mem::transmute::<[u32; 8], [u8; 32]>(risc0_id) }
}
impl StfProof {
pub fn from_risc0(risc0_id: [u32; 8], risc0_receipt: risc0_zkvm::Receipt) -> Self {
Self {
risc0_id,
public: risc0_receipt.journal.decode().unwrap(),
risc0_receipt,
}
}
pub fn stf(&self) -> Stf {
risc0_constraint(self.risc0_id)
}
pub fn verify(&self) -> bool {
self.risc0_receipt.verify(self.risc0_id).is_ok()
}
}

View File

@ -0,0 +1,103 @@
pub use crate::error::{Error, Result};
use crate::{ledger::ProvedLedgerTransition, stf::StfProof};
use cl::zone_layer::tx::UpdateBundle;
use std::collections::HashSet;
pub struct ProvedUpdateBundle {
pub bundle: UpdateBundle,
pub ledger_proofs: Vec<ProvedLedgerTransition>,
pub stf_proofs: Vec<StfProof>,
}
impl ProvedUpdateBundle {
// pub fn prove(bundle_witness: &BundleWitness) -> Result<Self> {
// // need to show that bundle is balanced.
// // i.e. the sum of ptx balances is 0
// let bundle_private = BundlePrivate {
// balances: bundle_witness
// .partials
// .iter()
// .map(|ptx| ptx.balance())
// .collect(),
// };
// let env = risc0_zkvm::ExecutorEnv::builder()
// .write(&bundle_private)
// .unwrap()
// .build()
// .unwrap();
// let prover = risc0_zkvm::default_prover();
// let start_t = std::time::Instant::now();
// let opts = risc0_zkvm::ProverOpts::succinct();
// let prove_info = prover
// .prove_with_opts(env, nomos_cl_risc0_proofs::BUNDLE_ELF, &opts)
// .map_err(|_| Error::Risc0ProofFailed)?;
// println!(
// "STARK 'bundle' prover time: {:.2?}, total_cycles: {}",
// start_t.elapsed(),
// prove_info.stats.total_cycles
// );
// let receipt = prove_info.receipt;
// Ok(Self {
// bundle: receipt.journal.decode()?,
// risc0_receipt: receipt,
// })
// }
pub fn verify(&self) -> bool {
let mut consumed_commitments = HashSet::new();
let mut produced_commitments = HashSet::new();
for proof in &self.ledger_proofs {
if !proof.verify() {
return false;
}
for comm in &proof.public.cross_out {
if produced_commitments.insert(comm) {
// already in?
}
}
for comm in &proof.public.cross_in {
if consumed_commitments.insert(comm) {
// already in?
}
}
}
// check that cross zone transactions match
if consumed_commitments != produced_commitments {
return false;
}
for ((update, stf_proof), ledger_proof) in self
.bundle
.updates
.iter()
.zip(self.stf_proofs.iter())
.zip(self.ledger_proofs.iter())
{
if !update.well_formed() {
return false;
}
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;
}
}
true
}
}

View File

@ -2,11 +2,15 @@ use crate::bundle::BundlePublic;
use crate::pact::PactPublic;
use crate::ptx::PtxPublic;
use cl::cl::Output;
use cl::zone_layer::*;
use cl::zone_layer::{
ledger::{Ledger, LedgerWitness},
notes::ZoneId,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct LedgerProofPublic {
pub old_ledger: Ledger,
pub ledger: Ledger,
pub id: ZoneId,
pub cross_in: Vec<Output>,

View File

@ -3,3 +3,4 @@ pub mod constraint;
pub mod ledger;
pub mod pact;
pub mod ptx;
pub mod stf;

View File

@ -0,0 +1,8 @@
use cl::zone_layer::notes::ZoneNote;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct StfPublic {
pub old: ZoneNote,
pub new: ZoneNote,
}

View File

@ -1,4 +1,7 @@
use cl::{zones::*, Output};
use cl::{
cl::Output,
zone_layer::{ledger::LedgerWitness, notes::ZoneId},
};
use ledger_proof_statements::{bundle::*, constraint::*, ledger::*, pact::PactPublic, ptx::*};
use risc0_zkvm::{guest::env, serde};
@ -9,6 +12,8 @@ fn main() {
txs,
} = env::read();
let old_ledger = ledger.commit();
let cm_root = ledger.cm_root();
let mut cross_in = vec![];
@ -30,6 +35,7 @@ fn main() {
}
env::commit(&LedgerProofPublic {
old_ledger,
ledger: ledger.commit(),
id,
cross_in,