Address review comments

This commit is contained in:
Giacomo Pasini 2024-07-17 17:32:05 +02:00
parent a4f9e182c4
commit dbdf335aac
No known key found for this signature in database
GPG Key ID: FC08489D2D895D4B
11 changed files with 90 additions and 80 deletions

View File

@ -51,8 +51,8 @@ impl InputWitness {
}
impl Input {
pub fn to_bytes(&self) -> [u8; 64] {
let mut bytes = [0u8; 64];
pub fn to_bytes(&self) -> [u8; 96] {
let mut bytes = [0u8; 96];
bytes[..32].copy_from_slice(self.nullifier.as_bytes());
bytes[32..64].copy_from_slice(&self.balance.to_bytes());
bytes[64..96].copy_from_slice(&self.death_cm.0);

View File

@ -0,0 +1,9 @@
use cl::{Nullifier, PtxRoot};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DeathConstraintPublic {
pub cm_root: [u8; 32],
pub nf: Nullifier,
pub ptx_root: PtxRoot,
}

View File

@ -1 +1,3 @@
pub mod death_constraint;
pub mod input;
pub mod ptx;

View File

@ -0,0 +1,35 @@
use cl::{merkle, InputWitness, OutputWitness, PtxRoot};
use serde::{Deserialize, Serialize};
/// An input to a partial transaction
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PartialTxInputPrivate {
pub input: InputWitness,
pub cm_path: Vec<merkle::PathNode>,
pub ptx_path: Vec<merkle::PathNode>,
}
impl PartialTxInputPrivate {
pub fn ptx_root(&self) -> PtxRoot {
let leaf = merkle::leaf(&self.input.commit().to_bytes());
PtxRoot(merkle::path_root(leaf, &self.ptx_path))
}
pub fn cm_root(&self) -> [u8; 32] {
let leaf = merkle::leaf(self.input.to_output_witness().commit_note().as_bytes());
merkle::path_root(leaf, &self.cm_path)
}
}
/// An output to a partial transaction
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PartialTxOutputPrivate {
pub output: OutputWitness,
pub ptx_path: Vec<merkle::PathNode>,
}
impl PartialTxOutputPrivate {
pub fn ptx_root(&self) -> PtxRoot {
let leaf = merkle::leaf(&self.output.commit().to_bytes());
PtxRoot(merkle::path_root(leaf, &self.ptx_path))
}
}

View File

@ -1,6 +1,6 @@
[workspace]
resolver = "2"
members = [ "common","host", "methods"]
members = [ "common","host", "methods", "proof_statements", "risc0_proofs"]
# Always optimize; building and running the guest takes much longer without optimization.
[profile.dev]

View File

@ -12,8 +12,8 @@ fn withdraw(mut state: StateWitness, withdraw: Withdraw) -> StateWitness {
nf,
} = withdraw;
let from = state.balances.entry(from).or_insert(0);
*from = from.checked_sub(amount).unwrap();
let from_balance = state.balances.entry(from).or_insert(0);
*from_balance = from.checked_sub(amount).expect("insufficient funds in account");
let spend_auth = Spend {
amount: amount.into(),
to,

View File

@ -5,4 +5,5 @@ edition = "2021"
[dependencies]
cl = { path = "../../cl/cl" }
proof_statements = { path = "../../cl/proof_statements" }
serde = { version = "1.0", features = ["derive"] }

View File

@ -1,12 +1,6 @@
use proof_statements::{ptx::PartialTxInputPrivate, ptx::PartialTxOutputPrivate};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SpendFundsPublic {
pub cm_root: [u8; 32],
pub nf: cl::Nullifier,
pub ptx_root: cl::PtxRoot,
}
/// An event that authorizes spending zone funds
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct Spend {
@ -32,23 +26,13 @@ impl Spend {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SpendFundsPrivate {
/// The note we're spending
pub in_zone_funds: cl::InputWitness,
/// Path to the ptx root
pub in_zone_funds_ptx_path: Vec<cl::merkle::PathNode>,
/// Path to the root of the merkle tree over the commitment set
pub in_zone_funds_cm_path: Vec<cl::merkle::PathNode>,
pub in_zone_funds_nf_sk: cl::NullifierSecret,
pub in_zone_funds: PartialTxInputPrivate,
/// The zone note that is authorizing the spend
pub zone_note: cl::OutputWitness,
/// Path to the ptx root
pub zone_note_ptx_path: Vec<cl::merkle::PathNode>,
pub zone_note: PartialTxOutputPrivate,
/// The note that is being created to send the change back to the zone
pub out_zone_funds: cl::OutputWitness,
/// Path to the ptx root
pub out_zone_funds_ptx_path: Vec<cl::merkle::PathNode>,
pub out_zone_funds: PartialTxOutputPrivate,
/// The spent funds note
pub spent_note: cl::OutputWitness,
pub spent_note_ptx_path: Vec<cl::merkle::PathNode>,
pub spent_note: PartialTxOutputPrivate,
/// The event emitted by the zone that authorizes the spend
pub spend_event: Spend,
/// Path to the zone output state

View File

@ -1,5 +1,5 @@
[package]
name = "nomos_cl_risc0_proofs"
name = "goas_risc0_proofs"
version = "0.1.0"
edition = "2021"

View File

@ -8,8 +8,9 @@ edition = "2021"
[dependencies]
risc0-zkvm = { version = "1.0", default-features = false, features = ['std'] }
serde = { version = "1.0", features = ["derive"] }
cl = { path = "../../cl" }
proof_statements = { path = "../../proof_statements" }
cl = { path = "../../../cl/cl" }
goas_proof_statements = { path = "../../proof_statements" }
proof_statements = { path = "../../../cl/proof_statements" }
sha2 = "0.10"

View File

@ -3,8 +3,8 @@
/// Our goal: prove the zone authorized spending of funds
use cl::merkle;
use cl::nullifier::{Nullifier, NullifierNonce, NullifierSecret};
use cl::partial_tx::PtxRoot;
use proof_statements::zone_funds::{SpendFundsPrivate, SpendFundsPublic};
use goas_proof_statements::zone_funds::SpendFundsPrivate;
use proof_statements::death_constraint::DeathConstraintPublic;
use risc0_zkvm::guest::env;
use sha2::{Digest, Sha256};
@ -15,97 +15,75 @@ fn main() {
zone_note,
spent_note,
spend_event,
in_zone_funds_ptx_path,
in_zone_funds_cm_path,
out_zone_funds_ptx_path,
zone_note_ptx_path,
spent_note_ptx_path,
spend_event_state_path,
in_zone_funds_nf_sk: _,
} = env::read();
let in_zone_funds_cm = in_zone_funds.commit();
let in_zone_funds_leaf = merkle::leaf(&in_zone_funds_cm.to_bytes());
let cm_root = merkle::path_root(in_zone_funds_leaf, &in_zone_funds_cm_path);
let ptx_root = merkle::path_root(in_zone_funds_leaf, &in_zone_funds_ptx_path);
let in_zone_funds_nf = Nullifier::new(in_zone_funds.nf_sk, in_zone_funds.nonce);
let cm_root = in_zone_funds.cm_root();
let ptx_root = in_zone_funds.ptx_root();
let nf = Nullifier::new(in_zone_funds.input.nf_sk, in_zone_funds.input.nonce);
// check the zone funds note is the one in the spend event
assert_eq!(in_zone_funds_nf, spend_event.nf);
let zone_note_cm = zone_note.commit_note();
let zone_note_leaf = merkle::leaf(zone_note_cm.as_bytes());
assert_eq!(
ptx_root,
merkle::path_root(zone_note_leaf, &zone_note_ptx_path)
);
assert_eq!(nf, spend_event.nf);
assert_eq!(ptx_root, zone_note.ptx_root());
// assert the spent event was an output of the zone stf
let spend_event_leaf = merkle::leaf(&spend_event.to_bytes());
// TODO: zones will have some more state
assert_eq!(
zone_note.note.state,
zone_note.output.note.state,
merkle::path_root(spend_event_leaf, &spend_event_state_path)
);
let out_zone_funds_cm = out_zone_funds.commit_note();
let out_zone_funds_leaf = merkle::leaf(out_zone_funds_cm.as_bytes());
assert_eq!(
ptx_root,
merkle::path_root(out_zone_funds_leaf, &out_zone_funds_ptx_path)
);
assert_eq!(ptx_root, out_zone_funds.ptx_root());
// Check we return the rest of the funds back to the zone
let change = in_zone_funds
.input
.note
.balance
.value
.checked_sub(spend_event.amount)
.unwrap();
assert_eq!(out_zone_funds.note.balance.value, change);
assert_eq!(out_zone_funds.output.note.balance.value, change);
// zone funds output should have the same death constraints as the zone funds input
assert_eq!(
out_zone_funds.note.death_constraint,
in_zone_funds.note.death_constraint
out_zone_funds.output.note.death_constraint,
in_zone_funds.input.note.death_constraint
);
assert_eq!(
out_zone_funds.note.balance.unit,
in_zone_funds.note.balance.unit
out_zone_funds.output.note.balance.unit,
in_zone_funds.input.note.balance.unit
);
// zone funds nullifier, nonce and value blinding should be public so that everybody can spend it
assert_eq!(
out_zone_funds.nf_pk,
out_zone_funds.output.nf_pk,
NullifierSecret::from_bytes([0; 16]).commit()
);
assert_eq!(
out_zone_funds.note.balance.blinding,
in_zone_funds.note.balance.blinding
out_zone_funds.output.note.balance.blinding,
in_zone_funds.input.note.balance.blinding
);
let mut evolved_nonce = [0; 16];
evolved_nonce[..16].copy_from_slice(&Sha256::digest(&out_zone_funds.nonce.as_bytes())[..16]);
evolved_nonce[..16]
.copy_from_slice(&Sha256::digest(&out_zone_funds.output.nonce.as_bytes())[..16]);
assert_eq!(
out_zone_funds.nonce,
out_zone_funds.output.nonce,
NullifierNonce::from_bytes(evolved_nonce)
);
let spent_note_cm = spent_note.commit_note();
let spent_note_leaf = merkle::leaf(spent_note_cm.as_bytes());
assert_eq!(
ptx_root,
merkle::path_root(spent_note_leaf, &spent_note_ptx_path)
);
assert_eq!(ptx_root, spent_note.ptx_root());
// check the correct amount of funds is being spent
assert_eq!(spent_note.note.balance.value, spend_event.amount);
assert_eq!(spent_note.output.note.balance.value, spend_event.amount);
assert_eq!(
spent_note.note.balance.unit,
in_zone_funds.note.balance.unit
spent_note.output.note.balance.unit,
in_zone_funds.input.note.balance.unit
);
// check the correct recipient is being paid
assert_eq!(spent_note.nf_pk, spend_event.to);
assert_eq!(spent_note.output.nf_pk, spend_event.to);
env::commit(&SpendFundsPublic {
env::commit(&DeathConstraintPublic {
cm_root,
ptx_root: PtxRoot::from(ptx_root),
nf: in_zone_funds_nf,
ptx_root,
nf,
});
}