Skip to content

Commit

Permalink
Merge pull request #242 from Al-Kindi-0/al-improv-fri-error
Browse files Browse the repository at this point in the history
Make dependence on number of openings explicit in security estimator
  • Loading branch information
irakliyk authored Feb 1, 2024
2 parents a450b81 + c7ed2fc commit 08c31cb
Showing 1 changed file with 278 additions and 23 deletions.
301 changes: 278 additions & 23 deletions air/src/proof/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,11 +288,30 @@ fn proven_security_protocol_for_m(
let m = m as f64;
let rho = 1.0 / options.blowup_factor() as f64;
let alpha = (1.0 + 0.5 / m) * sqrt(rho);
let theta = 1.0 - alpha;
let max_deg = options.blowup_factor() as f64;
let max_deg = options.blowup_factor() as f64 + 1.0;

// To apply Theorem 8 in https://eprint.iacr.org/2022/1216.pdf, we need to apply FRI with
// a slightly larger agreement parameter alpha.
// More concretely, we need alpha > rho_plus.sqrt() where rho_plus is the rate in function field
// F(Z) and defined as (trace_domain_size + 2.0) / lde_domain_size .
// This means that the range of m needs to be restricted in order to ensure that
// alpha := 1 - theta := rho.sqrt() * (1 + 1/2m) is greater than rho_plus.sqrt().
// Determining the range of m is the responsibility of the calling function.
// Now, once m is fixed, we need to make sure that we choose an m_plus such that
// alpha <= rho_plus.sqrt() * (1 + 1/2m_plus). This m_plus will be used to define
// the list-decoding list size in F(Z).

// Modified rate in function field F(Z)
let lde_domain_size = (trace_domain_size * options.blowup_factor()) as f64;
let trace_domain_size = trace_domain_size as f64;
let num_openings = 2.0;
let rho_plus = (trace_domain_size + num_openings) / lde_domain_size;

// New proximity parameter m_plus, corresponding to rho_plus, needed to make sure that
// alpha < rho_plus.sqrt() * (1 + 1 / (2 * m_plus))
let m_plus = ceil(1.0 / (2.0 * (alpha / sqrt(rho_plus) - 1.0)));
let alpha_plus = (1.0 + 0.5 / m_plus) * sqrt(rho_plus);
let theta_plus = 1.0 - alpha_plus;

// Computes FRI commit-phase (i.e., pre-query) soundness error.
// This considers only the first term given in eq. 7 in https://eprint.iacr.org/2022/1216.pdf,
Expand All @@ -302,7 +321,7 @@ fn proven_security_protocol_for_m(

// Compute FRI query-phase soundness error
let fri_queries_err_bits =
options.grinding_factor() as f64 - log2(powf(1.0 - theta, num_fri_queries));
options.grinding_factor() as f64 - log2(powf(1.0 - theta_plus, num_fri_queries));

// Combined error for FRI
let fri_err_bits = cmp::min(fri_commit_err_bits as u64, fri_queries_err_bits as u64);
Expand All @@ -311,23 +330,6 @@ fn proven_security_protocol_for_m(
}
let fri_err_bits = fri_err_bits - 1;

// To apply Theorem 8 in https://eprint.iacr.org/2022/1216.pdf, we need to apply FRI with
// a slightly larger agreement parameter alpha.
// More concretely, we need alpha > rho_plus.sqrt() where rho_plus is the rate in function field
// F(Z) and defined as (trace_domain_size + 2.0) / lde_domain_size .
// This means that the range of m needs to be restricted in order to ensure that
// alpha := 1 - theta := rho.sqrt() * (1 + 1/2m) is greater than rho_plus.sqrt().
// Determining the range of m is the responsibility of the calling function.
// Now, once m is fixed, we need to make sure that we choose an m_plus such that
// alpha <= rho_plus.sqrt() * (1 + 1/2m_plus). This m_plus will be used to define
// the list-decoding list size in F(Z).

// Modified rate in function field F(Z)
let rho_plus = (trace_domain_size + 2.0) / lde_domain_size;
// New proximity parameter m_plus, corresponding to rho_plus, needed to make sure that
// alpha < rho_plus.sqrt() * (1 + 1 / (2 * m_plus))
let m_plus = ceil(1.0 / (2.0 * (alpha / sqrt(rho_plus) - 1.0)));

// List size
let l_plus = (2.0 * m_plus + 1.0) / (2.0 * sqrt(rho_plus));

Expand All @@ -338,9 +340,9 @@ fn proven_security_protocol_for_m(
// DEEP related soundness error. Note that this uses that the denominator |F| - |D ∪ H|
// can be approximated by |F| for all practical domain sizes. We also use the blow-up factor
// as an upper bound for the maximal constraint degree.
let deep_err_bits =
-log2(l_plus * (max_deg * (trace_domain_size + 1.0) + (trace_domain_size - 1.0)))
+ extension_field_bits;
let deep_err_bits = -log2(
l_plus * (max_deg * (trace_domain_size + num_openings - 1.0) + (trace_domain_size - 1.0)),
) + extension_field_bits;

let min = cmp::min(cmp::min(fri_err_bits, ali_err_bits as u64), deep_err_bits as u64);
if min < 1 {
Expand Down Expand Up @@ -404,3 +406,256 @@ pub fn ceil(value: f64) -> f64 {
pub fn ceil(value: f64) -> f64 {
libm::ceil(value)
}

#[cfg(test)]
mod prove_security_tests {
use super::ProofOptions;
use crate::{proof::get_proven_security, FieldExtension};
use math::{fields::f64::BaseElement, StarkField};

#[test]
fn get_96_bits_security() {
let field_extension = FieldExtension::Cubic;
let base_field_bits = BaseElement::MODULUS_BITS;
let fri_folding_factor = 8;
let fri_remainder_max_degree = 127;
let grinding_factor = 20;
let blowup_factor = 4;
let num_queries = 80;
let collision_resistance = 128;
let trace_length = 2_usize.pow(18);

let mut options = ProofOptions::new(
num_queries,
blowup_factor,
grinding_factor,
field_extension,
fri_folding_factor as usize,
fri_remainder_max_degree as usize,
);
let security_1 =
get_proven_security(&options, base_field_bits, trace_length, collision_resistance);

assert_eq!(security_1, 97);

// increasing the blowup factor should increase the bits of security gained per query
let blowup_factor = 8;
let num_queries = 53;

options = ProofOptions::new(
num_queries,
blowup_factor,
grinding_factor,
field_extension,
fri_folding_factor as usize,
fri_remainder_max_degree as usize,
);
let security_2 =
get_proven_security(&options, base_field_bits, trace_length, collision_resistance);

assert_eq!(security_2, 97);
}

#[test]
fn get_128_bits_security() {
let field_extension = FieldExtension::Cubic;
let base_field_bits = BaseElement::MODULUS_BITS;
let fri_folding_factor = 8;
let fri_remainder_max_degree = 127;
let grinding_factor = 20;
let blowup_factor = 8;
let num_queries = 85;
let collision_resistance = 128;
let trace_length = 2_usize.pow(18);

let mut options = ProofOptions::new(
num_queries,
blowup_factor,
grinding_factor,
field_extension,
fri_folding_factor as usize,
fri_remainder_max_degree as usize,
);
let security_1 =
get_proven_security(&options, base_field_bits, trace_length, collision_resistance);

assert_eq!(security_1, 128);

// increasing the blowup factor should increase the bits of security gained per query
let blowup_factor = 16;
let num_queries = 65;

options = ProofOptions::new(
num_queries,
blowup_factor,
grinding_factor,
field_extension,
fri_folding_factor as usize,
fri_remainder_max_degree as usize,
);
let security_2 =
get_proven_security(&options, base_field_bits, trace_length, collision_resistance);

assert_eq!(security_2, 128);
}

#[test]
fn extension_degree() {
let field_extension = FieldExtension::Quadratic;
let base_field_bits = BaseElement::MODULUS_BITS;
let fri_folding_factor = 8;
let fri_remainder_max_degree = 127;
let grinding_factor = 20;
let blowup_factor = 8;
let num_queries = 85;
let collision_resistance = 128;
let trace_length = 2_usize.pow(18);

let mut options = ProofOptions::new(
num_queries,
blowup_factor,
grinding_factor,
field_extension,
fri_folding_factor as usize,
fri_remainder_max_degree as usize,
);
let security_1 =
get_proven_security(&options, base_field_bits, trace_length, collision_resistance);

assert_eq!(security_1, 67);

// increasing the extension degree improves the FRI commit phase soundness error and permits
// reaching 128 bits security
let field_extension = FieldExtension::Cubic;

options = ProofOptions::new(
num_queries,
blowup_factor,
grinding_factor,
field_extension,
fri_folding_factor as usize,
fri_remainder_max_degree as usize,
);
let security_2 =
get_proven_security(&options, base_field_bits, trace_length, collision_resistance);

assert_eq!(security_2, 128);
}

#[test]
fn trace_length() {
let field_extension = FieldExtension::Cubic;
let base_field_bits = BaseElement::MODULUS_BITS;
let fri_folding_factor = 8;
let fri_remainder_max_degree = 127;
let grinding_factor = 20;
let blowup_factor = 8;
let num_queries = 80;
let collision_resistance = 128;
let trace_length = 2_usize.pow(20);

let mut options = ProofOptions::new(
num_queries,
blowup_factor,
grinding_factor,
field_extension,
fri_folding_factor as usize,
fri_remainder_max_degree as usize,
);
let security_1 =
get_proven_security(&options, base_field_bits, trace_length, collision_resistance);

let trace_length = 2_usize.pow(16);

options = ProofOptions::new(
num_queries,
blowup_factor,
grinding_factor,
field_extension,
fri_folding_factor as usize,
fri_remainder_max_degree as usize,
);
let security_2 =
get_proven_security(&options, base_field_bits, trace_length, collision_resistance);

assert!(security_1 < security_2);
}

#[test]
fn num_fri_queries() {
let field_extension = FieldExtension::Cubic;
let base_field_bits = BaseElement::MODULUS_BITS;
let fri_folding_factor = 8;
let fri_remainder_max_degree = 127;
let grinding_factor = 20;
let blowup_factor = 8;
let num_queries = 60;
let collision_resistance = 128;
let trace_length = 2_usize.pow(20);

let mut options = ProofOptions::new(
num_queries,
blowup_factor,
grinding_factor,
field_extension,
fri_folding_factor as usize,
fri_remainder_max_degree as usize,
);
let security_1 =
get_proven_security(&options, base_field_bits, trace_length, collision_resistance);

let num_queries = 80;

options = ProofOptions::new(
num_queries,
blowup_factor,
grinding_factor,
field_extension,
fri_folding_factor as usize,
fri_remainder_max_degree as usize,
);
let security_2 =
get_proven_security(&options, base_field_bits, trace_length, collision_resistance);

assert!(security_1 < security_2);
}

#[test]
fn blowup_factor() {
let field_extension = FieldExtension::Cubic;
let base_field_bits = BaseElement::MODULUS_BITS;
let fri_folding_factor = 8;
let fri_remainder_max_degree = 127;
let grinding_factor = 20;
let blowup_factor = 8;
let num_queries = 30;
let collision_resistance = 128;
let trace_length = 2_usize.pow(20);

let mut options = ProofOptions::new(
num_queries,
blowup_factor,
grinding_factor,
field_extension,
fri_folding_factor as usize,
fri_remainder_max_degree as usize,
);
let security_1 =
get_proven_security(&options, base_field_bits, trace_length, collision_resistance);

let blowup_factor = 16;

options = ProofOptions::new(
num_queries,
blowup_factor,
grinding_factor,
field_extension,
fri_folding_factor as usize,
fri_remainder_max_degree as usize,
);
let security_2 =
get_proven_security(&options, base_field_bits, trace_length, collision_resistance);

assert!(security_1 < security_2);
}
}

0 comments on commit 08c31cb

Please sign in to comment.