goas: remove input/output proofs

This commit is contained in:
David Rusu 2024-08-21 00:03:41 +04:00
parent 310932818a
commit edd69d63bd
10 changed files with 1 additions and 398 deletions

View File

@ -1,181 +0,0 @@
use ledger_proof_statements::input::{InputPrivate, InputPublic};
use crate::error::{Error, Result};
const MAX_NOTE_COMMS: usize = 2usize.pow(8);
#[derive(Debug, Clone)]
pub struct ProvedInput {
pub input: InputPublic,
pub risc0_receipt: risc0_zkvm::Receipt,
}
impl ProvedInput {
pub fn prove(
input: &cl::InputWitness,
note_commitments: &[cl::NoteCommitment],
) -> Result<Self> {
let output_cm = input.note_commitment();
let cm_leaves = note_commitment_leaves(note_commitments);
let cm_idx = note_commitments
.iter()
.position(|c| c == &output_cm)
.unwrap();
let cm_path = cl::merkle::path(cm_leaves, cm_idx);
let secrets = InputPrivate {
input: *input,
cm_path,
};
let env = risc0_zkvm::ExecutorEnv::builder()
.write(&secrets)
.unwrap()
.build()
.unwrap();
// Obtain the default prover.
let prover = risc0_zkvm::default_prover();
let start_t = std::time::Instant::now();
// Proof information by proving the specified ELF binary.
// This struct contains the receipt along with statistics about execution of the guest
let opts = risc0_zkvm::ProverOpts::succinct();
let prove_info = prover
.prove_with_opts(env, nomos_cl_risc0_proofs::INPUT_ELF, &opts)
.map_err(|_| Error::Risc0ProofFailed)?;
println!(
"STARK 'input' prover time: {:.2?}, total_cycles: {}",
start_t.elapsed(),
prove_info.stats.total_cycles
);
// extract the receipt.
let receipt = prove_info.receipt;
Ok(Self {
input: InputPublic {
cm_root: cl::merkle::root(cm_leaves),
input: input.commit(),
},
risc0_receipt: receipt,
})
}
pub fn public(&self) -> Result<InputPublic> {
Ok(self.risc0_receipt.journal.decode()?)
}
pub fn verify(&self) -> bool {
let Ok(proved_public_inputs) = self.public() else {
return false;
};
self.input == proved_public_inputs
&& self
.risc0_receipt
.verify(nomos_cl_risc0_proofs::INPUT_ID)
.is_ok()
}
}
fn note_commitment_leaves(note_commitments: &[cl::NoteCommitment]) -> [[u8; 32]; MAX_NOTE_COMMS] {
let note_comm_bytes = Vec::from_iter(note_commitments.iter().map(|c| c.as_bytes().to_vec()));
let cm_leaves = cl::merkle::padded_leaves::<MAX_NOTE_COMMS>(&note_comm_bytes);
cm_leaves
}
#[cfg(test)]
mod test {
use super::*;
use cl::note::unit_point;
use rand::thread_rng;
#[test]
fn test_input_prover() {
let nmo = unit_point("NMO");
let mut rng = thread_rng();
let input = cl::InputWitness {
note: cl::NoteWitness::basic(32, nmo),
balance_blinding: cl::BalanceWitness::random(&mut rng),
nf_sk: cl::NullifierSecret::random(&mut rng),
nonce: cl::NullifierNonce::random(&mut rng),
};
let notes = vec![input.note_commitment()];
let mut proved_input = ProvedInput::prove(&input, &notes).unwrap();
let expected_public_inputs = InputPublic {
cm_root: cl::merkle::root(note_commitment_leaves(&notes)),
input: input.commit(),
};
assert_eq!(proved_input.input, expected_public_inputs);
assert!(proved_input.verify());
let wrong_public_inputs = [
InputPublic {
cm_root: cl::merkle::root([cl::merkle::leaf(b"bad_root")]),
..expected_public_inputs
},
InputPublic {
input: cl::Input {
nullifier: cl::Nullifier::new(
cl::NullifierSecret::random(&mut rng),
input.note_commitment(),
),
..expected_public_inputs.input
},
..expected_public_inputs
},
InputPublic {
input: cl::Input {
death_cm: cl::note::death_commitment(b"wrong death vk"),
..expected_public_inputs.input
},
..expected_public_inputs
},
InputPublic {
input: cl::Input {
balance: cl::BalanceWitness::random(&mut rng)
.commit(&cl::NoteWitness::basic(32, nmo)),
..expected_public_inputs.input
},
..expected_public_inputs
},
];
for wrong_input in wrong_public_inputs {
proved_input.input = wrong_input;
assert!(!proved_input.verify());
}
}
// ----- The following tests still need to be built. -----
// #[test]
// fn test_input_ptx_coupling() {
// let mut rng = rand::thread_rng();
// let note = cl::NoteWitness::new(10, "NMO", [0u8; 32], &mut rng);
// let nf_sk = cl::NullifierSecret::random(&mut rng);
// let nonce = cl::NullifierNonce::random(&mut rng);
// let witness = cl::InputWitness { note, nf_sk, nonce };
// let input = witness.commit();
// let ptx_root = cl::PtxRoot::random(&mut rng);
// let proof = input.prove(&witness, ptx_root, vec![]).unwrap();
// assert!(input.verify(ptx_root, &proof));
// // The same input proof can not be used in another partial transaction.
// let another_ptx_root = cl::PtxRoot::random(&mut rng);
// assert!(!input.verify(another_ptx_root, &proof));
// }
}

View File

@ -1,8 +1,6 @@
pub mod bundle; pub mod bundle;
pub mod death_constraint; pub mod death_constraint;
pub mod error; pub mod error;
pub mod input;
pub mod output;
pub mod partial_tx; pub mod partial_tx;
pub use death_constraint::DeathProof; pub use death_constraint::DeathProof;

View File

@ -1,119 +0,0 @@
use crate::error::{Error, Result};
pub struct ProvedOutput {
pub output: cl::Output,
pub risc0_receipt: risc0_zkvm::Receipt,
}
impl ProvedOutput {
pub fn prove(witness: &cl::OutputWitness) -> Result<Self> {
let env = risc0_zkvm::ExecutorEnv::builder()
.write(&witness)
.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::OUTPUT_ELF, &opts)
.map_err(|_| Error::Risc0ProofFailed)?;
println!(
"STARK 'output' prover time: {:.2?}, total_cycles: {}",
start_t.elapsed(),
prove_info.stats.total_cycles
);
let receipt = prove_info.receipt;
Ok(Self {
output: witness.commit(),
risc0_receipt: receipt,
})
}
pub fn public(&self) -> Result<cl::Output> {
Ok(self.risc0_receipt.journal.decode()?)
}
pub fn verify(&self) -> bool {
let Ok(output_commitments) = self.public() else {
return false;
};
self.output == output_commitments
&& self
.risc0_receipt
.verify(nomos_cl_risc0_proofs::OUTPUT_ID)
.is_ok()
}
}
#[cfg(test)]
mod test {
use super::*;
use cl::note::unit_point;
use rand::thread_rng;
#[test]
fn test_output_prover() {
let nmo = unit_point("NMO");
let mut rng = thread_rng();
let output = cl::OutputWitness {
note: cl::NoteWitness::basic(32, nmo),
balance_blinding: cl::BalanceWitness::random(&mut rng),
nf_pk: cl::NullifierSecret::random(&mut rng).commit(),
nonce: cl::NullifierNonce::random(&mut rng),
};
let mut proved_output = ProvedOutput::prove(&output).unwrap();
let expected_output_cm = output.commit();
assert_eq!(proved_output.output, expected_output_cm);
assert!(proved_output.verify());
let wrong_output_cms = [
cl::Output {
note_comm: cl::NoteWitness::basic(100, nmo).commit(
cl::NullifierSecret::random(&mut rng).commit(),
cl::NullifierNonce::random(&mut rng),
),
..expected_output_cm
},
cl::Output {
note_comm: cl::NoteWitness::basic(100, nmo).commit(
cl::NullifierSecret::random(&mut rng).commit(),
cl::NullifierNonce::random(&mut rng),
),
balance: cl::BalanceWitness::random(&mut rng)
.commit(&cl::NoteWitness::basic(100, nmo)),
},
];
for wrong_output_cm in wrong_output_cms {
proved_output.output = wrong_output_cm;
assert!(!proved_output.verify());
}
}
#[test]
fn test_zero_output_is_rejected() {
let nmo = unit_point("NMO");
let mut rng = thread_rng();
let output = cl::OutputWitness::random(
cl::NoteWitness::basic(0, nmo),
cl::NullifierSecret::random(&mut rng).commit(),
&mut rng,
);
assert!(ProvedOutput::prove(&output).is_err());
}
}

View File

@ -1,21 +0,0 @@
use serde::{Deserialize, Serialize};
/// for public inputs `nf` (nullifier), `root_cm` (root of merkle tree over commitment set) and `death_cm` (commitment to death constraint).
/// the prover has knowledge of `output = (note, nf_pk, nonce)`, `nf` and `path` s.t. that the following constraints hold
/// 0. nf_pk = hash(nf_sk)
/// 1. nf = hash(nonce||nf_sk)
/// 2. note_cm = output_commitment(output)
/// 3. verify_merkle_path(note_cm, root, path)
/// 4. death_cm = death_commitment(note.death_constraint)
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct InputPublic {
pub cm_root: [u8; 32],
pub input: cl::Input,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct InputPrivate {
pub input: cl::InputWitness,
pub cm_path: Vec<cl::merkle::PathNode>,
}

View File

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

View File

@ -7,5 +7,5 @@ edition = "2021"
risc0-build = { version = "1.0" } risc0-build = { version = "1.0" }
[package.metadata.risc0] [package.metadata.risc0]
methods = ["input", "output", "bundle", "death_constraint_nop", "ptx"] methods = ["bundle", "death_constraint_nop", "ptx"]

View File

@ -1,19 +0,0 @@
[package]
name = "input"
version = "0.1.0"
edition = "2021"
[workspace]
[dependencies]
risc0-zkvm = { version = "1.0", default-features = false, features = ['std'] }
serde = { version = "1.0", features = ["derive"] }
cl = { path = "../../cl" }
ledger_proof_statements = { path = "../../ledger_proof_statements" }
[patch.crates-io]
# add RISC Zero accelerator support for all downstream usages of the following crates.
sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.8-risczero.0" }
crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" }
curve25519-dalek = { git = "https://github.com/risc0/curve25519-dalek", tag = "curve25519-4.1.2-risczero.0" }

View File

@ -1,17 +0,0 @@
/// Input Proof
use cl::merkle;
use ledger_proof_statements::input::{InputPrivate, InputPublic};
use risc0_zkvm::guest::env;
fn main() {
let secret: InputPrivate = env::read();
let out_cm = secret.input.note_commitment();
let cm_leaf = merkle::leaf(out_cm.as_bytes());
let cm_root = merkle::path_root(cm_leaf, &secret.cm_path);
env::commit(&InputPublic {
input: secret.input.commit(),
cm_root,
});
}

View File

@ -1,19 +0,0 @@
[package]
name = "output"
version = "0.1.0"
edition = "2021"
[workspace]
[dependencies]
risc0-zkvm = { version = "1.0", default-features = false, features = ['std'] }
serde = { version = "1.0", features = ["derive"] }
cl = { path = "../../cl" }
ledger_proof_statements = { path = "../../ledger_proof_statements" }
[patch.crates-io]
# add RISC Zero accelerator support for all downstream usages of the following crates.
sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.8-risczero.0" }
crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" }
curve25519-dalek = { git = "https://github.com/risc0/curve25519-dalek", tag = "curve25519-4.1.2-risczero.0" }

View File

@ -1,18 +0,0 @@
/// Output Proof
///
/// given randomness `r` and `note=(value, unit, ...)` prove that
/// - balance = balance_commit(value, unit, r)
/// - note_cm = note_commit(note)
use risc0_zkvm::guest::env;
fn main() {
let output: cl::OutputWitness = env::read();
// 0 does not contribute to balance, implications of this are unclear
// therefore out of an abundance of caution, we disallow these zero
// valued "dummy notes".
assert!(output.note.value > 0);
let output_cm = output.commit();
env::commit(&output_cm);
}