Skip to content

VDAF-18 test vecs and Rhizomes math#1400

Merged
tgeoghegan merged 4 commits intomainfrom
timg/update-test-vecs
Mar 11, 2026
Merged

VDAF-18 test vecs and Rhizomes math#1400
tgeoghegan merged 4 commits intomainfrom
timg/update-test-vecs

Conversation

@tgeoghegan
Copy link
Contributor

@tgeoghegan tgeoghegan commented Mar 9, 2026

Don't be discouraged by the size of the diff! It's mostly test vectors. The first commit contains only test vector updates for draft-irtf-cfrg-vdaf-18. The functional changes are all in the second commit:

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.

Closes #1394

- update test vectors paths from "/15/" to "/18"
- change various variable names, field names from "prep", "prepare" to
  "verifier", "verify"

We still have lots and lots of things throughout the crate called
"prepare" that should be "verify". This commit deliberately only deals
with the test vector code to keep the diff smaller.
@tgeoghegan tgeoghegan force-pushed the timg/update-test-vecs branch 2 times, most recently from d303f46 to 73033c5 Compare March 10, 2026 22:08
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
@tgeoghegan tgeoghegan force-pushed the timg/update-test-vecs branch from 73033c5 to 73a3cd5 Compare March 10, 2026 22:31
Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the Rhizomes world, we just always do the NTT and don't bother with the NTT threshold stuff.

// assert!(polynomials[0].as_ref().len().is_power_of_two());
// assert_eq!(roots.len(), poly_len, "incorrect number of roots provided");
assert!(polynomials[0].as_ref().len().is_power_of_two());
let roots = nth_root_powers(poly_len);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the previous PR, we discussed the possibility of precomputing roots of unity and passing them in here. I'm open to re-introducing the roots function argument but would point out that since poly_eval_lagrange_batched is internal to the crate, we can change it freely in the future without breaking SemVer promises, should we choose to build such an optimization.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have #1392 to generally change "prepare" to "verify", which will be a big messy diff that stomps on a great many lines. I chose to jump the gun in this particular area because the test vectors we need to move to for draft-irtf-cfrg-vdaf-18 use a new encoding that discusses verify_init and verifier_shares and so on. So I felt it made sense to take just this bite of the whole meal.

let mut p_doubled = double_evaluations(p)?;
double_evaluations(output, p)?;

for (p_element, q_element) in p_doubled.iter_mut().zip(double_evaluations(q)?) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we could do even better if we had a version of double_evaluations that returns an iterator, and the same idea could be applied to a few things in polynomial or ntt, but, well, you have to stop somewhere.

@tgeoghegan tgeoghegan marked this pull request as ready for review March 10, 2026 22:34
@tgeoghegan tgeoghegan requested a review from a team as a code owner March 10, 2026 22:34
Copy link
Collaborator

Choose a reason for hiding this comment

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

This file isn't currently used in tests

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ouch, sloppy of me. I double checked that all other test vectors do get exercised.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fortunately you already had the HigherDegree type in place. I moved it to a new module flp::types::higher_degree so it's easier to use from prio3_test.

src/flp.rs Outdated
== Self::Field::one()
// polynomial at any of these points would be a privacy violation, since these
// points were used by the prover to construct the wire polynomials.
if r.pow(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since the query randomness is no longer needed to construct query shim gadgets, we could split apart the zipped iterators here, and move this check to a separate loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We still need to zip gadgets and query rand together so we can compute each gadget's wire poly length in the query randomness check, but I agree that two separate iterators is easier to read.

src/flp.rs Outdated
Comment on lines +638 to +640
/// Input wire values recorded during successive evaluations of this gadget. Indexed by wire
/// number and number of calls. i.e., `wire_values[i][j]` is the value of the `i`-th input wire
/// during the `j`-th invocation of this gadget.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This description is off by one, as wire_values[i][0] is reserved for a seed value from the prover randomness.

src/flp.rs Outdated
Comment on lines +704 to +706
/// Input wire values recorded during successive evaluations of this gadget. Indexed by wire
/// number and number of calls. i.e., `wire_values[i][j]` is the value of the `i`-th input wire
/// during the `j`-th invocation of this gadget.
Copy link
Collaborator

Choose a reason for hiding this comment

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

See above, wire_values[i][0] is a randomly chosen seed value.

@tgeoghegan tgeoghegan merged commit 21df690 into main Mar 11, 2026
6 checks passed
@tgeoghegan tgeoghegan deleted the timg/update-test-vecs branch March 11, 2026 23:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Evaluate polynomials in Lagrange basis (Rhizomes)

2 participants