goas: output + partial_tx + bundle proofs all working together!
This commit is contained in:
parent
91e0108fb2
commit
9ca5e8af57
|
@ -40,22 +40,26 @@ pub struct NoteWitness {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NoteWitness {
|
impl NoteWitness {
|
||||||
pub fn new(value: u64, unit: impl Into<String>, state: [u8; 32]) -> Self {
|
pub fn new(
|
||||||
|
value: u64,
|
||||||
|
unit: impl Into<String>,
|
||||||
|
death_constraint: [u8; 32],
|
||||||
|
state: [u8; 32],
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value,
|
value,
|
||||||
unit: unit_point(&unit.into()),
|
unit: unit_point(&unit.into()),
|
||||||
death_constraint: [0u8; 32],
|
death_constraint,
|
||||||
state,
|
state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn basic(value: u64, unit: impl Into<String>) -> Self {
|
pub fn basic(value: u64, unit: impl Into<String>) -> Self {
|
||||||
Self {
|
Self::new(value, unit, [0u8; 32], [0u8; 32])
|
||||||
value,
|
}
|
||||||
unit: unit_point(&unit.into()),
|
|
||||||
death_constraint: [0u8; 32],
|
pub fn stateless(value: u64, unit: impl Into<String>, death_constraint: [u8; 32]) -> Self {
|
||||||
state: [0u8; 32],
|
Self::new(value, unit, death_constraint, [0u8; 32])
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn commit(&self, nf_pk: NullifierCommitment, nonce: NullifierNonce) -> NoteCommitment {
|
pub fn commit(&self, nf_pk: NullifierCommitment, nonce: NullifierNonce) -> NoteCommitment {
|
||||||
|
|
|
@ -10,4 +10,5 @@ nomos_cl_risc0_proofs = { path = "../risc0_proofs" }
|
||||||
risc0-zkvm = { version = "1.0", features = ["prove", "metal"] }
|
risc0-zkvm = { version = "1.0", features = ["prove", "metal"] }
|
||||||
risc0-groth16 = { version = "1.0" }
|
risc0-groth16 = { version = "1.0" }
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
rand_core = "0.6.0"
|
||||||
thiserror = "1.0.62"
|
thiserror = "1.0.62"
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
use crate::error::Result;
|
||||||
|
|
||||||
|
pub struct ProvedBundle {
|
||||||
|
pub bundle: cl::Bundle,
|
||||||
|
pub risc0_receipt: risc0_zkvm::Receipt,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProvedBundle {
|
||||||
|
pub fn prove(bundle: &cl::Bundle, balance_witness: &cl::BalanceWitness) -> Self {
|
||||||
|
// need to show that bundle is balanced.
|
||||||
|
// i.e. the sum of ptx balances is 0
|
||||||
|
|
||||||
|
let env = risc0_zkvm::ExecutorEnv::builder()
|
||||||
|
.write(&balance_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::BUNDLE_ELF, &opts)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"STARK 'bundle' prover time: {:.2?}, total_cycles: {}",
|
||||||
|
start_t.elapsed(),
|
||||||
|
prove_info.stats.total_cycles
|
||||||
|
);
|
||||||
|
|
||||||
|
let receipt = prove_info.receipt;
|
||||||
|
|
||||||
|
Self {
|
||||||
|
bundle: bundle.clone(),
|
||||||
|
risc0_receipt: receipt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn public(&self) -> Result<cl::Balance> {
|
||||||
|
Ok(self.risc0_receipt.journal.decode()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify(&self) -> bool {
|
||||||
|
let Ok(zero_commitment) = self.public() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.bundle.balance() == zero_commitment
|
||||||
|
&& self
|
||||||
|
.risc0_receipt
|
||||||
|
.verify(nomos_cl_risc0_proofs::BUNDLE_ID)
|
||||||
|
.is_ok()
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,11 +6,11 @@ const MAX_NOTE_COMMS: usize = 2usize.pow(8);
|
||||||
|
|
||||||
pub struct ProvedInput {
|
pub struct ProvedInput {
|
||||||
pub input: InputPublic,
|
pub input: InputPublic,
|
||||||
pub proof: InputProof,
|
pub risc0_receipt: risc0_zkvm::Receipt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProvedInput {
|
impl ProvedInput {
|
||||||
pub fn prove(input: cl::InputWitness, note_commitments: &[cl::NoteCommitment]) -> Self {
|
pub fn prove(input: &cl::InputWitness, note_commitments: &[cl::NoteCommitment]) -> Self {
|
||||||
let output_cm = input.to_output().commit_note();
|
let output_cm = input.to_output().commit_note();
|
||||||
|
|
||||||
let cm_leaves = note_commitment_leaves(note_commitments);
|
let cm_leaves = note_commitment_leaves(note_commitments);
|
||||||
|
@ -20,7 +20,10 @@ impl ProvedInput {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let cm_path = cl::merkle::path(cm_leaves, cm_idx);
|
let cm_path = cl::merkle::path(cm_leaves, cm_idx);
|
||||||
|
|
||||||
let secrets = InputPrivate { input, cm_path };
|
let secrets = InputPrivate {
|
||||||
|
input: *input,
|
||||||
|
cm_path,
|
||||||
|
};
|
||||||
|
|
||||||
let env = risc0_zkvm::ExecutorEnv::builder()
|
let env = risc0_zkvm::ExecutorEnv::builder()
|
||||||
.write(&secrets)
|
.write(&secrets)
|
||||||
|
@ -31,8 +34,7 @@ impl ProvedInput {
|
||||||
// Obtain the default prover.
|
// Obtain the default prover.
|
||||||
let prover = risc0_zkvm::default_prover();
|
let prover = risc0_zkvm::default_prover();
|
||||||
|
|
||||||
use std::time::Instant;
|
let start_t = std::time::Instant::now();
|
||||||
let start_t = Instant::now();
|
|
||||||
|
|
||||||
// Proof information by proving the specified ELF binary.
|
// Proof information by proving the specified ELF binary.
|
||||||
// This struct contains the receipt along with statistics about execution of the guest
|
// This struct contains the receipt along with statistics about execution of the guest
|
||||||
|
@ -54,34 +56,31 @@ impl ProvedInput {
|
||||||
cm_root: cl::merkle::root(cm_leaves),
|
cm_root: cl::merkle::root(cm_leaves),
|
||||||
input: input.commit(),
|
input: input.commit(),
|
||||||
},
|
},
|
||||||
proof: InputProof { receipt },
|
risc0_receipt: receipt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn public(&self) -> Result<InputPublic> {
|
||||||
|
Ok(self.risc0_receipt.journal.decode()?)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn verify(&self) -> bool {
|
pub fn verify(&self) -> bool {
|
||||||
self.proof.verify(&self.input)
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct InputProof {
|
pub struct InputProof {}
|
||||||
receipt: risc0_zkvm::Receipt,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InputProof {
|
impl InputProof {}
|
||||||
pub fn public(&self) -> Result<InputPublic> {
|
|
||||||
Ok(self.receipt.journal.decode()?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn verify(&self, expected_public_inputs: &InputPublic) -> bool {
|
|
||||||
let Ok(public_inputs) = self.public() else {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
&public_inputs == expected_public_inputs
|
|
||||||
&& self.receipt.verify(nomos_cl_risc0_proofs::INPUT_ID).is_ok()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn note_commitment_leaves(note_commitments: &[cl::NoteCommitment]) -> [[u8; 32]; MAX_NOTE_COMMS] {
|
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 note_comm_bytes = Vec::from_iter(note_commitments.iter().map(|c| c.as_bytes().to_vec()));
|
||||||
|
@ -109,7 +108,7 @@ mod test {
|
||||||
|
|
||||||
let notes = vec![input.to_output().commit_note()];
|
let notes = vec![input.to_output().commit_note()];
|
||||||
|
|
||||||
let proved_input = ProvedInput::prove(input, ¬es);
|
let mut proved_input = ProvedInput::prove(&input, ¬es);
|
||||||
|
|
||||||
let expected_public_inputs = InputPublic {
|
let expected_public_inputs = InputPublic {
|
||||||
cm_root: cl::merkle::root(note_commitment_leaves(¬es)),
|
cm_root: cl::merkle::root(note_commitment_leaves(¬es)),
|
||||||
|
@ -152,57 +151,12 @@ mod test {
|
||||||
];
|
];
|
||||||
|
|
||||||
for wrong_input in wrong_public_inputs {
|
for wrong_input in wrong_public_inputs {
|
||||||
assert!(!proved_input.proof.verify(&wrong_input));
|
proved_input.input = wrong_input;
|
||||||
|
assert!(!proved_input.verify());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----- The following tests still need to be built. -----
|
// ----- The following tests still need to be built. -----
|
||||||
//
|
|
||||||
// #[test]
|
|
||||||
// fn test_input_proof() {
|
|
||||||
// let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
// let ptx_root = cl::PtxRoot::default();
|
|
||||||
|
|
||||||
// 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 input_witness = cl::InputWitness { note, nf_sk, nonce };
|
|
||||||
|
|
||||||
// let input = input_witness.commit();
|
|
||||||
// let proof = input.prove(&input_witness, ptx_root, vec![]).unwrap();
|
|
||||||
|
|
||||||
// assert!(input.verify(ptx_root, &proof));
|
|
||||||
|
|
||||||
// let wrong_witnesses = [
|
|
||||||
// cl::InputWitness {
|
|
||||||
// note: cl::NoteWitness::new(11, "NMO", [0u8; 32], &mut rng),
|
|
||||||
// ..input_witness.clone()
|
|
||||||
// },
|
|
||||||
// cl::InputWitness {
|
|
||||||
// note: cl::NoteWitness::new(10, "ETH", [0u8; 32], &mut rng),
|
|
||||||
// ..input_witness.clone()
|
|
||||||
// },
|
|
||||||
// cl::InputWitness {
|
|
||||||
// nf_sk: cl::NullifierSecret::random(&mut rng),
|
|
||||||
// ..input_witness.clone()
|
|
||||||
// },
|
|
||||||
// cl::InputWitness {
|
|
||||||
// nonce: cl::NullifierNonce::random(&mut rng),
|
|
||||||
// ..input_witness.clone()
|
|
||||||
// },
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// for wrong_witness in wrong_witnesses {
|
|
||||||
// assert!(input.prove(&wrong_witness, ptx_root, vec![]).is_err());
|
|
||||||
|
|
||||||
// let wrong_input = wrong_witness.commit();
|
|
||||||
// let wrong_proof = wrong_input.prove(&wrong_witness, ptx_root, vec![]).unwrap();
|
|
||||||
// assert!(!input.verify(ptx_root, &wrong_proof));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn test_input_ptx_coupling() {
|
// fn test_input_ptx_coupling() {
|
||||||
// let mut rng = rand::thread_rng();
|
// let mut rng = rand::thread_rng();
|
||||||
|
|
|
@ -1,2 +1,6 @@
|
||||||
|
// pub mod death_constraint;
|
||||||
|
pub mod bundle;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod input;
|
pub mod input;
|
||||||
|
pub mod output;
|
||||||
|
pub mod partial_tx;
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
use crate::error::Result;
|
||||||
|
|
||||||
|
pub struct ProvedOutput {
|
||||||
|
pub output: cl::Output,
|
||||||
|
pub risc0_receipt: risc0_zkvm::Receipt,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProvedOutput {
|
||||||
|
pub fn prove(witness: &cl::OutputWitness) -> 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)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"STARK 'output' prover time: {:.2?}, total_cycles: {}",
|
||||||
|
start_t.elapsed(),
|
||||||
|
prove_info.stats.total_cycles
|
||||||
|
);
|
||||||
|
|
||||||
|
let receipt = prove_info.receipt;
|
||||||
|
|
||||||
|
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 rand::thread_rng;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_output_prover() {
|
||||||
|
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);
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
use crate::{input::ProvedInput, output::ProvedOutput};
|
||||||
|
|
||||||
|
pub struct ProvedPartialTx {
|
||||||
|
pub inputs: Vec<ProvedInput>,
|
||||||
|
pub outputs: Vec<ProvedOutput>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProvedPartialTx {
|
||||||
|
pub fn prove(
|
||||||
|
ptx: &cl::PartialTxWitness,
|
||||||
|
note_commitments: &[cl::NoteCommitment],
|
||||||
|
) -> ProvedPartialTx {
|
||||||
|
Self {
|
||||||
|
inputs: Vec::from_iter(
|
||||||
|
ptx.inputs
|
||||||
|
.iter()
|
||||||
|
.map(|i| ProvedInput::prove(i, note_commitments)),
|
||||||
|
),
|
||||||
|
outputs: Vec::from_iter(ptx.outputs.iter().map(ProvedOutput::prove)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify(&self) -> bool {
|
||||||
|
self.inputs.iter().all(ProvedInput::verify) && self.outputs.iter().all(ProvedOutput::verify)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
use ledger::{bundle::ProvedBundle, partial_tx::ProvedPartialTx};
|
||||||
|
use rand_core::CryptoRngCore;
|
||||||
|
|
||||||
|
fn receive_utxo(
|
||||||
|
note: cl::NoteWitness,
|
||||||
|
nf_pk: cl::NullifierCommitment,
|
||||||
|
rng: impl CryptoRngCore,
|
||||||
|
) -> cl::OutputWitness {
|
||||||
|
cl::OutputWitness::random(note, nf_pk, rng)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_simple_transfer() {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
|
let sender_nf_sk = cl::NullifierSecret::random(&mut rng);
|
||||||
|
let sender_nf_pk = sender_nf_sk.commit();
|
||||||
|
|
||||||
|
let recipient_nf_pk = cl::NullifierSecret::random(&mut rng).commit();
|
||||||
|
|
||||||
|
// Assume the sender has received an unspent output from somewhere
|
||||||
|
let utxo = receive_utxo(cl::NoteWitness::basic(10, "NMO"), sender_nf_pk, &mut rng);
|
||||||
|
|
||||||
|
let note_commitments = vec![utxo.commit_note()];
|
||||||
|
|
||||||
|
let input = cl::InputWitness::random(utxo, sender_nf_sk, &mut rng);
|
||||||
|
|
||||||
|
// and wants to send 8 NMO to some recipient and return 2 NMO to itself.
|
||||||
|
let recipient_output =
|
||||||
|
cl::OutputWitness::random(cl::NoteWitness::basic(8, "NMO"), recipient_nf_pk, &mut rng);
|
||||||
|
let change_output =
|
||||||
|
cl::OutputWitness::random(cl::NoteWitness::basic(2, "NMO"), sender_nf_pk, &mut rng);
|
||||||
|
|
||||||
|
let ptx_witness = cl::PartialTxWitness {
|
||||||
|
inputs: vec![input],
|
||||||
|
outputs: vec![recipient_output, change_output],
|
||||||
|
};
|
||||||
|
|
||||||
|
let proved_ptx = ProvedPartialTx::prove(&ptx_witness, ¬e_commitments);
|
||||||
|
|
||||||
|
assert!(proved_ptx.verify());
|
||||||
|
|
||||||
|
let bundle = cl::Bundle {
|
||||||
|
partials: vec![ptx_witness.commit()],
|
||||||
|
};
|
||||||
|
|
||||||
|
let proved_bundle = ProvedBundle::prove(&bundle, &ptx_witness.balance_blinding());
|
||||||
|
assert!(proved_bundle.verify());
|
||||||
|
}
|
|
@ -3,7 +3,6 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct DeathConstraintPublic {
|
pub struct DeathConstraintPublic {
|
||||||
pub cm_root: [u8; 32],
|
|
||||||
pub nf: Nullifier,
|
pub nf: Nullifier,
|
||||||
pub ptx_root: PtxRoot,
|
pub ptx_root: PtxRoot,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
pub mod death_constraint;
|
pub mod death_constraint;
|
||||||
pub mod input;
|
pub mod input;
|
||||||
|
pub mod partial_tx;
|
||||||
pub mod ptx;
|
pub mod ptx;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use cl::{merkle, InputWitness, OutputWitness, PtxRoot};
|
use cl::{merkle, InputWitness, OutputWitness, PtxRoot};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// An input to a partial transaction
|
/// An input to a partial transaction
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct PartialTxInputPrivate {
|
pub struct PartialTxInputPrivate {
|
||||||
|
|
|
@ -7,5 +7,5 @@ edition = "2021"
|
||||||
risc0-build = { version = "1.0" }
|
risc0-build = { version = "1.0" }
|
||||||
|
|
||||||
[package.metadata.risc0]
|
[package.metadata.risc0]
|
||||||
methods = ["input"]
|
methods = ["input", "output", "bundle", "death_constraint_nop"]
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
[package]
|
||||||
|
name = "bundle"
|
||||||
|
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" }
|
||||||
|
proof_statements = { path = "../../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" }
|
|
@ -0,0 +1,17 @@
|
||||||
|
/// Bundle Proof
|
||||||
|
///
|
||||||
|
/// The bundle proof demonstrates that the set of partial transactions
|
||||||
|
/// balance to zero. i.e. \sum inputs = \sum outputs.
|
||||||
|
///
|
||||||
|
/// This is done by proving knowledge of some blinding factor `r` s.t.
|
||||||
|
/// \sum outputs - \sum input = 0*G + r*H
|
||||||
|
///
|
||||||
|
/// To avoid doing costly ECC in stark, we compute only the RHS in stark.
|
||||||
|
/// The sums and equality is checked outside of stark during proof verification.
|
||||||
|
use risc0_zkvm::guest::env;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let zero_witness: cl::BalanceWitness = env::read();
|
||||||
|
let zero_balance = cl::Balance::zero(zero_witness);
|
||||||
|
env::commit(&zero_balance);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
[package]
|
||||||
|
name = "death_constraint_nop"
|
||||||
|
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" }
|
||||||
|
proof_statements = { path = "../../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" }
|
|
@ -0,0 +1,8 @@
|
||||||
|
/// Death Constraint No-op Proof
|
||||||
|
use proof_statements::death_constraint::DeathConstraintPublic;
|
||||||
|
use risc0_zkvm::guest::env;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let public: DeathConstraintPublic = env::read();
|
||||||
|
env::commit(&public);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
[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" }
|
||||||
|
proof_statements = { path = "../../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" }
|
|
@ -0,0 +1,12 @@
|
||||||
|
/// 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();
|
||||||
|
let output_cm = output.commit();
|
||||||
|
env::commit(&output_cm);
|
||||||
|
}
|
Loading…
Reference in New Issue