mirror of
https://github.com/arnaucube/Nova.git
synced 2026-01-10 16:11:29 +01:00
implement transcript methods for various types (#49)
* implement transcript methods for various types * address clippy * add shape to transcript
This commit is contained in:
@@ -27,6 +27,9 @@ neptune = "6.1"
|
|||||||
generic-array = "0.14.4"
|
generic-array = "0.14.4"
|
||||||
bellperson-nonnative = { version = "0.2.1", default-features = false, features = ["wasm"] }
|
bellperson-nonnative = { version = "0.2.1", default-features = false, features = ["wasm"] }
|
||||||
rug = { version = "1.10", default-features = false, features = ["integer", "serde", "rand"] }
|
rug = { version = "1.10", default-features = false, features = ["integer", "serde", "rand"] }
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
bincode = "1.2.1"
|
||||||
|
flate2 = "1.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [ "bellperson/default", "bellperson-nonnative/default" ]
|
default = [ "bellperson/default", "bellperson-nonnative/default" ]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use super::{
|
use super::{
|
||||||
errors::NovaError,
|
errors::NovaError,
|
||||||
traits::{CompressedGroup, Group},
|
traits::{AppendToTranscriptTrait, CompressedGroup, Group},
|
||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
@@ -80,10 +80,6 @@ impl<G: Group> CommitTrait<G> for [G::Scalar] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait AppendToTranscriptTrait {
|
|
||||||
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<G: Group> AppendToTranscriptTrait for Commitment<G> {
|
impl<G: Group> AppendToTranscriptTrait for Commitment<G> {
|
||||||
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) {
|
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) {
|
||||||
transcript.append_message(label, self.comm.compress().as_bytes());
|
transcript.append_message(label, self.comm.compress().as_bytes());
|
||||||
|
|||||||
23
src/lib.rs
23
src/lib.rs
@@ -16,13 +16,13 @@ pub mod traits;
|
|||||||
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use commitments::{AppendToTranscriptTrait, CompressedCommitment};
|
use commitments::CompressedCommitment;
|
||||||
use errors::NovaError;
|
use errors::NovaError;
|
||||||
use merlin::Transcript;
|
use merlin::Transcript;
|
||||||
use r1cs::{
|
use r1cs::{
|
||||||
R1CSGens, R1CSInstance, R1CSShape, R1CSWitness, RelaxedR1CSInstance, RelaxedR1CSWitness,
|
R1CSGens, R1CSInstance, R1CSShape, R1CSWitness, RelaxedR1CSInstance, RelaxedR1CSWitness,
|
||||||
};
|
};
|
||||||
use traits::{ChallengeTrait, Group};
|
use traits::{AppendToTranscriptTrait, ChallengeTrait, Group};
|
||||||
|
|
||||||
/// A SNARK that holds the proof of a step of an incremental computation
|
/// A SNARK that holds the proof of a step of an incremental computation
|
||||||
pub struct StepSNARK<G: Group> {
|
pub struct StepSNARK<G: Group> {
|
||||||
@@ -59,6 +59,13 @@ impl<G: Group> StepSNARK<G> {
|
|||||||
// append the protocol name to the transcript
|
// append the protocol name to the transcript
|
||||||
transcript.append_message(b"protocol-name", StepSNARK::<G>::protocol_name());
|
transcript.append_message(b"protocol-name", StepSNARK::<G>::protocol_name());
|
||||||
|
|
||||||
|
// append S to the transcript
|
||||||
|
S.append_to_transcript(b"S", transcript);
|
||||||
|
|
||||||
|
// append U1 and U2 to transcript
|
||||||
|
U1.append_to_transcript(b"U1", transcript);
|
||||||
|
U2.append_to_transcript(b"U2", transcript);
|
||||||
|
|
||||||
// compute a commitment to the cross-term
|
// compute a commitment to the cross-term
|
||||||
let (T, comm_T) = S.commit_T(gens, U1, W1, U2, W2)?;
|
let (T, comm_T) = S.commit_T(gens, U1, W1, U2, W2)?;
|
||||||
|
|
||||||
@@ -91,6 +98,7 @@ impl<G: Group> StepSNARK<G> {
|
|||||||
/// if and only if `U1` and `U2` are satisfiable.
|
/// if and only if `U1` and `U2` are satisfiable.
|
||||||
pub fn verify(
|
pub fn verify(
|
||||||
&self,
|
&self,
|
||||||
|
S: &R1CSShape<G>,
|
||||||
U1: &RelaxedR1CSInstance<G>,
|
U1: &RelaxedR1CSInstance<G>,
|
||||||
U2: &R1CSInstance<G>,
|
U2: &R1CSInstance<G>,
|
||||||
transcript: &mut Transcript,
|
transcript: &mut Transcript,
|
||||||
@@ -98,6 +106,13 @@ impl<G: Group> StepSNARK<G> {
|
|||||||
// append the protocol name to the transcript
|
// append the protocol name to the transcript
|
||||||
transcript.append_message(b"protocol-name", StepSNARK::<G>::protocol_name());
|
transcript.append_message(b"protocol-name", StepSNARK::<G>::protocol_name());
|
||||||
|
|
||||||
|
// append S to the transcript
|
||||||
|
S.append_to_transcript(b"S", transcript);
|
||||||
|
|
||||||
|
// append U1 and U2 to transcript
|
||||||
|
U1.append_to_transcript(b"U1", transcript);
|
||||||
|
U2.append_to_transcript(b"U2", transcript);
|
||||||
|
|
||||||
// append `comm_T` to the transcript and obtain a challenge
|
// append `comm_T` to the transcript and obtain a challenge
|
||||||
self.comm_T.append_to_transcript(b"comm_T", transcript);
|
self.comm_T.append_to_transcript(b"comm_T", transcript);
|
||||||
|
|
||||||
@@ -232,7 +247,7 @@ mod tests {
|
|||||||
|
|
||||||
// verify the step SNARK with U1 as the first incoming instance
|
// verify the step SNARK with U1 as the first incoming instance
|
||||||
let mut verifier_transcript = Transcript::new(b"StepSNARKExample");
|
let mut verifier_transcript = Transcript::new(b"StepSNARKExample");
|
||||||
let res = step_snark.verify(&r_U, U1, &mut verifier_transcript);
|
let res = step_snark.verify(shape, &r_U, U1, &mut verifier_transcript);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
let U = res.unwrap();
|
let U = res.unwrap();
|
||||||
|
|
||||||
@@ -248,7 +263,7 @@ mod tests {
|
|||||||
let (step_snark, (_U, W)) = res.unwrap();
|
let (step_snark, (_U, W)) = res.unwrap();
|
||||||
|
|
||||||
// verify the step SNARK with U1 as the first incoming instance
|
// verify the step SNARK with U1 as the first incoming instance
|
||||||
let res = step_snark.verify(&r_U, U2, &mut verifier_transcript);
|
let res = step_snark.verify(shape, &r_U, U2, &mut verifier_transcript);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
let U = res.unwrap();
|
let U = res.unwrap();
|
||||||
|
|
||||||
|
|||||||
63
src/r1cs.rs
63
src/r1cs.rs
@@ -3,11 +3,14 @@
|
|||||||
use super::{
|
use super::{
|
||||||
commitments::{CommitGens, CommitTrait, Commitment, CompressedCommitment},
|
commitments::{CommitGens, CommitTrait, Commitment, CompressedCommitment},
|
||||||
errors::NovaError,
|
errors::NovaError,
|
||||||
traits::Group,
|
traits::{AppendToTranscriptTrait, Group},
|
||||||
};
|
};
|
||||||
use ff::Field;
|
use ff::{Field, PrimeField};
|
||||||
|
use flate2::{write::ZlibEncoder, Compression};
|
||||||
use itertools::concat;
|
use itertools::concat;
|
||||||
|
use merlin::Transcript;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Public parameters for a given R1CS
|
/// Public parameters for a given R1CS
|
||||||
pub struct R1CSGens<G: Group> {
|
pub struct R1CSGens<G: Group> {
|
||||||
@@ -292,6 +295,46 @@ impl<G: Group> R1CSShape<G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
struct R1CSShapeSerialized {
|
||||||
|
num_cons: usize,
|
||||||
|
num_vars: usize,
|
||||||
|
num_io: usize,
|
||||||
|
A: Vec<(usize, usize, Vec<u8>)>,
|
||||||
|
B: Vec<(usize, usize, Vec<u8>)>,
|
||||||
|
C: Vec<(usize, usize, Vec<u8>)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G: Group> AppendToTranscriptTrait for R1CSShape<G> {
|
||||||
|
fn append_to_transcript(&self, _label: &'static [u8], transcript: &mut Transcript) {
|
||||||
|
let shape_serialized = R1CSShapeSerialized {
|
||||||
|
num_cons: self.num_cons,
|
||||||
|
num_vars: self.num_vars,
|
||||||
|
num_io: self.num_io,
|
||||||
|
A: self
|
||||||
|
.A
|
||||||
|
.iter()
|
||||||
|
.map(|(i, j, v)| (*i, *j, v.to_repr().as_ref().to_vec()))
|
||||||
|
.collect(),
|
||||||
|
B: self
|
||||||
|
.B
|
||||||
|
.iter()
|
||||||
|
.map(|(i, j, v)| (*i, *j, v.to_repr().as_ref().to_vec()))
|
||||||
|
.collect(),
|
||||||
|
C: self
|
||||||
|
.C
|
||||||
|
.iter()
|
||||||
|
.map(|(i, j, v)| (*i, *j, v.to_repr().as_ref().to_vec()))
|
||||||
|
.collect(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());
|
||||||
|
bincode::serialize_into(&mut encoder, &shape_serialized).unwrap();
|
||||||
|
let shape_bytes = encoder.finish().unwrap();
|
||||||
|
transcript.append_message(b"R1CSShape", &shape_bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<G: Group> R1CSWitness<G> {
|
impl<G: Group> R1CSWitness<G> {
|
||||||
/// A method to create a witness object using a vector of scalars
|
/// A method to create a witness object using a vector of scalars
|
||||||
pub fn new(S: &R1CSShape<G>, W: &[G::Scalar]) -> Result<R1CSWitness<G>, NovaError> {
|
pub fn new(S: &R1CSShape<G>, W: &[G::Scalar]) -> Result<R1CSWitness<G>, NovaError> {
|
||||||
@@ -326,6 +369,13 @@ impl<G: Group> R1CSInstance<G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<G: Group> AppendToTranscriptTrait for R1CSInstance<G> {
|
||||||
|
fn append_to_transcript(&self, _label: &'static [u8], transcript: &mut Transcript) {
|
||||||
|
self.comm_W.append_to_transcript(b"comm_W", transcript);
|
||||||
|
self.X.append_to_transcript(b"X", transcript);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<G: Group> RelaxedR1CSWitness<G> {
|
impl<G: Group> RelaxedR1CSWitness<G> {
|
||||||
/// Produces a default RelaxedR1CSWitness given an R1CSShape
|
/// Produces a default RelaxedR1CSWitness given an R1CSShape
|
||||||
pub fn default(S: &R1CSShape<G>) -> RelaxedR1CSWitness<G> {
|
pub fn default(S: &R1CSShape<G>) -> RelaxedR1CSWitness<G> {
|
||||||
@@ -427,3 +477,12 @@ impl<G: Group> RelaxedR1CSInstance<G> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<G: Group> AppendToTranscriptTrait for RelaxedR1CSInstance<G> {
|
||||||
|
fn append_to_transcript(&self, _label: &'static [u8], transcript: &mut Transcript) {
|
||||||
|
self.comm_W.append_to_transcript(b"comm_W", transcript);
|
||||||
|
self.comm_E.append_to_transcript(b"comm_E", transcript);
|
||||||
|
self.X.append_to_transcript(b"X", transcript);
|
||||||
|
self.u.append_to_transcript(b"u", transcript);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -68,6 +68,12 @@ pub trait CompressedGroup: Clone + Copy + Debug + Eq + Sized + Send + Sync + 'st
|
|||||||
fn as_bytes(&self) -> &[u8];
|
fn as_bytes(&self) -> &[u8];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A helper trait to append different types to the transcript
|
||||||
|
pub trait AppendToTranscriptTrait {
|
||||||
|
/// appends the value to the transcript under the provided label
|
||||||
|
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript);
|
||||||
|
}
|
||||||
|
|
||||||
/// A helper trait to generate challenges using a transcript object
|
/// A helper trait to generate challenges using a transcript object
|
||||||
pub trait ChallengeTrait {
|
pub trait ChallengeTrait {
|
||||||
/// Returns a Scalar representing the challenge using the transcript
|
/// Returns a Scalar representing the challenge using the transcript
|
||||||
@@ -133,3 +139,17 @@ pub trait StepCircuit<F: PrimeField> {
|
|||||||
z: AllocatedNum<F>,
|
z: AllocatedNum<F>,
|
||||||
) -> Result<AllocatedNum<F>, SynthesisError>;
|
) -> Result<AllocatedNum<F>, SynthesisError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<F: PrimeField> AppendToTranscriptTrait for F {
|
||||||
|
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) {
|
||||||
|
transcript.append_message(label, self.to_repr().as_ref());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: PrimeField> AppendToTranscriptTrait for [F] {
|
||||||
|
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) {
|
||||||
|
for s in self {
|
||||||
|
s.append_to_transcript(label, transcript);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user