Skip to content
10 changes: 7 additions & 3 deletions air/src/air/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use super::{
};
use crate::{AuxTraceRandElements, FieldExtension};
use crypto::{hashers::Blake3_256, DefaultRandomCoin, RandomCoin};
use fri::fri_schedule::FoldingSchedule;
use math::{fields::f64::BaseElement, get_power_series, polynom, FieldElement, StarkField};
use utils::collections::{BTreeMap, Vec};

Expand Down Expand Up @@ -219,20 +220,22 @@ impl MockAir {
column_values: Vec<Vec<BaseElement>>,
trace_length: usize,
) -> Self {
let fri_constant_schedule = FoldingSchedule::new_constant(4, 31);
let mut result = Self::new(
TraceInfo::with_meta(4, trace_length, vec![1]),
(),
ProofOptions::new(32, 8, 0, FieldExtension::None, 4, 31),
ProofOptions::new(32, 8, 0, FieldExtension::None, &fri_constant_schedule),
);
result.periodic_columns = column_values;
result
}

pub fn with_assertions(assertions: Vec<Assertion<BaseElement>>, trace_length: usize) -> Self {
let fri_constant_schedule = FoldingSchedule::new_constant(4, 31);
let mut result = Self::new(
TraceInfo::with_meta(4, trace_length, vec![assertions.len() as u8]),
(),
ProofOptions::new(32, 8, 0, FieldExtension::None, 4, 31),
ProofOptions::new(32, 8, 0, FieldExtension::None, &fri_constant_schedule),
);
result.assertions = assertions;
result
Expand Down Expand Up @@ -282,7 +285,8 @@ pub fn build_context<B: StarkField>(
trace_width: usize,
num_assertions: usize,
) -> AirContext<B> {
let options = ProofOptions::new(32, 8, 0, FieldExtension::None, 4, 31);
let fri_constant_schedule = FoldingSchedule::new_constant(4, 31);
let options = ProofOptions::new(32, 8, 0, FieldExtension::None, &fri_constant_schedule);
let t_degrees = vec![TransitionConstraintDegree::new(2)];
let trace_info = TraceInfo::new(trace_width, trace_length);
AirContext::new(trace_info, t_degrees, num_assertions, options)
Expand Down
92 changes: 59 additions & 33 deletions air/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.

use fri::FriOptions;
use fri::{fri_schedule::FoldingSchedule, FriOptions};
use math::{StarkField, ToElements};
use utils::{
collections::Vec, ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
Expand Down Expand Up @@ -69,6 +69,10 @@ pub enum FieldExtension {
/// 4. Grinding factor - higher values increase proof soundness, but also may increase proof
/// generation time. More precisely, conjectured proof soundness is bounded by
/// `num_queries * log2(blowup_factor) + grinding_factor`.
/// 5. FRI Schedule - The strategy for the FRI reduction process, which can be either a constant
/// folding factor or a dynamic schedule of factors. This setting influences the FRI proof
/// generation process, potentially affecting both the proof generation time and the resultant
/// proof size.
///
/// Another important parameter in defining STARK security level, which is not a part of [ProofOptions]
/// is the hash function used in the protocol. The soundness of a STARK proof is limited by the
Expand All @@ -80,8 +84,7 @@ pub struct ProofOptions {
blowup_factor: u8,
grinding_factor: u8,
field_extension: FieldExtension,
fri_folding_factor: u8,
fri_remainder_max_degree: u8,
fri_schedule: FoldingSchedule,
}

// PROOF OPTIONS IMPLEMENTATION
Expand All @@ -106,16 +109,16 @@ impl ProofOptions {
/// - `num_queries` is zero or greater than 255.
/// - `blowup_factor` is smaller than 2, greater than 128, or is not a power of two.
/// - `grinding_factor` is greater than 32.
/// - `fri_folding_factor` is not 2, 4, 8, or 16.
/// - `fri_remainder_max_degree` is greater than 255 or is not a power of two minus 1.
/// - `fri_folding_schedule` is not 2, 4, 8, or 16 in case of a constant FRI schedule, or is not
/// a power of two in case of a dynamic FRI schedule. In the case of constant FRI schedule, the
/// max remainder degree must be less than 255 and must be one less than a power of two.
#[rustfmt::skip]
pub fn new(
num_queries: usize,
blowup_factor: usize,
grinding_factor: u32,
field_extension: FieldExtension,
fri_folding_factor: usize,
fri_remainder_max_degree: usize,
fri_folding_schedule: &FoldingSchedule,
) -> ProofOptions {
// TODO: return errors instead of panicking
assert!(num_queries > 0, "number of queries must be greater than 0");
Expand All @@ -127,26 +130,36 @@ impl ProofOptions {

assert!(grinding_factor <= MAX_GRINDING_FACTOR, "grinding factor cannot be greater than {MAX_GRINDING_FACTOR}");

assert!(fri_folding_factor.is_power_of_two(), "FRI folding factor must be a power of 2");
assert!(fri_folding_factor >= FRI_MIN_FOLDING_FACTOR, "FRI folding factor cannot be smaller than {FRI_MIN_FOLDING_FACTOR}");
assert!(fri_folding_factor <= FRI_MAX_FOLDING_FACTOR, "FRI folding factor cannot be greater than {FRI_MAX_FOLDING_FACTOR}");

assert!(
(fri_remainder_max_degree + 1).is_power_of_two(),
"FRI polynomial remainder degree must be one less than a power of two"
);
assert!(
fri_remainder_max_degree <= FRI_MAX_REMAINDER_DEGREE,
"FRI polynomial remainder degree cannot be greater than {FRI_MAX_REMAINDER_DEGREE}"
);
// let fri_folding_factor = fri_folding_schedule.get_factor().unwrap_or(3);
// let fri_remainder_max_degree = fri_folding_schedule.get_max_remainder_degree().unwrap_or(127);
match fri_folding_schedule {
FoldingSchedule::Constant { fri_folding_factor, fri_remainder_max_degree } => {
assert!(fri_folding_factor.is_power_of_two(), "FRI folding factor must be a power of 2");
assert!(*fri_folding_factor as usize >= FRI_MIN_FOLDING_FACTOR, "FRI folding factor cannot be smaller than {FRI_MIN_FOLDING_FACTOR}");
assert!(*fri_folding_factor as usize <= FRI_MAX_FOLDING_FACTOR, "FRI folding factor cannot be greater than {FRI_MAX_FOLDING_FACTOR}");

assert!(
(fri_remainder_max_degree + 1).is_power_of_two(),
"FRI polynomial remainder degree must be one less than a power of two"
);
assert!(
*fri_remainder_max_degree as usize <= FRI_MAX_REMAINDER_DEGREE,
"FRI polynomial remainder degree cannot be greater than {FRI_MAX_REMAINDER_DEGREE}"
);

},
FoldingSchedule::Dynamic { schedule} => {
assert!(schedule.iter().all(|factor| factor.is_power_of_two()), "FRI folding factors must be powers of 2");
assert!(!schedule.is_empty(), "FRI folding schedule cannot be empty");
},
}

ProofOptions {
num_queries: num_queries as u8,
blowup_factor: blowup_factor as u8,
grinding_factor: grinding_factor as u8,
field_extension,
fri_folding_factor: fri_folding_factor as u8,
fri_remainder_max_degree: fri_remainder_max_degree as u8,
fri_schedule: fri_folding_schedule.clone(),
}
}

Expand Down Expand Up @@ -202,18 +215,29 @@ impl ProofOptions {

/// Returns options for FRI protocol instantiated with parameters from this proof options.
pub fn to_fri_options(&self) -> FriOptions {
let folding_factor = self.fri_folding_factor as usize;
let remainder_max_degree = self.fri_remainder_max_degree as usize;
FriOptions::new(self.blowup_factor(), folding_factor, remainder_max_degree)
FriOptions::new(self.blowup_factor(), self.fri_schedule.clone())
}
}

impl<E: StarkField> ToElements<E> for ProofOptions {
fn to_elements(&self) -> Vec<E> {
// encode field extension and FRI parameters into a single field element
let mut buf = self.field_extension as u32;
buf = (buf << 8) | self.fri_folding_factor as u32;
buf = (buf << 8) | self.fri_remainder_max_degree as u32;
match &self.fri_schedule {
FoldingSchedule::Constant {
fri_folding_factor,
fri_remainder_max_degree,
} => {
buf = (buf << 8) | *fri_folding_factor as u32;
buf = (buf << 8) | *fri_remainder_max_degree as u32;
}
FoldingSchedule::Dynamic { schedule } => {
buf = (buf << 8) | schedule.len() as u32;
for factor in schedule {
buf = (buf << 8) | *factor as u32;
}
}
}

vec![
E::from(buf),
Expand All @@ -231,8 +255,7 @@ impl Serializable for ProofOptions {
target.write_u8(self.blowup_factor);
target.write_u8(self.grinding_factor);
target.write(self.field_extension);
target.write_u8(self.fri_folding_factor);
target.write_u8(self.fri_remainder_max_degree);
target.write(self.fri_schedule.clone());
}
}

Expand All @@ -247,8 +270,7 @@ impl Deserializable for ProofOptions {
source.read_u8()? as usize,
source.read_u8()? as u32,
FieldExtension::read_from(source)?,
source.read_u8()? as usize,
source.read_u8()? as usize,
&FoldingSchedule::read_from(source)?,
))
}
}
Expand Down Expand Up @@ -299,13 +321,18 @@ impl Deserializable for FieldExtension {
#[cfg(test)]
mod tests {
use super::{FieldExtension, ProofOptions, ToElements};
use fri::fri_schedule::FoldingSchedule;
use math::fields::f64::BaseElement;

#[test]
fn proof_options_to_elements() {
let field_extension = FieldExtension::None;
let fri_folding_factor = 8;
let fri_remainder_max_degree = 127;
let fri_folding_schedule = FoldingSchedule::Constant {
fri_folding_factor,
fri_remainder_max_degree,
};
let grinding_factor = 20;
let blowup_factor = 8;
let num_queries = 30;
Expand All @@ -318,7 +345,7 @@ mod tests {
]);
let expected = vec![
BaseElement::from(ext_fri),
BaseElement::from(grinding_factor as u32),
BaseElement::from(grinding_factor),
BaseElement::from(blowup_factor as u32),
BaseElement::from(num_queries as u32),
];
Expand All @@ -328,8 +355,7 @@ mod tests {
blowup_factor,
grinding_factor,
field_extension,
fri_folding_factor as usize,
fri_remainder_max_degree as usize,
&fri_folding_schedule,
);
assert_eq!(expected, options.to_elements());
}
Expand Down
9 changes: 6 additions & 3 deletions air/src/proof/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ fn bytes_to_element<B: StarkField>(bytes: &[u8]) -> B {
mod tests {
use super::{Context, ProofOptions, ToElements, TraceInfo};
use crate::{FieldExtension, TraceLayout};
use fri::fri_schedule::FoldingSchedule;
use math::fields::f64::BaseElement;

#[test]
Expand All @@ -247,14 +248,17 @@ mod tests {
0,
]);

let fri_constant_schedule =
FoldingSchedule::new_constant(fri_folding_factor, fri_remainder_max_degree);

let layout_info = u32::from_le_bytes([aux_rands, aux_width, num_aux_segments, main_width]);

let expected = vec![
BaseElement::from(layout_info),
BaseElement::from(1_u32), // lower bits of field modulus
BaseElement::from(u32::MAX), // upper bits of field modulus
BaseElement::from(ext_fri),
BaseElement::from(grinding_factor as u32),
BaseElement::from(grinding_factor),
BaseElement::from(blowup_factor as u32),
BaseElement::from(num_queries as u32),
BaseElement::from(trace_length as u32),
Expand All @@ -265,8 +269,7 @@ mod tests {
blowup_factor,
grinding_factor,
field_extension,
fri_folding_factor as usize,
fri_remainder_max_degree as usize,
&fri_constant_schedule,
);
let layout = TraceLayout::new(
main_width as usize,
Expand Down
2 changes: 1 addition & 1 deletion crypto/src/hash/griffin/griffin64_256_jive/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ proptest! {
for i in 0..STATE_WIDTH {
v1[i] = BaseElement::new(a[i]);
}
v2 = v1.clone();
v2 = v1;

apply_mds_naive(&mut v1);
GriffinJive64_256::apply_linear(&mut v2);
Expand Down
2 changes: 1 addition & 1 deletion crypto/src/hash/rescue/rp64_256/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ proptest! {
for i in 0..STATE_WIDTH {
v1[i] = BaseElement::new(a[i]);
}
v2 = v1.clone();
v2 = v1;

apply_mds_naive(&mut v1);
Rp64_256::apply_mds(&mut v2);
Expand Down
4 changes: 2 additions & 2 deletions crypto/src/hash/rescue/rp64_256_jive/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ fn mds_inv_test() {
#[test]
fn test_alphas() {
let e: BaseElement = rand_value();
let e_exp = e.exp(ALPHA.into());
let e_exp = e.exp(ALPHA);
assert_eq!(e, e_exp.exp(INV_ALPHA));
}

Expand Down Expand Up @@ -197,7 +197,7 @@ proptest! {
for i in 0..STATE_WIDTH {
v1[i] = BaseElement::new(a[i]);
}
v2 = v1.clone();
v2 = v1;

apply_mds_naive(&mut v1);
RpJive64_256::apply_mds(&mut v2);
Expand Down
1 change: 1 addition & 0 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ std = ["hex/std", "winterfell/std", "core-utils/std", "rand-utils"]

[dependencies]
winterfell = { version="0.6", path = "../winterfell", default-features = false }
winter-fri = { version="0.6", path = "../fri", default-features = false }
core-utils = { version = "0.6", path = "../utils/core", package = "winter-utils", default-features = false }
rand-utils = { version = "0.6", path = "../utils/rand", package = "winter-rand-utils", optional = true }
hex = { version = "0.4", optional = true }
Expand Down
5 changes: 4 additions & 1 deletion examples/benches/fibonacci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use examples::{fibonacci, Example};
use std::time::Duration;
use winter_fri::fri_schedule::FoldingSchedule;
use winterfell::{
crypto::hashers::Blake3_256, math::fields::f128::BaseElement, FieldExtension, ProofOptions,
};
Expand All @@ -17,7 +18,9 @@ fn fibonacci(c: &mut Criterion) {
group.sample_size(10);
group.measurement_time(Duration::from_secs(20));

let options = ProofOptions::new(32, 8, 0, FieldExtension::None, 4, 255);
let fri_constant_schedule = FoldingSchedule::new_constant(4, 255);

let options = ProofOptions::new(32, 8, 0, FieldExtension::None, &fri_constant_schedule);

for &size in SIZES.iter() {
let fib =
Expand Down
5 changes: 4 additions & 1 deletion examples/benches/rescue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use examples::{rescue, Example};
use winter_fri::fri_schedule::FoldingSchedule;

use std::time::Duration;
use winterfell::{
Expand All @@ -18,7 +19,9 @@ fn rescue(c: &mut Criterion) {
group.sample_size(10);
group.measurement_time(Duration::from_secs(25));

let options = ProofOptions::new(32, 32, 0, FieldExtension::None, 4, 255);
let fri_constant_schedule = FoldingSchedule::new_constant(4, 255);

let options = ProofOptions::new(32, 32, 0, FieldExtension::None, &fri_constant_schedule);

for &size in SIZES.iter() {
let resc = rescue::RescueExample::<Blake3_256<BaseElement>>::new(size, options.clone());
Expand Down
5 changes: 4 additions & 1 deletion examples/src/fibonacci/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,15 @@ pub fn compute_mulfib_term(n: usize) -> BaseElement {

#[cfg(test)]
pub fn build_proof_options(use_extension_field: bool) -> winterfell::ProofOptions {
use winter_fri::fri_schedule::FoldingSchedule;
use winterfell::{FieldExtension, ProofOptions};

let extension = if use_extension_field {
FieldExtension::Quadratic
} else {
FieldExtension::None
};
ProofOptions::new(28, 8, 0, extension, 4, 7)

let fri_constant_schedule = FoldingSchedule::new_constant(4, 7);
ProofOptions::new(28, 8, 0, extension, &fri_constant_schedule)
}
Loading