mirror of
https://github.com/logos-co/nomos-pocs.git
synced 2025-01-11 09:56:11 +00:00
goas: remove input/output proofs
This commit is contained in:
parent
310932818a
commit
edd69d63bd
@ -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>(¬e_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, ¬es).unwrap();
|
|
||||||
|
|
||||||
let expected_public_inputs = InputPublic {
|
|
||||||
cm_root: cl::merkle::root(note_commitment_leaves(¬es)),
|
|
||||||
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));
|
|
||||||
// }
|
|
||||||
}
|
|
@ -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;
|
||||||
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>,
|
|
||||||
}
|
|
@ -1,3 +1,2 @@
|
|||||||
pub mod death_constraint;
|
pub mod death_constraint;
|
||||||
pub mod input;
|
|
||||||
pub mod ptx;
|
pub mod ptx;
|
||||||
|
@ -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"]
|
||||||
|
|
||||||
|
@ -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" }
|
|
@ -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,
|
|
||||||
});
|
|
||||||
}
|
|
@ -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" }
|
|
@ -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);
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user