Better errors for insufficient (routed) wires for FRI (#288)

For examlpe, if I change a test to use `ConstantArityBits(4, 5)`, I get

    To efficiently perform FRI checks with an arity of 16, at least 152 wires are needed. Consider reducing arity.
This commit is contained in:
Daniel Lubarov 2021-10-05 23:28:04 -07:00 committed by GitHub
parent a407e5e1a0
commit b922def48e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 0 deletions

View File

@ -32,4 +32,12 @@ impl FriParams {
pub(crate) fn total_arities(&self) -> usize {
self.reduction_arity_bits.iter().sum()
}
pub(crate) fn max_arity_bits(&self) -> Option<usize> {
self.reduction_arity_bits.iter().copied().max()
}
pub(crate) fn max_arity(&self) -> Option<usize> {
self.max_arity_bits().map(|bits| 1 << bits)
}
}

View File

@ -3,6 +3,9 @@ use crate::field::extension_field::Extendable;
use crate::field::field_types::{Field, RichField};
use crate::fri::proof::{FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget};
use crate::fri::FriConfig;
use crate::gates::gate::Gate;
use crate::gates::interpolation::InterpolationGate;
use crate::gates::random_access::RandomAccessGate;
use crate::hash::hash_types::MerkleCapTarget;
use crate::iop::challenger::RecursiveChallenger;
use crate::iop::target::{BoolTarget, Target};
@ -53,6 +56,35 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
self.interpolate(&points, beta)
}
/// Make sure we have enough wires and routed wires to do the FRI checks efficiently. This check
/// isn't required -- without it we'd get errors elsewhere in the stack -- but just gives more
/// helpful errors.
fn check_config(&self, arity: usize) {
let random_access = RandomAccessGate::<F, D>::new(arity);
let interpolation_gate = InterpolationGate::<F, D>::new(arity);
let min_wires = random_access
.num_wires()
.max(interpolation_gate.num_wires());
let min_routed_wires = random_access
.num_routed_wires()
.max(interpolation_gate.num_routed_wires());
assert!(
self.config.num_wires >= min_wires,
"To efficiently perform FRI checks with an arity of {}, at least {} wires are needed. Consider reducing arity.",
arity,
min_wires
);
assert!(
self.config.num_routed_wires >= min_routed_wires,
"To efficiently perform FRI checks with an arity of {}, at least {} routed wires are needed. Consider reducing arity.",
arity,
min_routed_wires
);
}
fn fri_verify_proof_of_work(
&mut self,
proof: &FriProofTarget<D>,
@ -81,6 +113,11 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
common_data: &CommonCircuitData<F, D>,
) {
let config = &common_data.config;
if let Some(max_arity) = common_data.fri_params.max_arity() {
self.check_config(max_arity);
}
debug_assert_eq!(
common_data.final_poly_len(),
proof.final_poly.len(),

View File

@ -81,6 +81,12 @@ impl<F: RichField + Extendable<D>, const D: usize> InterpolationGate<F, D> {
self.start_evaluation_value() + D
}
/// The number of routed wires required in the typical usage of this gate, where the points to
/// interpolate, the evaluation point, and the corresponding value are all routed.
pub(crate) fn num_routed_wires(&self) -> usize {
self.start_coeffs()
}
/// Wire indices of the interpolant's `i`th coefficient.
pub fn wires_coeff(&self, i: usize) -> Range<usize> {
debug_assert!(i < self.num_points);

View File

@ -45,6 +45,10 @@ impl<F: RichField + Extendable<D>, const D: usize> RandomAccessGate<F, D> {
(self.vec_size + 1) * D + 1
}
pub(crate) fn num_routed_wires(&self) -> usize {
self.start_of_intermediate_wires()
}
/// An intermediate wire for a dummy variable used to show equality.
/// The prover sets this to 1/(x-y) if x != y, or to an arbitrary value if
/// x == y.