Skip to content

Commit

Permalink
Make code generic over a TranscriptEngine (microsoft#139)
Browse files Browse the repository at this point in the history
  • Loading branch information
srinathsetty committed Feb 9, 2023
1 parent 3d8f5a9 commit 79c15ca
Show file tree
Hide file tree
Showing 13 changed files with 399 additions and 153 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ keywords = ["zkSNARKs", "cryptography", "proofs"]
[dependencies]
bellperson = { version = "0.24", default-features = false }
ff = { version = "0.12.0", features = ["derive"] }
merlin = {version = "3.0.0", default-features = false }
digest = "0.8.1"
sha3 = "0.8.2"
rayon = "1.3.0"
Expand All @@ -40,6 +39,7 @@ pasta-msm = { version = "0.1.0", package = "lurk-pasta-msm" }
[dev-dependencies]
criterion = "0.3.1"
rand = "0.8.4"
hex = "0.4.3"

[[bench]]
name = "recursive-snark"
Expand Down
3 changes: 3 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,7 @@ pub enum NovaError {
/// returned when the step execution produces an output whose length differs from a previously declared arity
#[error("InvalidStepOutputLength")]
InvalidStepOutputLength,
/// returned when the transcript engine encounters an overflow of the round number
#[error("InternalTranscriptError")]
InternalTranscriptError,
}
79 changes: 41 additions & 38 deletions src/provider/ipa_pc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ use crate::{
traits::{
commitment::{CommitmentEngineTrait, CommitmentGensTrait, CommitmentTrait},
evaluation::EvaluationEngineTrait,
AppendToTranscriptTrait, ChallengeTrait, Group,
AppendToTranscriptTrait, ChallengeTrait, Group, TranscriptEngineTrait,
},
Commitment, CommitmentGens, CompressedCommitment, CE,
};
use core::{cmp::max, iter};
use ff::Field;
use merlin::Transcript;
use rayon::prelude::*;

use std::marker::PhantomData;
Expand Down Expand Up @@ -56,7 +55,7 @@ where

fn prove_batch(
gens: &Self::EvaluationGens,
transcript: &mut Transcript,
transcript: &mut G::TE,
comms: &[Commitment<G>],
polys: &[Vec<G::Scalar>],
points: &[Vec<G::Scalar>],
Expand Down Expand Up @@ -87,7 +86,7 @@ where
),
&InnerProductWitness::new(&polys[i]),
transcript,
);
)?;
nifs.push(n);
r_U = u;
r_W = w;
Expand All @@ -101,7 +100,7 @@ where
/// A method to verify purported evaluations of a batch of polynomials
fn verify_batch(
gens: &Self::EvaluationGens,
transcript: &mut Transcript,
transcript: &mut G::TE,
comms: &[Commitment<G>],
points: &[Vec<G::Scalar>],
evals: &[G::Scalar],
Expand All @@ -127,7 +126,7 @@ where
&evals[i],
),
transcript,
);
)?;
r_U = u;
num_vars = max(num_vars, points[i].len());
}
Expand Down Expand Up @@ -217,9 +216,9 @@ impl<G: Group> NIFSForInnerProduct<G> {
W1: &InnerProductWitness<G>,
U2: &InnerProductInstance<G>,
W2: &InnerProductWitness<G>,
transcript: &mut Transcript,
) -> (Self, InnerProductInstance<G>, InnerProductWitness<G>) {
transcript.append_message(b"protocol-name", Self::protocol_name());
transcript: &mut G::TE,
) -> Result<(Self, InnerProductInstance<G>, InnerProductWitness<G>), NovaError> {
transcript.absorb_bytes(b"protocol-name", Self::protocol_name());

// pad the instances and witness so they are of the same length
let U1 = U1.pad(max(U1.b_vec.len(), U2.b_vec.len()));
Expand All @@ -228,21 +227,25 @@ impl<G: Group> NIFSForInnerProduct<G> {
let W2 = W2.pad(max(U1.b_vec.len(), U2.b_vec.len()));

// add the two commitments and two public vectors to the transcript
// we do not need to add public vectors as their compressed versions were
// read from the transcript
U1.comm_a_vec
.append_to_transcript(b"U1_comm_a_vec", transcript);
U1.b_vec.append_to_transcript(b"U1_b_vec", transcript);
U2.comm_a_vec
.append_to_transcript(b"U2_comm_a_vec", transcript);
U2.b_vec.append_to_transcript(b"U2_b_vec", transcript);

// compute the cross-term
let cross_term = inner_product(&W1.a_vec, &U2.b_vec) + inner_product(&W2.a_vec, &U1.b_vec);

// add the cross-term to the transcript
cross_term.append_to_transcript(b"cross_term", transcript);
<G::Scalar as AppendToTranscriptTrait<G>>::append_to_transcript(
&cross_term,
b"cross_term",
transcript,
);

// obtain a random challenge
let r = G::Scalar::challenge(b"r", transcript);
let r = G::Scalar::challenge(b"r", transcript)?;

// fold the vectors and their inner product
let a_vec = W1
Expand All @@ -268,36 +271,38 @@ impl<G: Group> NIFSForInnerProduct<G> {
c,
};

(NIFSForInnerProduct { cross_term }, U, W)
Ok((NIFSForInnerProduct { cross_term }, U, W))
}

fn verify(
&self,
U1: &InnerProductInstance<G>,
U2: &InnerProductInstance<G>,
transcript: &mut Transcript,
) -> InnerProductInstance<G> {
transcript.append_message(b"protocol-name", Self::protocol_name());
transcript: &mut G::TE,
) -> Result<InnerProductInstance<G>, NovaError> {
transcript.absorb_bytes(b"protocol-name", Self::protocol_name());

// pad the instances so they are of the same length
let U1 = U1.pad(max(U1.b_vec.len(), U2.b_vec.len()));
let U2 = U2.pad(max(U1.b_vec.len(), U2.b_vec.len()));

// add the two commitments and two public vectors to the transcript
// we do not need to add public vectors as their compressed representation
// were derived from the transcript
U1.comm_a_vec
.append_to_transcript(b"U1_comm_a_vec", transcript);
U1.b_vec.append_to_transcript(b"U1_b_vec", transcript);
U2.comm_a_vec
.append_to_transcript(b"U2_comm_a_vec", transcript);
U2.b_vec.append_to_transcript(b"U2_b_vec", transcript);

// add the cross-term to the transcript
self
.cross_term
.append_to_transcript(b"cross_term", transcript);
<G::Scalar as AppendToTranscriptTrait<G>>::append_to_transcript(
&self.cross_term,
b"cross_term",
transcript,
);

// obtain a random challenge
let r = G::Scalar::challenge(b"r", transcript);
let r = G::Scalar::challenge(b"r", transcript)?;

// fold the vectors and their inner product
let b_vec = U1
Expand All @@ -309,11 +314,11 @@ impl<G: Group> NIFSForInnerProduct<G> {
let c = U1.c + r * r * U2.c + r * self.cross_term;
let comm_a_vec = U1.comm_a_vec + U2.comm_a_vec * r;

InnerProductInstance {
Ok(InnerProductInstance {
comm_a_vec,
b_vec,
c,
}
})
}
}

Expand All @@ -340,27 +345,26 @@ where
gens_c: &CommitmentGens<G>,
U: &InnerProductInstance<G>,
W: &InnerProductWitness<G>,
transcript: &mut Transcript,
transcript: &mut G::TE,
) -> Result<Self, NovaError> {
transcript.append_message(b"protocol-name", Self::protocol_name());
transcript.absorb_bytes(b"protocol-name", Self::protocol_name());

if U.b_vec.len() != W.a_vec.len() {
return Err(NovaError::InvalidInputLength);
}

U.comm_a_vec.append_to_transcript(b"comm_a_vec", transcript);
U.b_vec.append_to_transcript(b"b_vec", transcript);
U.c.append_to_transcript(b"c", transcript);
<G::Scalar as AppendToTranscriptTrait<G>>::append_to_transcript(&U.c, b"c", transcript);

// sample a random base for commiting to the inner product
let r = G::Scalar::challenge(b"r", transcript);
let r = G::Scalar::challenge(b"r", transcript)?;
let gens_c = gens_c.scale(&r);

// a closure that executes a step of the recursive inner product argument
let prove_inner = |a_vec: &[G::Scalar],
b_vec: &[G::Scalar],
gens: &CommitmentGens<G>,
transcript: &mut Transcript|
transcript: &mut G::TE|
-> Result<
(
CompressedCommitment<G>,
Expand Down Expand Up @@ -399,7 +403,7 @@ where
L.append_to_transcript(b"L", transcript);
R.append_to_transcript(b"R", transcript);

let r = G::Scalar::challenge(b"challenge_r", transcript);
let r = G::Scalar::challenge(b"challenge_r", transcript)?;
let r_inverse = r.invert().unwrap();

// fold the left half and the right half
Expand Down Expand Up @@ -453,9 +457,9 @@ where
gens_c: &CommitmentGens<G>,
n: usize,
U: &InnerProductInstance<G>,
transcript: &mut Transcript,
transcript: &mut G::TE,
) -> Result<(), NovaError> {
transcript.append_message(b"protocol-name", Self::protocol_name());
transcript.absorb_bytes(b"protocol-name", Self::protocol_name());
if U.b_vec.len() != n
|| n != (1 << self.L_vec.len())
|| self.L_vec.len() != self.R_vec.len()
Expand All @@ -465,11 +469,10 @@ where
}

U.comm_a_vec.append_to_transcript(b"comm_a_vec", transcript);
U.b_vec.append_to_transcript(b"b_vec", transcript);
U.c.append_to_transcript(b"c", transcript);
<G::Scalar as AppendToTranscriptTrait<G>>::append_to_transcript(&U.c, b"c", transcript);

// sample a random base for commiting to the inner product
let r = G::Scalar::challenge(b"r", transcript);
let r = G::Scalar::challenge(b"r", transcript)?;
let gens_c = gens_c.scale(&r);

let P = U.comm_a_vec + CE::<G>::commit(&gens_c, &[U.c]);
Expand Down Expand Up @@ -508,7 +511,7 @@ where
self.R_vec[i].append_to_transcript(b"R", transcript);
G::Scalar::challenge(b"challenge_r", transcript)
})
.collect::<Vec<G::Scalar>>();
.collect::<Result<Vec<G::Scalar>, NovaError>>()?;

// precompute scalars necessary for verification
let r_square: Vec<G::Scalar> = (0..self.L_vec.len())
Expand Down
Loading

0 comments on commit 79c15ca

Please sign in to comment.