Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 9 additions & 14 deletions benches/whir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ type MyChallenger = DuplexChallenger<F, Poseidon16, 16, 8>;

#[allow(clippy::type_complexity)]
fn prepare_inputs() -> (
WhirConfig<EF, F, MerkleHash, MerkleCompress, MyChallenger>,
Radix2DFTSmallBatch<F>,
WhirConfig<EF, F, MerkleHash, MerkleCompress, MyChallenger, Radix2DFTSmallBatch<F>>,
EvaluationsList<F>,
EqStatement<EF>,
MyChallenger,
Expand Down Expand Up @@ -80,6 +79,7 @@ fn prepare_inputs() -> (
folding_factor,
merkle_hash,
merkle_compress,
dft: Radix2DFTSmallBatch::<F>::default(),
soundness_type,
starting_log_inv_rate: starting_rate,
rs_domain_initial_reduction_factor,
Expand Down Expand Up @@ -115,30 +115,25 @@ fn prepare_inputs() -> (
let mut domainsep = DomainSeparator::new(vec![]);

// Commit protocol parameters and proof type to the domain separator.
domainsep.commit_statement::<_, _, _, 32>(&params);
domainsep.add_whir_proof::<_, _, _, 32>(&params);
domainsep.commit_statement::<_, _, _, _, 32>(&params);
domainsep.add_whir_proof::<_, _, _, _, 32>(&params);

// Instantiate the Fiat-Shamir challenger from an empty seed and Keccak.
let challenger = MyChallenger::new(poseidon16);

// DFT backend setup

// Construct a Radix-2 FFT backend that supports small batch DFTs over `F`.
let dft = Radix2DFTSmallBatch::<F>::new(1 << params.max_fft_size());

// Return all preprocessed components needed to run commit/prove/verify benchmarks.
(params, dft, polynomial, statement, challenger, domainsep)
(params, polynomial, statement, challenger, domainsep)
}

fn benchmark_commit_and_prove(c: &mut Criterion) {
let (params, dft, polynomial, statement, challenger, domainsep) = prepare_inputs();
let (params, polynomial, statement, challenger, domainsep) = prepare_inputs();

c.bench_function("commit", |b| {
b.iter(|| {
let mut prover_state = domainsep.to_prover_state(challenger.clone());
let committer = CommitmentWriter::new(&params);
let _witness = committer
.commit(&dft, &mut prover_state, polynomial.clone())
.commit(&mut prover_state, polynomial.clone())
.unwrap();
});
});
Expand All @@ -148,12 +143,12 @@ fn benchmark_commit_and_prove(c: &mut Criterion) {
let mut prover_state = domainsep.to_prover_state(challenger.clone());
let committer = CommitmentWriter::new(&params);
let witness = committer
.commit(&dft, &mut prover_state, polynomial.clone())
.commit(&mut prover_state, polynomial.clone())
.unwrap();

let prover = Prover(&params);
prover
.prove(&dft, &mut prover_state, statement.clone(), witness)
.prove(&mut prover_state, statement.clone(), witness)
.unwrap();
});
});
Expand Down
15 changes: 6 additions & 9 deletions src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,14 @@ fn main() {
folding_factor,
merkle_hash,
merkle_compress,
dft: Radix2DFTSmallBatch::<F>::default(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It becomes a bit faster on my end when we configure the fft instance like

 let max_fft_size = num_variables + starting_rate - folding_factor.at_round(0);
 let dft = Radix2DFTSmallBatch::<F>::new(1 << max_fft_size);

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you are right (I've the same locally), let us not merge this for now since we don't want to degrade performance for now, especially for such a detail.

I've another idea that would unblock things and would be to add a new method new(size:usize) inside this trait https://github.com/Plonky3/Plonky3/blob/658115aae28312e97cd3ef38d1ab046839f734a8/dft/src/traits.rs#L27. This would allow us to just rely on this and be able to init any DFT. Will check this.

soundness_type,
starting_log_inv_rate: starting_rate,
rs_domain_initial_reduction_factor,
univariate_skip: false,
};

let params = WhirConfig::<EF, F, MerkleHash, MerkleCompress, MyChallenger>::new(
let params = WhirConfig::<EF, F, MerkleHash, MerkleCompress, MyChallenger, _>::new(
num_variables,
whir_params,
);
Expand All @@ -147,8 +148,8 @@ fn main() {

// Define the Fiat-Shamir domain separator pattern for committing and proving
let mut domainsep = DomainSeparator::new(vec![]);
domainsep.commit_statement::<_, _, _, 32>(&params);
domainsep.add_whir_proof::<_, _, _, 32>(&params);
domainsep.commit_statement::<_, _, _, _, 32>(&params);
domainsep.add_whir_proof::<_, _, _, _, 32>(&params);

println!("=========================================");
println!("Whir (PCS) 🌪️");
Expand All @@ -164,12 +165,8 @@ fn main() {
// Commit to the polynomial and produce a witness
let committer = CommitmentWriter::new(&params);

let dft = Radix2DFTSmallBatch::<F>::new(1 << params.max_fft_size());

let time = Instant::now();
let witness = committer
.commit(&dft, &mut prover_state, polynomial)
.unwrap();
let witness = committer.commit(&mut prover_state, polynomial).unwrap();
let commit_time = time.elapsed();

// Generate a proof using the prover
Expand All @@ -178,7 +175,7 @@ fn main() {
// Generate a proof for the given statement and witness
let time = Instant::now();
prover
.prove(&dft, &mut prover_state, statement.clone(), witness)
.prove(&mut prover_state, statement.clone(), witness)
.unwrap();
let opening_time = time.elapsed();

Expand Down
16 changes: 10 additions & 6 deletions src/fiat_shamir/domain_separator.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::marker::PhantomData;

use p3_challenger::{FieldChallenger, GrindingChallenger};
use p3_dft::TwoAdicSubgroupDft;
use p3_field::{ExtensionField, Field, TwoAdicField};

use crate::{
Expand Down Expand Up @@ -129,11 +130,13 @@ where
}
}

pub fn commit_statement<HC, C, Challenger, const DIGEST_ELEMS: usize>(
pub fn commit_statement<HC, C, Challenger, Dft, const DIGEST_ELEMS: usize>(
&mut self,
params: &WhirConfig<EF, F, HC, C, Challenger>,
params: &WhirConfig<EF, F, HC, C, Challenger, Dft>,
) where
F: TwoAdicField,
Challenger: FieldChallenger<F> + GrindingChallenger<Witness = F>,
Dft: TwoAdicSubgroupDft<F>,
{
// TODO: Add params
self.observe(DIGEST_ELEMS, Observe::MerkleDigest);
Expand All @@ -143,13 +146,14 @@ where
}
}

pub fn add_whir_proof<HC, C, Challenger, const DIGEST_ELEMS: usize>(
pub fn add_whir_proof<HC, C, Challenger, Dft, const DIGEST_ELEMS: usize>(
&mut self,
params: &WhirConfig<EF, F, HC, C, Challenger>,
params: &WhirConfig<EF, F, HC, C, Challenger, Dft>,
) where
Challenger: FieldChallenger<F> + GrindingChallenger<Witness = F>,
EF: TwoAdicField,
F: TwoAdicField,
EF: TwoAdicField,
Challenger: FieldChallenger<F> + GrindingChallenger<Witness = F>,
Dft: TwoAdicSubgroupDft<F>,
{
// TODO: Add statement
if params.initial_statement {
Expand Down
6 changes: 4 additions & 2 deletions src/parameters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ impl FoldingFactor {

/// Configuration parameters for WHIR proofs.
#[derive(Clone, Debug)]
pub struct ProtocolParameters<H, C> {
pub struct ProtocolParameters<H, C, Dft> {
/// Whether the initial statement is included in the proof.
pub initial_statement: bool,
/// The logarithmic inverse rate for sampling.
Expand All @@ -167,11 +167,13 @@ pub struct ProtocolParameters<H, C> {
pub merkle_hash: H,
/// Compression method used in the Merkle tree.
pub merkle_compress: C,
/// DFT implementation for polynomial operations.
pub dft: Dft,
/// Whether the univariate skip optimization is enabled for the sumcheck protocol.
pub univariate_skip: bool,
}

impl<H, C> Display for ProtocolParameters<H, C> {
impl<H, C, Dft> Display for ProtocolParameters<H, C, Dft> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(
f,
Expand Down
64 changes: 31 additions & 33 deletions src/whir/committer/reader.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{fmt::Debug, ops::Deref};

use p3_challenger::{FieldChallenger, GrindingChallenger};
use p3_dft::TwoAdicSubgroupDft;
use p3_field::{ExtensionField, Field, TwoAdicField};
use p3_symmetric::Hash;

Expand Down Expand Up @@ -97,27 +98,29 @@ where
/// The `CommitmentReader` wraps the WHIR configuration and provides a convenient
/// method to extract a `ParsedCommitment` by reading values from the Fiat-Shamir transcript.
#[derive(Debug)]
pub struct CommitmentReader<'a, EF, F, H, C, Challenger>(
/// Reference to the verifiers configuration object.
pub struct CommitmentReader<'a, EF, F, H, C, Challenger, Dft>(
/// Reference to the verifier's configuration object.
///
/// This contains all parameters needed to parse the commitment,
/// including how many out-of-domain samples are expected.
&'a WhirConfig<EF, F, H, C, Challenger>,
&'a WhirConfig<EF, F, H, C, Challenger, Dft>,
)
where
F: Field,
EF: ExtensionField<F>;
F: TwoAdicField,
EF: ExtensionField<F>,
Dft: TwoAdicSubgroupDft<F>;

impl<'a, EF, F, H, C, Challenger> CommitmentReader<'a, EF, F, H, C, Challenger>
impl<'a, EF, F, H, C, Challenger, Dft> CommitmentReader<'a, EF, F, H, C, Challenger, Dft>
where
F: TwoAdicField,
EF: ExtensionField<F> + TwoAdicField,
Challenger: FieldChallenger<F> + GrindingChallenger<Witness = F>,
Dft: TwoAdicSubgroupDft<F>,
{
/// Create a new commitment reader from a WHIR configuration.
///
/// This allows the verifier to parse a commitment from the Fiat-Shamir transcript.
pub const fn new(params: &'a WhirConfig<EF, F, H, C, Challenger>) -> Self {
pub const fn new(params: &'a WhirConfig<EF, F, H, C, Challenger, Dft>) -> Self {
Self(params)
}

Expand All @@ -137,12 +140,13 @@ where
}
}

impl<EF, F, H, C, Challenger> Deref for CommitmentReader<'_, EF, F, H, C, Challenger>
impl<EF, F, H, C, Challenger, Dft> Deref for CommitmentReader<'_, EF, F, H, C, Challenger, Dft>
where
F: Field,
F: TwoAdicField,
EF: ExtensionField<F>,
Dft: TwoAdicSubgroupDft<F>,
{
type Target = WhirConfig<EF, F, H, C, Challenger>;
type Target = WhirConfig<EF, F, H, C, Challenger, Dft>;

fn deref(&self) -> &Self::Target {
self.0
Expand Down Expand Up @@ -179,7 +183,14 @@ mod tests {
num_variables: usize,
ood_samples: usize,
) -> (
WhirConfig<BabyBear, BabyBear, MyHash, MyCompress, MyChallenger>,
WhirConfig<
BabyBear,
BabyBear,
MyHash,
MyCompress,
MyChallenger,
Radix2DFTSmallBatch<BabyBear>,
>,
rand::rngs::ThreadRng,
) {
let mut rng = SmallRng::seed_from_u64(1);
Expand All @@ -200,6 +211,7 @@ mod tests {
folding_factor: FoldingFactor::ConstantFromSecondRound(4, 4),
merkle_hash,
merkle_compress,
dft: Radix2DFTSmallBatch::<BabyBear>::default(),
soundness_type: SecurityAssumption::CapacityBound,
starting_log_inv_rate: 1,
univariate_skip: false,
Expand All @@ -226,12 +238,9 @@ mod tests {
// Instantiate the committer using the test config.
let committer = CommitmentWriter::new(&params);

// Use a DFT engine to expand/fold the polynomial for evaluation.
let dft = Radix2DFTSmallBatch::<F>::default();

// Set up Fiat-Shamir transcript and commit the protocol parameters.
let mut ds = DomainSeparator::new(vec![]);
ds.commit_statement::<_, _, _, 8>(&params);
ds.commit_statement::<_, _, _, _, 8>(&params);

// Create the prover state from the transcript.
let mut rng = SmallRng::seed_from_u64(1);
Expand All @@ -240,9 +249,7 @@ mod tests {
let mut prover_state = ds.to_prover_state(challenger.clone());

// Commit the polynomial and obtain a witness (root, Merkle proof, OOD evaluations).
let witness = committer
.commit(&dft, &mut prover_state, polynomial)
.unwrap();
let witness = committer.commit(&mut prover_state, polynomial).unwrap();

// Simulate verifier state using transcript view of prover’s nonce string.
let mut verifier_state =
Expand All @@ -269,21 +276,18 @@ mod tests {

// Set up the committer and DFT engine.
let committer = CommitmentWriter::new(&params);
let dft = Radix2DFTSmallBatch::<F>::default();

// Begin the transcript and commit to the statement parameters.
let mut ds = DomainSeparator::new(vec![]);
ds.commit_statement::<_, _, _, 8>(&params);
ds.commit_statement::<_, _, _, _, 8>(&params);

// Generate the prover state from the transcript.
let mut rng = SmallRng::seed_from_u64(1);
let challenger = MyChallenger::new(Perm::new_from_rng_128(&mut rng));
let mut prover_state = ds.to_prover_state(challenger.clone());

// Commit the polynomial to obtain the witness.
let witness = committer
.commit(&dft, &mut prover_state, polynomial)
.unwrap();
let witness = committer.commit(&mut prover_state, polynomial).unwrap();

// Initialize the verifier view of the transcript.
let mut verifier_state =
Expand All @@ -310,11 +314,10 @@ mod tests {

// Initialize the committer and DFT engine.
let committer = CommitmentWriter::new(&params);
let dft = Radix2DFTSmallBatch::<F>::default();

// Start a new transcript and commit to the public parameters.
let mut ds = DomainSeparator::new(vec![]);
ds.commit_statement::<_, _, _, 8>(&params);
ds.commit_statement::<_, _, _, _, 8>(&params);

// Create prover state from the transcript.
let mut rng = SmallRng::seed_from_u64(1);
Expand All @@ -323,9 +326,7 @@ mod tests {
let mut prover_state = ds.to_prover_state(challenger.clone());

// Commit the polynomial and obtain the witness.
let witness = committer
.commit(&dft, &mut prover_state, polynomial)
.unwrap();
let witness = committer.commit(&mut prover_state, polynomial).unwrap();

// Initialize verifier view from prover's transcript string.
let mut verifier_state =
Expand All @@ -350,20 +351,17 @@ mod tests {

// Instantiate a committer and DFT backend.
let committer = CommitmentWriter::new(&params);
let dft = Radix2DFTSmallBatch::<F>::default();

// Set up Fiat-Shamir transcript and commit to the public parameters.
let mut ds = DomainSeparator::new(vec![]);
ds.commit_statement::<_, _, _, 8>(&params);
ds.commit_statement::<_, _, _, _, 8>(&params);

// Generate prover and verifier transcript states.
let mut rng = SmallRng::seed_from_u64(1);
let challenger = MyChallenger::new(Perm::new_from_rng_128(&mut rng));

let mut prover_state = ds.to_prover_state(challenger.clone());
let witness = committer
.commit(&dft, &mut prover_state, polynomial)
.unwrap();
let witness = committer.commit(&mut prover_state, polynomial).unwrap();
let mut verifier_state =
ds.to_verifier_state(prover_state.proof_data().to_vec(), challenger);

Expand Down
Loading