From 56f560cb2791ac00a7d2ef3607ea7062498bfcfa Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 12 Nov 2024 16:12:56 +0000 Subject: [PATCH 01/19] Create Telescope structure --- src/centralized_telescope/algorithm.rs | 127 ++------------------ src/centralized_telescope/mod.rs | 6 +- src/centralized_telescope/telescope.rs | 157 +++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 122 deletions(-) create mode 100644 src/centralized_telescope/telescope.rs diff --git a/src/centralized_telescope/algorithm.rs b/src/centralized_telescope/algorithm.rs index 4acee0d5..32bca421 100644 --- a/src/centralized_telescope/algorithm.rs +++ b/src/centralized_telescope/algorithm.rs @@ -8,54 +8,14 @@ use crate::utils::sample; use crate::utils::types::Element; use blake2::{Blake2s256, Digest}; -/// Alba's proving algorithm, based on a depth-first search algorithm. -/// Calls up to setup.max_retries times the prove_index function and returns an empty -/// proof if no suitable candidate is found. -pub fn prove(setup: &Setup, prover_set: &[Element]) -> Option { - // Run prove_index up to max_retries times - (0..setup.max_retries).find_map(|retry_counter| prove_index(setup, prover_set, retry_counter).1) -} - -/// Alba's verification algorithm, returns true if the proof is -/// successfully verified, following the DFS verification, false otherwise. -pub fn verify(setup: &Setup, proof: &Proof) -> bool { - if proof.search_counter >= setup.search_width - || proof.retry_counter >= setup.max_retries - || proof.element_sequence.len() as u64 != setup.proof_size - { - return false; - } - - // Initialise a round with given retry and search counters - let Some(mut round) = Round::new(proof.retry_counter, proof.search_counter, setup.set_size) - else { - return false; - }; - - // For each element in the proof's sequence - for &element in &proof.element_sequence { - // Retrieve the bin id associated to this new element - let Some(bin_id) = bin_hash(setup, proof.retry_counter, element) else { - return false; - }; - // Check that the new element was chosen correctly - // i.e. that we chose the new element such that its bin id equals the round id - if round.id == bin_id { - match Round::update(&round, element) { - Some(r) => round = r, - None => return false, - } - } else { - return false; - } - } - proof_hash(setup, &round) -} - /// Indexed proving algorithm, returns the total number of DFS calls done /// to find a proof and Some(proof) if found within setup.dfs_bound calls of DFS, /// otherwise None -fn prove_index(setup: &Setup, prover_set: &[Element], retry_counter: u64) -> (u64, Option) { +pub(crate) fn prove_index( + setup: &Setup, + prover_set: &[Element], + retry_counter: u64, +) -> (u64, Option) { // Initialise set_size bins let mut bins: Vec> = Vec::with_capacity(setup.set_size as usize); for _ in 0..setup.set_size { @@ -141,7 +101,7 @@ fn dfs(setup: &Setup, bins: &[Vec], round: &Round, mut step: u64) -> (u } /// Oracle producing a uniformly random value in [0, set_size[ used for prehashing S_p -fn bin_hash(setup: &Setup, retry_counter: u64, element: Element) -> Option { +pub(crate) fn bin_hash(setup: &Setup, retry_counter: u64, element: Element) -> Option { let retry_bytes: [u8; 8] = retry_counter.to_be_bytes(); let mut hasher = Blake2s256::new(); hasher.update(b"Telescope-bin_hash"); @@ -152,83 +112,10 @@ fn bin_hash(setup: &Setup, retry_counter: u64, element: Element) -> Option } /// Oracle defined as Bernoulli(q) returning 1 with probability q and 0 otherwise -fn proof_hash(setup: &Setup, r: &Round) -> bool { +pub(crate) fn proof_hash(setup: &Setup, r: &Round) -> bool { let mut hasher = Blake2s256::new(); hasher.update(b"Telescope-proof_hash"); hasher.update(r.hash); let digest: Hash = hasher.finalize().into(); sample::sample_bernoulli(&digest, setup.valid_proof_probability) } - -#[cfg(test)] -mod tests { - use super::*; - use crate::centralized_telescope::{init, params::Params}; - use crate::utils::test_utils::gen_items; - use crate::utils::types::DATA_LENGTH; - use rand_chacha::ChaCha20Rng; - use rand_core::{RngCore, SeedableRng}; - - #[test] - fn test_verify() { - let mut rng = ChaCha20Rng::from_seed(Default::default()); - let nb_tests = 1_000; - let set_size = 1_000; - let params = Params { - soundness_param: 10.0, - completeness_param: 10.0, - set_size: 80 * set_size / 100, - lower_bound: 20 * set_size / 100, - }; - for _t in 0..nb_tests { - let seed = rng.next_u32().to_be_bytes().to_vec(); - let s_p = gen_items::(&seed, set_size); - let setup = init::make_setup(¶ms); - let proof = prove(&setup, &s_p).unwrap(); - assert!(verify(&setup, &proof.clone())); - // Checking that the proof fails if proof.search_counter is erroneous - let proof_t = Proof { - retry_counter: proof.retry_counter, - search_counter: proof.search_counter.wrapping_add(1), - element_sequence: proof.element_sequence.clone(), - }; - assert!(!verify(&setup, &proof_t)); - // Checking that the proof fails if proof.retry_counter is erroneous - let proof_v = Proof { - retry_counter: proof.retry_counter.wrapping_add(1), - search_counter: proof.search_counter, - element_sequence: proof.element_sequence.clone(), - }; - assert!(!verify(&setup, &proof_v)); - // Checking that the proof fails when no elements are included - let proof_item = Proof { - retry_counter: proof.retry_counter, - search_counter: proof.search_counter, - element_sequence: Vec::new(), - }; - assert!(!verify(&setup, &proof_item)); - // Checking that the proof fails when wrong elements are included - // We are trying to trigger proof_hash - let mut wrong_items = proof.element_sequence.clone(); - let last_item = wrong_items.pop().unwrap(); - let mut penultimate_item = wrong_items.pop().unwrap(); - let proof_itembis = Proof { - retry_counter: proof.retry_counter, - search_counter: proof.search_counter, - element_sequence: wrong_items.clone(), - }; - assert!(!verify(&setup, &proof_itembis)); - // Checking that the proof fails when wrong elements are included - // We are trying to trigger round_hash - penultimate_item[0] = penultimate_item[0].wrapping_add(42u8); - wrong_items.push(penultimate_item); - wrong_items.push(last_item); - let proof_itembis = Proof { - retry_counter: proof.retry_counter, - search_counter: proof.search_counter, - element_sequence: wrong_items.clone(), - }; - assert!(!verify(&setup, &proof_itembis)); - } - } -} diff --git a/src/centralized_telescope/mod.rs b/src/centralized_telescope/mod.rs index 76b293d5..0b832453 100644 --- a/src/centralized_telescope/mod.rs +++ b/src/centralized_telescope/mod.rs @@ -1,9 +1,9 @@ //! ALBA's bounded DFS scheme using Blake2b as hash function. //! (c.f. Section 3.2.2 of Alba paper) -pub mod algorithm; +mod algorithm; -pub mod init; +mod init; pub mod params; @@ -13,4 +13,6 @@ mod round; pub mod setup; +pub mod telescope; + mod types; diff --git a/src/centralized_telescope/telescope.rs b/src/centralized_telescope/telescope.rs new file mode 100644 index 00000000..25677074 --- /dev/null +++ b/src/centralized_telescope/telescope.rs @@ -0,0 +1,157 @@ +//! Customer facing Telescope structure + +use super::algorithm::{bin_hash, proof_hash, prove_index}; +use super::init::make_setup; +use super::params::Params; +use super::proof::Proof; +use super::round::Round; +use super::setup::Setup; + +/// Structure wrapping input and internal parameters to generate a proof from +/// and verify it +#[derive(Debug, Clone, Copy)] +pub struct Telescope { + /// Input parameters + pub params: Params, + /// Internal parameters + pub setup: Setup, +} + +impl Telescope { + /// Returns a Telescope structure from input parameters + pub fn new(params: Params) -> Self { + let setup = make_setup(¶ms); + Telescope { params, setup } + } + + /// Returns a Telescope structure from a set_size and Setup + pub fn from(set_size: u64, setup: Setup) -> Self { + let params = Params { + soundness_param: 0.0, + completeness_param: 0.0, + set_size, + lower_bound: 0, + }; + Telescope { params, setup } + } + + /// Alba's proving algorithm, based on a depth-first search algorithm. + /// Calls up to setup.max_retries times the prove_index function and returns an empty + /// proof if no suitable candidate is found. + pub fn prove(self, prover_set: &[crate::utils::types::Element]) -> Option { + // Run prove_index up to max_retries times + (0..self.setup.max_retries) + .find_map(|retry_counter| prove_index(&self.setup, prover_set, retry_counter).1) + } + + /// Alba's verification algorithm, returns true if the proof is + /// successfully verified, following the DFS verification, false otherwise. + pub fn verify(self, proof: &Proof) -> bool { + if proof.search_counter >= self.setup.search_width + || proof.retry_counter >= self.setup.max_retries + || proof.element_sequence.len() as u64 != self.setup.proof_size + { + return false; + } + + // Initialise a round with given retry and search counters + let Some(mut round) = Round::new( + proof.retry_counter, + proof.search_counter, + self.setup.set_size, + ) else { + return false; + }; + + // For each element in the proof's sequence + for &element in &proof.element_sequence { + // Retrieve the bin id associated to this new element + let Some(bin_id) = bin_hash(&self.setup, proof.retry_counter, element) else { + return false; + }; + // Check that the new element was chosen correctly + // i.e. that we chose the new element such that its bin id equals the round id + if round.id == bin_id { + match Round::update(&round, element) { + Some(r) => round = r, + None => return false, + } + } else { + return false; + } + } + proof_hash(&self.setup, &round) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::utils::test_utils::gen_items; + use crate::utils::types::DATA_LENGTH; + use rand_chacha::ChaCha20Rng; + use rand_core::{RngCore, SeedableRng}; + + #[test] + fn test_verify() { + let mut rng = ChaCha20Rng::from_seed(Default::default()); + let nb_tests = 1_000; + let set_size = 1_000; + let params = Params { + soundness_param: 10.0, + completeness_param: 10.0, + set_size: 80 * set_size / 100, + lower_bound: 20 * set_size / 100, + }; + for _t in 0..nb_tests { + let seed = rng.next_u32().to_be_bytes().to_vec(); + let s_p = gen_items::(&seed, set_size); + let telescope = Telescope::new(params); + let proof = telescope.prove(&s_p).unwrap(); + assert!(telescope.clone().verify(&proof.clone())); + // Checking that the proof fails if proof.search_counter is erroneous + let proof_t = Proof { + retry_counter: proof.retry_counter, + search_counter: proof.search_counter.wrapping_add(1), + element_sequence: proof.element_sequence.clone(), + }; + assert!(!telescope.verify(&proof_t)); + // Checking that the proof fails if proof.retry_counter is erroneous + let proof_v = Proof { + retry_counter: proof.retry_counter.wrapping_add(1), + search_counter: proof.search_counter, + element_sequence: proof.element_sequence.clone(), + }; + assert!(!telescope.verify(&proof_v)); + // Checking that the proof fails when no elements are included + let proof_item = Proof { + retry_counter: proof.retry_counter, + search_counter: proof.search_counter, + element_sequence: Vec::new(), + }; + assert!(!telescope.verify(&proof_item)); + // Checking that the proof fails when wrong elements are included + // We are trying to trigger proof_hash + let mut wrong_items = proof.element_sequence.clone(); + let last_item = wrong_items.pop().unwrap(); + let mut penultimate_item = wrong_items.pop().unwrap(); + let proof_itembis = Proof { + retry_counter: proof.retry_counter, + search_counter: proof.search_counter, + element_sequence: wrong_items.clone(), + }; + assert!(!telescope.verify(&proof_itembis)); + // Checking that the proof fails when wrong elements are included + // We are trying to trigger round_hash + penultimate_item[0] = penultimate_item[0].wrapping_add(42u8); + wrong_items.push(penultimate_item); + wrong_items.push(last_item); + let proof_itembis = Proof { + retry_counter: proof.retry_counter, + search_counter: proof.search_counter, + element_sequence: wrong_items.clone(), + }; + assert!(!telescope.verify(&proof_itembis)); + } + } +} From 02e0fb7fa1d71694d00c0a43973456f653505144 Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 12 Nov 2024 16:23:55 +0000 Subject: [PATCH 02/19] Deleting params.rs --- src/centralized_telescope/init.rs | 59 +++++++++++++++---------- src/centralized_telescope/mod.rs | 2 - src/centralized_telescope/params.rs | 14 ------ src/centralized_telescope/telescope.rs | 61 +++++++++++++++++--------- 4 files changed, 77 insertions(+), 59 deletions(-) delete mode 100644 src/centralized_telescope/params.rs diff --git a/src/centralized_telescope/init.rs b/src/centralized_telescope/init.rs index ac49bdf9..bfc506a9 100644 --- a/src/centralized_telescope/init.rs +++ b/src/centralized_telescope/init.rs @@ -1,18 +1,21 @@ //! ALBA's bounded DFS scheme setup functions -use super::params::Params; use super::setup::Setup; use std::f64::consts::LOG2_E; /// Setup algorithm taking a Params as input and returning setup parameters (u,d,q) -pub fn make_setup(params: &Params) -> Setup { - let set_size_f64 = params.set_size as f64; - let lower_bound_f64 = params.lower_bound as f64; +pub fn make_setup( + soundness_param: f64, + completeness_param: f64, + set_size: u64, + lower_bound: u64, +) -> Setup { + let set_size_f64 = set_size as f64; + let lower_bound_f64 = lower_bound as f64; let proof_size_f64 = { - let numerator = - params.soundness_param + params.completeness_param.log2() + 5.0 - LOG2_E.log2(); + let numerator = soundness_param + completeness_param.log2() + 5.0 - LOG2_E.log2(); let denominator = (set_size_f64 / lower_bound_f64).log2(); (numerator / denominator).ceil() }; @@ -23,27 +26,32 @@ pub fn make_setup(params: &Params) -> Setup { if s1 < 1.0 || s2 < 1.0 { // Small case, i.e. set_size <= λ^2 - param_small_case(params, proof_size_f64) + param_small_case(completeness_param, set_size, proof_size_f64) } else { - let completeness_param2 = params.completeness_param.min(s2); + let completeness_param2 = completeness_param.min(s2); if proof_size_f64 < completeness_param2 { // Case 3, Theorem 14, i.e. set_size >= λ^3 - param_high_case(params, proof_size_f64, completeness_param2) + param_high_case( + completeness_param, + set_size, + proof_size_f64, + completeness_param2, + ) } else { // Case 2, Theorem 13, i.e. λ^2 < set_size < λ^3 - param_mid_case(params, proof_size_f64, s1) + param_mid_case(completeness_param, set_size, proof_size_f64, s1) } } } /// Helper function that returns Setup, used when set_size <= λ^2 -fn param_small_case(params: &Params, proof_size_f64: f64) -> Setup { +fn param_small_case(completeness_param: f64, set_size: u64, proof_size_f64: f64) -> Setup { let ln12 = (12f64).ln(); let search_width = (32.0 * ln12 * proof_size_f64).ceil(); Setup { - set_size: params.set_size, + set_size, proof_size: proof_size_f64 as u64, - max_retries: params.completeness_param as u64, + max_retries: completeness_param as u64, search_width: search_width as u64, valid_proof_probability: 2.0 * ln12 / search_width, dfs_bound: (8.0 * (proof_size_f64 + 1.0) * search_width / ln12).floor() as u64, @@ -51,14 +59,19 @@ fn param_small_case(params: &Params, proof_size_f64: f64) -> Setup { } /// Helper function that returns Setup, used when set_size >= λ^3 -fn param_high_case(params: &Params, proof_size_f64: f64, completeness_param2: f64) -> Setup { +fn param_high_case( + completeness_param: f64, + set_size: u64, + proof_size_f64: f64, + completeness_param2: f64, +) -> Setup { let l2 = completeness_param2 + 2.0; let search_width = (16.0 * proof_size_f64 * l2 / LOG2_E).ceil(); - debug_assert!(params.set_size as f64 >= search_width * search_width * LOG2_E / (9.0 * l2)); + debug_assert!(set_size as f64 >= search_width * search_width * LOG2_E / (9.0 * l2)); Setup { - set_size: params.set_size, + set_size, proof_size: proof_size_f64 as u64, - max_retries: (params.completeness_param / completeness_param2).ceil() as u64, + max_retries: (completeness_param / completeness_param2).ceil() as u64, search_width: search_width as u64, valid_proof_probability: 2.0 * l2 / (search_width * LOG2_E), dfs_bound: (((l2 + proof_size_f64.log2()) / l2) @@ -70,7 +83,7 @@ fn param_high_case(params: &Params, proof_size_f64: f64, completeness_param2: f6 } /// Helper function that returns Setup, used when λ^2 < set_size < λ^3 -fn param_mid_case(params: &Params, proof_size_f64: f64, s1: f64) -> Setup { +fn param_mid_case(completeness_param: f64, set_size: u64, proof_size_f64: f64, s1: f64) -> Setup { fn max_vertices_visited(proof_size: f64, l1: f64) -> f64 { fn factorial_check(max_v: f64, l1: f64) -> bool { let bound = (-l1).exp2(); @@ -94,20 +107,20 @@ fn param_mid_case(params: &Params, proof_size_f64: f64, s1: f64) -> Setup { } max_v } - let completeness_param1 = params.completeness_param.min(s1); + let completeness_param1 = completeness_param.min(s1); let lbar = (completeness_param1 + 7.0) / LOG2_E; let search_width = (16.0 * proof_size_f64 * lbar).ceil(); let lbar_over_sw = lbar / search_width; - debug_assert!(params.set_size as f64 >= search_width * search_width / (9.0 * lbar)); + debug_assert!(set_size as f64 >= search_width * search_width / (9.0 * lbar)); let max_v = max_vertices_visited(proof_size_f64, completeness_param1); - let exponential = (2.0 * proof_size_f64 * max_v * lbar / params.set_size as f64 + let exponential = (2.0 * proof_size_f64 * max_v * lbar / set_size as f64 + 7.0 * proof_size_f64 / max_v) .exp(); Setup { - set_size: params.set_size, + set_size, proof_size: proof_size_f64 as u64, - max_retries: (params.completeness_param / completeness_param1).ceil() as u64, + max_retries: (completeness_param / completeness_param1).ceil() as u64, search_width: search_width as u64, valid_proof_probability: 2.0 * lbar_over_sw, dfs_bound: ((max_v * lbar_over_sw + 1.0) * exponential * search_width * proof_size_f64 diff --git a/src/centralized_telescope/mod.rs b/src/centralized_telescope/mod.rs index 0b832453..1e938a7c 100644 --- a/src/centralized_telescope/mod.rs +++ b/src/centralized_telescope/mod.rs @@ -5,8 +5,6 @@ mod algorithm; mod init; -pub mod params; - pub mod proof; mod round; diff --git a/src/centralized_telescope/params.rs b/src/centralized_telescope/params.rs deleted file mode 100644 index 680468eb..00000000 --- a/src/centralized_telescope/params.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! ALBA's Setup structure - -/// Setup input parameters -#[derive(Debug, Clone, Copy)] -pub struct Params { - /// Soundness security parameter - pub soundness_param: f64, - /// Completeness security parameter - pub completeness_param: f64, - /// Approximate size of the prover set to lower bound - pub set_size: u64, - /// Lower bound to prove on prover set - pub lower_bound: u64, -} diff --git a/src/centralized_telescope/telescope.rs b/src/centralized_telescope/telescope.rs index 25677074..845147c9 100644 --- a/src/centralized_telescope/telescope.rs +++ b/src/centralized_telescope/telescope.rs @@ -2,7 +2,6 @@ use super::algorithm::{bin_hash, proof_hash, prove_index}; use super::init::make_setup; -use super::params::Params; use super::proof::Proof; use super::round::Round; use super::setup::Setup; @@ -11,28 +10,51 @@ use super::setup::Setup; /// and verify it #[derive(Debug, Clone, Copy)] pub struct Telescope { - /// Input parameters - pub params: Params, + /// Soundness security parameter + pub soundness_param: f64, + /// Completeness security parameter + pub completeness_param: f64, + /// Approximate size of the prover set to lower bound + pub set_size: u64, + /// Lower bound to prove on prover set + pub lower_bound: u64, /// Internal parameters pub setup: Setup, } impl Telescope { /// Returns a Telescope structure from input parameters - pub fn new(params: Params) -> Self { - let setup = make_setup(¶ms); - Telescope { params, setup } + pub fn new( + soundness_param: f64, + completeness_param: f64, + set_size: u64, + lower_bound: u64, + ) -> Self { + let setup = make_setup(soundness_param, completeness_param, set_size, lower_bound); + Telescope { + soundness_param, + completeness_param, + set_size, + lower_bound, + setup, + } } /// Returns a Telescope structure from a set_size and Setup - pub fn from(set_size: u64, setup: Setup) -> Self { - let params = Params { - soundness_param: 0.0, - completeness_param: 0.0, + pub fn from( + soundness_param: f64, + completeness_param: f64, + set_size: u64, + lower_bound: u64, + setup: Setup, + ) -> Self { + Telescope { + soundness_param, + completeness_param, set_size, - lower_bound: 0, - }; - Telescope { params, setup } + lower_bound, + setup, + } } /// Alba's proving algorithm, based on a depth-first search algorithm. @@ -97,16 +119,15 @@ mod tests { let mut rng = ChaCha20Rng::from_seed(Default::default()); let nb_tests = 1_000; let set_size = 1_000; - let params = Params { - soundness_param: 10.0, - completeness_param: 10.0, - set_size: 80 * set_size / 100, - lower_bound: 20 * set_size / 100, - }; + let soundness_param = 10.0; + let completeness_param = 10.0; + let set_size = 80 * set_size / 100; + let lower_bound = 20 * set_size / 100; for _t in 0..nb_tests { let seed = rng.next_u32().to_be_bytes().to_vec(); let s_p = gen_items::(&seed, set_size); - let telescope = Telescope::new(params); + let telescope = + Telescope::new(soundness_param, completeness_param, set_size, lower_bound); let proof = telescope.prove(&s_p).unwrap(); assert!(telescope.clone().verify(&proof.clone())); // Checking that the proof fails if proof.search_counter is erroneous From f51e07528cece341dac72432b234ecb2c0065caf Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 12 Nov 2024 16:34:16 +0000 Subject: [PATCH 03/19] Updating visibility in algo.rs --- src/centralized_telescope/algorithm.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/centralized_telescope/algorithm.rs b/src/centralized_telescope/algorithm.rs index 32bca421..2d584164 100644 --- a/src/centralized_telescope/algorithm.rs +++ b/src/centralized_telescope/algorithm.rs @@ -11,7 +11,7 @@ use blake2::{Blake2s256, Digest}; /// Indexed proving algorithm, returns the total number of DFS calls done /// to find a proof and Some(proof) if found within setup.dfs_bound calls of DFS, /// otherwise None -pub(crate) fn prove_index( +pub(super) fn prove_index( setup: &Setup, prover_set: &[Element], retry_counter: u64, @@ -101,7 +101,7 @@ fn dfs(setup: &Setup, bins: &[Vec], round: &Round, mut step: u64) -> (u } /// Oracle producing a uniformly random value in [0, set_size[ used for prehashing S_p -pub(crate) fn bin_hash(setup: &Setup, retry_counter: u64, element: Element) -> Option { +pub(super) fn bin_hash(setup: &Setup, retry_counter: u64, element: Element) -> Option { let retry_bytes: [u8; 8] = retry_counter.to_be_bytes(); let mut hasher = Blake2s256::new(); hasher.update(b"Telescope-bin_hash"); @@ -112,7 +112,7 @@ pub(crate) fn bin_hash(setup: &Setup, retry_counter: u64, element: Element) -> O } /// Oracle defined as Bernoulli(q) returning 1 with probability q and 0 otherwise -pub(crate) fn proof_hash(setup: &Setup, r: &Round) -> bool { +pub(super) fn proof_hash(setup: &Setup, r: &Round) -> bool { let mut hasher = Blake2s256::new(); hasher.update(b"Telescope-proof_hash"); hasher.update(r.hash); From 685884f9d821013dbbb358ea11997b3103b3c489 Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 12 Nov 2024 16:37:28 +0000 Subject: [PATCH 04/19] Removing set_size from Setup --- src/centralized_telescope/algorithm.rs | 24 +++++++++++------------- src/centralized_telescope/init.rs | 7 ++----- src/centralized_telescope/setup.rs | 2 -- src/centralized_telescope/telescope.rs | 16 +++++++--------- 4 files changed, 20 insertions(+), 29 deletions(-) diff --git a/src/centralized_telescope/algorithm.rs b/src/centralized_telescope/algorithm.rs index 2d584164..238e32a9 100644 --- a/src/centralized_telescope/algorithm.rs +++ b/src/centralized_telescope/algorithm.rs @@ -12,22 +12,20 @@ use blake2::{Blake2s256, Digest}; /// to find a proof and Some(proof) if found within setup.dfs_bound calls of DFS, /// otherwise None pub(super) fn prove_index( + set_size: u64, setup: &Setup, prover_set: &[Element], retry_counter: u64, ) -> (u64, Option) { // Initialise set_size bins - let mut bins: Vec> = Vec::with_capacity(setup.set_size as usize); - for _ in 0..setup.set_size { + let mut bins: Vec> = Vec::with_capacity(set_size as usize); + for _ in 0..set_size { bins.push(Vec::new()); } // Take only up to 2*set_size elements for efficiency and fill the bins with them - for &element in prover_set - .iter() - .take(setup.set_size.saturating_mul(2) as usize) - { - match bin_hash(setup, retry_counter, element) { + for &element in prover_set.iter().take(set_size.saturating_mul(2) as usize) { + match bin_hash(set_size, retry_counter, element) { Some(bin_index) => { bins[bin_index as usize].push(element); } @@ -43,7 +41,7 @@ pub(super) fn prove_index( return (step, None); } // Initialise new round - if let Some(r) = Round::new(retry_counter, search_counter, setup.set_size) { + if let Some(r) = Round::new(retry_counter, search_counter, set_size) { // Run DFS on such round, incrementing step let (dfs_calls, proof_opt) = dfs(setup, &bins, &r, step.saturating_add(1)); // Returns proof if found @@ -66,7 +64,7 @@ pub(super) fn prove_index( fn dfs(setup: &Setup, bins: &[Vec], round: &Round, mut step: u64) -> (u64, Option) { // If current round comprises proof_size elements, returns it as Proof if round.element_sequence.len() as u64 == setup.proof_size { - let proof_opt = if proof_hash(setup, round) { + let proof_opt = if proof_hash(setup.valid_proof_probability, round) { Some(Proof { retry_counter: round.retry_counter, search_counter: round.search_counter, @@ -101,21 +99,21 @@ fn dfs(setup: &Setup, bins: &[Vec], round: &Round, mut step: u64) -> (u } /// Oracle producing a uniformly random value in [0, set_size[ used for prehashing S_p -pub(super) fn bin_hash(setup: &Setup, retry_counter: u64, element: Element) -> Option { +pub(super) fn bin_hash(set_size: u64, retry_counter: u64, element: Element) -> Option { let retry_bytes: [u8; 8] = retry_counter.to_be_bytes(); let mut hasher = Blake2s256::new(); hasher.update(b"Telescope-bin_hash"); hasher.update(retry_bytes); hasher.update(element); let digest: Hash = hasher.finalize().into(); - sample::sample_uniform(&digest, setup.set_size) + sample::sample_uniform(&digest, set_size) } /// Oracle defined as Bernoulli(q) returning 1 with probability q and 0 otherwise -pub(super) fn proof_hash(setup: &Setup, r: &Round) -> bool { +pub(super) fn proof_hash(valid_proof_probability: f64, r: &Round) -> bool { let mut hasher = Blake2s256::new(); hasher.update(b"Telescope-proof_hash"); hasher.update(r.hash); let digest: Hash = hasher.finalize().into(); - sample::sample_bernoulli(&digest, setup.valid_proof_probability) + sample::sample_bernoulli(&digest, valid_proof_probability) } diff --git a/src/centralized_telescope/init.rs b/src/centralized_telescope/init.rs index bfc506a9..86adf9e9 100644 --- a/src/centralized_telescope/init.rs +++ b/src/centralized_telescope/init.rs @@ -26,7 +26,7 @@ pub fn make_setup( if s1 < 1.0 || s2 < 1.0 { // Small case, i.e. set_size <= λ^2 - param_small_case(completeness_param, set_size, proof_size_f64) + param_small_case(completeness_param, proof_size_f64) } else { let completeness_param2 = completeness_param.min(s2); if proof_size_f64 < completeness_param2 { @@ -45,11 +45,10 @@ pub fn make_setup( } /// Helper function that returns Setup, used when set_size <= λ^2 -fn param_small_case(completeness_param: f64, set_size: u64, proof_size_f64: f64) -> Setup { +fn param_small_case(completeness_param: f64, proof_size_f64: f64) -> Setup { let ln12 = (12f64).ln(); let search_width = (32.0 * ln12 * proof_size_f64).ceil(); Setup { - set_size, proof_size: proof_size_f64 as u64, max_retries: completeness_param as u64, search_width: search_width as u64, @@ -69,7 +68,6 @@ fn param_high_case( let search_width = (16.0 * proof_size_f64 * l2 / LOG2_E).ceil(); debug_assert!(set_size as f64 >= search_width * search_width * LOG2_E / (9.0 * l2)); Setup { - set_size, proof_size: proof_size_f64 as u64, max_retries: (completeness_param / completeness_param2).ceil() as u64, search_width: search_width as u64, @@ -118,7 +116,6 @@ fn param_mid_case(completeness_param: f64, set_size: u64, proof_size_f64: f64, s + 7.0 * proof_size_f64 / max_v) .exp(); Setup { - set_size, proof_size: proof_size_f64 as u64, max_retries: (completeness_param / completeness_param1).ceil() as u64, search_width: search_width as u64, diff --git a/src/centralized_telescope/setup.rs b/src/centralized_telescope/setup.rs index 2900646a..ebaaeeb6 100644 --- a/src/centralized_telescope/setup.rs +++ b/src/centralized_telescope/setup.rs @@ -3,8 +3,6 @@ /// Setup output parameters #[derive(Debug, Clone, Copy)] pub struct Setup { - /// Total number of elements available to the prover - pub set_size: u64, /// Number of prover set's elements pub proof_size: u64, /// Maximum number of retries to find a proof diff --git a/src/centralized_telescope/telescope.rs b/src/centralized_telescope/telescope.rs index 845147c9..3183026f 100644 --- a/src/centralized_telescope/telescope.rs +++ b/src/centralized_telescope/telescope.rs @@ -62,8 +62,9 @@ impl Telescope { /// proof if no suitable candidate is found. pub fn prove(self, prover_set: &[crate::utils::types::Element]) -> Option { // Run prove_index up to max_retries times - (0..self.setup.max_retries) - .find_map(|retry_counter| prove_index(&self.setup, prover_set, retry_counter).1) + (0..self.setup.max_retries).find_map(|retry_counter| { + prove_index(self.set_size, &self.setup, prover_set, retry_counter).1 + }) } /// Alba's verification algorithm, returns true if the proof is @@ -77,18 +78,15 @@ impl Telescope { } // Initialise a round with given retry and search counters - let Some(mut round) = Round::new( - proof.retry_counter, - proof.search_counter, - self.setup.set_size, - ) else { + let Some(mut round) = Round::new(proof.retry_counter, proof.search_counter, self.set_size) + else { return false; }; // For each element in the proof's sequence for &element in &proof.element_sequence { // Retrieve the bin id associated to this new element - let Some(bin_id) = bin_hash(&self.setup, proof.retry_counter, element) else { + let Some(bin_id) = bin_hash(self.set_size, proof.retry_counter, element) else { return false; }; // Check that the new element was chosen correctly @@ -102,7 +100,7 @@ impl Telescope { return false; } } - proof_hash(&self.setup, &round) + proof_hash(self.setup.valid_proof_probability, &round) } } From 788456cc62c0746ab60b030e7253d5b33fd4a7b2 Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 12 Nov 2024 17:08:08 +0000 Subject: [PATCH 05/19] Renaming Setup(.rs) -> Params(.rs) --- src/centralized_telescope/algorithm.rs | 29 +++++++++++-------- src/centralized_telescope/init.rs | 24 +++++++-------- src/centralized_telescope/mod.rs | 2 +- .../{setup.rs => params.rs} | 6 ++-- src/centralized_telescope/telescope.rs | 28 +++++++++--------- src/simple_lottery/setup.rs | 4 +-- 6 files changed, 49 insertions(+), 44 deletions(-) rename src/centralized_telescope/{setup.rs => params.rs} (74%) diff --git a/src/centralized_telescope/algorithm.rs b/src/centralized_telescope/algorithm.rs index 238e32a9..59cd0811 100644 --- a/src/centralized_telescope/algorithm.rs +++ b/src/centralized_telescope/algorithm.rs @@ -1,19 +1,19 @@ //! ALBA's bounded DFS scheme prove and verification functions +use super::params::Params; use super::proof::Proof; use super::round::Round; -use super::setup::Setup; use super::types::Hash; use crate::utils::sample; use crate::utils::types::Element; use blake2::{Blake2s256, Digest}; /// Indexed proving algorithm, returns the total number of DFS calls done -/// to find a proof and Some(proof) if found within setup.dfs_bound calls of DFS, +/// to find a proof and Some(proof) if found within params.dfs_bound calls of DFS, /// otherwise None pub(super) fn prove_index( set_size: u64, - setup: &Setup, + params: &Params, prover_set: &[Element], retry_counter: u64, ) -> (u64, Option) { @@ -35,15 +35,15 @@ pub(super) fn prove_index( // Run the DFS algorithm on up to search_width different trees let mut step = 0; - for search_counter in 0..setup.search_width { + for search_counter in 0..params.search_width { // If DFS was called more than dfs_bound times, abort this retry - if step >= setup.dfs_bound { + if step >= params.dfs_bound { return (step, None); } // Initialise new round if let Some(r) = Round::new(retry_counter, search_counter, set_size) { // Run DFS on such round, incrementing step - let (dfs_calls, proof_opt) = dfs(setup, &bins, &r, step.saturating_add(1)); + let (dfs_calls, proof_opt) = dfs(params, &bins, &r, step.saturating_add(1)); // Returns proof if found if proof_opt.is_some() { return (dfs_calls, proof_opt); @@ -57,14 +57,19 @@ pub(super) fn prove_index( /// Depth-First Search which goes through all potential round candidates /// and returns the total number of recursive DFS calls done and, if not -/// found under setup.dfs_bound calls, returns None otherwise Some(Proof), +/// found under params.dfs_bound calls, returns None otherwise Some(Proof), /// that is the first round candidate Round{retry_counter, search_counter, x_1, ..., x_u)} such that: /// - ∀i ∈ [0, u-1], bin_hash(x_i+1) ∈ bins[round_hash(...round_hash(round_hash(v, t), x_1), ..., x_i)] /// - proof_hash(round_hash(... round_hash((round_hash(v, t), x_1), ..., x_u)) = true -fn dfs(setup: &Setup, bins: &[Vec], round: &Round, mut step: u64) -> (u64, Option) { +fn dfs( + params: &Params, + bins: &[Vec], + round: &Round, + mut step: u64, +) -> (u64, Option) { // If current round comprises proof_size elements, returns it as Proof - if round.element_sequence.len() as u64 == setup.proof_size { - let proof_opt = if proof_hash(setup.valid_proof_probability, round) { + if round.element_sequence.len() as u64 == params.proof_size { + let proof_opt = if proof_hash(params.valid_proof_probability, round) { Some(Proof { retry_counter: round.retry_counter, search_counter: round.search_counter, @@ -79,13 +84,13 @@ fn dfs(setup: &Setup, bins: &[Vec], round: &Round, mut step: u64) -> (u // For each element in bin numbered id for &element in &bins[round.id as usize] { // If DFS was called more than dfs_bound times, abort this round - if step == setup.dfs_bound { + if step == params.dfs_bound { return (step, None); } // Update round with such element if let Some(r) = Round::update(round, element) { // Run DFS on updated round, incrementing step - let (dfs_calls, proof_opt) = dfs(setup, bins, &r, step.saturating_add(1)); + let (dfs_calls, proof_opt) = dfs(params, bins, &r, step.saturating_add(1)); // Returns proof if found if proof_opt.is_some() { return (dfs_calls, proof_opt); diff --git a/src/centralized_telescope/init.rs b/src/centralized_telescope/init.rs index 86adf9e9..a11274da 100644 --- a/src/centralized_telescope/init.rs +++ b/src/centralized_telescope/init.rs @@ -1,16 +1,16 @@ //! ALBA's bounded DFS scheme setup functions -use super::setup::Setup; +use super::params::Params; use std::f64::consts::LOG2_E; -/// Setup algorithm taking a Params as input and returning setup parameters (u,d,q) +/// Params algorithm taking a Params as input and returning setup parameters (u,d,q) pub fn make_setup( soundness_param: f64, completeness_param: f64, set_size: u64, lower_bound: u64, -) -> Setup { +) -> Params { let set_size_f64 = set_size as f64; let lower_bound_f64 = lower_bound as f64; @@ -44,11 +44,11 @@ pub fn make_setup( } } -/// Helper function that returns Setup, used when set_size <= λ^2 -fn param_small_case(completeness_param: f64, proof_size_f64: f64) -> Setup { +/// Helper function that returns Params, used when set_size <= λ^2 +fn param_small_case(completeness_param: f64, proof_size_f64: f64) -> Params { let ln12 = (12f64).ln(); let search_width = (32.0 * ln12 * proof_size_f64).ceil(); - Setup { + Params { proof_size: proof_size_f64 as u64, max_retries: completeness_param as u64, search_width: search_width as u64, @@ -57,17 +57,17 @@ fn param_small_case(completeness_param: f64, proof_size_f64: f64) -> Setup { } } -/// Helper function that returns Setup, used when set_size >= λ^3 +/// Helper function that returns Params, used when set_size >= λ^3 fn param_high_case( completeness_param: f64, set_size: u64, proof_size_f64: f64, completeness_param2: f64, -) -> Setup { +) -> Params { let l2 = completeness_param2 + 2.0; let search_width = (16.0 * proof_size_f64 * l2 / LOG2_E).ceil(); debug_assert!(set_size as f64 >= search_width * search_width * LOG2_E / (9.0 * l2)); - Setup { + Params { proof_size: proof_size_f64 as u64, max_retries: (completeness_param / completeness_param2).ceil() as u64, search_width: search_width as u64, @@ -80,8 +80,8 @@ fn param_high_case( } } -/// Helper function that returns Setup, used when λ^2 < set_size < λ^3 -fn param_mid_case(completeness_param: f64, set_size: u64, proof_size_f64: f64, s1: f64) -> Setup { +/// Helper function that returns Params, used when λ^2 < set_size < λ^3 +fn param_mid_case(completeness_param: f64, set_size: u64, proof_size_f64: f64, s1: f64) -> Params { fn max_vertices_visited(proof_size: f64, l1: f64) -> f64 { fn factorial_check(max_v: f64, l1: f64) -> bool { let bound = (-l1).exp2(); @@ -115,7 +115,7 @@ fn param_mid_case(completeness_param: f64, set_size: u64, proof_size_f64: f64, s let exponential = (2.0 * proof_size_f64 * max_v * lbar / set_size as f64 + 7.0 * proof_size_f64 / max_v) .exp(); - Setup { + Params { proof_size: proof_size_f64 as u64, max_retries: (completeness_param / completeness_param1).ceil() as u64, search_width: search_width as u64, diff --git a/src/centralized_telescope/mod.rs b/src/centralized_telescope/mod.rs index 1e938a7c..041eae78 100644 --- a/src/centralized_telescope/mod.rs +++ b/src/centralized_telescope/mod.rs @@ -9,7 +9,7 @@ pub mod proof; mod round; -pub mod setup; +pub mod params; pub mod telescope; diff --git a/src/centralized_telescope/setup.rs b/src/centralized_telescope/params.rs similarity index 74% rename from src/centralized_telescope/setup.rs rename to src/centralized_telescope/params.rs index ebaaeeb6..0ab05829 100644 --- a/src/centralized_telescope/setup.rs +++ b/src/centralized_telescope/params.rs @@ -1,8 +1,8 @@ -//! ALBA's Setup structure comprising, among others, the number of elements and internal parameters +//! ALBA's Params structure comprising, among others, the number of elements and internal parameters -/// Setup output parameters +/// Params output parameters #[derive(Debug, Clone, Copy)] -pub struct Setup { +pub struct Params { /// Number of prover set's elements pub proof_size: u64, /// Maximum number of retries to find a proof diff --git a/src/centralized_telescope/telescope.rs b/src/centralized_telescope/telescope.rs index 3183026f..9243865f 100644 --- a/src/centralized_telescope/telescope.rs +++ b/src/centralized_telescope/telescope.rs @@ -2,9 +2,9 @@ use super::algorithm::{bin_hash, proof_hash, prove_index}; use super::init::make_setup; +use super::params::Params; use super::proof::Proof; use super::round::Round; -use super::setup::Setup; /// Structure wrapping input and internal parameters to generate a proof from /// and verify it @@ -19,7 +19,7 @@ pub struct Telescope { /// Lower bound to prove on prover set pub lower_bound: u64, /// Internal parameters - pub setup: Setup, + pub params: Params, } impl Telescope { @@ -30,49 +30,49 @@ impl Telescope { set_size: u64, lower_bound: u64, ) -> Self { - let setup = make_setup(soundness_param, completeness_param, set_size, lower_bound); + let params = make_setup(soundness_param, completeness_param, set_size, lower_bound); Telescope { soundness_param, completeness_param, set_size, lower_bound, - setup, + params, } } - /// Returns a Telescope structure from a set_size and Setup + /// Returns a Telescope structure from a set_size and Params pub fn from( soundness_param: f64, completeness_param: f64, set_size: u64, lower_bound: u64, - setup: Setup, + params: Params, ) -> Self { Telescope { soundness_param, completeness_param, set_size, lower_bound, - setup, + params, } } /// Alba's proving algorithm, based on a depth-first search algorithm. - /// Calls up to setup.max_retries times the prove_index function and returns an empty + /// Calls up to params.max_retries times the prove_index function and returns an empty /// proof if no suitable candidate is found. pub fn prove(self, prover_set: &[crate::utils::types::Element]) -> Option { // Run prove_index up to max_retries times - (0..self.setup.max_retries).find_map(|retry_counter| { - prove_index(self.set_size, &self.setup, prover_set, retry_counter).1 + (0..self.params.max_retries).find_map(|retry_counter| { + prove_index(self.set_size, &self.params, prover_set, retry_counter).1 }) } /// Alba's verification algorithm, returns true if the proof is /// successfully verified, following the DFS verification, false otherwise. pub fn verify(self, proof: &Proof) -> bool { - if proof.search_counter >= self.setup.search_width - || proof.retry_counter >= self.setup.max_retries - || proof.element_sequence.len() as u64 != self.setup.proof_size + if proof.search_counter >= self.params.search_width + || proof.retry_counter >= self.params.max_retries + || proof.element_sequence.len() as u64 != self.params.proof_size { return false; } @@ -100,7 +100,7 @@ impl Telescope { return false; } } - proof_hash(self.setup.valid_proof_probability, &round) + proof_hash(self.params.valid_proof_probability, &round) } } diff --git a/src/simple_lottery/setup.rs b/src/simple_lottery/setup.rs index 174a57ff..13a0b6c9 100644 --- a/src/simple_lottery/setup.rs +++ b/src/simple_lottery/setup.rs @@ -1,8 +1,8 @@ //! ALBA Simple lottery setup parameters. -/// Setup output parameters +/// Params output parameters #[derive(Debug, Clone, Copy)] -pub struct Setup { +pub struct Params { /// Number of prover set's elements pub proof_size: u64, /// Probability of winning the lottery, i.e. that one's element will be aggregated From 9417add0624fe1580fa3e153af1426142ddb0f98 Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 12 Nov 2024 17:08:48 +0000 Subject: [PATCH 06/19] Renaming make_setup -> setup --- src/centralized_telescope/init.rs | 2 +- src/centralized_telescope/telescope.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/centralized_telescope/init.rs b/src/centralized_telescope/init.rs index a11274da..15d2edd2 100644 --- a/src/centralized_telescope/init.rs +++ b/src/centralized_telescope/init.rs @@ -5,7 +5,7 @@ use super::params::Params; use std::f64::consts::LOG2_E; /// Params algorithm taking a Params as input and returning setup parameters (u,d,q) -pub fn make_setup( +pub fn setup( soundness_param: f64, completeness_param: f64, set_size: u64, diff --git a/src/centralized_telescope/telescope.rs b/src/centralized_telescope/telescope.rs index 9243865f..48e5f9bd 100644 --- a/src/centralized_telescope/telescope.rs +++ b/src/centralized_telescope/telescope.rs @@ -1,7 +1,7 @@ //! Customer facing Telescope structure use super::algorithm::{bin_hash, proof_hash, prove_index}; -use super::init::make_setup; +use super::init::setup; use super::params::Params; use super::proof::Proof; use super::round::Round; @@ -30,7 +30,7 @@ impl Telescope { set_size: u64, lower_bound: u64, ) -> Self { - let params = make_setup(soundness_param, completeness_param, set_size, lower_bound); + let params = setup(soundness_param, completeness_param, set_size, lower_bound); Telescope { soundness_param, completeness_param, From 3dbdbcb1f343c8285ef0da5664b15e91006234a6 Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 12 Nov 2024 17:14:05 +0000 Subject: [PATCH 07/19] Deleting algo.rs and init.rs --- src/centralized_telescope/algorithm.rs | 124 ----------------------- src/centralized_telescope/init.rs | 127 ------------------------ src/centralized_telescope/mod.rs | 15 ++- src/centralized_telescope/params.rs | 130 +++++++++++++++++++++++++ src/centralized_telescope/proof.rs | 122 +++++++++++++++++++++++ src/centralized_telescope/telescope.rs | 10 +- 6 files changed, 266 insertions(+), 262 deletions(-) delete mode 100644 src/centralized_telescope/algorithm.rs delete mode 100644 src/centralized_telescope/init.rs diff --git a/src/centralized_telescope/algorithm.rs b/src/centralized_telescope/algorithm.rs deleted file mode 100644 index 59cd0811..00000000 --- a/src/centralized_telescope/algorithm.rs +++ /dev/null @@ -1,124 +0,0 @@ -//! ALBA's bounded DFS scheme prove and verification functions - -use super::params::Params; -use super::proof::Proof; -use super::round::Round; -use super::types::Hash; -use crate::utils::sample; -use crate::utils::types::Element; -use blake2::{Blake2s256, Digest}; - -/// Indexed proving algorithm, returns the total number of DFS calls done -/// to find a proof and Some(proof) if found within params.dfs_bound calls of DFS, -/// otherwise None -pub(super) fn prove_index( - set_size: u64, - params: &Params, - prover_set: &[Element], - retry_counter: u64, -) -> (u64, Option) { - // Initialise set_size bins - let mut bins: Vec> = Vec::with_capacity(set_size as usize); - for _ in 0..set_size { - bins.push(Vec::new()); - } - - // Take only up to 2*set_size elements for efficiency and fill the bins with them - for &element in prover_set.iter().take(set_size.saturating_mul(2) as usize) { - match bin_hash(set_size, retry_counter, element) { - Some(bin_index) => { - bins[bin_index as usize].push(element); - } - None => return (0, None), - } - } - - // Run the DFS algorithm on up to search_width different trees - let mut step = 0; - for search_counter in 0..params.search_width { - // If DFS was called more than dfs_bound times, abort this retry - if step >= params.dfs_bound { - return (step, None); - } - // Initialise new round - if let Some(r) = Round::new(retry_counter, search_counter, set_size) { - // Run DFS on such round, incrementing step - let (dfs_calls, proof_opt) = dfs(params, &bins, &r, step.saturating_add(1)); - // Returns proof if found - if proof_opt.is_some() { - return (dfs_calls, proof_opt); - } - // Update step, that is the number of DFS calls - step = dfs_calls; - } - } - (step, None) -} - -/// Depth-First Search which goes through all potential round candidates -/// and returns the total number of recursive DFS calls done and, if not -/// found under params.dfs_bound calls, returns None otherwise Some(Proof), -/// that is the first round candidate Round{retry_counter, search_counter, x_1, ..., x_u)} such that: -/// - ∀i ∈ [0, u-1], bin_hash(x_i+1) ∈ bins[round_hash(...round_hash(round_hash(v, t), x_1), ..., x_i)] -/// - proof_hash(round_hash(... round_hash((round_hash(v, t), x_1), ..., x_u)) = true -fn dfs( - params: &Params, - bins: &[Vec], - round: &Round, - mut step: u64, -) -> (u64, Option) { - // If current round comprises proof_size elements, returns it as Proof - if round.element_sequence.len() as u64 == params.proof_size { - let proof_opt = if proof_hash(params.valid_proof_probability, round) { - Some(Proof { - retry_counter: round.retry_counter, - search_counter: round.search_counter, - element_sequence: round.element_sequence.clone(), - }) - } else { - None - }; - return (step, proof_opt); - } - - // For each element in bin numbered id - for &element in &bins[round.id as usize] { - // If DFS was called more than dfs_bound times, abort this round - if step == params.dfs_bound { - return (step, None); - } - // Update round with such element - if let Some(r) = Round::update(round, element) { - // Run DFS on updated round, incrementing step - let (dfs_calls, proof_opt) = dfs(params, bins, &r, step.saturating_add(1)); - // Returns proof if found - if proof_opt.is_some() { - return (dfs_calls, proof_opt); - } - // Update step, that is the number of DFS calls - step = dfs_calls; - } - } - // If no proof was found, return number of steps and None - (step, None) -} - -/// Oracle producing a uniformly random value in [0, set_size[ used for prehashing S_p -pub(super) fn bin_hash(set_size: u64, retry_counter: u64, element: Element) -> Option { - let retry_bytes: [u8; 8] = retry_counter.to_be_bytes(); - let mut hasher = Blake2s256::new(); - hasher.update(b"Telescope-bin_hash"); - hasher.update(retry_bytes); - hasher.update(element); - let digest: Hash = hasher.finalize().into(); - sample::sample_uniform(&digest, set_size) -} - -/// Oracle defined as Bernoulli(q) returning 1 with probability q and 0 otherwise -pub(super) fn proof_hash(valid_proof_probability: f64, r: &Round) -> bool { - let mut hasher = Blake2s256::new(); - hasher.update(b"Telescope-proof_hash"); - hasher.update(r.hash); - let digest: Hash = hasher.finalize().into(); - sample::sample_bernoulli(&digest, valid_proof_probability) -} diff --git a/src/centralized_telescope/init.rs b/src/centralized_telescope/init.rs deleted file mode 100644 index 15d2edd2..00000000 --- a/src/centralized_telescope/init.rs +++ /dev/null @@ -1,127 +0,0 @@ -//! ALBA's bounded DFS scheme setup functions - -use super::params::Params; - -use std::f64::consts::LOG2_E; - -/// Params algorithm taking a Params as input and returning setup parameters (u,d,q) -pub fn setup( - soundness_param: f64, - completeness_param: f64, - set_size: u64, - lower_bound: u64, -) -> Params { - let set_size_f64 = set_size as f64; - let lower_bound_f64 = lower_bound as f64; - - let proof_size_f64 = { - let numerator = soundness_param + completeness_param.log2() + 5.0 - LOG2_E.log2(); - let denominator = (set_size_f64 / lower_bound_f64).log2(); - (numerator / denominator).ceil() - }; - - let ratio = 9.0 * set_size_f64 * LOG2_E / ((17.0 * proof_size_f64).powi(2)); - let s1 = ratio - 7.0; - let s2 = ratio - 2.0; - - if s1 < 1.0 || s2 < 1.0 { - // Small case, i.e. set_size <= λ^2 - param_small_case(completeness_param, proof_size_f64) - } else { - let completeness_param2 = completeness_param.min(s2); - if proof_size_f64 < completeness_param2 { - // Case 3, Theorem 14, i.e. set_size >= λ^3 - param_high_case( - completeness_param, - set_size, - proof_size_f64, - completeness_param2, - ) - } else { - // Case 2, Theorem 13, i.e. λ^2 < set_size < λ^3 - param_mid_case(completeness_param, set_size, proof_size_f64, s1) - } - } -} - -/// Helper function that returns Params, used when set_size <= λ^2 -fn param_small_case(completeness_param: f64, proof_size_f64: f64) -> Params { - let ln12 = (12f64).ln(); - let search_width = (32.0 * ln12 * proof_size_f64).ceil(); - Params { - proof_size: proof_size_f64 as u64, - max_retries: completeness_param as u64, - search_width: search_width as u64, - valid_proof_probability: 2.0 * ln12 / search_width, - dfs_bound: (8.0 * (proof_size_f64 + 1.0) * search_width / ln12).floor() as u64, - } -} - -/// Helper function that returns Params, used when set_size >= λ^3 -fn param_high_case( - completeness_param: f64, - set_size: u64, - proof_size_f64: f64, - completeness_param2: f64, -) -> Params { - let l2 = completeness_param2 + 2.0; - let search_width = (16.0 * proof_size_f64 * l2 / LOG2_E).ceil(); - debug_assert!(set_size as f64 >= search_width * search_width * LOG2_E / (9.0 * l2)); - Params { - proof_size: proof_size_f64 as u64, - max_retries: (completeness_param / completeness_param2).ceil() as u64, - search_width: search_width as u64, - valid_proof_probability: 2.0 * l2 / (search_width * LOG2_E), - dfs_bound: (((l2 + proof_size_f64.log2()) / l2) - * (3.0 * proof_size_f64 * search_width / 4.0) - + search_width - + proof_size_f64) - .floor() as u64, - } -} - -/// Helper function that returns Params, used when λ^2 < set_size < λ^3 -fn param_mid_case(completeness_param: f64, set_size: u64, proof_size_f64: f64, s1: f64) -> Params { - fn max_vertices_visited(proof_size: f64, l1: f64) -> f64 { - fn factorial_check(max_v: f64, l1: f64) -> bool { - let bound = (-l1).exp2(); - let mut factor = (max_v.ceil() as u64).saturating_add(1); - let max_v_2 = max_v + 2.0; - let exp_1_over_max_v = max_v.recip().exp(); - let mut ratio = - (14.0 * max_v * max_v * max_v_2 * exp_1_over_max_v) / (max_v_2 - exp_1_over_max_v); - while factor != 0 { - ratio /= factor as f64; - if ratio <= bound { - return true; - } - factor = factor.saturating_sub(1); - } - false - } - let mut max_v = proof_size; - while !factorial_check(max_v, l1) { - max_v += 1.0; - } - max_v - } - let completeness_param1 = completeness_param.min(s1); - let lbar = (completeness_param1 + 7.0) / LOG2_E; - let search_width = (16.0 * proof_size_f64 * lbar).ceil(); - let lbar_over_sw = lbar / search_width; - debug_assert!(set_size as f64 >= search_width * search_width / (9.0 * lbar)); - - let max_v = max_vertices_visited(proof_size_f64, completeness_param1); - let exponential = (2.0 * proof_size_f64 * max_v * lbar / set_size as f64 - + 7.0 * proof_size_f64 / max_v) - .exp(); - Params { - proof_size: proof_size_f64 as u64, - max_retries: (completeness_param / completeness_param1).ceil() as u64, - search_width: search_width as u64, - valid_proof_probability: 2.0 * lbar_over_sw, - dfs_bound: ((max_v * lbar_over_sw + 1.0) * exponential * search_width * proof_size_f64 - + search_width) - .floor() as u64, - } -} diff --git a/src/centralized_telescope/mod.rs b/src/centralized_telescope/mod.rs index 041eae78..9b335a24 100644 --- a/src/centralized_telescope/mod.rs +++ b/src/centralized_telescope/mod.rs @@ -1,16 +1,21 @@ //! ALBA's bounded DFS scheme using Blake2b as hash function. //! (c.f. Section 3.2.2 of Alba paper) -mod algorithm; - -mod init; +// Defines the internal parameters and provide functions for their generation +pub mod params; +// Defines the proof structure and provide high level functions, i.e. the depth +// first search algorithm (DFS) and indexed proving function, as well as helper +// hash functions pub mod proof; +// Defines the internal round structure to facilitate the updating and checking +// of a proof candidate mod round; -pub mod params; - +// Defines the user facing telescope structure, that is instantiated to +// generate an Alba proof out of a set and verify it pub mod telescope; +// Modules defining internal types mod types; diff --git a/src/centralized_telescope/params.rs b/src/centralized_telescope/params.rs index 0ab05829..cf5f57f3 100644 --- a/src/centralized_telescope/params.rs +++ b/src/centralized_telescope/params.rs @@ -1,4 +1,5 @@ //! ALBA's Params structure comprising, among others, the number of elements and internal parameters +use std::f64::consts::LOG2_E; /// Params output parameters #[derive(Debug, Clone, Copy)] @@ -14,3 +15,132 @@ pub struct Params { /// Maximum number of DFS calls permitted to find a proof pub dfs_bound: u64, } + +impl Params { + /// Params algorithm taking a Params as input and returning internal parameters (u,d,q) + pub fn setup( + soundness_param: f64, + completeness_param: f64, + set_size: u64, + lower_bound: u64, + ) -> Self { + let set_size_f64 = set_size as f64; + let lower_bound_f64 = lower_bound as f64; + + let proof_size_f64 = { + let numerator = soundness_param + completeness_param.log2() + 5.0 - LOG2_E.log2(); + let denominator = (set_size_f64 / lower_bound_f64).log2(); + (numerator / denominator).ceil() + }; + + let ratio = 9.0 * set_size_f64 * LOG2_E / ((17.0 * proof_size_f64).powi(2)); + let s1 = ratio - 7.0; + let s2 = ratio - 2.0; + + if s1 < 1.0 || s2 < 1.0 { + // Small case, i.e. set_size <= λ^2 + Params::param_small_case(completeness_param, proof_size_f64) + } else { + let completeness_param2 = completeness_param.min(s2); + if proof_size_f64 < completeness_param2 { + // Case 3, Theorem 14, i.e. set_size >= λ^3 + Params::param_high_case( + completeness_param, + set_size, + proof_size_f64, + completeness_param2, + ) + } else { + // Case 2, Theorem 13, i.e. λ^2 < set_size < λ^3 + Params::param_mid_case(completeness_param, set_size, proof_size_f64, s1) + } + } + } + + /// Helper function that returns Params, used when set_size <= λ^2 + fn param_small_case(completeness_param: f64, proof_size_f64: f64) -> Params { + let ln12 = (12f64).ln(); + let search_width = (32.0 * ln12 * proof_size_f64).ceil(); + Params { + proof_size: proof_size_f64 as u64, + max_retries: completeness_param as u64, + search_width: search_width as u64, + valid_proof_probability: 2.0 * ln12 / search_width, + dfs_bound: (8.0 * (proof_size_f64 + 1.0) * search_width / ln12).floor() as u64, + } + } + + /// Helper function that returns Params, used when set_size >= λ^3 + fn param_high_case( + completeness_param: f64, + set_size: u64, + proof_size_f64: f64, + completeness_param2: f64, + ) -> Params { + let l2 = completeness_param2 + 2.0; + let search_width = (16.0 * proof_size_f64 * l2 / LOG2_E).ceil(); + debug_assert!(set_size as f64 >= search_width * search_width * LOG2_E / (9.0 * l2)); + Params { + proof_size: proof_size_f64 as u64, + max_retries: (completeness_param / completeness_param2).ceil() as u64, + search_width: search_width as u64, + valid_proof_probability: 2.0 * l2 / (search_width * LOG2_E), + dfs_bound: (((l2 + proof_size_f64.log2()) / l2) + * (3.0 * proof_size_f64 * search_width / 4.0) + + search_width + + proof_size_f64) + .floor() as u64, + } + } + + /// Helper function that returns Params, used when λ^2 < set_size < λ^3 + fn param_mid_case( + completeness_param: f64, + set_size: u64, + proof_size_f64: f64, + s1: f64, + ) -> Params { + fn max_vertices_visited(proof_size: f64, l1: f64) -> f64 { + fn factorial_check(max_v: f64, l1: f64) -> bool { + let bound = (-l1).exp2(); + let mut factor = (max_v.ceil() as u64).saturating_add(1); + let max_v_2 = max_v + 2.0; + let exp_1_over_max_v = max_v.recip().exp(); + let mut ratio = (14.0 * max_v * max_v * max_v_2 * exp_1_over_max_v) + / (max_v_2 - exp_1_over_max_v); + while factor != 0 { + ratio /= factor as f64; + if ratio <= bound { + return true; + } + factor = factor.saturating_sub(1); + } + false + } + let mut max_v = proof_size; + while !factorial_check(max_v, l1) { + max_v += 1.0; + } + max_v + } + let completeness_param1 = completeness_param.min(s1); + let lbar = (completeness_param1 + 7.0) / LOG2_E; + let search_width = (16.0 * proof_size_f64 * lbar).ceil(); + let lbar_over_sw = lbar / search_width; + debug_assert!(set_size as f64 >= search_width * search_width / (9.0 * lbar)); + + let max_v = max_vertices_visited(proof_size_f64, completeness_param1); + let exponential = (2.0 * proof_size_f64 * max_v * lbar / set_size as f64 + + 7.0 * proof_size_f64 / max_v) + .exp(); + Params { + proof_size: proof_size_f64 as u64, + max_retries: (completeness_param / completeness_param1).ceil() as u64, + search_width: search_width as u64, + valid_proof_probability: 2.0 * lbar_over_sw, + dfs_bound: ((max_v * lbar_over_sw + 1.0) * exponential * search_width * proof_size_f64 + + search_width) + .floor() as u64, + } + } +} diff --git a/src/centralized_telescope/proof.rs b/src/centralized_telescope/proof.rs index 19ae72f1..661683e6 100644 --- a/src/centralized_telescope/proof.rs +++ b/src/centralized_telescope/proof.rs @@ -1,6 +1,11 @@ //! ALBA's Proof structure +use super::params::Params; +use super::round::Round; +use super::types::Hash; +use crate::utils::sample; use crate::utils::types::Element; +use blake2::{Blake2s256, Digest}; /// Alba proof #[derive(Debug, Clone)] @@ -12,3 +17,120 @@ pub struct Proof { /// Sequence of elements from prover set pub element_sequence: Vec, } + +impl Proof { + /// Indexed proving algorithm, returns the total number of DFS calls done + /// to find a proof and Some(proof) if found within params.dfs_bound calls of DFS, + /// otherwise None + pub(super) fn prove_index( + set_size: u64, + params: &Params, + prover_set: &[Element], + retry_counter: u64, + ) -> (u64, Option) { + // Initialise set_size bins + let mut bins: Vec> = Vec::with_capacity(set_size as usize); + for _ in 0..set_size { + bins.push(Vec::new()); + } + + // Take only up to 2*set_size elements for efficiency and fill the bins with them + for &element in prover_set.iter().take(set_size.saturating_mul(2) as usize) { + match Proof::bin_hash(set_size, retry_counter, element) { + Some(bin_index) => { + bins[bin_index as usize].push(element); + } + None => return (0, None), + } + } + + // Run the DFS algorithm on up to search_width different trees + let mut step = 0; + for search_counter in 0..params.search_width { + // If DFS was called more than dfs_bound times, abort this retry + if step >= params.dfs_bound { + return (step, None); + } + // Initialise new round + if let Some(r) = Round::new(retry_counter, search_counter, set_size) { + // Run DFS on such round, incrementing step + let (dfs_calls, proof_opt) = Proof::dfs(params, &bins, &r, step.saturating_add(1)); + // Returns proof if found + if proof_opt.is_some() { + return (dfs_calls, proof_opt); + } + // Update step, that is the number of DFS calls + step = dfs_calls; + } + } + (step, None) + } + + /// Depth-First Search which goes through all potential round candidates + /// and returns the total number of recursive DFS calls done and, if not + /// found under params.dfs_bound calls, returns None otherwise Some(Proof), + /// that is the first round candidate Round{retry_counter, search_counter, x_1, ..., x_u)} such that: + /// - ∀i ∈ [0, u-1], bin_hash(x_i+1) ∈ bins[round_hash(...round_hash(round_hash(v, t), x_1), ..., x_i)] + /// - proof_hash(round_hash(... round_hash((round_hash(v, t), x_1), ..., x_u)) = true + fn dfs( + params: &Params, + bins: &[Vec], + round: &Round, + mut step: u64, + ) -> (u64, Option) { + // If current round comprises proof_size elements, returns it as Proof + if round.element_sequence.len() as u64 == params.proof_size { + let proof_opt = if Proof::proof_hash(params.valid_proof_probability, round) { + Some(Proof { + retry_counter: round.retry_counter, + search_counter: round.search_counter, + element_sequence: round.element_sequence.clone(), + }) + } else { + None + }; + return (step, proof_opt); + } + + // For each element in bin numbered id + for &element in &bins[round.id as usize] { + // If DFS was called more than dfs_bound times, abort this round + if step == params.dfs_bound { + return (step, None); + } + // Update round with such element + if let Some(r) = Round::update(round, element) { + // Run DFS on updated round, incrementing step + let (dfs_calls, proof_opt) = Proof::dfs(params, bins, &r, step.saturating_add(1)); + // Returns proof if found + if proof_opt.is_some() { + return (dfs_calls, proof_opt); + } + // Update step, that is the number of DFS calls + step = dfs_calls; + } + } + // If no proof was found, return number of steps and None + (step, None) + } + + /// Oracle producing a uniformly random value in [0, set_size[ used for prehashing S_p + pub(super) fn bin_hash(set_size: u64, retry_counter: u64, element: Element) -> Option { + let retry_bytes: [u8; 8] = retry_counter.to_be_bytes(); + let mut hasher = Blake2s256::new(); + hasher.update(b"Telescope-bin_hash"); + hasher.update(retry_bytes); + hasher.update(element); + let digest: Hash = hasher.finalize().into(); + sample::sample_uniform(&digest, set_size) + } + + /// Oracle defined as Bernoulli(q) returning 1 with probability q and 0 otherwise + pub(super) fn proof_hash(valid_proof_probability: f64, r: &Round) -> bool { + let mut hasher = Blake2s256::new(); + hasher.update(b"Telescope-proof_hash"); + hasher.update(r.hash); + let digest: Hash = hasher.finalize().into(); + sample::sample_bernoulli(&digest, valid_proof_probability) + } +} diff --git a/src/centralized_telescope/telescope.rs b/src/centralized_telescope/telescope.rs index 48e5f9bd..059c4af4 100644 --- a/src/centralized_telescope/telescope.rs +++ b/src/centralized_telescope/telescope.rs @@ -1,7 +1,5 @@ //! Customer facing Telescope structure -use super::algorithm::{bin_hash, proof_hash, prove_index}; -use super::init::setup; use super::params::Params; use super::proof::Proof; use super::round::Round; @@ -30,7 +28,7 @@ impl Telescope { set_size: u64, lower_bound: u64, ) -> Self { - let params = setup(soundness_param, completeness_param, set_size, lower_bound); + let params = Params::setup(soundness_param, completeness_param, set_size, lower_bound); Telescope { soundness_param, completeness_param, @@ -63,7 +61,7 @@ impl Telescope { pub fn prove(self, prover_set: &[crate::utils::types::Element]) -> Option { // Run prove_index up to max_retries times (0..self.params.max_retries).find_map(|retry_counter| { - prove_index(self.set_size, &self.params, prover_set, retry_counter).1 + Proof::prove_index(self.set_size, &self.params, prover_set, retry_counter).1 }) } @@ -86,7 +84,7 @@ impl Telescope { // For each element in the proof's sequence for &element in &proof.element_sequence { // Retrieve the bin id associated to this new element - let Some(bin_id) = bin_hash(self.set_size, proof.retry_counter, element) else { + let Some(bin_id) = Proof::bin_hash(self.set_size, proof.retry_counter, element) else { return false; }; // Check that the new element was chosen correctly @@ -100,7 +98,7 @@ impl Telescope { return false; } } - proof_hash(self.params.valid_proof_probability, &round) + Proof::proof_hash(self.params.valid_proof_probability, &round) } } From 3246e15cc8137a5c66c709c04dc86218852713c4 Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 12 Nov 2024 17:41:43 +0000 Subject: [PATCH 08/19] prove/verify takes a reference as input --- src/centralized_telescope/telescope.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/centralized_telescope/telescope.rs b/src/centralized_telescope/telescope.rs index 059c4af4..e8780b8f 100644 --- a/src/centralized_telescope/telescope.rs +++ b/src/centralized_telescope/telescope.rs @@ -55,19 +55,16 @@ impl Telescope { } } - /// Alba's proving algorithm, based on a depth-first search algorithm. - /// Calls up to params.max_retries times the prove_index function and returns an empty - /// proof if no suitable candidate is found. - pub fn prove(self, prover_set: &[crate::utils::types::Element]) -> Option { + + pub fn prove(&self, prover_set: &[crate::utils::types::Element]) -> Option { // Run prove_index up to max_retries times (0..self.params.max_retries).find_map(|retry_counter| { Proof::prove_index(self.set_size, &self.params, prover_set, retry_counter).1 }) } - /// Alba's verification algorithm, returns true if the proof is - /// successfully verified, following the DFS verification, false otherwise. - pub fn verify(self, proof: &Proof) -> bool { + + pub fn verify(&self, proof: &Proof) -> bool { if proof.search_counter >= self.params.search_width || proof.retry_counter >= self.params.max_retries || proof.element_sequence.len() as u64 != self.params.proof_size @@ -125,7 +122,7 @@ mod tests { let telescope = Telescope::new(soundness_param, completeness_param, set_size, lower_bound); let proof = telescope.prove(&s_p).unwrap(); - assert!(telescope.clone().verify(&proof.clone())); + assert!(telescope.verify(&proof.clone())); // Checking that the proof fails if proof.search_counter is erroneous let proof_t = Proof { retry_counter: proof.retry_counter, From bffbc9d21c073d19dc16d8b54566f46d1805f4f1 Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 12 Nov 2024 17:42:31 +0000 Subject: [PATCH 09/19] Updating Params comments and visibility --- src/centralized_telescope/params.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/centralized_telescope/params.rs b/src/centralized_telescope/params.rs index cf5f57f3..052a800a 100644 --- a/src/centralized_telescope/params.rs +++ b/src/centralized_telescope/params.rs @@ -1,7 +1,7 @@ -//! ALBA's Params structure comprising, among others, the number of elements and internal parameters +//! ALBA's Params structure comprising internal parameters use std::f64::consts::LOG2_E; -/// Params output parameters +/// Params structure comprising internal parameters #[derive(Debug, Clone, Copy)] pub struct Params { /// Number of prover set's elements @@ -17,8 +17,9 @@ pub struct Params { } impl Params { - /// Params algorithm taking a Params as input and returning internal parameters (u,d,q) - pub fn setup( + /// Setup algorithm taking as input the security parameters, the set size + /// and the lower bound and returning the internal parameters Params + pub(super) fn setup( soundness_param: f64, completeness_param: f64, set_size: u64, From 11a353463289a96b29d2a17b5fd2caf3401aae9e Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 12 Nov 2024 17:42:50 +0000 Subject: [PATCH 10/19] Updating proof comments --- src/centralized_telescope/proof.rs | 34 ++++++++++++++++++------------ 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/centralized_telescope/proof.rs b/src/centralized_telescope/proof.rs index 661683e6..0d21811e 100644 --- a/src/centralized_telescope/proof.rs +++ b/src/centralized_telescope/proof.rs @@ -20,21 +20,22 @@ pub struct Proof { impl Proof { /// Indexed proving algorithm, returns the total number of DFS calls done - /// to find a proof and Some(proof) if found within params.dfs_bound calls of DFS, - /// otherwise None + /// to find a proof and Some(proof) if found within params.dfs_bound calls + /// of DFS, otherwise None pub(super) fn prove_index( set_size: u64, params: &Params, prover_set: &[Element], retry_counter: u64, ) -> (u64, Option) { - // Initialise set_size bins + // Initialize set_size bins let mut bins: Vec> = Vec::with_capacity(set_size as usize); for _ in 0..set_size { bins.push(Vec::new()); } - // Take only up to 2*set_size elements for efficiency and fill the bins with them + // Take only up to 2*set_size elements for efficiency and fill the bins + // with them for &element in prover_set.iter().take(set_size.saturating_mul(2) as usize) { match Proof::bin_hash(set_size, retry_counter, element) { Some(bin_index) => { @@ -44,18 +45,18 @@ impl Proof { } } - // Run the DFS algorithm on up to search_width different trees + // Run the DFS algorithm on up to params.search_width different trees let mut step = 0; for search_counter in 0..params.search_width { // If DFS was called more than dfs_bound times, abort this retry if step >= params.dfs_bound { return (step, None); } - // Initialise new round + // Initialize new round if let Some(r) = Round::new(retry_counter, search_counter, set_size) { // Run DFS on such round, incrementing step let (dfs_calls, proof_opt) = Proof::dfs(params, &bins, &r, step.saturating_add(1)); - // Returns proof if found + // Return proof if found if proof_opt.is_some() { return (dfs_calls, proof_opt); } @@ -69,7 +70,8 @@ impl Proof { /// Depth-First Search which goes through all potential round candidates /// and returns the total number of recursive DFS calls done and, if not /// found under params.dfs_bound calls, returns None otherwise Some(Proof), - /// that is the first round candidate Round{retry_counter, search_counter, x_1, ..., x_u)} such that: + /// that is the first "round", i.e. the first proof candidate, + /// Round{retry_counter, search_counter, x_1, ..., x_u)} such that: /// - ∀i ∈ [0, u-1], bin_hash(x_i+1) ∈ bins[round_hash(...round_hash(round_hash(v, t), x_1), ..., x_i)] /// - proof_hash(round_hash(... round_hash((round_hash(v, t), x_1), ..., x_u)) = true fn dfs( @@ -78,7 +80,8 @@ impl Proof { round: &Round, mut step: u64, ) -> (u64, Option) { - // If current round comprises proof_size elements, returns it as Proof + // If current round comprises params.proof_size elements and satisfies + // the proof_hash check, return it cast as a Proof if round.element_sequence.len() as u64 == params.proof_size { let proof_opt = if Proof::proof_hash(params.valid_proof_probability, round) { Some(Proof { @@ -94,7 +97,8 @@ impl Proof { // For each element in bin numbered id for &element in &bins[round.id as usize] { - // If DFS was called more than dfs_bound times, abort this round + // If DFS was called more than params.dfs_bound times, abort this + // round if step == params.dfs_bound { return (step, None); } @@ -102,11 +106,11 @@ impl Proof { if let Some(r) = Round::update(round, element) { // Run DFS on updated round, incrementing step let (dfs_calls, proof_opt) = Proof::dfs(params, bins, &r, step.saturating_add(1)); - // Returns proof if found + // Return proof if found if proof_opt.is_some() { return (dfs_calls, proof_opt); } - // Update step, that is the number of DFS calls + // Update step, i.e. is the number of DFS calls step = dfs_calls; } } @@ -114,7 +118,8 @@ impl Proof { (step, None) } - /// Oracle producing a uniformly random value in [0, set_size[ used for prehashing S_p + /// Oracle producing a uniformly random value in [0, set_size[ used for + /// prehashing S_p pub(super) fn bin_hash(set_size: u64, retry_counter: u64, element: Element) -> Option { let retry_bytes: [u8; 8] = retry_counter.to_be_bytes(); let mut hasher = Blake2s256::new(); @@ -125,7 +130,8 @@ impl Proof { sample::sample_uniform(&digest, set_size) } - /// Oracle defined as Bernoulli(q) returning 1 with probability q and 0 otherwise + /// Oracle defined as Bernoulli(q) returning 1 with probability q and 0 + /// otherwise pub(super) fn proof_hash(valid_proof_probability: f64, r: &Round) -> bool { let mut hasher = Blake2s256::new(); hasher.update(b"Telescope-proof_hash"); From 20e536b811ce7d0062de37a0a3288e7e2c54d100 Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 12 Nov 2024 17:43:08 +0000 Subject: [PATCH 11/19] Updating round comments --- src/centralized_telescope/round.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/centralized_telescope/round.rs b/src/centralized_telescope/round.rs index ce1bbe93..e23fa262 100644 --- a/src/centralized_telescope/round.rs +++ b/src/centralized_telescope/round.rs @@ -24,8 +24,9 @@ pub struct Round { impl Round { /// Output a round from retry and search counters as well as set_size - /// Initilialises the hash with round_hash(retry_counter || search_bytes) - /// and random value as oracle(round_hash(retry_counter || search_bytes), set_size) + /// Initilializes the hash with round_hash(retry_counter || search_bytes) + /// and random value as + /// oracle(round_hash(retry_counter || search_bytes), set_size) pub(super) fn new(retry_counter: u64, search_counter: u64, set_size: u64) -> Option { let retry_bytes: [u8; 8] = retry_counter.to_be_bytes(); let search_bytes: [u8; 8] = search_counter.to_be_bytes(); @@ -41,7 +42,8 @@ impl Round { } /// Updates a round with an element - /// Replaces the hash $h$ with $h' = round_hash(h, s)$ and the random value as oracle(h', set_size) + /// Replaces the hash $h$ with $h' = round_hash(h, s)$ and the random value + /// as oracle(h', set_size) pub(super) fn update(r: &Self, element: Element) -> Option { let mut element_sequence = r.element_sequence.clone(); element_sequence.push(element); @@ -56,8 +58,9 @@ impl Round { }) } - /// Oracle producing a uniformly random value in [0, set_size[ used for round candidates - /// We also return hash(data) to follow the optimization presented in Section 3.3 + /// Oracle producing a uniformly random value in [0, set_size[ used for + /// round candidates. We also return hash(data) to follow the optimization + /// presented in Section 3.3 fn round_hash(first_input: &[u8], second_input: &[u8], set_size: u64) -> (Hash, Option) { let mut hasher = Blake2s256::new(); hasher.update(b"Telescope-round_hash"); From ba4e1c848f3772db104d37b1bb80ad0497ce52b7 Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 12 Nov 2024 17:43:26 +0000 Subject: [PATCH 12/19] Updating telescope comments --- src/centralized_telescope/telescope.rs | 37 +++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/centralized_telescope/telescope.rs b/src/centralized_telescope/telescope.rs index e8780b8f..767d9432 100644 --- a/src/centralized_telescope/telescope.rs +++ b/src/centralized_telescope/telescope.rs @@ -55,6 +55,23 @@ impl Telescope { } } + /// Generates a Centralized Telescope proof. + /// + /// # Arguments + /// + /// * `self` - the current Telescope structure + /// * `prover_set` - an array of elements to generate an Alba proof on + /// + /// # Returns + /// + /// A proof if found, None otherwise + /// + /// # Example + /// + /// ``` + /// let telescope = Telescope::new(128, 128, 1_000, 750); + /// let proof = telescope.prove(prover_set)?; + /// ``` pub fn prove(&self, prover_set: &[crate::utils::types::Element]) -> Option { // Run prove_index up to max_retries times @@ -63,6 +80,24 @@ impl Telescope { }) } + /// Verifies a Centralized Telescope proof. + /// + /// # Arguments + /// + /// * `self` - the current Telescope structure + /// * `proof` - a centralized Telescope proof + /// + /// # Returns + /// + /// True if the verification is successful, false otherwise + /// + /// # Example + /// + /// ``` + /// let telescope = Telescope::new(128, 128, 1_000, 750); + /// let proof = telescope.prove(prover_set)?; + /// assert!(telescope.verify(proof)); + /// ``` pub fn verify(&self, proof: &Proof) -> bool { if proof.search_counter >= self.params.search_width @@ -72,7 +107,7 @@ impl Telescope { return false; } - // Initialise a round with given retry and search counters + // Initialize a round with given retry and search counters let Some(mut round) = Round::new(proof.retry_counter, proof.search_counter, self.set_size) else { return false; From 5de10a31f8a3727f43f8d7657b3c94a6e275ea9f Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 12 Nov 2024 17:45:09 +0000 Subject: [PATCH 13/19] Updating Params::setup -> Params::new --- src/centralized_telescope/params.rs | 2 +- src/centralized_telescope/telescope.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/centralized_telescope/params.rs b/src/centralized_telescope/params.rs index 052a800a..fa0f6cf6 100644 --- a/src/centralized_telescope/params.rs +++ b/src/centralized_telescope/params.rs @@ -19,7 +19,7 @@ pub struct Params { impl Params { /// Setup algorithm taking as input the security parameters, the set size /// and the lower bound and returning the internal parameters Params - pub(super) fn setup( + pub(super) fn new( soundness_param: f64, completeness_param: f64, set_size: u64, diff --git a/src/centralized_telescope/telescope.rs b/src/centralized_telescope/telescope.rs index 767d9432..3327ce4f 100644 --- a/src/centralized_telescope/telescope.rs +++ b/src/centralized_telescope/telescope.rs @@ -28,7 +28,7 @@ impl Telescope { set_size: u64, lower_bound: u64, ) -> Self { - let params = Params::setup(soundness_param, completeness_param, set_size, lower_bound); + let params = Params::new(soundness_param, completeness_param, set_size, lower_bound); Telescope { soundness_param, completeness_param, @@ -72,7 +72,7 @@ impl Telescope { /// let telescope = Telescope::new(128, 128, 1_000, 750); /// let proof = telescope.prove(prover_set)?; /// ``` - + pub fn prove(&self, prover_set: &[crate::utils::types::Element]) -> Option { // Run prove_index up to max_retries times (0..self.params.max_retries).find_map(|retry_counter| { @@ -98,7 +98,7 @@ impl Telescope { /// let proof = telescope.prove(prover_set)?; /// assert!(telescope.verify(proof)); /// ``` - + pub fn verify(&self, proof: &Proof) -> bool { if proof.search_counter >= self.params.search_width || proof.retry_counter >= self.params.max_retries From 8f0f7e1c673a062d4ac9e851cdeaed17da8de861 Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 12 Nov 2024 18:07:07 +0000 Subject: [PATCH 14/19] Fixup comments in telescope.rs --- src/centralized_telescope/telescope.rs | 63 +++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/src/centralized_telescope/telescope.rs b/src/centralized_telescope/telescope.rs index 3327ce4f..b0a92952 100644 --- a/src/centralized_telescope/telescope.rs +++ b/src/centralized_telescope/telescope.rs @@ -22,6 +22,24 @@ pub struct Telescope { impl Telescope { /// Returns a Telescope structure from input parameters + /// + /// # Arguments + /// + /// * `soundness_param` - the protocol soundness parameter, typically set at 128 + /// * `completeness_param` - the protocol completeness parameter, typically set at 128 + /// * `set_size` - the size of the prover set to lower bound + /// * `lower_bound` - the lower bound to prove + /// + /// # Returns + /// + /// A Telescope structure + /// + /// # Example + /// + /// ``` + /// use alba::centralized_telescope::telescope::Telescope; + /// let telescope = Telescope::new(128.0, 128.0, 1_000, 750); + /// ``` pub fn new( soundness_param: f64, completeness_param: f64, @@ -38,7 +56,28 @@ impl Telescope { } } - /// Returns a Telescope structure from a set_size and Params + /// Returns a Telescope structure from input and internal parameters, to use for backward compability + /// + /// # Arguments + /// + /// * `soundness_param` - the protocol soundness parameter, typically set at 128 + /// * `completeness_param` - the protocol completeness parameter, typically set at 128 + /// * `set_size` - the size of the prover set to lower bound + /// * `lower_bound` - the lower bound to prove + /// * `params` - some centralized Telescope internal parameters + /// + /// # Returns + /// + /// A Telescope structure + /// + /// # Example + /// + /// ``` + /// use alba::centralized_telescope::telescope::Telescope; + /// use alba::centralized_telescope::params::Params; + /// let params = Params {proof_size : 200, max_retries: 128, search_width: 10, valid_proof_probability: 0.001, dfs_bound: 40_000}; + /// let telescope = Telescope::from(128.0, 128.0, 1_000, 750, params); + /// ``` pub fn from( soundness_param: f64, completeness_param: f64, @@ -69,8 +108,14 @@ impl Telescope { /// # Example /// /// ``` - /// let telescope = Telescope::new(128, 128, 1_000, 750); - /// let proof = telescope.prove(prover_set)?; + /// use alba::centralized_telescope::telescope::Telescope; + /// let set_size = 200; + /// let telescope = Telescope::new(128.0, 128.0, set_size, 150); + /// let mut prover_set = Vec::new(); + /// for i in 0..set_size { + /// prover_set.push([(i % 256) as u8 ;32]); + /// } + /// let proof = telescope.prove(&prover_set).unwrap(); /// ``` pub fn prove(&self, prover_set: &[crate::utils::types::Element]) -> Option { @@ -94,9 +139,15 @@ impl Telescope { /// # Example /// /// ``` - /// let telescope = Telescope::new(128, 128, 1_000, 750); - /// let proof = telescope.prove(prover_set)?; - /// assert!(telescope.verify(proof)); + /// use alba::centralized_telescope::telescope::Telescope; + /// let set_size = 200; + /// let telescope = Telescope::new(128.0, 128.0, set_size, 150); + /// let mut prover_set = Vec::new(); + /// for i in 0..set_size { + /// prover_set.push([(i % 256) as u8 ;32]); + /// } + /// let proof = telescope.prove(&prover_set).unwrap(); + /// assert!(telescope.verify(&proof)); /// ``` pub fn verify(&self, proof: &Proof) -> bool { From 34b75fcef6a8db43ff081d1c41be158c06116330 Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 26 Nov 2024 00:40:15 +0000 Subject: [PATCH 15/19] Adding back cases --- src/centralized_telescope/params.rs | 303 +++++++++++++++++++--------- 1 file changed, 205 insertions(+), 98 deletions(-) diff --git a/src/centralized_telescope/params.rs b/src/centralized_telescope/params.rs index fa0f6cf6..806428c8 100644 --- a/src/centralized_telescope/params.rs +++ b/src/centralized_telescope/params.rs @@ -16,132 +16,239 @@ pub struct Params { pub dfs_bound: u64, } -impl Params { - /// Setup algorithm taking as input the security parameters, the set size - /// and the lower bound and returning the internal parameters Params - pub(super) fn new( - soundness_param: f64, - completeness_param: f64, - set_size: u64, - lower_bound: u64, - ) -> Self { - let set_size_f64 = set_size as f64; - let lower_bound_f64 = lower_bound as f64; +pub(super) struct Small { + completeness_param: f64, +} - let proof_size_f64 = { - let numerator = soundness_param + completeness_param.log2() + 5.0 - LOG2_E.log2(); - let denominator = (set_size_f64 / lower_bound_f64).log2(); - (numerator / denominator).ceil() - }; +pub(super) struct Mid { + completeness_param: f64, + completeness_param1: f64, + set_size: u64, +} + +pub(super) struct High { + completeness_param: f64, + completeness_param2: f64, +} + +pub(super) enum Cases { + Small, + Mid, + High, +} + +/// Trait to compute internal parameters depending on which case we are +pub(super) trait Case { + /// Trait constructor + fn new(completeness_param: f64, set_size: u64, proof_size: f64) -> Self; + + /// Returns the maximum number of retries + fn max_retries(&self) -> u64; + + /// Returns the search width + fn search_width(&self, proof_size: f64) -> u64; + + /// Returns the valid proof probability + fn valid_proof_probability(&self, search_width: u64) -> f64; + + /// Returns the DFS bound + fn dfs_bound(&self, proof_size: f64, search_width: u64) -> u64; + + /// Returns Params + fn create_params(&self, proof_size: f64) -> Params { + let search_width = self.search_width(proof_size); + Params { + proof_size: proof_size as u64, + max_retries: self.max_retries(), + search_width, + valid_proof_probability: self.valid_proof_probability(search_width), + dfs_bound: self.dfs_bound(proof_size, search_width), + } + } +} +impl Cases { + pub(super) fn which(completeness_param: f64, set_size: u64, proof_size: u64) -> Cases { + let set_size_f64 = set_size as f64; + let proof_size_f64 = proof_size as f64; let ratio = 9.0 * set_size_f64 * LOG2_E / ((17.0 * proof_size_f64).powi(2)); let s1 = ratio - 7.0; let s2 = ratio - 2.0; if s1 < 1.0 || s2 < 1.0 { // Small case, i.e. set_size <= λ^2 - Params::param_small_case(completeness_param, proof_size_f64) + Cases::Small } else { let completeness_param2 = completeness_param.min(s2); if proof_size_f64 < completeness_param2 { // Case 3, Theorem 14, i.e. set_size >= λ^3 - Params::param_high_case( - completeness_param, - set_size, - proof_size_f64, - completeness_param2, - ) + Cases::High } else { // Case 2, Theorem 13, i.e. λ^2 < set_size < λ^3 - Params::param_mid_case(completeness_param, set_size, proof_size_f64, s1) + Cases::Mid } } } +} - /// Helper function that returns Params, used when set_size <= λ^2 - fn param_small_case(completeness_param: f64, proof_size_f64: f64) -> Params { - let ln12 = (12f64).ln(); - let search_width = (32.0 * ln12 * proof_size_f64).ceil(); - Params { - proof_size: proof_size_f64 as u64, - max_retries: completeness_param as u64, - search_width: search_width as u64, - valid_proof_probability: 2.0 * ln12 / search_width, - dfs_bound: (8.0 * (proof_size_f64 + 1.0) * search_width / ln12).floor() as u64, - } +impl Case for Small { + fn new(completeness_param: f64, _set_size: u64, _proof_size: f64) -> Self { + Self { completeness_param } } - /// Helper function that returns Params, used when set_size >= λ^3 - fn param_high_case( - completeness_param: f64, - set_size: u64, - proof_size_f64: f64, - completeness_param2: f64, - ) -> Params { - let l2 = completeness_param2 + 2.0; - let search_width = (16.0 * proof_size_f64 * l2 / LOG2_E).ceil(); - debug_assert!(set_size as f64 >= search_width * search_width * LOG2_E / (9.0 * l2)); - Params { - proof_size: proof_size_f64 as u64, - max_retries: (completeness_param / completeness_param2).ceil() as u64, - search_width: search_width as u64, - valid_proof_probability: 2.0 * l2 / (search_width * LOG2_E), - dfs_bound: (((l2 + proof_size_f64.log2()) / l2) - * (3.0 * proof_size_f64 * search_width / 4.0) - + search_width - + proof_size_f64) - .floor() as u64, + fn max_retries(&self) -> u64 { + self.completeness_param as u64 + } + + fn search_width(&self, proof_size: f64) -> u64 { + (32.0 * (12f64).ln() * proof_size).ceil() as u64 + } + + fn valid_proof_probability(&self, search_width: u64) -> f64 { + 2.0 * 12f64.ln() / search_width as f64 + } + + fn dfs_bound(&self, proof_size: f64, search_width: u64) -> u64 { + (8.0 * (proof_size + 1.0) * search_width as f64 / (12f64).ln()).ceil() as u64 + } +} + +impl Case for High { + fn new(completeness_param: f64, set_size: u64, proof_size: f64) -> Self { + let ratio = 9.0 * set_size as f64 * LOG2_E / ((17.0 * proof_size).powi(2)); + let s2 = ratio - 2.0; + let completeness_param2 = completeness_param.min(s2); + + Self { + completeness_param, + completeness_param2, } } - /// Helper function that returns Params, used when λ^2 < set_size < λ^3 - fn param_mid_case( - completeness_param: f64, - set_size: u64, - proof_size_f64: f64, - s1: f64, - ) -> Params { - fn max_vertices_visited(proof_size: f64, l1: f64) -> f64 { - fn factorial_check(max_v: f64, l1: f64) -> bool { - let bound = (-l1).exp2(); - let mut factor = (max_v.ceil() as u64).saturating_add(1); - let max_v_2 = max_v + 2.0; - let exp_1_over_max_v = max_v.recip().exp(); - let mut ratio = (14.0 * max_v * max_v * max_v_2 * exp_1_over_max_v) - / (max_v_2 - exp_1_over_max_v); - while factor != 0 { - ratio /= factor as f64; - if ratio <= bound { - return true; - } - factor = factor.saturating_sub(1); + fn max_retries(&self) -> u64 { + (self.completeness_param / self.completeness_param2).ceil() as u64 + } + + fn search_width(&self, proof_size: f64) -> u64 { + (16.0 * proof_size * (self.completeness_param2 + 2.0) / LOG2_E).ceil() as u64 + } + + fn valid_proof_probability(&self, search_width: u64) -> f64 { + (4.0 + 2.0 * self.completeness_param2) / (search_width as f64 * LOG2_E) + } + + fn dfs_bound(&self, proof_size: f64, search_width: u64) -> u64 { + let search_width_f64 = search_width as f64; + ((1.0 + proof_size.log2() * (self.completeness_param2 + 2.0).recip()) + * 3.0 + * proof_size + * search_width_f64 + / 4.0 + + proof_size + + search_width_f64) + .floor() as u64 + } +} + +impl Mid { + fn max_vertices_visited(proof_size: f64, l1: f64) -> f64 { + fn factorial_check(max_v: f64, l1: f64) -> bool { + let bound = (-l1).exp2(); + let mut factor = (max_v.ceil() as u64).saturating_add(1); + let max_v_2 = max_v + 2.0; + let exp_1_over_max_v = max_v.recip().exp(); + let mut ratio = + (14.0 * max_v * max_v * max_v_2 * exp_1_over_max_v) / (max_v_2 - exp_1_over_max_v); + while factor != 0 { + ratio /= factor as f64; + if ratio <= bound { + return true; } - false + factor = factor.saturating_sub(1); } - let mut max_v = proof_size; - while !factorial_check(max_v, l1) { - max_v += 1.0; - } - max_v + false + } + let mut max_v = proof_size; + while !factorial_check(max_v, l1) { + max_v += 1.0; } + max_v + } +} + +impl Case for Mid { + fn new(completeness_param: f64, set_size: u64, proof_size: f64) -> Self { + let ratio = 9.0 * set_size as f64 * LOG2_E / ((17.0 * proof_size).powi(2)); + let s1 = ratio - 7.0; let completeness_param1 = completeness_param.min(s1); - let lbar = (completeness_param1 + 7.0) / LOG2_E; - let search_width = (16.0 * proof_size_f64 * lbar).ceil(); - let lbar_over_sw = lbar / search_width; - debug_assert!(set_size as f64 >= search_width * search_width / (9.0 * lbar)); - - let max_v = max_vertices_visited(proof_size_f64, completeness_param1); - let exponential = (2.0 * proof_size_f64 * max_v * lbar / set_size as f64 - + 7.0 * proof_size_f64 / max_v) + + Self { + completeness_param, + completeness_param1, + set_size, + } + } + + fn max_retries(&self) -> u64 { + (self.completeness_param / self.completeness_param1).ceil() as u64 + } + + fn search_width(&self, proof_size: f64) -> u64 { + (16.0 * proof_size * (self.completeness_param1 + 7.0) / LOG2_E).ceil() as u64 + } + + fn valid_proof_probability(&self, search_width: u64) -> f64 { + 2.0 * (self.completeness_param1 + 7.0) / (LOG2_E * search_width as f64) + } + + fn dfs_bound(&self, proof_size: f64, search_width: u64) -> u64 { + let search_width_f64 = search_width as f64; + let lbar = (self.completeness_param1 + 7.0) / LOG2_E; + let max_v = Mid::max_vertices_visited(proof_size, self.completeness_param1); + let exponential = (2.0 * proof_size * max_v * lbar / self.set_size as f64 + + 7.0 * proof_size / max_v) .exp(); - Params { - proof_size: proof_size_f64 as u64, - max_retries: (completeness_param / completeness_param1).ceil() as u64, - search_width: search_width as u64, - valid_proof_probability: 2.0 * lbar_over_sw, - dfs_bound: ((max_v * lbar_over_sw + 1.0) * exponential * search_width * proof_size_f64 - + search_width) - .floor() as u64, + + ((max_v * lbar + search_width_f64) * proof_size * exponential + search_width_f64).floor() + as u64 + } +} + +impl Params { + /// Setup algorithm taking as input the security parameters, the set size + /// and the lower bound and returning the internal parameters Params + pub(super) fn new( + soundness_param: f64, + completeness_param: f64, + set_size: u64, + lower_bound: u64, + ) -> Self { + let proof_size_f64 = Self::proof_size( + soundness_param, + completeness_param, + set_size as f64, + lower_bound as f64, + ); + + match Cases::which(completeness_param, set_size, proof_size_f64 as u64) { + Cases::Small => Small::new(completeness_param, set_size, proof_size_f64) + .create_params(proof_size_f64), + Cases::Mid => { + Mid::new(completeness_param, set_size, proof_size_f64).create_params(proof_size_f64) + } + Cases::High => High::new(completeness_param, set_size, proof_size_f64) + .create_params(proof_size_f64), } } + + pub(super) fn proof_size( + soundness_param: f64, + completeness_param: f64, + set_size: f64, + lower_bound: f64, + ) -> f64 { + let numerator = soundness_param + completeness_param.log2() + 5.0 - LOG2_E.log2(); + let denominator = (set_size / lower_bound).log2(); + (numerator / denominator).ceil() + } } From 757e4ace17e61cbb95e890a1cda2d32a21167ed6 Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 26 Nov 2024 00:40:49 +0000 Subject: [PATCH 16/19] Adding from_unsafe, checking in from --- src/centralized_telescope/telescope.rs | 168 ++++++++++++++++++++++++- 1 file changed, 166 insertions(+), 2 deletions(-) diff --git a/src/centralized_telescope/telescope.rs b/src/centralized_telescope/telescope.rs index b0a92952..cdd9c70a 100644 --- a/src/centralized_telescope/telescope.rs +++ b/src/centralized_telescope/telescope.rs @@ -1,6 +1,6 @@ //! Customer facing Telescope structure -use super::params::Params; +use super::params::{Case, Cases, High, Mid, Params, Small}; use super::proof::Proof; use super::round::Round; @@ -56,7 +56,9 @@ impl Telescope { } } - /// Returns a Telescope structure from input and internal parameters, to use for backward compability + /// Returns a Telescope structure from input and internal parameters, to + /// use for backward compability if the parameters verifies the paper + /// bounds, otherwise None /// /// # Arguments /// @@ -84,6 +86,168 @@ impl Telescope { set_size: u64, lower_bound: u64, params: Params, + ) -> Option { + let proof_size_f64 = params.proof_size as f64; + + let bool = match Cases::which(completeness_param, set_size, proof_size_f64 as u64) { + Cases::Small => { + let small = Small::new(completeness_param, set_size, proof_size_f64); + Self::check_from( + soundness_param, + completeness_param, + set_size, + lower_bound, + params, + &small, + ) + } + Cases::Mid => { + let mid = Mid::new(completeness_param, set_size, proof_size_f64); + Self::check_from( + soundness_param, + completeness_param, + set_size, + lower_bound, + params, + &mid, + ) + } + Cases::High => { + let high = High::new(completeness_param, set_size, proof_size_f64); + Self::check_from( + soundness_param, + completeness_param, + set_size, + lower_bound, + params, + &high, + ) + } + }; + + bool.then_some(Telescope { + soundness_param, + completeness_param, + set_size, + lower_bound, + params, + }) + } + + fn check_from( + soundness_param: f64, + completeness_param: f64, + set_size: u64, + lower_bound: u64, + params: Params, + case: &impl Case, + ) -> bool { + fn completeness_error(u: f64, d: u64, q: f64) -> f64 { + (-(q - u * q * q / 2.0) * d as f64).exp() + } + fn soundness_error(np: u64, nf: u64, u: f64, d: u64, q: f64) -> f64 { + (nf as f64 / np as f64).powf(u) * d as f64 * q + } + let mut bool = true; + + // Checks the proof size given is at least as big as one computed from user parameters + let proof_size = params.proof_size as f64; + if Params::proof_size( + soundness_param, + completeness_param, + set_size as f64, + lower_bound as f64, + ) > proof_size + { + bool = false; + } + + // Check that the number of max retries is at least as big as one + // computed from given user parameters + if case.max_retries() > params.max_retries { + bool = false; + } + + // Check that the search width is at least as big as the one computed + // from given user parameters and given proof size + let search_width = case.search_width(proof_size); + if search_width > params.search_width { + bool = false; + }; + + // Check that the valid proof probability is close enough from the one + // computed from the given user and internal parameters + let error = 8f64.recip(); + let valid_proof_probability = case.valid_proof_probability(params.search_width); + // Checking the completness error difference is bounded by the error + if (completeness_error(proof_size, params.search_width, valid_proof_probability) + / completeness_error( proof_size, search_width, params.valid_proof_probability)) + .log2() // Computes log2(2^-l1 / 2^-l2) = (-l1) - (-l2) + .abs() // Computes |l1 - l2| + > error + { + bool = false; + }; + // Checking the soundness error difference is bounded by the error + if (soundness_error( + set_size, + lower_bound, + proof_size, + params.search_width, + params.valid_proof_probability, + ) / soundness_error( + set_size, + lower_bound, + proof_size, + params.search_width, + valid_proof_probability, + )) + .log2()// Computes log2(2^-l1 / 2^-l2) = (-l1) - (-l2) + .abs() // Computes |l1 - l2| + > error + { + bool = false; + } + + // Check that the DFS bound is at least as big as the one given by the user and internal parametesr. + let dfs_bound = case.dfs_bound(proof_size, search_width); + if dfs_bound > params.dfs_bound { + bool = false; + }; + + bool + } + + /// Use with caution. Returns a Telescope structure from input and internal + /// parameters, to use for backward compability without checking the + /// consistency between input and internal parameters. + /// + /// # Arguments + /// + /// * `soundness_param` - the protocol soundness parameter, typically set at 128 + /// * `completeness_param` - the protocol completeness parameter, typically set at 128 + /// * `set_size` - the size of the prover set to lower bound + /// * `lower_bound` - the lower bound to prove + /// * `params` - some centralized Telescope internal parameters + /// + /// # Returns + /// + /// A Telescope structure + /// + /// # Example + /// + /// ``` + /// use alba::centralized_telescope::telescope::Telescope; + /// use alba::centralized_telescope::params::Params; + /// let params = Params {proof_size : 200, max_retries: 128, search_width: 10, valid_proof_probability: 0.001, dfs_bound: 40_000}; + /// let telescope = Telescope::from(128.0, 128.0, 1_000, 750, params); + /// ``` + pub fn from_unsafe( + soundness_param: f64, + completeness_param: f64, + set_size: u64, + lower_bound: u64, + params: Params, ) -> Self { Telescope { soundness_param, From 09aa6cd5e79feb8bbcdec61010be63f055226836 Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 26 Nov 2024 10:54:06 +0000 Subject: [PATCH 17/19] fixup doctest --- src/centralized_telescope/telescope.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/centralized_telescope/telescope.rs b/src/centralized_telescope/telescope.rs index cdd9c70a..43a10b92 100644 --- a/src/centralized_telescope/telescope.rs +++ b/src/centralized_telescope/telescope.rs @@ -240,7 +240,7 @@ impl Telescope { /// use alba::centralized_telescope::telescope::Telescope; /// use alba::centralized_telescope::params::Params; /// let params = Params {proof_size : 200, max_retries: 128, search_width: 10, valid_proof_probability: 0.001, dfs_bound: 40_000}; - /// let telescope = Telescope::from(128.0, 128.0, 1_000, 750, params); + /// let telescope = Telescope::from_unsafe(128.0, 128.0, 1_000, 750, params); /// ``` pub fn from_unsafe( soundness_param: f64, From d916ee3dce6c67ae412a8772b2781417d5aa5e8b Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 26 Nov 2024 11:08:05 +0000 Subject: [PATCH 18/19] Creating cases.rs and moving functions around --- src/centralized_telescope/cases.rs | 202 +++++++++++++++ src/centralized_telescope/mod.rs | 3 + src/centralized_telescope/params.rs | 332 ++++++++++--------------- src/centralized_telescope/telescope.rs | 125 +--------- 4 files changed, 343 insertions(+), 319 deletions(-) create mode 100644 src/centralized_telescope/cases.rs diff --git a/src/centralized_telescope/cases.rs b/src/centralized_telescope/cases.rs new file mode 100644 index 00000000..fff3edba --- /dev/null +++ b/src/centralized_telescope/cases.rs @@ -0,0 +1,202 @@ +//! ALBA's helper structures and trait for generating parameters + +use super::params::Params; +use std::f64::consts::LOG2_E; + +pub(super) enum Cases { + Small, + Mid, + High, +} + +impl Cases { + pub(super) fn which(completeness_param: f64, set_size: u64, proof_size: u64) -> Cases { + let set_size_f64 = set_size as f64; + let proof_size_f64 = proof_size as f64; + let ratio = 9.0 * set_size_f64 * LOG2_E / ((17.0 * proof_size_f64).powi(2)); + let s1 = ratio - 7.0; + let s2 = ratio - 2.0; + + if s1 < 1.0 || s2 < 1.0 { + // Small case, i.e. set_size <= λ^2 + Cases::Small + } else { + let completeness_param2 = completeness_param.min(s2); + if proof_size_f64 < completeness_param2 { + // Case 3, Theorem 14, i.e. set_size >= λ^3 + Cases::High + } else { + // Case 2, Theorem 13, i.e. λ^2 < set_size < λ^3 + Cases::Mid + } + } + } +} + +/// Trait to compute internal parameters depending on which case we are +pub(super) trait Case { + /// Trait constructor + fn new(completeness_param: f64, set_size: u64, proof_size: f64) -> Self; + + /// Returns the maximum number of retries + fn max_retries(&self) -> u64; + + /// Returns the search width + fn search_width(&self, proof_size: f64) -> u64; + + /// Returns the valid proof probability + fn valid_proof_probability(&self, search_width: u64) -> f64; + + /// Returns the DFS bound + fn dfs_bound(&self, proof_size: f64, search_width: u64) -> u64; + + /// Returns Params + fn create_params(&self, proof_size: f64) -> Params { + let search_width = self.search_width(proof_size); + Params { + proof_size: proof_size as u64, + max_retries: self.max_retries(), + search_width, + valid_proof_probability: self.valid_proof_probability(search_width), + dfs_bound: self.dfs_bound(proof_size, search_width), + } + } +} + +pub(super) struct Small { + completeness_param: f64, +} + +pub(super) struct Mid { + completeness_param: f64, + completeness_param1: f64, + set_size: u64, +} + +pub(super) struct High { + completeness_param: f64, + completeness_param2: f64, +} + +impl Case for Small { + fn new(completeness_param: f64, _set_size: u64, _proof_size: f64) -> Self { + Self { completeness_param } + } + + fn max_retries(&self) -> u64 { + self.completeness_param as u64 + } + + fn search_width(&self, proof_size: f64) -> u64 { + (32.0 * (12f64).ln() * proof_size).ceil() as u64 + } + + fn valid_proof_probability(&self, search_width: u64) -> f64 { + 2.0 * 12f64.ln() / search_width as f64 + } + + fn dfs_bound(&self, proof_size: f64, search_width: u64) -> u64 { + (8.0 * (proof_size + 1.0) * search_width as f64 / (12f64).ln()).ceil() as u64 + } +} + +impl Case for High { + fn new(completeness_param: f64, set_size: u64, proof_size: f64) -> Self { + let ratio = 9.0 * set_size as f64 * LOG2_E / ((17.0 * proof_size).powi(2)); + let s2 = ratio - 2.0; + let completeness_param2 = completeness_param.min(s2); + + Self { + completeness_param, + completeness_param2, + } + } + + fn max_retries(&self) -> u64 { + (self.completeness_param / self.completeness_param2).ceil() as u64 + } + + fn search_width(&self, proof_size: f64) -> u64 { + (16.0 * proof_size * (self.completeness_param2 + 2.0) / LOG2_E).ceil() as u64 + } + + fn valid_proof_probability(&self, search_width: u64) -> f64 { + (4.0 + 2.0 * self.completeness_param2) / (search_width as f64 * LOG2_E) + } + + fn dfs_bound(&self, proof_size: f64, search_width: u64) -> u64 { + let search_width_f64 = search_width as f64; + ((1.0 + proof_size.log2() * (self.completeness_param2 + 2.0).recip()) + * 3.0 + * proof_size + * search_width_f64 + / 4.0 + + proof_size + + search_width_f64) + .floor() as u64 + } +} + +impl Mid { + fn max_vertices_visited(proof_size: f64, l1: f64) -> f64 { + fn factorial_check(max_v: f64, l1: f64) -> bool { + let bound = (-l1).exp2(); + let mut factor = (max_v.ceil() as u64).saturating_add(1); + let max_v_2 = max_v + 2.0; + let exp_1_over_max_v = max_v.recip().exp(); + let mut ratio = + (14.0 * max_v * max_v * max_v_2 * exp_1_over_max_v) / (max_v_2 - exp_1_over_max_v); + while factor != 0 { + ratio /= factor as f64; + if ratio <= bound { + return true; + } + factor = factor.saturating_sub(1); + } + false + } + let mut max_v = proof_size; + while !factorial_check(max_v, l1) { + max_v += 1.0; + } + max_v + } +} + +impl Case for Mid { + fn new(completeness_param: f64, set_size: u64, proof_size: f64) -> Self { + let ratio = 9.0 * set_size as f64 * LOG2_E / ((17.0 * proof_size).powi(2)); + let s1 = ratio - 7.0; + let completeness_param1 = completeness_param.min(s1); + + Self { + completeness_param, + completeness_param1, + set_size, + } + } + + fn max_retries(&self) -> u64 { + (self.completeness_param / self.completeness_param1).ceil() as u64 + } + + fn search_width(&self, proof_size: f64) -> u64 { + (16.0 * proof_size * (self.completeness_param1 + 7.0) / LOG2_E).ceil() as u64 + } + + fn valid_proof_probability(&self, search_width: u64) -> f64 { + 2.0 * (self.completeness_param1 + 7.0) / (LOG2_E * search_width as f64) + } + + fn dfs_bound(&self, proof_size: f64, search_width: u64) -> u64 { + let search_width_f64 = search_width as f64; + let lbar = (self.completeness_param1 + 7.0) / LOG2_E; + let max_v = Mid::max_vertices_visited(proof_size, self.completeness_param1); + let exponential = (2.0 * proof_size * max_v * lbar / self.set_size as f64 + + 7.0 * proof_size / max_v) + .exp(); + + ((max_v * lbar + search_width_f64) * proof_size * exponential + search_width_f64).floor() + as u64 + } +} diff --git a/src/centralized_telescope/mod.rs b/src/centralized_telescope/mod.rs index 9b335a24..dbfcc872 100644 --- a/src/centralized_telescope/mod.rs +++ b/src/centralized_telescope/mod.rs @@ -4,6 +4,9 @@ // Defines the internal parameters and provide functions for their generation pub mod params; +// Defines different scenarios of parameter generation +mod cases; + // Defines the proof structure and provide high level functions, i.e. the depth // first search algorithm (DFS) and indexed proving function, as well as helper // hash functions diff --git a/src/centralized_telescope/params.rs b/src/centralized_telescope/params.rs index 806428c8..3e2fba78 100644 --- a/src/centralized_telescope/params.rs +++ b/src/centralized_telescope/params.rs @@ -1,4 +1,5 @@ //! ALBA's Params structure comprising internal parameters +use super::cases::{Case, Cases, High, Mid, Small}; use std::f64::consts::LOG2_E; /// Params structure comprising internal parameters @@ -16,204 +17,6 @@ pub struct Params { pub dfs_bound: u64, } -pub(super) struct Small { - completeness_param: f64, -} - -pub(super) struct Mid { - completeness_param: f64, - completeness_param1: f64, - set_size: u64, -} - -pub(super) struct High { - completeness_param: f64, - completeness_param2: f64, -} - -pub(super) enum Cases { - Small, - Mid, - High, -} - -/// Trait to compute internal parameters depending on which case we are -pub(super) trait Case { - /// Trait constructor - fn new(completeness_param: f64, set_size: u64, proof_size: f64) -> Self; - - /// Returns the maximum number of retries - fn max_retries(&self) -> u64; - - /// Returns the search width - fn search_width(&self, proof_size: f64) -> u64; - - /// Returns the valid proof probability - fn valid_proof_probability(&self, search_width: u64) -> f64; - - /// Returns the DFS bound - fn dfs_bound(&self, proof_size: f64, search_width: u64) -> u64; - - /// Returns Params - fn create_params(&self, proof_size: f64) -> Params { - let search_width = self.search_width(proof_size); - Params { - proof_size: proof_size as u64, - max_retries: self.max_retries(), - search_width, - valid_proof_probability: self.valid_proof_probability(search_width), - dfs_bound: self.dfs_bound(proof_size, search_width), - } - } -} - -impl Cases { - pub(super) fn which(completeness_param: f64, set_size: u64, proof_size: u64) -> Cases { - let set_size_f64 = set_size as f64; - let proof_size_f64 = proof_size as f64; - let ratio = 9.0 * set_size_f64 * LOG2_E / ((17.0 * proof_size_f64).powi(2)); - let s1 = ratio - 7.0; - let s2 = ratio - 2.0; - - if s1 < 1.0 || s2 < 1.0 { - // Small case, i.e. set_size <= λ^2 - Cases::Small - } else { - let completeness_param2 = completeness_param.min(s2); - if proof_size_f64 < completeness_param2 { - // Case 3, Theorem 14, i.e. set_size >= λ^3 - Cases::High - } else { - // Case 2, Theorem 13, i.e. λ^2 < set_size < λ^3 - Cases::Mid - } - } - } -} - -impl Case for Small { - fn new(completeness_param: f64, _set_size: u64, _proof_size: f64) -> Self { - Self { completeness_param } - } - - fn max_retries(&self) -> u64 { - self.completeness_param as u64 - } - - fn search_width(&self, proof_size: f64) -> u64 { - (32.0 * (12f64).ln() * proof_size).ceil() as u64 - } - - fn valid_proof_probability(&self, search_width: u64) -> f64 { - 2.0 * 12f64.ln() / search_width as f64 - } - - fn dfs_bound(&self, proof_size: f64, search_width: u64) -> u64 { - (8.0 * (proof_size + 1.0) * search_width as f64 / (12f64).ln()).ceil() as u64 - } -} - -impl Case for High { - fn new(completeness_param: f64, set_size: u64, proof_size: f64) -> Self { - let ratio = 9.0 * set_size as f64 * LOG2_E / ((17.0 * proof_size).powi(2)); - let s2 = ratio - 2.0; - let completeness_param2 = completeness_param.min(s2); - - Self { - completeness_param, - completeness_param2, - } - } - - fn max_retries(&self) -> u64 { - (self.completeness_param / self.completeness_param2).ceil() as u64 - } - - fn search_width(&self, proof_size: f64) -> u64 { - (16.0 * proof_size * (self.completeness_param2 + 2.0) / LOG2_E).ceil() as u64 - } - - fn valid_proof_probability(&self, search_width: u64) -> f64 { - (4.0 + 2.0 * self.completeness_param2) / (search_width as f64 * LOG2_E) - } - - fn dfs_bound(&self, proof_size: f64, search_width: u64) -> u64 { - let search_width_f64 = search_width as f64; - ((1.0 + proof_size.log2() * (self.completeness_param2 + 2.0).recip()) - * 3.0 - * proof_size - * search_width_f64 - / 4.0 - + proof_size - + search_width_f64) - .floor() as u64 - } -} - -impl Mid { - fn max_vertices_visited(proof_size: f64, l1: f64) -> f64 { - fn factorial_check(max_v: f64, l1: f64) -> bool { - let bound = (-l1).exp2(); - let mut factor = (max_v.ceil() as u64).saturating_add(1); - let max_v_2 = max_v + 2.0; - let exp_1_over_max_v = max_v.recip().exp(); - let mut ratio = - (14.0 * max_v * max_v * max_v_2 * exp_1_over_max_v) / (max_v_2 - exp_1_over_max_v); - while factor != 0 { - ratio /= factor as f64; - if ratio <= bound { - return true; - } - factor = factor.saturating_sub(1); - } - false - } - let mut max_v = proof_size; - while !factorial_check(max_v, l1) { - max_v += 1.0; - } - max_v - } -} - -impl Case for Mid { - fn new(completeness_param: f64, set_size: u64, proof_size: f64) -> Self { - let ratio = 9.0 * set_size as f64 * LOG2_E / ((17.0 * proof_size).powi(2)); - let s1 = ratio - 7.0; - let completeness_param1 = completeness_param.min(s1); - - Self { - completeness_param, - completeness_param1, - set_size, - } - } - - fn max_retries(&self) -> u64 { - (self.completeness_param / self.completeness_param1).ceil() as u64 - } - - fn search_width(&self, proof_size: f64) -> u64 { - (16.0 * proof_size * (self.completeness_param1 + 7.0) / LOG2_E).ceil() as u64 - } - - fn valid_proof_probability(&self, search_width: u64) -> f64 { - 2.0 * (self.completeness_param1 + 7.0) / (LOG2_E * search_width as f64) - } - - fn dfs_bound(&self, proof_size: f64, search_width: u64) -> u64 { - let search_width_f64 = search_width as f64; - let lbar = (self.completeness_param1 + 7.0) / LOG2_E; - let max_v = Mid::max_vertices_visited(proof_size, self.completeness_param1); - let exponential = (2.0 * proof_size * max_v * lbar / self.set_size as f64 - + 7.0 * proof_size / max_v) - .exp(); - - ((max_v * lbar + search_width_f64) * proof_size * exponential + search_width_f64).floor() - as u64 - } -} - impl Params { /// Setup algorithm taking as input the security parameters, the set size /// and the lower bound and returning the internal parameters Params @@ -241,7 +44,138 @@ impl Params { } } - pub(super) fn proof_size( + pub(super) fn check_from( + soundness_param: f64, + completeness_param: f64, + set_size: u64, + lower_bound: u64, + params: Params, + ) -> bool { + let proof_size_f64 = params.proof_size as f64; + + match Cases::which(completeness_param, set_size, proof_size_f64 as u64) { + Cases::Small => { + let small = Small::new(completeness_param, set_size, proof_size_f64); + Params::check_case( + soundness_param, + completeness_param, + set_size, + lower_bound, + params, + &small, + ) + } + Cases::Mid => { + let mid = Mid::new(completeness_param, set_size, proof_size_f64); + Params::check_case( + soundness_param, + completeness_param, + set_size, + lower_bound, + params, + &mid, + ) + } + Cases::High => { + let high = High::new(completeness_param, set_size, proof_size_f64); + Params::check_case( + soundness_param, + completeness_param, + set_size, + lower_bound, + params, + &high, + ) + } + } + } + + /// Check that internal parameters are consistent wit user parameters + fn check_case( + soundness_param: f64, + completeness_param: f64, + set_size: u64, + lower_bound: u64, + params: Params, + case: &impl Case, + ) -> bool { + fn completeness_error(u: f64, d: u64, q: f64) -> f64 { + (-(q - u * q * q / 2.0) * d as f64).exp() + } + fn soundness_error(np: u64, nf: u64, u: f64, d: u64, q: f64) -> f64 { + (nf as f64 / np as f64).powf(u) * d as f64 * q + } + let mut bool = true; + + // Checks the proof size given is at least as big as one computed from user parameters + let proof_size = params.proof_size as f64; + if Params::proof_size( + soundness_param, + completeness_param, + set_size as f64, + lower_bound as f64, + ) > proof_size + { + bool = false; + } + + // Check that the number of max retries is at least as big as one + // computed from given user parameters + if case.max_retries() > params.max_retries { + bool = false; + } + + // Check that the search width is at least as big as the one computed + // from given user parameters and given proof size + let search_width = case.search_width(proof_size); + if search_width > params.search_width { + bool = false; + }; + + // Check that the valid proof probability is close enough from the one + // computed from the given user and internal parameters + let error = 8f64.recip(); + let valid_proof_probability = case.valid_proof_probability(params.search_width); + // Checking the completness error difference is bounded by the error + if (completeness_error(proof_size, params.search_width, valid_proof_probability) + / completeness_error( proof_size, search_width, params.valid_proof_probability)) + .log2() // Computes log2(2^-l1 / 2^-l2) = (-l1) - (-l2) + .abs() // Computes |l1 - l2| + > error + { + bool = false; + }; + // Checking the soundness error difference is bounded by the error + if (soundness_error( + set_size, + lower_bound, + proof_size, + params.search_width, + params.valid_proof_probability, + ) / soundness_error( + set_size, + lower_bound, + proof_size, + params.search_width, + valid_proof_probability, + )) + .log2()// Computes log2(2^-l1 / 2^-l2) = (-l1) - (-l2) + .abs() // Computes |l1 - l2| + > error + { + bool = false; + } + + // Check that the DFS bound is at least as big as the one given by the user and internal parametesr. + let dfs_bound = case.dfs_bound(proof_size, search_width); + if dfs_bound > params.dfs_bound { + bool = false; + }; + + bool + } + + fn proof_size( soundness_param: f64, completeness_param: f64, set_size: f64, diff --git a/src/centralized_telescope/telescope.rs b/src/centralized_telescope/telescope.rs index 43a10b92..7b8aa0a0 100644 --- a/src/centralized_telescope/telescope.rs +++ b/src/centralized_telescope/telescope.rs @@ -1,6 +1,6 @@ //! Customer facing Telescope structure -use super::params::{Case, Cases, High, Mid, Params, Small}; +use super::params::Params; use super::proof::Proof; use super::round::Round; @@ -87,135 +87,20 @@ impl Telescope { lower_bound: u64, params: Params, ) -> Option { - let proof_size_f64 = params.proof_size as f64; - - let bool = match Cases::which(completeness_param, set_size, proof_size_f64 as u64) { - Cases::Small => { - let small = Small::new(completeness_param, set_size, proof_size_f64); - Self::check_from( - soundness_param, - completeness_param, - set_size, - lower_bound, - params, - &small, - ) - } - Cases::Mid => { - let mid = Mid::new(completeness_param, set_size, proof_size_f64); - Self::check_from( - soundness_param, - completeness_param, - set_size, - lower_bound, - params, - &mid, - ) - } - Cases::High => { - let high = High::new(completeness_param, set_size, proof_size_f64); - Self::check_from( - soundness_param, - completeness_param, - set_size, - lower_bound, - params, - &high, - ) - } - }; - - bool.then_some(Telescope { + Params::check_from( soundness_param, completeness_param, set_size, lower_bound, params, - }) - } - - fn check_from( - soundness_param: f64, - completeness_param: f64, - set_size: u64, - lower_bound: u64, - params: Params, - case: &impl Case, - ) -> bool { - fn completeness_error(u: f64, d: u64, q: f64) -> f64 { - (-(q - u * q * q / 2.0) * d as f64).exp() - } - fn soundness_error(np: u64, nf: u64, u: f64, d: u64, q: f64) -> f64 { - (nf as f64 / np as f64).powf(u) * d as f64 * q - } - let mut bool = true; - - // Checks the proof size given is at least as big as one computed from user parameters - let proof_size = params.proof_size as f64; - if Params::proof_size( + ) + .then_some(Self::from_unsafe( soundness_param, completeness_param, - set_size as f64, - lower_bound as f64, - ) > proof_size - { - bool = false; - } - - // Check that the number of max retries is at least as big as one - // computed from given user parameters - if case.max_retries() > params.max_retries { - bool = false; - } - - // Check that the search width is at least as big as the one computed - // from given user parameters and given proof size - let search_width = case.search_width(proof_size); - if search_width > params.search_width { - bool = false; - }; - - // Check that the valid proof probability is close enough from the one - // computed from the given user and internal parameters - let error = 8f64.recip(); - let valid_proof_probability = case.valid_proof_probability(params.search_width); - // Checking the completness error difference is bounded by the error - if (completeness_error(proof_size, params.search_width, valid_proof_probability) - / completeness_error( proof_size, search_width, params.valid_proof_probability)) - .log2() // Computes log2(2^-l1 / 2^-l2) = (-l1) - (-l2) - .abs() // Computes |l1 - l2| - > error - { - bool = false; - }; - // Checking the soundness error difference is bounded by the error - if (soundness_error( set_size, lower_bound, - proof_size, - params.search_width, - params.valid_proof_probability, - ) / soundness_error( - set_size, - lower_bound, - proof_size, - params.search_width, - valid_proof_probability, + params, )) - .log2()// Computes log2(2^-l1 / 2^-l2) = (-l1) - (-l2) - .abs() // Computes |l1 - l2| - > error - { - bool = false; - } - - // Check that the DFS bound is at least as big as the one given by the user and internal parametesr. - let dfs_bound = case.dfs_bound(proof_size, search_width); - if dfs_bound > params.dfs_bound { - bool = false; - }; - - bool } /// Use with caution. Returns a Telescope structure from input and internal From 3ecc4d349945ba969621b802ad4f19efc2ddfd84 Mon Sep 17 00:00:00 2001 From: Raphael Toledo Date: Tue, 26 Nov 2024 11:13:51 +0000 Subject: [PATCH 19/19] fixup check_case --- src/centralized_telescope/params.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/centralized_telescope/params.rs b/src/centralized_telescope/params.rs index 3e2fba78..8b04b8f9 100644 --- a/src/centralized_telescope/params.rs +++ b/src/centralized_telescope/params.rs @@ -137,7 +137,7 @@ impl Params { let error = 8f64.recip(); let valid_proof_probability = case.valid_proof_probability(params.search_width); // Checking the completness error difference is bounded by the error - if (completeness_error(proof_size, params.search_width, valid_proof_probability) + if (completeness_error(proof_size, search_width, valid_proof_probability) / completeness_error( proof_size, search_width, params.valid_proof_probability)) .log2() // Computes log2(2^-l1 / 2^-l2) = (-l1) - (-l2) .abs() // Computes |l1 - l2|