mirror of
https://github.com/arnaucube/Nova.git
synced 2026-01-11 16:41:28 +01:00
Simplify TranscriptEngine usage (#148)
* simplify transcript engine usage * update version
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nova-snark"
|
name = "nova-snark"
|
||||||
version = "0.17.0"
|
version = "0.18.0"
|
||||||
authors = ["Srinath Setty <srinath@microsoft.com>"]
|
authors = ["Srinath Setty <srinath@microsoft.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Recursive zkSNARKs without trusted setup"
|
description = "Recursive zkSNARKs without trusted setup"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crate::{
|
|||||||
traits::{
|
traits::{
|
||||||
commitment::{CommitmentEngineTrait, CommitmentKeyTrait, CommitmentTrait},
|
commitment::{CommitmentEngineTrait, CommitmentKeyTrait, CommitmentTrait},
|
||||||
evaluation::EvaluationEngineTrait,
|
evaluation::EvaluationEngineTrait,
|
||||||
AppendToTranscriptTrait, ChallengeTrait, Group, TranscriptEngineTrait,
|
Group, TranscriptEngineTrait, TranscriptReprTrait,
|
||||||
},
|
},
|
||||||
Commitment, CommitmentKey, CompressedCommitment, CE,
|
Commitment, CommitmentKey, CompressedCommitment, CE,
|
||||||
};
|
};
|
||||||
@@ -139,6 +139,17 @@ impl<G: Group> InnerProductInstance<G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<G: Group> TranscriptReprTrait<G> for InnerProductInstance<G> {
|
||||||
|
fn to_transcript_bytes(&self) -> Vec<u8> {
|
||||||
|
// we do not need to include self.b_vec as in our context it is produced from the transcript
|
||||||
|
[
|
||||||
|
self.comm_a_vec.to_transcript_bytes(),
|
||||||
|
self.c.to_transcript_bytes(),
|
||||||
|
]
|
||||||
|
.concat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct InnerProductWitness<G: Group> {
|
struct InnerProductWitness<G: Group> {
|
||||||
a_vec: Vec<G::Scalar>,
|
a_vec: Vec<G::Scalar>,
|
||||||
}
|
}
|
||||||
@@ -167,7 +178,7 @@ where
|
|||||||
CommitmentKey<G>: CommitmentKeyExtTrait<G, CE = G::CE>,
|
CommitmentKey<G>: CommitmentKeyExtTrait<G, CE = G::CE>,
|
||||||
{
|
{
|
||||||
fn protocol_name() -> &'static [u8] {
|
fn protocol_name() -> &'static [u8] {
|
||||||
b"inner product argument"
|
b"IPA"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prove(
|
fn prove(
|
||||||
@@ -177,17 +188,17 @@ where
|
|||||||
W: &InnerProductWitness<G>,
|
W: &InnerProductWitness<G>,
|
||||||
transcript: &mut G::TE,
|
transcript: &mut G::TE,
|
||||||
) -> Result<Self, NovaError> {
|
) -> Result<Self, NovaError> {
|
||||||
transcript.absorb_bytes(b"protocol-name", Self::protocol_name());
|
transcript.dom_sep(Self::protocol_name());
|
||||||
|
|
||||||
if U.b_vec.len() != W.a_vec.len() {
|
if U.b_vec.len() != W.a_vec.len() {
|
||||||
return Err(NovaError::InvalidInputLength);
|
return Err(NovaError::InvalidInputLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
U.comm_a_vec.append_to_transcript(b"comm_a_vec", transcript);
|
// absorb the instance in the transcript
|
||||||
<G::Scalar as AppendToTranscriptTrait<G>>::append_to_transcript(&U.c, b"c", transcript);
|
transcript.absorb(b"U", U);
|
||||||
|
|
||||||
// sample a random base for commiting to the inner product
|
// sample a random base for commiting to the inner product
|
||||||
let r = G::Scalar::challenge(b"r", transcript)?;
|
let r = transcript.squeeze(b"r")?;
|
||||||
let ck_c = ck_c.scale(&r);
|
let ck_c = ck_c.scale(&r);
|
||||||
|
|
||||||
// a closure that executes a step of the recursive inner product argument
|
// a closure that executes a step of the recursive inner product argument
|
||||||
@@ -230,10 +241,10 @@ where
|
|||||||
)
|
)
|
||||||
.compress();
|
.compress();
|
||||||
|
|
||||||
L.append_to_transcript(b"L", transcript);
|
transcript.absorb(b"L", &L);
|
||||||
R.append_to_transcript(b"R", transcript);
|
transcript.absorb(b"R", &R);
|
||||||
|
|
||||||
let r = G::Scalar::challenge(b"challenge_r", transcript)?;
|
let r = transcript.squeeze(b"r")?;
|
||||||
let r_inverse = r.invert().unwrap();
|
let r_inverse = r.invert().unwrap();
|
||||||
|
|
||||||
// fold the left half and the right half
|
// fold the left half and the right half
|
||||||
@@ -289,7 +300,7 @@ where
|
|||||||
U: &InnerProductInstance<G>,
|
U: &InnerProductInstance<G>,
|
||||||
transcript: &mut G::TE,
|
transcript: &mut G::TE,
|
||||||
) -> Result<(), NovaError> {
|
) -> Result<(), NovaError> {
|
||||||
transcript.absorb_bytes(b"protocol-name", Self::protocol_name());
|
transcript.dom_sep(Self::protocol_name());
|
||||||
if U.b_vec.len() != n
|
if U.b_vec.len() != n
|
||||||
|| n != (1 << self.L_vec.len())
|
|| n != (1 << self.L_vec.len())
|
||||||
|| self.L_vec.len() != self.R_vec.len()
|
|| self.L_vec.len() != self.R_vec.len()
|
||||||
@@ -298,11 +309,11 @@ where
|
|||||||
return Err(NovaError::InvalidInputLength);
|
return Err(NovaError::InvalidInputLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
U.comm_a_vec.append_to_transcript(b"comm_a_vec", transcript);
|
// absorb the instance in the transcript
|
||||||
<G::Scalar as AppendToTranscriptTrait<G>>::append_to_transcript(&U.c, b"c", transcript);
|
transcript.absorb(b"U", U);
|
||||||
|
|
||||||
// sample a random base for commiting to the inner product
|
// sample a random base for commiting to the inner product
|
||||||
let r = G::Scalar::challenge(b"r", transcript)?;
|
let r = transcript.squeeze(b"r")?;
|
||||||
let ck_c = ck_c.scale(&r);
|
let ck_c = ck_c.scale(&r);
|
||||||
|
|
||||||
let P = U.comm_a_vec + CE::<G>::commit(&ck_c, &[U.c]);
|
let P = U.comm_a_vec + CE::<G>::commit(&ck_c, &[U.c]);
|
||||||
@@ -337,9 +348,9 @@ where
|
|||||||
// compute a vector of public coins using self.L_vec and self.R_vec
|
// compute a vector of public coins using self.L_vec and self.R_vec
|
||||||
let r = (0..self.L_vec.len())
|
let r = (0..self.L_vec.len())
|
||||||
.map(|i| {
|
.map(|i| {
|
||||||
self.L_vec[i].append_to_transcript(b"L", transcript);
|
transcript.absorb(b"L", &self.L_vec[i]);
|
||||||
self.R_vec[i].append_to_transcript(b"R", transcript);
|
transcript.absorb(b"R", &self.R_vec[i]);
|
||||||
G::Scalar::challenge(b"challenge_r", transcript)
|
transcript.squeeze(b"r")
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<G::Scalar>, NovaError>>()?;
|
.collect::<Result<Vec<G::Scalar>, NovaError>>()?;
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
use crate::traits::PrimeFieldExt;
|
use crate::traits::PrimeFieldExt;
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::NovaError,
|
errors::NovaError,
|
||||||
traits::{Group, TranscriptEngineTrait},
|
traits::{Group, TranscriptEngineTrait, TranscriptReprTrait},
|
||||||
};
|
};
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use sha3::{Digest, Keccak256};
|
use sha3::{Digest, Keccak256};
|
||||||
|
|
||||||
const PERSONA_TAG: &[u8] = b"NovaTranscript";
|
const PERSONA_TAG: &[u8] = b"NoTR";
|
||||||
const DOM_SEP_TAG: &[u8] = b"NovaRound";
|
const DOM_SEP_TAG: &[u8] = b"NoDS";
|
||||||
const KECCAK256_STATE_SIZE: usize = 64;
|
const KECCAK256_STATE_SIZE: usize = 64;
|
||||||
const KECCAK256_PREFIX_CHALLENGE_LO: u8 = 0;
|
const KECCAK256_PREFIX_CHALLENGE_LO: u8 = 0;
|
||||||
const KECCAK256_PREFIX_CHALLENGE_HI: u8 = 1;
|
const KECCAK256_PREFIX_CHALLENGE_HI: u8 = 1;
|
||||||
@@ -55,7 +55,7 @@ impl<G: Group> TranscriptEngineTrait<G> for Keccak256Transcript<G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn squeeze_scalar(&mut self, label: &'static [u8]) -> Result<G::Scalar, NovaError> {
|
fn squeeze(&mut self, label: &'static [u8]) -> Result<G::Scalar, NovaError> {
|
||||||
let input = [
|
let input = [
|
||||||
DOM_SEP_TAG,
|
DOM_SEP_TAG,
|
||||||
self.round.to_le_bytes().as_ref(),
|
self.round.to_le_bytes().as_ref(),
|
||||||
@@ -81,8 +81,13 @@ impl<G: Group> TranscriptEngineTrait<G> for Keccak256Transcript<G> {
|
|||||||
Ok(G::Scalar::from_uniform(&output))
|
Ok(G::Scalar::from_uniform(&output))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn absorb_bytes(&mut self, label: &'static [u8], bytes: &[u8]) {
|
fn absorb<T: TranscriptReprTrait<G>>(&mut self, label: &'static [u8], o: &T) {
|
||||||
self.transcript.extend_from_slice(label);
|
self.transcript.extend_from_slice(label);
|
||||||
|
self.transcript.extend_from_slice(&o.to_transcript_bytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dom_sep(&mut self, bytes: &'static [u8]) {
|
||||||
|
self.transcript.extend_from_slice(DOM_SEP_TAG);
|
||||||
self.transcript.extend_from_slice(bytes);
|
self.transcript.extend_from_slice(bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,7 +96,7 @@ impl<G: Group> TranscriptEngineTrait<G> for Keccak256Transcript<G> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
provider::keccak::Keccak256Transcript,
|
provider::keccak::Keccak256Transcript,
|
||||||
traits::{AppendToTranscriptTrait, ChallengeTrait, Group, TranscriptEngineTrait},
|
traits::{Group, TranscriptEngineTrait},
|
||||||
};
|
};
|
||||||
use ff::PrimeField;
|
use ff::PrimeField;
|
||||||
use sha3::{Digest, Keccak256};
|
use sha3::{Digest, Keccak256};
|
||||||
@@ -100,50 +105,34 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_keccak_transcript() {
|
fn test_keccak_transcript() {
|
||||||
let mut transcript = Keccak256Transcript::new(b"test");
|
let mut transcript: Keccak256Transcript<G> = Keccak256Transcript::new(b"test");
|
||||||
|
|
||||||
// two scalars
|
// two scalars
|
||||||
let s1 = <G as Group>::Scalar::from(2u64);
|
let s1 = <G as Group>::Scalar::from(2u64);
|
||||||
let s2 = <G as Group>::Scalar::from(5u64);
|
let s2 = <G as Group>::Scalar::from(5u64);
|
||||||
|
|
||||||
// add the scalars to the transcript
|
// add the scalars to the transcript
|
||||||
<<G as Group>::Scalar as AppendToTranscriptTrait<G>>::append_to_transcript(
|
transcript.absorb(b"s1", &s1);
|
||||||
&s1,
|
transcript.absorb(b"s2", &s2);
|
||||||
b"s1",
|
|
||||||
&mut transcript,
|
|
||||||
);
|
|
||||||
<<G as Group>::Scalar as AppendToTranscriptTrait<G>>::append_to_transcript(
|
|
||||||
&s2,
|
|
||||||
b"s2",
|
|
||||||
&mut transcript,
|
|
||||||
);
|
|
||||||
|
|
||||||
// make a challenge
|
// make a challenge
|
||||||
let c1 =
|
let c1: <G as Group>::Scalar = transcript.squeeze(b"c1").unwrap();
|
||||||
<<G as Group>::Scalar as ChallengeTrait<G>>::challenge(b"challenge_c1", &mut transcript)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hex::encode(c1.to_repr().as_ref()),
|
hex::encode(c1.to_repr().as_ref()),
|
||||||
"51648083af5387a04a7aa2aec789ee78fdabe45dc1391d270a38fcb576447c01"
|
"432d5811c8be3d44d47f52108a8749ae18482efd1a37b830f966456b5d75340c"
|
||||||
);
|
);
|
||||||
|
|
||||||
// a scalar
|
// a scalar
|
||||||
let s3 = <G as Group>::Scalar::from(128u64);
|
let s3 = <G as Group>::Scalar::from(128u64);
|
||||||
|
|
||||||
// add the scalar to the transcript
|
// add the scalar to the transcript
|
||||||
<<G as Group>::Scalar as AppendToTranscriptTrait<G>>::append_to_transcript(
|
transcript.absorb(b"s3", &s3);
|
||||||
&s3,
|
|
||||||
b"s3",
|
|
||||||
&mut transcript,
|
|
||||||
);
|
|
||||||
|
|
||||||
// make a challenge
|
// make a challenge
|
||||||
let c2 =
|
let c2: <G as Group>::Scalar = transcript.squeeze(b"c2").unwrap();
|
||||||
<<G as Group>::Scalar as ChallengeTrait<G>>::challenge(b"challenge_c2", &mut transcript)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hex::encode(c2.to_repr().as_ref()),
|
hex::encode(c2.to_repr().as_ref()),
|
||||||
"9773f3349f7308153f6012e72b97fc304e48372bbd28bd122b37a8e46855d50f"
|
"65f7908d53abcd18f3b1d767456ef9009b91c7566a635e9ca7be26e21d4d7a10"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
//! This module implements the Nova traits for pallas::Point, pallas::Scalar, vesta::Point, vesta::Scalar.
|
//! This module implements the Nova traits for pallas::Point, pallas::Scalar, vesta::Point, vesta::Scalar.
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::NovaError,
|
|
||||||
provider::{
|
provider::{
|
||||||
keccak::Keccak256Transcript,
|
keccak::Keccak256Transcript,
|
||||||
pedersen::CommitmentEngine,
|
pedersen::CommitmentEngine,
|
||||||
poseidon::{PoseidonRO, PoseidonROCircuit},
|
poseidon::{PoseidonRO, PoseidonROCircuit},
|
||||||
},
|
},
|
||||||
traits::{ChallengeTrait, CompressedGroup, Group, PrimeFieldExt, TranscriptEngineTrait},
|
traits::{CompressedGroup, Group, PrimeFieldExt, TranscriptReprTrait},
|
||||||
};
|
};
|
||||||
use digest::{ExtendableOutput, Input};
|
use digest::{ExtendableOutput, Input};
|
||||||
use ff::PrimeField;
|
use ff::PrimeField;
|
||||||
@@ -177,9 +176,11 @@ macro_rules! impl_traits {
|
|||||||
let bytes_arr: [u8; 64] = bytes.try_into().unwrap();
|
let bytes_arr: [u8; 64] = bytes.try_into().unwrap();
|
||||||
$name::Scalar::from_bytes_wide(&bytes_arr)
|
$name::Scalar::from_bytes_wide(&bytes_arr)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn to_bytes(&self) -> Vec<u8> {
|
impl<G: Group> TranscriptReprTrait<G> for $name_compressed {
|
||||||
self.to_repr().as_ref().to_vec()
|
fn to_transcript_bytes(&self) -> Vec<u8> {
|
||||||
|
self.repr.to_vec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,17 +190,19 @@ macro_rules! impl_traits {
|
|||||||
fn decompress(&self) -> Option<$name::Point> {
|
fn decompress(&self) -> Option<$name::Point> {
|
||||||
Some($name_curve::from_bytes(&self.repr).unwrap())
|
Some($name_curve::from_bytes(&self.repr).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_bytes(&self) -> Vec<u8> {
|
|
||||||
self.repr.to_vec()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: Group<Scalar = F>, F: PrimeField> ChallengeTrait<G> for F {
|
impl<G: Group> TranscriptReprTrait<G> for pallas::Base {
|
||||||
fn challenge(label: &'static [u8], transcript: &mut G::TE) -> Result<F, NovaError> {
|
fn to_transcript_bytes(&self) -> Vec<u8> {
|
||||||
transcript.squeeze_scalar(label)
|
self.to_repr().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<G: Group> TranscriptReprTrait<G> for pallas::Scalar {
|
||||||
|
fn to_transcript_bytes(&self) -> Vec<u8> {
|
||||||
|
self.to_repr().to_vec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ use crate::{
|
|||||||
errors::NovaError,
|
errors::NovaError,
|
||||||
traits::{
|
traits::{
|
||||||
commitment::{CommitmentEngineTrait, CommitmentKeyTrait, CommitmentTrait},
|
commitment::{CommitmentEngineTrait, CommitmentKeyTrait, CommitmentTrait},
|
||||||
AbsorbInROTrait, AppendToTranscriptTrait, CompressedGroup, Group, ROTrait,
|
AbsorbInROTrait, CompressedGroup, Group, ROTrait, TranscriptReprTrait,
|
||||||
TranscriptEngineTrait,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
@@ -12,7 +11,7 @@ use core::{
|
|||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
ops::{Add, AddAssign, Mul, MulAssign},
|
ops::{Add, AddAssign, Mul, MulAssign},
|
||||||
};
|
};
|
||||||
use ff::{Field, PrimeField};
|
use ff::Field;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@@ -89,17 +88,16 @@ impl<G: Group> Default for Commitment<G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: Group> AppendToTranscriptTrait<G> for Commitment<G> {
|
impl<G: Group> TranscriptReprTrait<G> for Commitment<G> {
|
||||||
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE) {
|
fn to_transcript_bytes(&self) -> Vec<u8> {
|
||||||
let (x, y, is_infinity) = self.comm.to_coordinates();
|
let (x, y, is_infinity) = self.comm.to_coordinates();
|
||||||
let is_infinity_byte = if is_infinity { 0u8 } else { 1u8 };
|
let is_infinity_byte = if is_infinity { 0u8 } else { 1u8 };
|
||||||
let bytes = [
|
[
|
||||||
x.to_repr().as_ref(),
|
x.to_transcript_bytes(),
|
||||||
y.to_repr().as_ref(),
|
y.to_transcript_bytes(),
|
||||||
&[is_infinity_byte],
|
[is_infinity_byte].to_vec(),
|
||||||
]
|
]
|
||||||
.concat();
|
.concat()
|
||||||
transcript.absorb_bytes(label, &bytes);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,9 +114,9 @@ impl<G: Group> AbsorbInROTrait<G> for Commitment<G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: Group> AppendToTranscriptTrait<G> for CompressedCommitment<G> {
|
impl<G: Group> TranscriptReprTrait<G> for CompressedCommitment<G> {
|
||||||
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE) {
|
fn to_transcript_bytes(&self) -> Vec<u8> {
|
||||||
transcript.absorb_bytes(label, &self.comm.as_bytes());
|
self.comm.to_transcript_bytes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
34
src/r1cs.rs
34
src/r1cs.rs
@@ -9,7 +9,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
traits::{
|
traits::{
|
||||||
commitment::{CommitmentEngineTrait, CommitmentKeyTrait},
|
commitment::{CommitmentEngineTrait, CommitmentKeyTrait},
|
||||||
AbsorbInROTrait, AppendToTranscriptTrait, Group, ROTrait,
|
AbsorbInROTrait, Group, ROTrait, TranscriptReprTrait,
|
||||||
},
|
},
|
||||||
Commitment, CommitmentKey, CE,
|
Commitment, CommitmentKey, CE,
|
||||||
};
|
};
|
||||||
@@ -435,13 +435,9 @@ impl<G: Group> R1CSShape<G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: Group> AppendToTranscriptTrait<G> for R1CSShape<G> {
|
impl<G: Group> TranscriptReprTrait<G> for R1CSShape<G> {
|
||||||
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE) {
|
fn to_transcript_bytes(&self) -> Vec<u8> {
|
||||||
<<G as Group>::Scalar as AppendToTranscriptTrait<G>>::append_to_transcript(
|
self.get_digest().to_transcript_bytes()
|
||||||
&self.get_digest(),
|
|
||||||
label,
|
|
||||||
transcript,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,13 +481,6 @@ impl<G: Group> R1CSInstance<G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: Group> AppendToTranscriptTrait<G> for R1CSInstance<G> {
|
|
||||||
fn append_to_transcript(&self, _label: &'static [u8], transcript: &mut G::TE) {
|
|
||||||
self.comm_W.append_to_transcript(b"comm_W", transcript);
|
|
||||||
<[G::Scalar] as AppendToTranscriptTrait<G>>::append_to_transcript(&self.X, b"X", transcript);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<G: Group> AbsorbInROTrait<G> for R1CSInstance<G> {
|
impl<G: Group> AbsorbInROTrait<G> for R1CSInstance<G> {
|
||||||
fn absorb_in_ro(&self, ro: &mut G::RO) {
|
fn absorb_in_ro(&self, ro: &mut G::RO) {
|
||||||
self.comm_W.absorb_in_ro(ro);
|
self.comm_W.absorb_in_ro(ro);
|
||||||
@@ -623,12 +612,15 @@ impl<G: Group> RelaxedR1CSInstance<G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: Group> AppendToTranscriptTrait<G> for RelaxedR1CSInstance<G> {
|
impl<G: Group> TranscriptReprTrait<G> for RelaxedR1CSInstance<G> {
|
||||||
fn append_to_transcript(&self, _label: &'static [u8], transcript: &mut G::TE) {
|
fn to_transcript_bytes(&self) -> Vec<u8> {
|
||||||
self.comm_W.append_to_transcript(b"comm_W", transcript);
|
[
|
||||||
self.comm_E.append_to_transcript(b"comm_E", transcript);
|
self.comm_W.to_transcript_bytes(),
|
||||||
<G::Scalar as AppendToTranscriptTrait<G>>::append_to_transcript(&self.u, b"u", transcript);
|
self.comm_E.to_transcript_bytes(),
|
||||||
<[G::Scalar] as AppendToTranscriptTrait<G>>::append_to_transcript(&self.X, b"X", transcript);
|
self.u.to_transcript_bytes(),
|
||||||
|
self.X.as_slice().to_transcript_bytes(),
|
||||||
|
]
|
||||||
|
.concat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ use crate::{
|
|||||||
errors::NovaError,
|
errors::NovaError,
|
||||||
r1cs::{R1CSShape, RelaxedR1CSInstance, RelaxedR1CSWitness},
|
r1cs::{R1CSShape, RelaxedR1CSInstance, RelaxedR1CSWitness},
|
||||||
traits::{
|
traits::{
|
||||||
evaluation::EvaluationEngineTrait, snark::RelaxedR1CSSNARKTrait, AppendToTranscriptTrait,
|
evaluation::EvaluationEngineTrait, snark::RelaxedR1CSSNARKTrait, Group, TranscriptEngineTrait,
|
||||||
ChallengeTrait, Group, TranscriptEngineTrait,
|
|
||||||
},
|
},
|
||||||
CommitmentKey,
|
CommitmentKey,
|
||||||
};
|
};
|
||||||
@@ -83,8 +82,8 @@ impl<G: Group, EE: EvaluationEngineTrait<G, CE = G::CE>> RelaxedR1CSSNARKTrait<G
|
|||||||
assert!(pk.S.num_io < pk.S.num_vars);
|
assert!(pk.S.num_io < pk.S.num_vars);
|
||||||
|
|
||||||
// append the R1CSShape and RelaxedR1CSInstance to the transcript
|
// append the R1CSShape and RelaxedR1CSInstance to the transcript
|
||||||
pk.S.append_to_transcript(b"S", &mut transcript);
|
transcript.absorb(b"S", &pk.S);
|
||||||
U.append_to_transcript(b"U", &mut transcript);
|
transcript.absorb(b"U", U);
|
||||||
|
|
||||||
// compute the full satisfying assignment by concatenating W.W, U.u, and U.X
|
// compute the full satisfying assignment by concatenating W.W, U.u, and U.X
|
||||||
let mut z = concat(vec![W.W.clone(), vec![U.u], U.X.clone()]);
|
let mut z = concat(vec![W.W.clone(), vec![U.u], U.X.clone()]);
|
||||||
@@ -96,7 +95,7 @@ impl<G: Group, EE: EvaluationEngineTrait<G, CE = G::CE>> RelaxedR1CSSNARKTrait<G
|
|||||||
|
|
||||||
// outer sum-check
|
// outer sum-check
|
||||||
let tau = (0..num_rounds_x)
|
let tau = (0..num_rounds_x)
|
||||||
.map(|_i| G::Scalar::challenge(b"tau", &mut transcript))
|
.map(|_i| transcript.squeeze(b"t"))
|
||||||
.collect::<Result<Vec<G::Scalar>, NovaError>>()?;
|
.collect::<Result<Vec<G::Scalar>, NovaError>>()?;
|
||||||
|
|
||||||
let mut poly_tau = MultilinearPolynomial::new(EqPolynomial::new(tau).evals());
|
let mut poly_tau = MultilinearPolynomial::new(EqPolynomial::new(tau).evals());
|
||||||
@@ -134,15 +133,13 @@ impl<G: Group, EE: EvaluationEngineTrait<G, CE = G::CE>> RelaxedR1CSSNARKTrait<G
|
|||||||
let (claim_Az, claim_Bz): (G::Scalar, G::Scalar) = (claims_outer[1], claims_outer[2]);
|
let (claim_Az, claim_Bz): (G::Scalar, G::Scalar) = (claims_outer[1], claims_outer[2]);
|
||||||
let claim_Cz = poly_Cz.evaluate(&r_x);
|
let claim_Cz = poly_Cz.evaluate(&r_x);
|
||||||
let eval_E = MultilinearPolynomial::new(W.E.clone()).evaluate(&r_x);
|
let eval_E = MultilinearPolynomial::new(W.E.clone()).evaluate(&r_x);
|
||||||
|
transcript.absorb(
|
||||||
<[G::Scalar] as AppendToTranscriptTrait<G>>::append_to_transcript(
|
|
||||||
&[claim_Az, claim_Bz, claim_Cz, eval_E],
|
|
||||||
b"claims_outer",
|
b"claims_outer",
|
||||||
&mut transcript,
|
&[claim_Az, claim_Bz, claim_Cz, eval_E].as_slice(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// inner sum-check
|
// inner sum-check
|
||||||
let r = G::Scalar::challenge(b"r", &mut transcript)?;
|
let r = transcript.squeeze(b"r")?;
|
||||||
let claim_inner_joint = claim_Az + r * claim_Bz + r * r * claim_Cz;
|
let claim_inner_joint = claim_Az + r * claim_Bz + r * r * claim_Cz;
|
||||||
|
|
||||||
let poly_ABC = {
|
let poly_ABC = {
|
||||||
@@ -213,11 +210,7 @@ impl<G: Group, EE: EvaluationEngineTrait<G, CE = G::CE>> RelaxedR1CSSNARKTrait<G
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
let eval_W = MultilinearPolynomial::new(W.W.clone()).evaluate(&r_y[1..]);
|
let eval_W = MultilinearPolynomial::new(W.W.clone()).evaluate(&r_y[1..]);
|
||||||
<G::Scalar as AppendToTranscriptTrait<G>>::append_to_transcript(
|
transcript.absorb(b"eval_W", &eval_W);
|
||||||
&eval_W,
|
|
||||||
b"eval_W",
|
|
||||||
&mut transcript,
|
|
||||||
);
|
|
||||||
|
|
||||||
// We will now reduce eval_W =? W(r_y[1..]) and eval_W =? E(r_x) into
|
// We will now reduce eval_W =? W(r_y[1..]) and eval_W =? E(r_x) into
|
||||||
// two claims: eval_W_prime =? W(rz) and eval_E_prime =? E(rz)
|
// two claims: eval_W_prime =? W(rz) and eval_E_prime =? E(rz)
|
||||||
@@ -225,7 +218,7 @@ impl<G: Group, EE: EvaluationEngineTrait<G, CE = G::CE>> RelaxedR1CSSNARKTrait<G
|
|||||||
// where gamma is a public challenge
|
// where gamma is a public challenge
|
||||||
// Since commitments to W and E are homomorphic, the verifier can compute a commitment
|
// Since commitments to W and E are homomorphic, the verifier can compute a commitment
|
||||||
// to the batched polynomial.
|
// to the batched polynomial.
|
||||||
let rho = G::Scalar::challenge(b"rho", &mut transcript)?;
|
let rho = transcript.squeeze(b"rho")?;
|
||||||
|
|
||||||
let claim_batch_joint = eval_E + rho * eval_W;
|
let claim_batch_joint = eval_E + rho * eval_W;
|
||||||
let num_rounds_z = num_rounds_x;
|
let num_rounds_z = num_rounds_x;
|
||||||
@@ -248,14 +241,10 @@ impl<G: Group, EE: EvaluationEngineTrait<G, CE = G::CE>> RelaxedR1CSSNARKTrait<G
|
|||||||
|
|
||||||
let eval_E_prime = claims_batch[1];
|
let eval_E_prime = claims_batch[1];
|
||||||
let eval_W_prime = claims_batch[3];
|
let eval_W_prime = claims_batch[3];
|
||||||
<[G::Scalar] as AppendToTranscriptTrait<G>>::append_to_transcript(
|
transcript.absorb(b"claims_batch", &[eval_E_prime, eval_W_prime].as_slice());
|
||||||
&[eval_E_prime, eval_W_prime],
|
|
||||||
b"claims_batch",
|
|
||||||
&mut transcript,
|
|
||||||
);
|
|
||||||
|
|
||||||
// we now combine evaluation claims at the same point rz into one
|
// we now combine evaluation claims at the same point rz into one
|
||||||
let gamma = G::Scalar::challenge(b"gamma", &mut transcript)?;
|
let gamma = transcript.squeeze(b"gamma")?;
|
||||||
let comm = U.comm_E + U.comm_W * gamma;
|
let comm = U.comm_E + U.comm_W * gamma;
|
||||||
let poly = W
|
let poly = W
|
||||||
.E
|
.E
|
||||||
@@ -285,8 +274,8 @@ impl<G: Group, EE: EvaluationEngineTrait<G, CE = G::CE>> RelaxedR1CSSNARKTrait<G
|
|||||||
let mut transcript = G::TE::new(b"RelaxedR1CSSNARK");
|
let mut transcript = G::TE::new(b"RelaxedR1CSSNARK");
|
||||||
|
|
||||||
// append the R1CSShape and RelaxedR1CSInstance to the transcript
|
// append the R1CSShape and RelaxedR1CSInstance to the transcript
|
||||||
vk.S.append_to_transcript(b"S", &mut transcript);
|
transcript.absorb(b"S", &vk.S);
|
||||||
U.append_to_transcript(b"U", &mut transcript);
|
transcript.absorb(b"U", U);
|
||||||
|
|
||||||
let (num_rounds_x, num_rounds_y) = (
|
let (num_rounds_x, num_rounds_y) = (
|
||||||
(vk.S.num_cons as f64).log2() as usize,
|
(vk.S.num_cons as f64).log2() as usize,
|
||||||
@@ -295,7 +284,7 @@ impl<G: Group, EE: EvaluationEngineTrait<G, CE = G::CE>> RelaxedR1CSSNARKTrait<G
|
|||||||
|
|
||||||
// outer sum-check
|
// outer sum-check
|
||||||
let tau = (0..num_rounds_x)
|
let tau = (0..num_rounds_x)
|
||||||
.map(|_i| G::Scalar::challenge(b"tau", &mut transcript))
|
.map(|_i| transcript.squeeze(b"t"))
|
||||||
.collect::<Result<Vec<G::Scalar>, NovaError>>()?;
|
.collect::<Result<Vec<G::Scalar>, NovaError>>()?;
|
||||||
|
|
||||||
let (claim_outer_final, r_x) =
|
let (claim_outer_final, r_x) =
|
||||||
@@ -312,19 +301,19 @@ impl<G: Group, EE: EvaluationEngineTrait<G, CE = G::CE>> RelaxedR1CSSNARKTrait<G
|
|||||||
return Err(NovaError::InvalidSumcheckProof);
|
return Err(NovaError::InvalidSumcheckProof);
|
||||||
}
|
}
|
||||||
|
|
||||||
<[G::Scalar] as AppendToTranscriptTrait<G>>::append_to_transcript(
|
transcript.absorb(
|
||||||
|
b"claims_outer",
|
||||||
&[
|
&[
|
||||||
self.claims_outer.0,
|
self.claims_outer.0,
|
||||||
self.claims_outer.1,
|
self.claims_outer.1,
|
||||||
self.claims_outer.2,
|
self.claims_outer.2,
|
||||||
self.eval_E,
|
self.eval_E,
|
||||||
],
|
]
|
||||||
b"claims_outer",
|
.as_slice(),
|
||||||
&mut transcript,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// inner sum-check
|
// inner sum-check
|
||||||
let r = G::Scalar::challenge(b"r", &mut transcript)?;
|
let r = transcript.squeeze(b"r")?;
|
||||||
let claim_inner_joint =
|
let claim_inner_joint =
|
||||||
self.claims_outer.0 + r * self.claims_outer.1 + r * r * self.claims_outer.2;
|
self.claims_outer.0 + r * self.claims_outer.1 + r * r * self.claims_outer.2;
|
||||||
|
|
||||||
@@ -380,13 +369,9 @@ impl<G: Group, EE: EvaluationEngineTrait<G, CE = G::CE>> RelaxedR1CSSNARKTrait<G
|
|||||||
}
|
}
|
||||||
|
|
||||||
// batch sum-check
|
// batch sum-check
|
||||||
<G::Scalar as AppendToTranscriptTrait<G>>::append_to_transcript(
|
transcript.absorb(b"eval_W", &self.eval_W);
|
||||||
&self.eval_W,
|
|
||||||
b"eval_W",
|
|
||||||
&mut transcript,
|
|
||||||
);
|
|
||||||
|
|
||||||
let rho = G::Scalar::challenge(b"rho", &mut transcript)?;
|
let rho = transcript.squeeze(b"rho")?;
|
||||||
let claim_batch_joint = self.eval_E + rho * self.eval_W;
|
let claim_batch_joint = self.eval_E + rho * self.eval_W;
|
||||||
let num_rounds_z = num_rounds_x;
|
let num_rounds_z = num_rounds_x;
|
||||||
let (claim_batch_final, r_z) =
|
let (claim_batch_final, r_z) =
|
||||||
@@ -405,14 +390,13 @@ impl<G: Group, EE: EvaluationEngineTrait<G, CE = G::CE>> RelaxedR1CSSNARKTrait<G
|
|||||||
return Err(NovaError::InvalidSumcheckProof);
|
return Err(NovaError::InvalidSumcheckProof);
|
||||||
}
|
}
|
||||||
|
|
||||||
<[G::Scalar] as AppendToTranscriptTrait<G>>::append_to_transcript(
|
transcript.absorb(
|
||||||
&[self.eval_E_prime, self.eval_W_prime],
|
|
||||||
b"claims_batch",
|
b"claims_batch",
|
||||||
&mut transcript,
|
&[self.eval_E_prime, self.eval_W_prime].as_slice(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// we now combine evaluation claims at the same point rz into one
|
// we now combine evaluation claims at the same point rz into one
|
||||||
let gamma = G::Scalar::challenge(b"gamma", &mut transcript)?;
|
let gamma = transcript.squeeze(b"gamma")?;
|
||||||
let comm = U.comm_E + U.comm_W * gamma;
|
let comm = U.comm_E + U.comm_W * gamma;
|
||||||
let eval = self.eval_E_prime + gamma * self.eval_W_prime;
|
let eval = self.eval_E_prime + gamma * self.eval_W_prime;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#![allow(clippy::type_complexity)]
|
#![allow(clippy::type_complexity)]
|
||||||
use super::polynomial::MultilinearPolynomial;
|
use super::polynomial::MultilinearPolynomial;
|
||||||
use crate::errors::NovaError;
|
use crate::errors::NovaError;
|
||||||
use crate::traits::{AppendToTranscriptTrait, ChallengeTrait, Group};
|
use crate::traits::{Group, TranscriptEngineTrait, TranscriptReprTrait};
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use ff::Field;
|
use ff::Field;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
@@ -43,10 +43,10 @@ impl<G: Group> SumcheckProof<G> {
|
|||||||
debug_assert_eq!(poly.eval_at_zero() + poly.eval_at_one(), e);
|
debug_assert_eq!(poly.eval_at_zero() + poly.eval_at_one(), e);
|
||||||
|
|
||||||
// append the prover's message to the transcript
|
// append the prover's message to the transcript
|
||||||
poly.append_to_transcript(b"poly", transcript);
|
transcript.absorb(b"p", &poly);
|
||||||
|
|
||||||
//derive the verifier's challenge for the next round
|
//derive the verifier's challenge for the next round
|
||||||
let r_i = G::Scalar::challenge(b"challenge", transcript)?;
|
let r_i = transcript.squeeze(b"c")?;
|
||||||
|
|
||||||
r.push(r_i);
|
r.push(r_i);
|
||||||
|
|
||||||
@@ -98,10 +98,10 @@ impl<G: Group> SumcheckProof<G> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// append the prover's message to the transcript
|
// append the prover's message to the transcript
|
||||||
poly.append_to_transcript(b"poly", transcript);
|
transcript.absorb(b"p", &poly);
|
||||||
|
|
||||||
//derive the verifier's challenge for the next round
|
//derive the verifier's challenge for the next round
|
||||||
let r_i = G::Scalar::challenge(b"challenge", transcript)?;
|
let r_i = transcript.squeeze(b"c")?;
|
||||||
r.push(r_i);
|
r.push(r_i);
|
||||||
polys.push(poly.compress());
|
polys.push(poly.compress());
|
||||||
|
|
||||||
@@ -172,10 +172,10 @@ impl<G: Group> SumcheckProof<G> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// append the prover's message to the transcript
|
// append the prover's message to the transcript
|
||||||
poly.append_to_transcript(b"poly", transcript);
|
transcript.absorb(b"p", &poly);
|
||||||
|
|
||||||
//derive the verifier's challenge for the next round
|
// derive the verifier's challenge for the next round
|
||||||
let r_i = G::Scalar::challenge(b"challenge", transcript)?;
|
let r_i = transcript.squeeze(b"c")?;
|
||||||
r.push(r_i);
|
r.push(r_i);
|
||||||
polys.push(poly.compress());
|
polys.push(poly.compress());
|
||||||
|
|
||||||
@@ -266,10 +266,10 @@ impl<G: Group> SumcheckProof<G> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// append the prover's message to the transcript
|
// append the prover's message to the transcript
|
||||||
poly.append_to_transcript(b"poly", transcript);
|
transcript.absorb(b"p", &poly);
|
||||||
|
|
||||||
//derive the verifier's challenge for the next round
|
//derive the verifier's challenge for the next round
|
||||||
let r_i = G::Scalar::challenge(b"challenge", transcript)?;
|
let r_i = transcript.squeeze(b"c")?;
|
||||||
r.push(r_i);
|
r.push(r_i);
|
||||||
polys.push(poly.compress());
|
polys.push(poly.compress());
|
||||||
|
|
||||||
@@ -396,12 +396,9 @@ impl<G: Group> CompressedUniPoly<G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: Group> AppendToTranscriptTrait<G> for UniPoly<G> {
|
impl<G: Group> TranscriptReprTrait<G> for UniPoly<G> {
|
||||||
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE) {
|
fn to_transcript_bytes(&self) -> Vec<u8> {
|
||||||
<[G::Scalar] as AppendToTranscriptTrait<G>>::append_to_transcript(
|
let coeffs = self.compress().coeffs_except_linear_term;
|
||||||
&self.coeffs,
|
coeffs.as_slice().to_transcript_bytes()
|
||||||
label,
|
|
||||||
transcript,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//! We require the commitment engine to provide a commitment to vectors with a single group element
|
//! We require the commitment engine to provide a commitment to vectors with a single group element
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::NovaError,
|
errors::NovaError,
|
||||||
traits::{AbsorbInROTrait, AppendToTranscriptTrait, Group},
|
traits::{AbsorbInROTrait, Group, TranscriptReprTrait},
|
||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
@@ -65,10 +65,10 @@ pub trait CommitmentTrait<G: Group>:
|
|||||||
+ Eq
|
+ Eq
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync
|
+ Sync
|
||||||
|
+ TranscriptReprTrait<G>
|
||||||
+ Serialize
|
+ Serialize
|
||||||
+ for<'de> Deserialize<'de>
|
+ for<'de> Deserialize<'de>
|
||||||
+ AbsorbInROTrait<G>
|
+ AbsorbInROTrait<G>
|
||||||
+ AppendToTranscriptTrait<G>
|
|
||||||
+ CommitmentOps
|
+ CommitmentOps
|
||||||
+ CommitmentOpsOwned
|
+ CommitmentOpsOwned
|
||||||
+ ScalarMul<G::Scalar>
|
+ ScalarMul<G::Scalar>
|
||||||
@@ -80,9 +80,9 @@ pub trait CommitmentTrait<G: Group>:
|
|||||||
+ Eq
|
+ Eq
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync
|
+ Sync
|
||||||
|
+ TranscriptReprTrait<G>
|
||||||
+ Serialize
|
+ Serialize
|
||||||
+ for<'de> Deserialize<'de>
|
+ for<'de> Deserialize<'de>;
|
||||||
+ AppendToTranscriptTrait<G>;
|
|
||||||
|
|
||||||
/// Compresses self into a compressed commitment
|
/// Compresses self into a compressed commitment
|
||||||
fn compress(&self) -> Self::CompressedCommitment;
|
fn compress(&self) -> Self::CompressedCommitment;
|
||||||
|
|||||||
@@ -34,15 +34,19 @@ pub trait Group:
|
|||||||
+ for<'de> Deserialize<'de>
|
+ for<'de> Deserialize<'de>
|
||||||
{
|
{
|
||||||
/// A type representing an element of the base field of the group
|
/// A type representing an element of the base field of the group
|
||||||
type Base: PrimeField + PrimeFieldBits + Serialize + for<'de> Deserialize<'de>;
|
type Base: PrimeField
|
||||||
|
+ PrimeFieldBits
|
||||||
|
+ TranscriptReprTrait<Self>
|
||||||
|
+ Serialize
|
||||||
|
+ for<'de> Deserialize<'de>;
|
||||||
|
|
||||||
/// A type representing an element of the scalar field of the group
|
/// A type representing an element of the scalar field of the group
|
||||||
type Scalar: PrimeField
|
type Scalar: PrimeField
|
||||||
+ PrimeFieldBits
|
+ PrimeFieldBits
|
||||||
+ PrimeFieldExt
|
+ PrimeFieldExt
|
||||||
+ ChallengeTrait<Self>
|
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync
|
+ Sync
|
||||||
|
+ TranscriptReprTrait<Self>
|
||||||
+ Serialize
|
+ Serialize
|
||||||
+ for<'de> Deserialize<'de>;
|
+ for<'de> Deserialize<'de>;
|
||||||
|
|
||||||
@@ -97,16 +101,23 @@ pub trait Group:
|
|||||||
|
|
||||||
/// Represents a compressed version of a group element
|
/// Represents a compressed version of a group element
|
||||||
pub trait CompressedGroup:
|
pub trait CompressedGroup:
|
||||||
Clone + Copy + Debug + Eq + Sized + Send + Sync + Serialize + for<'de> Deserialize<'de> + 'static
|
Clone
|
||||||
|
+ Copy
|
||||||
|
+ Debug
|
||||||
|
+ Eq
|
||||||
|
+ Sized
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ TranscriptReprTrait<Self::GroupElement>
|
||||||
|
+ Serialize
|
||||||
|
+ for<'de> Deserialize<'de>
|
||||||
|
+ 'static
|
||||||
{
|
{
|
||||||
/// A type that holds the decompressed version of the compressed group element
|
/// A type that holds the decompressed version of the compressed group element
|
||||||
type GroupElement: Group + Serialize + for<'de> Deserialize<'de>;
|
type GroupElement: Group + Serialize + for<'de> Deserialize<'de>;
|
||||||
|
|
||||||
/// Decompresses the compressed group element
|
/// Decompresses the compressed group element
|
||||||
fn decompress(&self) -> Option<Self::GroupElement>;
|
fn decompress(&self) -> Option<Self::GroupElement>;
|
||||||
|
|
||||||
/// Returns a byte array representing the compressed group element
|
|
||||||
fn as_bytes(&self) -> Vec<u8>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A helper trait to absorb different objects in RO
|
/// A helper trait to absorb different objects in RO
|
||||||
@@ -196,56 +207,43 @@ impl<T, Rhs, Output> ScalarMul<Rhs, Output> for T where T: Mul<Rhs, Output = Out
|
|||||||
pub trait ScalarMulOwned<Rhs, Output = Self>: for<'r> ScalarMul<&'r Rhs, Output> {}
|
pub trait ScalarMulOwned<Rhs, Output = Self>: for<'r> ScalarMul<&'r Rhs, Output> {}
|
||||||
impl<T, Rhs, Output> ScalarMulOwned<Rhs, Output> for T where T: for<'r> ScalarMul<&'r Rhs, Output> {}
|
impl<T, Rhs, Output> ScalarMulOwned<Rhs, Output> for T where T: for<'r> ScalarMul<&'r Rhs, Output> {}
|
||||||
|
|
||||||
|
/// This trait allows types to implement how they want to be added to TranscriptEngine
|
||||||
|
pub trait TranscriptReprTrait<G: Group>: Send + Sync {
|
||||||
|
/// returns a byte representation of self to be added to the transcript
|
||||||
|
fn to_transcript_bytes(&self) -> Vec<u8>;
|
||||||
|
}
|
||||||
|
|
||||||
/// This trait defines the behavior of a transcript engine compatible with Spartan
|
/// This trait defines the behavior of a transcript engine compatible with Spartan
|
||||||
pub trait TranscriptEngineTrait<G: Group>: Send + Sync {
|
pub trait TranscriptEngineTrait<G: Group>: Send + Sync {
|
||||||
/// initializes the transcript
|
/// initializes the transcript
|
||||||
fn new(label: &'static [u8]) -> Self;
|
fn new(label: &'static [u8]) -> Self;
|
||||||
|
|
||||||
/// returns a scalar element of the group as a challenge
|
/// returns a scalar element of the group as a challenge
|
||||||
fn squeeze_scalar(&mut self, label: &'static [u8]) -> Result<G::Scalar, NovaError>;
|
fn squeeze(&mut self, label: &'static [u8]) -> Result<G::Scalar, NovaError>;
|
||||||
|
|
||||||
/// absorbs a label and a sequence of bytes
|
/// absorbs any type that implements TranscriptReprTrait under a label
|
||||||
fn absorb_bytes(&mut self, label: &'static [u8], bytes: &[u8]);
|
fn absorb<T: TranscriptReprTrait<G>>(&mut self, label: &'static [u8], o: &T);
|
||||||
}
|
|
||||||
|
|
||||||
/// A helper trait to append different types to the transcript
|
/// adds a domain separator
|
||||||
pub trait AppendToTranscriptTrait<G: Group> {
|
fn dom_sep(&mut self, bytes: &'static [u8]);
|
||||||
/// appends the value to the transcript under the provided label
|
|
||||||
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A helper trait to generate challenges using a transcript object
|
|
||||||
pub trait ChallengeTrait<G: Group> {
|
|
||||||
/// Returns a challenge from the transcript
|
|
||||||
fn challenge(label: &'static [u8], transcript: &mut G::TE) -> Result<Self, NovaError>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defines additional methods on PrimeField objects
|
/// Defines additional methods on PrimeField objects
|
||||||
pub trait PrimeFieldExt: PrimeField {
|
pub trait PrimeFieldExt: PrimeField {
|
||||||
/// Returns a scalar representing the bytes
|
/// Returns a scalar representing the bytes
|
||||||
fn from_uniform(bytes: &[u8]) -> Self;
|
fn from_uniform(bytes: &[u8]) -> Self;
|
||||||
|
|
||||||
/// Returns a vector of bytes representing the scalar
|
|
||||||
fn to_bytes(&self) -> Vec<u8>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: Group<Scalar = F>, F: PrimeField + PrimeFieldExt> AppendToTranscriptTrait<G> for F {
|
impl<G: Group<Scalar = F>, F: PrimeField + TranscriptReprTrait<G>> TranscriptReprTrait<G>
|
||||||
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE) {
|
for &[F]
|
||||||
transcript.absorb_bytes(label, &<Self as PrimeFieldExt>::to_bytes(self));
|
{
|
||||||
}
|
fn to_transcript_bytes(&self) -> Vec<u8> {
|
||||||
}
|
(0..self.len())
|
||||||
|
.map(|i| <F as TranscriptReprTrait<G>>::to_transcript_bytes(&self[i]))
|
||||||
impl<G: Group<Scalar = F>, F: PrimeField + PrimeFieldExt> AppendToTranscriptTrait<G> for [F] {
|
|
||||||
fn append_to_transcript(&self, label: &'static [u8], transcript: &mut G::TE) {
|
|
||||||
let bytes = (0..self.len())
|
|
||||||
.map(|i| <F as PrimeFieldExt>::to_bytes(&self[i]))
|
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect::<Vec<u8>>();
|
.collect::<Vec<u8>>()
|
||||||
transcript.absorb_bytes(label, &bytes);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user