Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
3833e84
add from_beta_to_index function
ColoCarletti Sep 3, 2025
01ebb68
add from_beta_to_index function
ColoCarletti Sep 3, 2025
952506d
add comments
nicole-graus Sep 4, 2025
7689906
add accumulators functions
ColoCarletti Sep 5, 2025
a32b93c
implement calculate_p_beta harcoded adn idx4
nicole-graus Sep 5, 2025
ad01a1f
function compute_accumulators finished and working
nicole-graus Sep 8, 2025
69a01f1
refactor, save work
nicole-graus Sep 8, 2025
15c4f04
First draft of algorithm 4 (svo three rounds)
nicole-graus Sep 9, 2025
7cdd0c3
fix small_value_sumcheck_three_rounds: change L_inf. And add test
nicole-graus Sep 10, 2025
b2baf94
Add comments
nicole-graus Sep 15, 2025
7bde7f6
implement procedure 2 from the paper
jotabulacios Sep 15, 2025
9df232c
add procedura 9
ColoCarletti Sep 15, 2025
cb919ee
Merge branch 'implement_svo' of github.com:lambdaclass/whir-p3 into i…
ColoCarletti Sep 15, 2025
4d5429a
rm changes in poly/evals
ColoCarletti Sep 16, 2025
4bd1875
add acc test for round 2
ColoCarletti Sep 17, 2025
3bb2007
fix t_accumulators
ColoCarletti Sep 17, 2025
044c1d8
add test for A_2(inf, 0)
jotabulacios Sep 18, 2025
d0b1ee0
add lienar utils
ColoCarletti Sep 19, 2025
a44622e
Merge branch 'implement_svo' of github.com:lambdaclass/whir-p3 into i…
ColoCarletti Sep 19, 2025
c606bda
fix imports
ColoCarletti Sep 19, 2025
d923a5e
save work
jotabulacios Sep 19, 2025
e66ca90
save work
jotabulacios Sep 22, 2025
6c856cd
save works
nicole-graus Sep 22, 2025
3b9053f
add linear function tests
ColoCarletti Sep 25, 2025
9482c39
refactor
ColoCarletti Sep 25, 2025
05e49ad
randomize tests
ColoCarletti Sep 25, 2025
b1ce338
fix x_out num of variables
ColoCarletti Sep 25, 2025
af5fbb0
compare test
ColoCarletti Sep 25, 2025
5619228
magic fix
ColoCarletti Sep 25, 2025
f0bb4d2
fix svo eq and refactor (new files)
nicole-graus Sep 26, 2025
fc7bcf2
start integration. Test not working
nicole-graus Sep 29, 2025
a5c8dd3
final assert not working
nicole-graus Sep 29, 2025
3c3fdff
test not working. prover and verifier are doing the same
nicole-graus Sep 29, 2025
cd269bf
final assert not working
nicole-graus Oct 1, 2025
b926cf7
refactor
ColoCarletti Oct 1, 2025
46671a1
We change the order of the challenges: r_1, r_2, r_8, ..., r_3
nicole-graus Oct 1, 2025
616b198
test working
nicole-graus Oct 3, 2025
af12bd9
Merge pull request #1 from lambdaclass/svo_integration
nicole-graus Oct 3, 2025
954c005
wip
ColoCarletti Oct 3, 2025
f210d40
rm evaluations of t in infinity
ColoCarletti Oct 6, 2025
139046f
merge implement_svo
ColoCarletti Oct 6, 2025
313fbc2
fix merge errors
ColoCarletti Oct 6, 2025
f804e11
fix
ColoCarletti Oct 6, 2025
3ff1dec
Merge pull request #2 from lambdaclass/refactor_svo
ColoCarletti Oct 6, 2025
534c156
rm unused imports
ColoCarletti Oct 8, 2025
05f0f59
implement algorithm 5. Test not working
nicole-graus Oct 13, 2025
9154aa5
fix errors. Test not working
nicole-graus Oct 13, 2025
7d836b5
fix indexing problem
jotabulacios Oct 14, 2025
0a03c8f
improve function documentation
jotabulacios Oct 15, 2025
03eaa7c
Merge pull request #4 from lambdaclass/algorithm_5
ColoCarletti Oct 15, 2025
bbd1ea7
Merge branch 'implement_svo' of github.com:lambdaclass/whir-p3 into i…
ColoCarletti Oct 15, 2025
34d8021
minor changes in algorithm_5. Add parallel for compress_svo
nicole-graus Oct 16, 2025
6856c4a
Merge branch 'implement_svo' of github.com:lambdaclass/whir-p3 into i…
ColoCarletti Oct 27, 2025
a2f7501
use par_iter and hardcode accumulators
jotabulacios Oct 27, 2025
bc31b7a
reuse buffer in accumulator calculation
jotabulacios Oct 27, 2025
159b751
Improve memory access pattern in accumulator loopp
jotabulacios Oct 27, 2025
ea0c26b
Merge pull request #5 from lambdaclass/implement_svo_paralellize
jotabulacios Oct 27, 2025
4aad600
add algorithm 2
ColoCarletti Oct 29, 2025
a274571
make alg5 not depend on round start
ColoCarletti Oct 29, 2025
b351b32
improve alg2
ColoCarletti Oct 29, 2025
2086213
improve compute accumulators function: remove accumulators not used
nicole-graus Oct 30, 2025
6471b83
change algorithm 5 for an optimized one
nicole-graus Oct 31, 2025
1fea351
refactor
ColoCarletti Oct 31, 2025
4af1e9b
Merge branch 'implement_svo' of github.com:lambdaclass/whir-p3 into i…
ColoCarletti Oct 31, 2025
06e2063
add 22 var bench
ColoCarletti Oct 31, 2025
277053b
refactor
ColoCarletti Oct 31, 2025
c85741a
rm svo_pq
ColoCarletti Oct 31, 2025
3127e71
refactor
ColoCarletti Oct 31, 2025
0cf6204
add tests
ColoCarletti Oct 31, 2025
5fc008b
rm old comment
ColoCarletti Oct 31, 2025
c74f312
fix tests
ColoCarletti Oct 31, 2025
2ed58ee
remove commented code
jotabulacios Oct 31, 2025
f8b8cd0
Merge branch 'main' into implement_svo
ColoCarletti Nov 3, 2025
b427034
update svo with new api
ColoCarletti Nov 3, 2025
75088fb
change vec input to a slice in eval_eq_in_hypercube
nicole-graus Nov 4, 2025
9a15cc8
improve compute_accumulators funtion
jotabulacios Nov 4, 2025
179b5da
restore verifier test after api change
jotabulacios Nov 4, 2025
b51786a
Fix PR comments
ColoCarletti Nov 4, 2025
aec9af6
Merge branch 'implement_svo' of github.com:lambdaclass/whir-p3 into i…
ColoCarletti Nov 4, 2025
5fbad50
fix merge
ColoCarletti Nov 4, 2025
a496094
fix clippy
ColoCarletti Nov 4, 2025
011a1be
small fix on compress_svo
jotabulacios Nov 5, 2025
2cf1bb3
changes algorithm 5 and its auxiliary functions
nicole-graus Nov 5, 2025
ea25139
fix clippy
ColoCarletti Nov 5, 2025
ff94af1
fix clippy
ColoCarletti Nov 5, 2025
8b07cbb
add grinding
jotabulacios Nov 5, 2025
baa805a
Merge remote-tracking branch 'origin/implement_svo' into implement_svo
jotabulacios Nov 5, 2025
dd0abc9
compute t_evals in one shot
jotabulacios Nov 5, 2025
542f9e2
delete old test
jotabulacios Nov 5, 2025
1e890f1
fix no-default-features
jotabulacios Nov 5, 2025
9a2d865
remove RoundAccumulators
nicole-graus Nov 6, 2025
eec71d0
improve parallelization
jotabulacios Nov 6, 2025
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
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ harness = false
name = "sumcheck"
harness = false

[[bench]]
name = "sumcheck_svo"
harness = false

[[bench]]
name = "stir_queries"
harness = false
82 changes: 82 additions & 0 deletions benches/sumcheck_svo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use p3_challenger::{DuplexChallenger, FieldChallenger, GrindingChallenger};
use p3_field::extension::BinomialExtensionField;
use p3_koala_bear::{KoalaBear, Poseidon2KoalaBear};
use rand::{Rng, SeedableRng, rngs::StdRng};
use whir::{
fiat_shamir::{domain_separator::DomainSeparator, prover::ProverState},
poly::{evals::EvaluationsList, multilinear::MultilinearPoint},
sumcheck::sumcheck_single::SumcheckSingle,
whir::constraints::{evaluator::Constraint, statement::EqStatement},
};
use whir_p3 as whir;

type F = KoalaBear;
type EF = BinomialExtensionField<F, 8>;
type Poseidon16 = Poseidon2KoalaBear<16>;
type MyChallenger = DuplexChallenger<F, Poseidon16, 16, 8>;

const NUM_CONSTRAINTS: usize = 1;
const FOLDING_FACTOR: usize = 5;
const POW_BITS: usize = 0;

fn setup_prover() -> ProverState<F, EF, MyChallenger> {
let mut rng = StdRng::seed_from_u64(0);
let poseidon = Poseidon16::new_from_rng_128(&mut rng);
let challenger = MyChallenger::new(poseidon);
DomainSeparator::new(vec![]).to_prover_state(challenger)
}

fn generate_poly(num_vars: usize) -> EvaluationsList<F> {
let mut rng = StdRng::seed_from_u64(1 + num_vars as u64);
EvaluationsList::new((0..1 << num_vars).map(|_| rng.random()).collect())
}

/// Helper to generate an initial statement with a few constraints.
fn generate_statement<C>(
prover: &mut ProverState<F, EF, C>,
num_vars: usize,
poly: &EvaluationsList<F>,
num_constraints: usize,
) -> EqStatement<EF>
where
C: FieldChallenger<F> + GrindingChallenger<Witness = F>,
{
let mut statement = EqStatement::initialize(num_vars);
for _ in 0..num_constraints {
let point = MultilinearPoint::expand_from_univariate(prover.sample(), num_vars);
statement.add_unevaluated_constraint_hypercube(point, poly);
}
statement
}

fn bench_sumcheck_prover_svo(c: &mut Criterion) {
let mut group = c.benchmark_group("SumcheckProver");
// Use a smaller sample size for long-running benchmarks
group.sample_size(10);

// Define the range of variable counts to benchmark.
for num_vars in &[16, 18, 20, 22, 24] {
// Generate a large polynomial to use for this set of benchmarks.
let poly = generate_poly(*num_vars);

let mut prover = setup_prover();
let statement = generate_statement(&mut prover, *num_vars, &poly, 3);
let constraint = Constraint::new_eq_only(prover.sample(), statement.clone());

group.bench_with_input(BenchmarkId::new("Classic", *num_vars), &poly, |b, poly| {
b.iter(|| {
SumcheckSingle::from_base_evals(poly, &mut prover, *num_vars, 0, &constraint);
});
});
group.bench_with_input(BenchmarkId::new("SVO", *num_vars), &poly, |b, poly| {
b.iter(|| {
SumcheckSingle::from_base_evals_svo(poly, &mut prover, *num_vars, 0, &constraint);
});
});
}
group.finish();
}

criterion_group!(benches, bench_sumcheck_prover_svo);
criterion_main!(benches);
26 changes: 26 additions & 0 deletions src/poly/evals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,32 @@ where
}
}

#[inline]
pub fn compress_svo(&mut self, r: F) {
assert_ne!(self.num_variables(), 0);
let mid = self.num_evals() / 2;
// For large inputs, we use a parallel, out-of-place strategy.
if self.num_evals() >= PARALLEL_THRESHOLD {
let (left, right) = self.0.split_at_mut(mid);
left.par_iter_mut()
.zip(right.par_iter())
.for_each(|(p0_mut, &p1)| {
// Read the original p0 value
let p0 = *p0_mut;
// Compute the new value and write it back to the left half.
*p0_mut = r * (p1 - p0) + p0;
});
} else {
// For smaller inputs, we use a sequential, in-place strategy.
for i in 0..mid {
let p0 = self.0[i];
let p1 = self.0[mid + i];
self.0[i] = r * (p1 - p0) + p0;
}
}
self.0.truncate(mid);
}

/// Folds a list of evaluations from a base field `F` into an extension field `EF`.
///
/// ## Arguments
Expand Down
2 changes: 2 additions & 0 deletions src/sumcheck/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
pub mod sumcheck_polynomial;
pub mod sumcheck_single;
pub mod sumcheck_single_skip;
pub mod sumcheck_single_svo;
pub mod sumcheck_small_value;
#[cfg(test)]
mod tests;
pub mod utils;
9 changes: 9 additions & 0 deletions src/sumcheck/sumcheck_single.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ where
{
// Compute the quadratic sumcheck polynomial for the current variable.
let sumcheck_poly = compute_sumcheck_polynomial(evals, weights, *sum);

prover_state.add_extension_scalar(sumcheck_poly.evaluations()[0]);
prover_state.add_extension_scalar(sumcheck_poly.evaluations()[1]);
prover_state.add_extension_scalar(sumcheck_poly.evaluations()[2]);
Expand Down Expand Up @@ -227,6 +228,14 @@ where
F: Field + Ord,
EF: ExtensionField<F>,
{
pub const fn new(evals: EvaluationsList<EF>, weights: EvaluationsList<EF>, sum: EF) -> Self {
Self {
evals,
weights,
sum,
phantom: std::marker::PhantomData,
}
}
/// Constructs a new `SumcheckSingle` instance from evaluations in the extension field.
///
/// This function:
Expand Down
67 changes: 67 additions & 0 deletions src/sumcheck/sumcheck_single_svo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use p3_challenger::{FieldChallenger, GrindingChallenger};
use p3_field::{ExtensionField, Field, TwoAdicField};

use crate::{
fiat_shamir::prover::ProverState,
poly::{evals::EvaluationsList, multilinear::MultilinearPoint},
sumcheck::{
sumcheck_single::SumcheckSingle,
sumcheck_small_value::{algorithm_5, fold_evals_with_challenges, svo_three_rounds},
},
whir::constraints::evaluator::Constraint,
};

impl<F, EF> SumcheckSingle<F, EF>
where
F: Field + Ord,
EF: ExtensionField<F>,
{
/// Compute a Sumcheck using the Small Value Optimization (SVO) for the first three rounds and
/// Algorithm 5 (page 18) for the remaining rounds.
/// See Algorithm 6 (page 19) in <https://eprint.iacr.org/2025/1117>.
pub fn from_base_evals_svo<Challenger>(
evals: &EvaluationsList<F>,
prover_state: &mut ProverState<F, EF, Challenger>,
folding_factor: usize,
pow_bits: usize,
constraint: &Constraint<F, EF>,
) -> (Self, MultilinearPoint<EF>)
where
F: TwoAdicField,
EF: TwoAdicField,
Challenger: FieldChallenger<F> + GrindingChallenger<Witness = F>,
{
assert_ne!(folding_factor, 0);
let mut challenges = Vec::with_capacity(folding_factor);

// Here we are assuming the the equality statement has only one constraint.
// TODO: Handle multiple constraints for a general WHIR implementation.
let mut sum = constraint.eq_statement.evaluations[0];
let w = &constraint.eq_statement.points[0];

let (r_1, r_2, r_3) = svo_three_rounds(prover_state, evals, w, &mut sum, pow_bits);
#[allow(clippy::tuple_array_conversions)]
challenges.extend([r_1, r_2, r_3]);

// We fold to obtaind p(r1, r2, r3, x).
let mut folded_evals = fold_evals_with_challenges(evals, &challenges);

algorithm_5(
prover_state,
&mut folded_evals,
w,
&mut challenges,
&mut sum,
pow_bits,
);

let challenge_point = MultilinearPoint::new(challenges);

// Final weight: eq(w, r)
let weights = EvaluationsList::new(vec![w.eq_poly(&challenge_point)]);

let sumcheck = Self::new(folded_evals, weights, sum);

(sumcheck, challenge_point)
}
}
Loading