Transcript (#46) * add items to transcript * add additional items to transcript * fix benches * cargo fmt
@@ -1,6 +1,6 @@
[package] name = "spartan" -version = "0.5.0" +version = "0.6.0" authors = ["Srinath Setty <srinath@microsoft.com>"] edition = "2018" description = "High-speed zkSNARKs without trusted setup"
@@ -58,7 +58,7 @@ let (comm, decomm) = SNARK::encode(&inst, &gens);
// produce a proof of satisfiability let mut prover_transcript = Transcript::new(b"snark_example"); - let proof = SNARK::prove(&inst, &decomm, vars, &inputs, &gens, &mut prover_transcript); + let proof = SNARK::prove(&inst, &comm, &decomm, vars, &inputs, &gens, &mut prover_transcript); // verify the proof of satisfiability let mut verifier_transcript = Transcript::new(b"snark_example");@@ -132,6 +132,7 @@ // produce a proof of satisfiability
let mut prover_transcript = Transcript::new(b"snark_example"); let proof = SNARK::prove( &inst, + &comm, &decomm, assignment_vars, &assignment_inputs,
@@ -47,7 +47,7 @@ // produce public parameters
let gens = SNARKGens::new(num_cons, num_vars, num_inputs, num_cons); // produce a commitment to R1CS instance - let (_comm, decomm) = SNARK::encode(&inst, &gens); + let (comm, decomm) = SNARK::encode(&inst, &gens); // produce a proof let name = format!("SNARK_prove_{}", num_cons);@@ -56,6 +56,7 @@ b.iter(|| {
let mut prover_transcript = Transcript::new(b"example"); SNARK::prove( black_box(&inst), + black_box(&comm), black_box(&decomm), black_box(vars.clone()), black_box(&inputs),@@ -87,7 +88,15 @@ let (comm, decomm) = SNARK::encode(&inst, &gens);
// produce a proof of satisfiability let mut prover_transcript = Transcript::new(b"example"); - let proof = SNARK::prove(&inst, &decomm, vars, &inputs, &gens, &mut prover_transcript); + let proof = SNARK::prove( + &inst, + &comm, + &decomm, + vars, + &inputs, + &gens, + &mut prover_transcript, + ); // verify the proof let name = format!("SNARK_verify_{}", num_cons);
@@ -128,6 +128,7 @@ // produce a proof of satisfiability
let mut prover_transcript = Transcript::new(b"snark_example"); let proof = SNARK::prove( &inst, + &comm, &decomm, assignment_vars, &assignment_inputs,
@@ -33,7 +33,15 @@ let (comm, decomm) = SNARK::encode(&inst, &gens);
// produce a proof of satisfiability let mut prover_transcript = Transcript::new(b"snark_example"); - let proof = SNARK::prove(&inst, &decomm, vars, &inputs, &gens, &mut prover_transcript); + let proof = SNARK::prove( + &inst, + &comm, + &decomm, + vars, + &inputs, + &gens, + &mut prover_transcript, + ); let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default()); bincode::serialize_into(&mut encoder, &proof).unwrap();
@@ -336,6 +336,7 @@
/// A method to produce a SNARK proof of the satisfiability of an R1CS instance pub fn prove( inst: &Instance, + comm: &ComputationCommitment, decomm: &ComputationDecommitment, vars: VarsAssignment, inputs: &InputsAssignment,@@ -347,7 +348,10 @@
// we create a Transcript object seeded with a random Scalar // to aid the prover produce its randomness let mut random_tape = RandomTape::new(b"proof"); + transcript.append_protocol_name(SNARK::protocol_name()); + comm.comm.append_to_transcript(b"comm", transcript); + let (r1cs_sat_proof, rx, ry) = { let (proof, rx, ry) = { // we might need to pad variables@@ -424,6 +428,9 @@ ) -> Result<(), ProofVerifyError> {
let timer_verify = Timer::new("SNARK::verify"); transcript.append_protocol_name(SNARK::protocol_name()); + // append a commitment to the computation to the transcript + comm.comm.append_to_transcript(b"comm", transcript); + let timer_sat_proof = Timer::new("verify_sat_proof"); assert_eq!(input.assignment.len(), comm.comm.get_num_inputs()); let (rx, ry) = self.r1cs_sat_proof.verify(@@ -500,7 +507,10 @@ let timer_prove = Timer::new("NIZK::prove");
// we create a Transcript object seeded with a random Scalar // to aid the prover produce its randomness let mut random_tape = RandomTape::new(b"proof"); + transcript.append_protocol_name(NIZK::protocol_name()); + inst.inst.append_to_transcript(b"inst", transcript); + let (r1cs_sat_proof, rx, ry) = { // we might need to pad variables let padded_vars = {@@ -544,6 +554,7 @@ ) -> Result<(), ProofVerifyError> {
let timer_verify = Timer::new("NIZK::verify"); transcript.append_protocol_name(NIZK::protocol_name()); + inst.inst.append_to_transcript(b"inst", transcript); // We send evaluations of A, B, C at r = (rx, ry) as claims // to enable the verifier complete the first sum-check@@ -594,7 +605,15 @@ let (comm, decomm) = SNARK::encode(&inst, &gens);
// produce a proof let mut prover_transcript = Transcript::new(b"example"); - let proof = SNARK::prove(&inst, &decomm, vars, &inputs, &gens, &mut prover_transcript); + let proof = SNARK::prove( + &inst, + &comm, + &decomm, + vars, + &inputs, + &gens, + &mut prover_transcript, + ); // verify the proof let mut verifier_transcript = Transcript::new(b"example");@@ -696,6 +715,7 @@ // produce a SNARK
let mut prover_transcript = Transcript::new(b"snark_example"); let proof = SNARK::prove( &inst, + &comm, &decomm, assignment_vars.clone(), &assignment_inputs,
@@ -336,6 +336,8 @@
let Cy = y.commit(blind_y, gens_1).compress(); Cy.append_to_transcript(b"Cy", transcript); + a_vec.append_to_transcript(b"a", transcript); + let delta = d_vec.commit(&r_delta, gens_n).compress(); delta.append_to_transcript(b"delta", transcript);@@ -381,6 +383,7 @@
transcript.append_protocol_name(DotProductProof::protocol_name()); Cx.append_to_transcript(b"Cx", transcript); Cy.append_to_transcript(b"Cy", transcript); + a.append_to_transcript(b"a", transcript); self.delta.append_to_transcript(b"delta", transcript); self.beta.append_to_transcript(b"beta", transcript);@@ -466,6 +469,8 @@
let Cy = y.commit(blind_y, &gens.gens_1).compress(); Cy.append_to_transcript(b"Cy", transcript); + a_vec.append_to_transcript(b"a", transcript); + let blind_Gamma = blind_x + blind_y; let (bullet_reduction_proof, _Gamma_hat, x_hat, a_hat, g_hat, rhat_Gamma) = BulletReductionProof::prove(@@ -526,6 +531,7 @@
transcript.append_protocol_name(DotProductProofLog::protocol_name()); Cx.append_to_transcript(b"Cx", transcript); Cy.append_to_transcript(b"Cy", transcript); + a.append_to_transcript(b"a", transcript); let Gamma = Cx.unpack()? + Cy.unpack()?;
@@ -1,3 +1,5 @@
+use crate::transcript::AppendToTranscript; + use super::dense_mlpoly::DensePolynomial; use super::errors::ProofVerifyError; use super::math::Math;@@ -8,11 +10,12 @@ MultiSparseMatPolynomialAsDense, SparseMatEntry, SparseMatPolyCommitment,
SparseMatPolyCommitmentGens, SparseMatPolyEvalProof, SparseMatPolynomial, }; use super::timer::Timer; +use flate2::{write::ZlibEncoder, Compression}; use merlin::Transcript; use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct R1CSInstance { num_cons: usize, num_vars: usize,@@ -22,6 +25,15 @@ B: SparseMatPolynomial,
C: SparseMatPolynomial, } +impl AppendToTranscript for R1CSInstance { + fn append_to_transcript(&self, _label: &'static [u8], transcript: &mut Transcript) { + let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default()); + bincode::serialize_into(&mut encoder, &self).unwrap(); + let bytes = encoder.finish().unwrap(); + transcript.append_message(b"R1CSInstance", &bytes); + } +} + pub struct R1CSCommitmentGens { gens: SparseMatPolyCommitmentGens, }@@ -43,11 +55,21 @@ R1CSCommitmentGens { gens }
} } +#[derive(Debug, Serialize, Deserialize)] pub struct R1CSCommitment { num_cons: usize, num_vars: usize, num_inputs: usize, comm: SparseMatPolyCommitment, +} + +impl AppendToTranscript for R1CSCommitment { + fn append_to_transcript(&self, _label: &'static [u8], transcript: &mut Transcript) { + transcript.append_u64(b"num_cons", self.num_cons as u64); + transcript.append_u64(b"num_vars", self.num_vars as u64); + transcript.append_u64(b"num_inputs", self.num_inputs as u64); + self.comm.append_to_transcript(b"comm", transcript); + } } pub struct R1CSDecommitment {
@@ -152,6 +152,8 @@
// we currently require the number of |inputs| + 1 to be at most number of vars assert!(input.len() < vars.len()); + input.append_to_transcript(b"input", transcript); + let timer_commit = Timer::new("polycommit"); let (poly_vars, comm_vars, blinds_vars) = { // create a multilinear polynomial using the supplied assignment for variables@@ -354,6 +356,8 @@ transcript: &mut Transcript,
gens: &R1CSGens, ) -> Result<(Vec<Scalar>, Vec<Scalar>), ProofVerifyError> { transcript.append_protocol_name(R1CSProof::protocol_name()); + + input.append_to_transcript(b"input", transcript); let n = num_vars; // add the commitment to the verifier's transcript
@@ -16,7 +16,7 @@ use core::cmp::Ordering;
use merlin::Transcript; use serde::{Deserialize, Serialize}; -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct SparseMatEntry { row: usize, col: usize,@@ -29,7 +29,7 @@ SparseMatEntry { row, col, val }
} } -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct SparseMatPolynomial { num_vars_x: usize, num_vars_y: usize,@@ -328,6 +328,20 @@ num_ops: usize,
num_mem_cells: usize, comm_comb_ops: PolyCommitment, comm_comb_mem: PolyCommitment, +} + +impl AppendToTranscript for SparseMatPolyCommitment { + fn append_to_transcript(&self, _label: &'static [u8], transcript: &mut Transcript) { + transcript.append_u64(b"batch_size", self.batch_size as u64); + transcript.append_u64(b"num_ops", self.num_ops as u64); + transcript.append_u64(b"num_mem_cells", self.num_mem_cells as u64); + self + .comm_comb_ops + .append_to_transcript(b"comm_comb_ops", transcript); + self + .comm_comb_mem + .append_to_transcript(b"comm_comb_mem", transcript); + } } impl SparseMatPolynomial {
@@ -46,7 +46,7 @@ transcript.append_scalar(label, self);
} } -impl AppendToTranscript for Vec<Scalar> { +impl AppendToTranscript for [Scalar] { fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) { transcript.append_message(label, b"begin_append_vector"); for item in self {