winter_fri/options.rs
1// Copyright (c) Facebook, Inc. and its affiliates.
2//
3// This source code is licensed under the MIT license found in the
4// LICENSE file in the root directory of this source tree.
5
6use math::StarkField;
7
8// FRI OPTIONS
9// ================================================================================================
10
11/// FRI protocol config options for proof generation and verification.
12#[derive(Clone, PartialEq, Eq)]
13pub struct FriOptions {
14 folding_factor: usize,
15 remainder_max_degree: usize,
16 blowup_factor: usize,
17}
18
19impl FriOptions {
20 /// Returns a new [FriOptions] struct instantiated with the specified parameters.
21 ///
22 /// # Panics
23 /// Panics if:
24 /// - `blowup_factor` is not a power of two.
25 /// - `folding_factor` is not 2, 4, 8, or 16.
26 pub fn new(blowup_factor: usize, folding_factor: usize, remainder_max_degree: usize) -> Self {
27 // TODO: change panics to errors
28 assert!(
29 blowup_factor.is_power_of_two(),
30 "blowup factor must be a power of two, but was {blowup_factor}"
31 );
32 assert!(
33 folding_factor == 2
34 || folding_factor == 4
35 || folding_factor == 8
36 || folding_factor == 16,
37 "folding factor {folding_factor} is not supported"
38 );
39 FriOptions {
40 folding_factor,
41 remainder_max_degree,
42 blowup_factor,
43 }
44 }
45
46 /// Returns the offset by which the evaluation domain is shifted.
47 ///
48 /// The domain is shifted by multiplying every element in the domain by this offset.
49 ///
50 /// Currently, the offset is hard-coded to be the primitive element in the field specified by
51 /// type parameter `B`.
52 pub fn domain_offset<B: StarkField>(&self) -> B {
53 B::GENERATOR
54 }
55
56 /// Returns the factor by which the degree of a polynomial is reduced with each FRI layer.
57 ///
58 /// In combination with `remainder_max_degree_plus_1` this property defines how many FRI layers
59 /// are needed for an evaluation domain of a given size.
60 pub fn folding_factor(&self) -> usize {
61 self.folding_factor
62 }
63
64 /// Returns maximum allowed remainder polynomial degree.
65 ///
66 /// In combination with `folding_factor` this property defines how many FRI layers are needed
67 /// for an evaluation domain of a given size.
68 pub fn remainder_max_degree(&self) -> usize {
69 self.remainder_max_degree
70 }
71
72 /// Returns a blowup factor of the evaluation domain.
73 ///
74 /// Specifically, if the polynomial for which the FRI protocol is executed is of degree `d`
75 /// where `d` is one less than a power of two, then the evaluation domain size will be
76 /// equal to `(d + 1) * blowup_factor`.
77 pub fn blowup_factor(&self) -> usize {
78 self.blowup_factor
79 }
80
81 /// Computes and return the number of FRI layers required for a domain of the specified size.
82 ///
83 /// The number of layers for a given domain size is defined by the `folding_factor` and
84 /// `remainder_max_degree` and `blowup_factor` settings.
85 pub fn num_fri_layers(&self, mut domain_size: usize) -> usize {
86 let mut result = 0;
87 let max_remainder_size = (self.remainder_max_degree + 1) * self.blowup_factor;
88 while domain_size > max_remainder_size {
89 domain_size /= self.folding_factor;
90 result += 1;
91 }
92 result
93 }
94}