Skip to content

Commit 73a3cd5

Browse files
committed
flp: Maintain polynomials in Lagrange basis
Update the implementation of fully linear proofs to do polynomial multiplications and evaluations in the Lagrange basis, using algorithms from Faz25 ([1]), as specified in draft-irtf-cfrg-vdaf-18 ([2]). The most important changes are in: - `flp::Flp::{prove, query, decide}` - `flp::ProveShimGadget` - `flp::QueryShimGadget` - `flp::gadgets::Mul` - `flp::gadgets::PolyEval` Since we no longer need to precompute a multiplicative inverse, `flp::Gadgets::Mul` is no longer generic over `FieldElement`, and removing that generic parameter is reflected in a number of places in the codebase. Finally, in order to avoid an unnecessary copy, we make minor changes to the interfaces in `mod polynomial`: - `poly_mul_lagrange` now writes output to a provided output buffer instead of allocating and returning `Vec<F>` - `double_evaluations` (which returns its output as `Vec<F>`) is renamed `get_double_evaluations` (matching the convention set in `mod ntt`) and we add `double_evaluations` which writes output to a provided buffer. [1]: https://eprint.iacr.org/2025/1727.pdf [2]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-18#name-polynomial-evaluation Closes #1394
1 parent b17450b commit 73a3cd5

File tree

16 files changed

+348
-541
lines changed

16 files changed

+348
-541
lines changed

benches/speed_tests.rs

Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ use prio::vdaf::prio2::Prio2;
2020
#[cfg(feature = "experimental")]
2121
use prio::vidpf::VidpfServerId;
2222
use prio::{
23-
benchmarked::*,
2423
field::{Field128 as F, FieldElement},
25-
flp::gadgets::Mul,
2624
vdaf::{prio3::Prio3, Aggregator, Client},
2725
};
2826
#[cfg(feature = "experimental")]
@@ -81,44 +79,6 @@ pub fn dp_noise(c: &mut Criterion) {
8179
group.finish();
8280
}
8381

84-
/// The asymptotic cost of polynomial multiplication is `O(n log n)` using NTT and `O(n^2)` using
85-
/// the naive method. This benchmark demonstrates that the latter has better concrete performance
86-
/// for small polynomials. The result is used to pick the `NTT_THRESHOLD` constant in
87-
/// `src/flp/gadgets.rs`.
88-
fn poly_mul(c: &mut Criterion) {
89-
let test_sizes = [1_usize, 30, 60, 90, 120, 150, 255];
90-
91-
let mut group = c.benchmark_group("poly_mul");
92-
for size in test_sizes {
93-
group.bench_with_input(BenchmarkId::new("ntt", size), &size, |b, size| {
94-
let m = (size + 1).next_power_of_two();
95-
let mut g: Mul<F> = Mul::new(*size);
96-
let mut outp = vec![F::zero(); 2 * m];
97-
let mut inp = vec![];
98-
inp.push(F::random_vector(m));
99-
inp.push(F::random_vector(m));
100-
101-
b.iter(|| {
102-
benchmarked_gadget_mul_call_poly_ntt(&mut g, &mut outp, &inp).unwrap();
103-
})
104-
});
105-
106-
group.bench_with_input(BenchmarkId::new("direct", size), &size, |b, size| {
107-
let m = (size + 1).next_power_of_two();
108-
let mut g: Mul<F> = Mul::new(*size);
109-
let mut outp = vec![F::zero(); 2 * m];
110-
let mut inp = vec![];
111-
inp.push(F::random_vector(m));
112-
inp.push(F::random_vector(m));
113-
114-
b.iter(|| {
115-
benchmarked_gadget_mul_call_poly_direct(&mut g, &mut outp, &inp).unwrap();
116-
})
117-
});
118-
}
119-
group.finish();
120-
}
121-
12282
/// Benchmark prio2.
12383
#[cfg(feature = "experimental")]
12484
fn prio2(c: &mut Criterion) {
@@ -1022,8 +982,8 @@ fn vidpf(c: &mut Criterion) {
1022982
}
1023983

1024984
#[cfg(feature = "experimental")]
1025-
criterion_group!(benches, poplar1, prio3, prio2, poly_mul, prng, idpf, dp_noise, vidpf);
985+
criterion_group!(benches, poplar1, prio3, prio2, prng, idpf, dp_noise, vidpf);
1026986
#[cfg(not(feature = "experimental"))]
1027-
criterion_group!(benches, prio3, prng, poly_mul);
987+
criterion_group!(benches, prio3, prng);
1028988

1029989
criterion_main!(benches);

src/benchmarked.rs

Lines changed: 0 additions & 30 deletions
This file was deleted.

0 commit comments

Comments
 (0)