diff --git a/Cargo.toml b/Cargo.toml index 8c4968ec..bbd0bfdf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ unroll = "0.1.5" anyhow = "1.0.40" serde = { version = "1.0", features = ["derive"] } serde_cbor = "0.11.1" +num_bigint = "0.2.3" [profile.release] opt-level = 3 diff --git a/src/field/cosets.rs b/src/field/cosets.rs index 33f95242..8c1a03d6 100644 --- a/src/field/cosets.rs +++ b/src/field/cosets.rs @@ -1,14 +1,27 @@ -use crate::field::field::Field; +use num_bigint::BigUInt; +use crate::field::field::{Field, FieldOrder}; /// Finds a set of shifts that result in unique cosets for the multiplicative subgroup of size /// `2^subgroup_bits`. pub(crate) fn get_unique_coset_shifts(subgroup_size: usize, num_shifts: usize) -> Vec { - // From Lagrange's theorem. - let num_cosets = (F::ORDER - 1) / (subgroup_size as u64); - assert!( - num_shifts as u64 <= num_cosets, - "The subgroup does not have enough distinct cosets" - ); + match F::ORDER { + FieldOrder::U64(order) => { + // From Lagrange's theorem. + let num_cosets = (order - 1) / (subgroup_size as u64); + assert!( + num_shifts as u64 <= num_cosets, + "The subgroup does not have enough distinct cosets" + ); + }, + FieldOrder::Big(order) => { + // From Lagrange's theorem. + let num_cosets = (order - 1) / (subgroup_size as BigUInt); + assert!( + num_shifts as BigUInt <= num_cosets, + "The subgroup does not have enough distinct cosets" + ); + } + } // Let g be a generator of the entire multiplicative group. Let n be the order of the subgroup. // The subgroup can be written as . We can use g^0, ..., g^(num_shifts - 1) as our diff --git a/src/field/field.rs b/src/field/field.rs index 28a52202..4928ffb7 100644 --- a/src/field/field.rs +++ b/src/field/field.rs @@ -4,6 +4,7 @@ use std::hash::Hash; use std::iter::{Product, Sum}; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; +use num_bigint::BigUInt; use num::Integer; use rand::Rng; use serde::de::DeserializeOwned; @@ -12,6 +13,11 @@ use serde::Serialize; use crate::field::extension_field::Frobenius; use crate::util::bits_u64; +pub enum FieldOrder { + U64(u64), + Big(BigUInt) + } + /// A finite field with prime order less than 2^64. pub trait Field: 'static @@ -44,7 +50,7 @@ pub trait Field: const NEG_ONE: Self; const CHARACTERISTIC: u64; - const ORDER: u64; + const ORDER: FieldOrder; const TWO_ADICITY: usize; /// Generator of the entire multiplicative group, i.e. all non-zero elements. diff --git a/src/fri/mod.rs b/src/fri/mod.rs index ab7137c2..89e75875 100644 --- a/src/fri/mod.rs +++ b/src/fri/mod.rs @@ -10,6 +10,8 @@ const EPSILON: f64 = 0.01; pub struct FriConfig { pub proof_of_work_bits: u32, + pub rate_bits: usize, + /// The arity of each FRI reduction step, expressed (i.e. the log2 of the actual arity). /// For example, `[3, 2, 1]` would describe a FRI reduction tree with 8-to-1 reduction, then /// a 4-to-1 reduction, then a 2-to-1 reduction. After these reductions, the reduced polynomial @@ -42,3 +44,21 @@ fn fri_l(codeword_len: usize, rate_log: usize, conjecture: bool) -> f64 { 1.0 / (2.0 * EPSILON * rate.sqrt()) } } + +fn fri_soundness( + num_functions: usize, + rate_bits: usize, + codeword_size_bits: usize, + m: usize, + arity_bits: usize, + num_rounds: usize, + field_size_bits: usize, + num_queries: usize, +) { + let rho = 1.0 / ((1 >> rate_bits) as f32); + + let alpha = rho.sqrt() * (1.0 + 1.0 / (2.0 * m as f32)); + + let term_1 = (m as f32 + 0.5).powi(7) / (rho.powf(1.5) * (1 << (field_size_bits - 2 * codeword_size_bits + 1)) as f32); + let term_2 = (2.0 * m + 1.0) * ((1 << codeword_size_bits) as f32 + 1.0) +}