mirror of
https://github.com/logos-blockchain/logos-blockchain-pocs.git
synced 2026-01-08 16:13:07 +00:00
Address review comments
This commit is contained in:
parent
a4f9e182c4
commit
dbdf335aac
@ -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);
|
||||
|
||||
9
goas/cl/proof_statements/src/death_constraint.rs
Normal file
9
goas/cl/proof_statements/src/death_constraint.rs
Normal 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,
|
||||
}
|
||||
@ -1 +1,3 @@
|
||||
pub mod death_constraint;
|
||||
pub mod input;
|
||||
pub mod ptx;
|
||||
|
||||
35
goas/cl/proof_statements/src/ptx.rs
Normal file
35
goas/cl/proof_statements/src/ptx.rs
Normal 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))
|
||||
}
|
||||
}
|
||||
@ -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]
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -5,4 +5,5 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
cl = { path = "../../cl/cl" }
|
||||
proof_statements = { path = "../../cl/proof_statements" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
||||
@ -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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "nomos_cl_risc0_proofs"
|
||||
name = "goas_risc0_proofs"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
|
||||
@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user