remove limitation of single ptx origin
This commit is contained in:
parent
854fab935b
commit
a0b9b357da
|
@ -1,16 +1,50 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::cl::{partial_tx::PartialTx, BalanceWitness, PartialTxWitness};
|
use crate::{
|
||||||
|
cl::{partial_tx::PartialTx, BalanceWitness, PartialTxWitness},
|
||||||
|
zone_layer::notes::ZoneId,
|
||||||
|
};
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
/// The transaction bundle is a collection of partial transactions.
|
/// The transaction bundle is a collection of partial transactions.
|
||||||
/// The goal in bundling transactions is to produce a set of partial transactions
|
/// The goal in bundling transactions is to produce a set of partial transactions
|
||||||
/// that balance each other.
|
/// that balance each other.
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
|
pub struct BundleId(pub [u8; 32]);
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Bundle {
|
pub struct Bundle {
|
||||||
pub partials: Vec<PartialTx>,
|
pub partials: Vec<PartialTx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Bundle {
|
||||||
|
pub fn zones(&self) -> HashSet<ZoneId> {
|
||||||
|
self.partials
|
||||||
|
.iter()
|
||||||
|
.flat_map(|ptx| {
|
||||||
|
ptx.inputs
|
||||||
|
.iter()
|
||||||
|
.map(|i| i.zone_id)
|
||||||
|
.chain(ptx.outputs.iter().map(|o| o.zone_id))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pub fn id(&self) -> BundleId {
|
||||||
|
// TODO: change to merkle root
|
||||||
|
let mut hasher = Sha256::new();
|
||||||
|
hasher.update(b"NOMOS_CL_BUNDLE_ID");
|
||||||
|
for ptx in &self.partials {
|
||||||
|
hasher.update(&ptx.root().0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BundleId(hasher.finalize().into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct BundleWitness {
|
pub struct BundleWitness {
|
||||||
pub partials: Vec<PartialTxWitness>,
|
pub partials: Vec<PartialTxWitness>,
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
use crate::error::{Error, Result};
|
use crate::error::{Error, Result};
|
||||||
use cl::cl::BundleWitness;
|
use cl::cl::BundleWitness;
|
||||||
use ledger_proof_statements::bundle::{BundlePrivate, BundlePublic};
|
use ledger_proof_statements::balance::{BalancePrivate, BalancePublic};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ProvedBundle {
|
pub struct ProvedBalance {
|
||||||
pub bundle: BundlePublic,
|
pub bundle: BalancePublic,
|
||||||
pub risc0_receipt: risc0_zkvm::Receipt,
|
pub risc0_receipt: risc0_zkvm::Receipt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProvedBundle {
|
impl ProvedBalance {
|
||||||
pub fn prove(bundle_witness: &BundleWitness) -> Result<Self> {
|
pub fn prove(bundle_witness: &BundleWitness) -> Result<Self> {
|
||||||
// need to show that bundle is balanced.
|
// need to show that bundle is balanced.
|
||||||
// i.e. the sum of ptx balances is 0
|
// i.e. the sum of ptx balances is 0
|
||||||
|
|
||||||
let bundle_private = BundlePrivate {
|
let bundle_private = BalancePrivate {
|
||||||
balances: bundle_witness
|
balances: bundle_witness
|
||||||
.partials
|
.partials
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -33,7 +33,7 @@ impl ProvedBundle {
|
||||||
|
|
||||||
let opts = risc0_zkvm::ProverOpts::succinct();
|
let opts = risc0_zkvm::ProverOpts::succinct();
|
||||||
let prove_info = prover
|
let prove_info = prover
|
||||||
.prove_with_opts(env, nomos_cl_risc0_proofs::BUNDLE_ELF, &opts)
|
.prove_with_opts(env, nomos_cl_risc0_proofs::BALANCE_ELF, &opts)
|
||||||
.map_err(|_| Error::Risc0ProofFailed)?;
|
.map_err(|_| Error::Risc0ProofFailed)?;
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
|
@ -50,7 +50,7 @@ impl ProvedBundle {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn public(&self) -> Result<ledger_proof_statements::bundle::BundlePublic> {
|
pub fn public(&self) -> Result<ledger_proof_statements::balance::BalancePublic> {
|
||||||
Ok(self.risc0_receipt.journal.decode()?)
|
Ok(self.risc0_receipt.journal.decode()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ impl ProvedBundle {
|
||||||
// Vec::from_iter(self.bundle.partials.iter().map(|ptx| ptx.balance)) == bundle_public.balances
|
// Vec::from_iter(self.bundle.partials.iter().map(|ptx| ptx.balance)) == bundle_public.balances
|
||||||
// &&
|
// &&
|
||||||
self.risc0_receipt
|
self.risc0_receipt
|
||||||
.verify(nomos_cl_risc0_proofs::BUNDLE_ID)
|
.verify(nomos_cl_risc0_proofs::BALANCE_ID)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@ use ledger_proof_statements::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bundle::ProvedBundle,
|
balance::ProvedBalance,
|
||||||
constraint::ConstraintProof,
|
constraint::ConstraintProof,
|
||||||
error::{Error, Result},
|
error::{Error, Result},
|
||||||
partial_tx::ProvedPartialTx,
|
partial_tx::ProvedPartialTx,
|
||||||
|
@ -19,14 +19,14 @@ pub struct ProvedLedgerTransition {
|
||||||
|
|
||||||
// TODO: find a better name
|
// TODO: find a better name
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ProvedZoneTx {
|
pub struct ProvedBundle {
|
||||||
pub bundle: ProvedBundle,
|
pub bundle: ProvedBalance,
|
||||||
pub ptxs: Vec<ProvedPartialTx>,
|
pub ptxs: Vec<ProvedPartialTx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProvedZoneTx {
|
impl ProvedBundle {
|
||||||
fn to_public(&self) -> Vec<PtxPublic> {
|
fn to_public(&self) -> Vec<PtxPublic> {
|
||||||
self.ptxs.iter().map(|p| p.public().unwrap()).collect()
|
self.ptxs.iter().map(|p| p.public.clone()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn proofs(&self) -> Vec<risc0_zkvm::Receipt> {
|
fn proofs(&self) -> Vec<risc0_zkvm::Receipt> {
|
||||||
|
@ -40,19 +40,19 @@ impl ProvedLedgerTransition {
|
||||||
pub fn prove(
|
pub fn prove(
|
||||||
ledger: LedgerWitness,
|
ledger: LedgerWitness,
|
||||||
zone_id: ZoneId,
|
zone_id: ZoneId,
|
||||||
ptxs: Vec<ProvedZoneTx>,
|
bundles: Vec<ProvedBundle>,
|
||||||
constraints: Vec<ConstraintProof>,
|
constraints: Vec<ConstraintProof>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let witness = LedgerProofPrivate {
|
let witness = LedgerProofPrivate {
|
||||||
bundles: ptxs.iter().map(|p| p.to_public()).collect(),
|
bundles: bundles.iter().map(|p| p.to_public()).collect(),
|
||||||
ledger,
|
ledger,
|
||||||
id: zone_id,
|
id: zone_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut env = risc0_zkvm::ExecutorEnv::builder();
|
let mut env = risc0_zkvm::ExecutorEnv::builder();
|
||||||
|
|
||||||
for ptx in ptxs {
|
for bundle in bundles {
|
||||||
for proof in ptx.proofs() {
|
for proof in bundle.proofs() {
|
||||||
env.add_assumption(proof);
|
env.add_assumption(proof);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod bundle;
|
pub mod balance;
|
||||||
pub mod constraint;
|
pub mod constraint;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod ledger;
|
pub mod ledger;
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
use ledger_proof_statements::ptx::{PtxPrivate, PtxPublic};
|
use ledger_proof_statements::ptx::{PtxPrivate, PtxPublic};
|
||||||
|
|
||||||
use crate::error::{Error, Result};
|
use crate::error::{Error, Result};
|
||||||
use cl::cl::{merkle, PartialTx, PartialTxWitness};
|
use cl::cl::{merkle, PartialTxWitness};
|
||||||
use cl::zone_layer::notes::ZoneId;
|
use cl::zone_layer::notes::ZoneId;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ProvedPartialTx {
|
pub struct ProvedPartialTx {
|
||||||
pub ptx: PartialTx,
|
pub public: PtxPublic,
|
||||||
pub cm_root: [u8; 32],
|
|
||||||
pub risc0_receipt: risc0_zkvm::Receipt,
|
pub risc0_receipt: risc0_zkvm::Receipt,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,15 +14,14 @@ impl ProvedPartialTx {
|
||||||
pub fn prove(
|
pub fn prove(
|
||||||
ptx_witness: PartialTxWitness,
|
ptx_witness: PartialTxWitness,
|
||||||
input_cm_paths: Vec<Vec<merkle::PathNode>>,
|
input_cm_paths: Vec<Vec<merkle::PathNode>>,
|
||||||
cm_root: [u8; 32],
|
cm_roots: Vec<[u8; 32]>,
|
||||||
from: Vec<ZoneId>,
|
from: Vec<ZoneId>,
|
||||||
to: Vec<ZoneId>,
|
to: Vec<ZoneId>,
|
||||||
) -> Result<ProvedPartialTx> {
|
) -> Result<ProvedPartialTx> {
|
||||||
let ptx = ptx_witness.commit(&from, &to);
|
|
||||||
let ptx_private = PtxPrivate {
|
let ptx_private = PtxPrivate {
|
||||||
ptx: ptx_witness,
|
ptx: ptx_witness,
|
||||||
input_cm_paths,
|
input_cm_paths,
|
||||||
cm_root,
|
cm_roots: cm_roots.clone(),
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
};
|
};
|
||||||
|
@ -53,28 +51,12 @@ impl ProvedPartialTx {
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
ptx,
|
public: prove_info.receipt.journal.decode()?,
|
||||||
cm_root,
|
|
||||||
risc0_receipt: prove_info.receipt,
|
risc0_receipt: prove_info.receipt,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn public(&self) -> Result<PtxPublic> {
|
|
||||||
Ok(self.risc0_receipt.journal.decode()?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn verify(&self) -> bool {
|
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,
|
|
||||||
};
|
|
||||||
if expected_ptx_inputs != proved_ptx_inputs {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.risc0_receipt
|
self.risc0_receipt
|
||||||
.verify(nomos_cl_risc0_proofs::PTX_ID)
|
.verify(nomos_cl_risc0_proofs::PTX_ID)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
pub use crate::error::{Error, Result};
|
pub use crate::error::{Error, Result};
|
||||||
use crate::{ledger::ProvedLedgerTransition, stf::StfProof};
|
use crate::{ledger::ProvedLedgerTransition, stf::StfProof};
|
||||||
use cl::zone_layer::tx::UpdateBundle;
|
use cl::zone_layer::tx::UpdateBundle;
|
||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
pub struct ProvedUpdateBundle {
|
pub struct ProvedUpdateBundle {
|
||||||
pub bundle: UpdateBundle,
|
pub bundle: UpdateBundle,
|
||||||
|
@ -11,28 +11,31 @@ pub struct ProvedUpdateBundle {
|
||||||
|
|
||||||
impl ProvedUpdateBundle {
|
impl ProvedUpdateBundle {
|
||||||
pub fn verify(&self) -> bool {
|
pub fn verify(&self) -> bool {
|
||||||
let mut consumed_commitments = HashSet::new();
|
let mut expected_zones = HashMap::new();
|
||||||
let mut produced_commitments = HashSet::new();
|
let mut actual_zones = HashMap::new();
|
||||||
for proof in &self.ledger_proofs {
|
for proof in &self.ledger_proofs {
|
||||||
if !proof.verify() {
|
if !proof.verify() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for comm in &proof.public.cross_out {
|
for bundle in &proof.public.cross_bundles {
|
||||||
if produced_commitments.insert(comm) {
|
expected_zones.insert(bundle.id, HashSet::from_iter(bundle.zones.clone()));
|
||||||
// already in?
|
actual_zones
|
||||||
}
|
.entry(bundle.id)
|
||||||
}
|
.or_insert_with(|| HashSet::new())
|
||||||
for comm in &proof.public.cross_in {
|
.insert(proof.public.id);
|
||||||
if consumed_commitments.insert(comm) {
|
|
||||||
// already in?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that cross zone transactions match
|
println!("{:?} | {:?}", expected_zones, actual_zones);
|
||||||
if consumed_commitments != produced_commitments {
|
for (bundle, expected) in expected_zones.iter() {
|
||||||
return false;
|
if let Some(actual) = actual_zones.get(bundle) {
|
||||||
|
if actual != expected {
|
||||||
|
panic!("{:?} | {:?}", actual, expected);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ((update, stf_proof), ledger_proof) in self
|
for ((update, stf_proof), ledger_proof) in self
|
||||||
|
|
|
@ -10,9 +10,9 @@ use cl::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use ledger::{
|
use ledger::{
|
||||||
bundle::ProvedBundle,
|
balance::ProvedBalance,
|
||||||
constraint::ConstraintProof,
|
constraint::ConstraintProof,
|
||||||
ledger::{ProvedLedgerTransition, ProvedZoneTx},
|
ledger::{ProvedBundle, ProvedLedgerTransition},
|
||||||
partial_tx::ProvedPartialTx,
|
partial_tx::ProvedPartialTx,
|
||||||
stf::StfProof,
|
stf::StfProof,
|
||||||
zone_update::ProvedUpdateBundle,
|
zone_update::ProvedUpdateBundle,
|
||||||
|
@ -73,25 +73,25 @@ fn cross_transfer_transition(
|
||||||
let proved_ptx = ProvedPartialTx::prove(
|
let proved_ptx = ProvedPartialTx::prove(
|
||||||
ptx_witness.clone(),
|
ptx_witness.clone(),
|
||||||
vec![ledger_a.cm_path(&input.note_commitment(&zone_a)).unwrap()],
|
vec![ledger_a.cm_path(&input.note_commitment(&zone_a)).unwrap()],
|
||||||
ledger_a.cm_root(),
|
vec![ledger_a.cm_root()],
|
||||||
vec![zone_a],
|
vec![zone_a],
|
||||||
vec![zone_b, zone_a],
|
vec![zone_b, zone_a],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let bundle = ProvedBundle::prove(&BundleWitness {
|
let bundle = ProvedBalance::prove(&BundleWitness {
|
||||||
partials: vec![ptx_witness],
|
partials: vec![ptx_witness],
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let zone_tx = ProvedZoneTx {
|
let zone_tx = ProvedBundle {
|
||||||
ptxs: vec![proved_ptx.clone()],
|
ptxs: vec![proved_ptx.clone()],
|
||||||
bundle,
|
bundle,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Prove the constraints for alices input (she uses the no-op constraint)
|
// Prove the constraints for alices input (she uses the no-op constraint)
|
||||||
let constraint_proof =
|
let constraint_proof =
|
||||||
ConstraintProof::prove_nop(input.nullifier(&zone_a), proved_ptx.ptx.root());
|
ConstraintProof::prove_nop(input.nullifier(&zone_a), proved_ptx.public.ptx.root());
|
||||||
|
|
||||||
let ledger_a_transition = ProvedLedgerTransition::prove(
|
let ledger_a_transition = ProvedLedgerTransition::prove(
|
||||||
ledger_a,
|
ledger_a,
|
||||||
|
|
|
@ -2,11 +2,11 @@ use cl::cl::{Balance, BalanceWitness};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct BundlePublic {
|
pub struct BalancePublic {
|
||||||
pub balances: Vec<Balance>,
|
pub balances: Vec<Balance>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct BundlePrivate {
|
pub struct BalancePrivate {
|
||||||
pub balances: Vec<BalanceWitness>,
|
pub balances: Vec<BalanceWitness>,
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::ptx::PtxPublic;
|
use crate::ptx::PtxPublic;
|
||||||
use cl::cl::Output;
|
use cl::cl::{bundle::BundleId, Output};
|
||||||
use cl::zone_layer::{
|
use cl::zone_layer::{
|
||||||
ledger::{Ledger, LedgerWitness},
|
ledger::{Ledger, LedgerWitness},
|
||||||
notes::ZoneId,
|
notes::ZoneId,
|
||||||
|
@ -11,8 +11,8 @@ pub struct LedgerProofPublic {
|
||||||
pub old_ledger: Ledger,
|
pub old_ledger: Ledger,
|
||||||
pub ledger: Ledger,
|
pub ledger: Ledger,
|
||||||
pub id: ZoneId,
|
pub id: ZoneId,
|
||||||
pub cross_in: Vec<Output>,
|
pub cross_bundles: Vec<CrossZoneBundle>,
|
||||||
pub cross_out: Vec<Output>,
|
pub outputs: Vec<Output>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
@ -21,3 +21,9 @@ pub struct LedgerProofPrivate {
|
||||||
pub id: ZoneId,
|
pub id: ZoneId,
|
||||||
pub bundles: Vec<Vec<PtxPublic>>,
|
pub bundles: Vec<Vec<PtxPublic>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct CrossZoneBundle {
|
||||||
|
pub id: BundleId,
|
||||||
|
pub zones: Vec<ZoneId>,
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod bundle;
|
pub mod balance;
|
||||||
pub mod constraint;
|
pub mod constraint;
|
||||||
pub mod ledger;
|
pub mod ledger;
|
||||||
pub mod ptx;
|
pub mod ptx;
|
||||||
|
|
|
@ -7,14 +7,14 @@ 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_root: [u8; 32],
|
pub cm_roots: Vec<[u8; 32]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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<Vec<merkle::PathNode>>,
|
||||||
pub cm_root: [u8; 32],
|
pub cm_roots: Vec<[u8; 32]>,
|
||||||
pub from: Vec<ZoneId>,
|
pub from: Vec<ZoneId>,
|
||||||
pub to: Vec<ZoneId>,
|
pub to: Vec<ZoneId>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use cl::{
|
use cl::{
|
||||||
cl::Output,
|
cl::{Bundle, Output},
|
||||||
zone_layer::{ledger::LedgerWitness, notes::ZoneId},
|
zone_layer::{ledger::LedgerWitness, notes::ZoneId},
|
||||||
};
|
};
|
||||||
use ledger_proof_statements::{
|
use ledger_proof_statements::{
|
||||||
bundle::BundlePublic,
|
balance::BalancePublic,
|
||||||
constraint::ConstraintPublic,
|
constraint::ConstraintPublic,
|
||||||
ledger::{LedgerProofPrivate, LedgerProofPublic},
|
ledger::{CrossZoneBundle, LedgerProofPrivate, LedgerProofPublic},
|
||||||
ptx::PtxPublic,
|
ptx::PtxPublic,
|
||||||
};
|
};
|
||||||
use risc0_zkvm::{guest::env, serde};
|
use risc0_zkvm::{guest::env, serde};
|
||||||
|
@ -18,29 +18,37 @@ fn main() {
|
||||||
} = env::read();
|
} = env::read();
|
||||||
|
|
||||||
let old_ledger = ledger.commit();
|
let old_ledger = ledger.commit();
|
||||||
|
let mut cross_bundles = vec![];
|
||||||
|
let mut outputs = vec![];
|
||||||
|
|
||||||
let cm_root = ledger.cm_root();
|
let cm_root = ledger.cm_root();
|
||||||
|
|
||||||
let mut cross_in = vec![];
|
|
||||||
let mut cross_out = vec![];
|
|
||||||
|
|
||||||
for bundle in bundles {
|
for bundle in bundles {
|
||||||
let bundle_public = BundlePublic {
|
let balance_public = BalancePublic {
|
||||||
balances: bundle.iter().map(|ptx| ptx.ptx.balance).collect::<Vec<_>>(),
|
balances: bundle.iter().map(|ptx| ptx.ptx.balance).collect::<Vec<_>>(),
|
||||||
};
|
};
|
||||||
// verify bundle is balanced
|
// verify bundle is balanced
|
||||||
env::verify(
|
env::verify(
|
||||||
nomos_cl_risc0_proofs::BUNDLE_ID,
|
nomos_cl_risc0_proofs::BALANCE_ID,
|
||||||
&serde::to_vec(&bundle_public).unwrap(),
|
&serde::to_vec(&balance_public).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
for ptx in &bundle {
|
for ptx in &bundle {
|
||||||
let (new_ledger, consumed_commitments, produced_commitments) =
|
let (new_ledger, ptx_outputs) = process_ptx(ledger, ptx, id, cm_root);
|
||||||
process_ptx(ledger, ptx, id, cm_root);
|
|
||||||
cross_in.extend(consumed_commitments);
|
|
||||||
cross_out.extend(produced_commitments);
|
|
||||||
ledger = new_ledger;
|
ledger = new_ledger;
|
||||||
|
outputs.extend(ptx_outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
let bundle = Bundle {
|
||||||
|
partials: bundle.into_iter().map(|ptx| ptx.ptx).collect(),
|
||||||
|
};
|
||||||
|
let zones = bundle.zones();
|
||||||
|
if zones.len() > 1 {
|
||||||
|
cross_bundles.push(CrossZoneBundle {
|
||||||
|
id: bundle.id(),
|
||||||
|
zones: zones.into_iter().collect(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,8 +56,8 @@ fn main() {
|
||||||
old_ledger,
|
old_ledger,
|
||||||
ledger: ledger.commit(),
|
ledger: ledger.commit(),
|
||||||
id,
|
id,
|
||||||
cross_in,
|
cross_bundles,
|
||||||
cross_out,
|
outputs,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,21 +66,18 @@ fn process_ptx(
|
||||||
ptx: &PtxPublic,
|
ptx: &PtxPublic,
|
||||||
zone_id: ZoneId,
|
zone_id: ZoneId,
|
||||||
cm_root: [u8; 32],
|
cm_root: [u8; 32],
|
||||||
) -> (LedgerWitness, Vec<Output>, Vec<Output>) {
|
) -> (LedgerWitness, Vec<Output>) {
|
||||||
let mut cross_in = vec![];
|
// always verify the ptx to ensure outputs were derived with the correct zone id
|
||||||
let mut cross_out = vec![];
|
|
||||||
|
|
||||||
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 ptx_cm_root = ptx.cm_root;
|
let cm_roots = &ptx.cm_roots;
|
||||||
let ptx = &ptx.ptx;
|
let ptx = &ptx.ptx;
|
||||||
|
|
||||||
// TODO: accept inputs from multiple zones
|
let mut outputs = vec![];
|
||||||
let check_inputs = ptx.inputs.iter().all(|input| input.zone_id == zone_id);
|
|
||||||
|
|
||||||
if check_inputs {
|
for (input, input_cm_root) in ptx.inputs.iter().zip(cm_roots) {
|
||||||
assert_eq!(ptx_cm_root, cm_root);
|
if input.zone_id == zone_id {
|
||||||
for input in &ptx.inputs {
|
assert_eq!(*input_cm_root, cm_root);
|
||||||
assert!(!ledger.nullifiers.contains(&input.nullifier));
|
assert!(!ledger.nullifiers.contains(&input.nullifier));
|
||||||
ledger.nullifiers.push(input.nullifier);
|
ledger.nullifiers.push(input.nullifier);
|
||||||
|
|
||||||
|
@ -91,17 +96,9 @@ fn process_ptx(
|
||||||
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);
|
ledger.commitments.push(output.note_comm);
|
||||||
// if this output was not originating from this zone, it is a cross zone transaction
|
outputs.push(*output);
|
||||||
if !check_inputs {
|
|
||||||
cross_in.push(*output);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// if this output is not going to this zone but originated from this zone, it is a cross zone transaction
|
|
||||||
if check_inputs {
|
|
||||||
cross_out.push(*output);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(ledger, cross_in, cross_out)
|
(ledger, outputs)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,5 +7,5 @@ edition = "2021"
|
||||||
risc0-build = { version = "1.0" }
|
risc0-build = { version = "1.0" }
|
||||||
|
|
||||||
[package.metadata.risc0]
|
[package.metadata.risc0]
|
||||||
methods = ["bundle", "constraint_nop", "ptx", "stf_nop"]
|
methods = ["balance", "constraint_nop", "ptx", "stf_nop"]
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "bundle"
|
name = "balance"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
|
@ -12,13 +12,13 @@ use cl::cl::BalanceWitness;
|
||||||
use risc0_zkvm::guest::env;
|
use risc0_zkvm::guest::env;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let bundle_private: ledger_proof_statements::bundle::BundlePrivate = env::read();
|
let balance_private: ledger_proof_statements::balance::BalancePrivate = env::read();
|
||||||
|
|
||||||
let bundle_public = ledger_proof_statements::bundle::BundlePublic {
|
let balance_public = ledger_proof_statements::balance::BalancePublic {
|
||||||
balances: Vec::from_iter(bundle_private.balances.iter().map(|b| b.commit())),
|
balances: Vec::from_iter(balance_private.balances.iter().map(|b| b.commit())),
|
||||||
};
|
};
|
||||||
|
|
||||||
assert!(BalanceWitness::combine(bundle_private.balances, [0u8; 16]).is_zero());
|
assert!(BalanceWitness::combine(balance_private.balances, [0u8; 16]).is_zero());
|
||||||
|
|
||||||
env::commit(&bundle_public);
|
env::commit(&balance_public);
|
||||||
}
|
}
|
|
@ -7,16 +7,22 @@ fn main() {
|
||||||
let PtxPrivate {
|
let PtxPrivate {
|
||||||
ptx,
|
ptx,
|
||||||
input_cm_paths,
|
input_cm_paths,
|
||||||
cm_root,
|
cm_roots,
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
} = env::read();
|
} = env::read();
|
||||||
|
|
||||||
assert_eq!(ptx.inputs.len(), input_cm_paths.len());
|
assert_eq!(ptx.inputs.len(), input_cm_paths.len());
|
||||||
for ((input, cm_path), zone_id) in ptx.inputs.iter().zip(input_cm_paths).zip(&from) {
|
for (((input, cm_path), zone_id), cm_root) in ptx
|
||||||
|
.inputs
|
||||||
|
.iter()
|
||||||
|
.zip(input_cm_paths)
|
||||||
|
.zip(&from)
|
||||||
|
.zip(&cm_roots)
|
||||||
|
{
|
||||||
let note_cm = input.note_commitment(zone_id);
|
let note_cm = input.note_commitment(zone_id);
|
||||||
let cm_leaf = merkle::leaf(note_cm.as_bytes());
|
let cm_leaf = merkle::leaf(note_cm.as_bytes());
|
||||||
assert_eq!(cm_root, merkle::path_root(cm_leaf, &cm_path));
|
assert_eq!(*cm_root, merkle::path_root(cm_leaf, &cm_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
for output in ptx.outputs.iter() {
|
for output in ptx.outputs.iter() {
|
||||||
|
@ -25,6 +31,6 @@ fn main() {
|
||||||
|
|
||||||
env::commit(&PtxPublic {
|
env::commit(&PtxPublic {
|
||||||
ptx: ptx.commit(&from, &to),
|
ptx: ptx.commit(&from, &to),
|
||||||
cm_root,
|
cm_roots,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue