Skip to content

Commit

Permalink
fix docstring
Browse files Browse the repository at this point in the history
  • Loading branch information
zk-steve committed May 16, 2024
1 parent 7a4a780 commit 16f63c4
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 7 deletions.
84 changes: 78 additions & 6 deletions fri/src/fiat_shamir/transcript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,38 @@ use rand::prelude::StdRng;
use rand::SeedableRng;
use sha2::Digest;

/// A transcript for generating cryptographic challenges using the Fiat-Shamir transform with a cryptographic hash function and a prime field.
///
/// The `Transcript` struct maintains an internal state and accumulates data to produce cryptographic challenges using the Fiat-Shamir transform.
/// It utilizes a cryptographic hash function `T` and a prime field `F` for generating challenges.
///
/// # Type Parameters
///
/// - `T`: A type implementing the `Digest` trait from the `sha2` crate, used as the cryptographic hash function.
/// - `F`: A prime field type implementing the `PrimeField` trait from the `ark_ff` crate, used for generating challenges.
///
/// # Fiat-Shamir Transform
///
/// The Fiat-Shamir transform is a method for transforming a protocol that involves interactive proofs into one that is non-interactive,
/// using the output of a random oracle (hash function) to simulate the interaction.
///
/// # Examples
///
/// ```
/// use ark_ff::Field;
/// use rand::prelude::StdRng;
/// use rand::{Rng, SeedableRng};
/// use sha2::Sha256;
/// use fri::fiat_shamir::transcript::Transcript;
/// use fri::fields::goldilocks::Fq;
///
/// static SECRET_X: Fq = Fq::ZERO;
///
/// let mut transcript = Transcript::<Sha256, Fq>::new(SECRET_X);
/// let query = Fq::from(928459);
/// transcript.digest(query);
/// let c1 = transcript.generate_a_challenge();
/// ```
#[derive(Default, Clone)]
pub struct Transcript<T: Digest + Default, F: PrimeField> {
data: Option<Vec<u8>>,
Expand All @@ -17,20 +49,34 @@ pub struct Transcript<T: Digest + Default, F: PrimeField> {
}

impl<T: Digest + Default, F: PrimeField> Transcript<T, F> {
pub fn new(secret: F) -> Self {
/// Constructs a new `Transcript` initialized with the given message value.
///
/// # Parameters
///
/// - `message`: A message value of type `F` used to initialize the transcript.
///
/// # Returns
///
/// A new `Transcript` initialized with the given message value.
pub fn new(message: F) -> Self {
let mut transcript = Self {
data: None,
index: 0,
generated: true,
_phantom_data: Default::default(),
_phantom_data2: Default::default(),
};
transcript.digest(secret);
transcript.digest(message);
transcript
}
}

impl<T: Digest + Default, F: PrimeField> Transcript<T, F> {
/// Updates the transcript by digesting the provided message.
///
/// # Parameters
///
/// - `message`: A message of type `F` to be digested into the transcript.
pub fn digest(&mut self, message: F) {
let mut hasher = T::default();
hasher.update(self.data.take().unwrap_or_default());
Expand All @@ -52,20 +98,39 @@ impl<T: Digest + Default, F: PrimeField> Transcript<T, F> {
StdRng::seed_from_u64(seed)
}

/// Generates a cryptographic challenge using the internal state of the transcript.
///
/// # Returns
///
/// A cryptographic challenge of type `F`.
pub fn generate_a_challenge(&mut self) -> F {
let mut rng = self.generate_rng_with_seed();
F::rand(&mut rng)
}

/// Generates multiple cryptographic challenges using the internal state of the transcript.
///
/// # Parameters
///
/// - `number`: The number of challenges to generate.
///
/// # Returns
///
/// A vector containing the generated cryptographic challenges.
pub fn generate_challenges(&mut self, number: usize) -> Vec<F> {
let mut rng = self.generate_rng_with_seed();
(0..number).map(|_| F::rand(&mut rng)).collect()
}

pub fn generate_a_challenge_usize(&mut self) -> usize {
self.generate_a_challenge().into_bigint().as_ref()[0] as usize
}

/// Generates multiple cryptographic challenges as `usize` values using the internal state of the transcript.
///
/// # Parameters
///
/// - `number`: The number of challenges to generate.
///
/// # Returns
///
/// A vector containing the generated cryptographic challenges as `usize` values.
pub fn generate_challenge_list_usize(&mut self, number: usize) -> Vec<usize> {
self.generate_challenges(number)
.into_iter()
Expand All @@ -87,6 +152,7 @@ mod tests {

#[test]
fn test_generate_a_challenge_should_return_different() {
// Ensure that each generated challenge is different when using different queries.
let mut transcript = Transcript::<Sha256, Fq>::new(SECRET_X);
let query = Fq::from(StdRng::from_entropy().gen::<u128>());
transcript.digest(query);
Expand All @@ -98,6 +164,7 @@ mod tests {

#[test]
fn test_generate_a_challenge_deterministic() {
// Ensure that the same query generates the same challenge.
let mut transcript = Transcript::<Sha256, Fq>::new(SECRET_X);
let query = Fq::from(928459);

Expand All @@ -111,6 +178,7 @@ mod tests {

#[test]
fn test_generate_challenge_list_diff_elements() {
// Ensure that a list of generated challenges contains different elements.
let mut transcript = Transcript::<Sha256, Fq>::new(SECRET_X);
let size = 5;
transcript.digest(Fq::from(31313213));
Expand All @@ -125,6 +193,7 @@ mod tests {

#[test]
fn test_generate_challenge_list_deterministic() {
// Ensure that generating challenges multiple times with the same inputs produces the same results.
let mut transcript = Transcript::<Sha256, Fq>::new(SECRET_X);
let mut transcript2 = Transcript::<Sha256, Fq>::new(SECRET_X);
let size = 5;
Expand All @@ -139,6 +208,7 @@ mod tests {
#[test]
#[should_panic]
fn safe_guard() {
// Ensure that panic is triggered when generating challenges without digesting any more queries.
let mut transcript = Transcript::<Sha256, Fq>::new(SECRET_X);
let size = 5;
transcript.digest(Fq::from(StdRng::from_entropy().gen::<u128>()));
Expand All @@ -148,6 +218,7 @@ mod tests {

#[test]
fn test_generate_index_list_diff_elements() {
// Ensure that a list of generated challenges as `usize` values contains different elements.
let mut transcript = Transcript::<Sha256, Fq>::new(SECRET_X);
let size = 5;
transcript.digest(Fq::from(31313213));
Expand All @@ -162,6 +233,7 @@ mod tests {

#[test]
fn test_generate_index_list_deterministic() {
// Ensure that generating challenges as `usize` values multiple times with the same inputs produces the same results.
let mut transcript = Transcript::<Sha256, Fq>::new(SECRET_X);
let mut transcript2 = Transcript::<Sha256, Fq>::new(SECRET_X);
let size = 5;
Expand Down
2 changes: 1 addition & 1 deletion fri/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mod fiat_shamir;
pub mod fiat_shamir;
pub mod fields;
mod fri_layer;
mod hasher;
Expand Down

0 comments on commit 16f63c4

Please sign in to comment.