Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error handling #143

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion benches/centralized_telescope/proving_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn prove_duration(params: &BenchParam, truncate_size: u64, n: u64) -> Duration {
for _ in 0..n {
// Bench the proving time
let start = Instant::now();
black_box(telescope.prove(&dataset));
let _proof = black_box(telescope.prove(&dataset));
total_duration = total_duration.saturating_add(start.elapsed());
}
total_duration
Expand Down
6 changes: 3 additions & 3 deletions benches/centralized_telescope/verifying_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ fn verify_duration(params: &BenchParam, truncate_size: u64, n: u64) -> Duration
// Truncate the dataset to give truncate_size elements to the prover
dataset.truncate(truncate_size as usize);
// Generate the proof
let proof_opt: Option<alba::centralized_telescope::proof::Proof> = telescope.prove(&dataset);
let proof = telescope.prove(&dataset);

if let Some(proof) = proof_opt {
if let Ok(proof) = proof {
// Iterate on each sample `n` times
for _ in 0..n {
// Benching the verification time
let start = Instant::now();
black_box(telescope.verify(&proof));
let _ = black_box(telescope.verify(&proof));
total_duration = total_duration.saturating_add(start.elapsed());
}
}
Expand Down
2 changes: 1 addition & 1 deletion benches/simple_lottery/proving_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn prove_duration(params: &BenchParam, truncate_size: u64, n: u64) -> Duration {
for _ in 0..n {
// Bench the proving time
let start = Instant::now();
black_box(telescope.prove(&dataset));
let _proof = black_box(telescope.prove(&dataset));
total_duration = total_duration.saturating_add(start.elapsed());
}
total_duration
Expand Down
4 changes: 2 additions & 2 deletions benches/simple_lottery/verifying_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ fn verify_duration(params: &BenchParam, truncate_size: u64, n: u64) -> Duration
// Generate the proof
let proof_opt = telescope.prove(&dataset);

if let Some(proof) = proof_opt {
if let Ok(proof) = proof_opt {
// Iterate on each sample `n` times
for _ in 0..n {
// Benching the verification time
let start = Instant::now();
black_box(telescope.verify(&proof));
let _ = black_box(telescope.verify(&proof));
total_duration = total_duration.saturating_add(start.elapsed());
}
}
Expand Down
7 changes: 4 additions & 3 deletions examples/centralized_threshold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl AlbaThresholdSignature {

println!("-- Creating alba proof. ");
let time_gen_proof = Instant::now();
let proof = alba.prove(&prover_set)?;
let proof = alba.prove(&prover_set).unwrap();
println!(
"-- Alba proof is created in {:.3}s.",
time_gen_proof.elapsed().as_secs_f64()
Expand Down Expand Up @@ -132,15 +132,16 @@ impl AlbaThresholdSignature {
let time_verify_proof = Instant::now();
let result = alba.verify(&self.proof);

if result {
if result.is_ok() {
println!(
"-- Success: Alba proof verification took {:?}µs.",
time_verify_proof.elapsed().as_micros()
);
true
} else {
println!("Error: Alba proof verification failed.");
false
}
result
} else {
println!("Error: Registration is not closed.");
false
Expand Down
2 changes: 1 addition & 1 deletion examples/simple_threshold_signature/threshold_signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,6 @@ impl ThresholdSignature {
public_key_list: &[(usize, PublicKey)],
indices: &[usize],
) -> bool {
self.validate_signatures(msg, public_key_list, indices) && alba.verify(&self.proof)
self.validate_signatures(msg, public_key_list, indices) && alba.verify(&self.proof).is_ok()
}
}
115 changes: 74 additions & 41 deletions src/centralized_telescope/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use super::params::Params;
use super::round::Round;
use crate::utils::{
sample,
types::{Element, Hash},
types::{Element, Hash, ProofGenerationError, VerificationError},
};
use blake2::{Blake2s256, Digest};

Expand Down Expand Up @@ -35,9 +35,22 @@ impl Proof {
/// # Returns
///
/// A `Proof` structure
pub(super) fn new(set_size: u64, params: &Params, prover_set: &[Element]) -> Option<Self> {
///
/// # Errors
///
/// Returns a `ProofGenerationError`
pub(super) fn new(
set_size: u64,
params: &Params,
prover_set: &[Element],
) -> Result<Self, ProofGenerationError> {
debug_assert!(crate::utils::misc::check_distinct(prover_set));

// TODO we should check that these elements are distinct
if (prover_set.len() as u64) < set_size {
return Err(ProofGenerationError::NotEnoughElements);
}

Self::prove_routine(set_size, params, prover_set).1
}

Expand Down Expand Up @@ -68,7 +81,15 @@ impl Proof {
/// }
/// let (setps, proof_opt) = Proof::bench(set_size, &params, &prover_set);
/// ```
pub fn bench(set_size: u64, params: &Params, prover_set: &[Element]) -> (u64, Option<Proof>) {
///
/// # Errors
///
/// Returns a `ProofGenerationError`
pub fn bench(
set_size: u64,
params: &Params,
prover_set: &[Element],
) -> (u64, Result<Proof, ProofGenerationError>) {
Self::prove_routine(set_size, params, prover_set)
}

Expand All @@ -80,23 +101,28 @@ impl Proof {
set_size: u64,
params: &Params,
prover_set: &[Element],
) -> (u64, Option<Proof>) {
) -> (u64, Result<Self, ProofGenerationError>) {
let mut steps: u64 = 0;

// Run prove_index up to max_retries times
for retry_counter in 0..params.max_retries {
let (dfs_calls, proof_opt) = Self::prove_index(
let (dfs_calls, proof) = Self::prove_index(
set_size,
params,
prover_set,
retry_counter.saturating_add(1),
);
steps = steps.saturating_add(dfs_calls);
if proof_opt.is_some() {
return (steps, proof_opt);
if proof.is_ok() {
return (steps, proof);
}
}
(steps, None)

if steps >= params.dfs_bound {
(steps, Err(ProofGenerationError::NotFoundInBounds))
} else {
(steps, Err(ProofGenerationError::NotFound))
}
}

/// Centralized Telescope's verification algorithm, returns true if the
Expand All @@ -112,37 +138,47 @@ impl Proof {
/// # Returns
///
/// A boolean, true if the proof verifies successfully otherwise false
pub(super) fn verify(&self, set_size: u64, params: &Params) -> bool {
if self.search_counter >= params.search_width
|| self.retry_counter >= params.max_retries
|| self.element_sequence.len() as u64 != params.proof_size
{
return false;
///
/// # Errors
///
/// Returns a `VerificationError`
pub(super) fn verify(&self, set_size: u64, params: &Params) -> Result<(), VerificationError> {
if self.element_sequence.len() as u64 != params.proof_size {
return Err(VerificationError::IncorrectNumberElements);
}

if self.search_counter >= params.search_width || self.retry_counter >= params.max_retries {
return Err(VerificationError::InvalidParameters);
}

// Initialise a round with given retry and search counters
let Some(mut round) = Round::new(self.retry_counter, self.search_counter, set_size) else {
return false;
return Err(VerificationError::InvalidProof);
};

// For each element in the proof's sequence
for &element in &self.element_sequence {
// Retrieve the bin id associated to this new element
let Some(bin_id) = Proof::bin_hash(set_size, self.retry_counter, element) else {
return false;
return Err(VerificationError::InvalidProof);
};
// 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,
None => return Err(VerificationError::InvalidProof),
}
} else {
return false;
return Err(VerificationError::InvalidProof);
}
}
Proof::proof_hash(params.valid_proof_probability, &round)

if Proof::proof_hash(params.valid_proof_probability, &round) {
Ok(())
} else {
Err(VerificationError::InvalidProof)
}
}

/// Indexed proving algorithm, returns the total number of DFS calls done
Expand All @@ -153,7 +189,7 @@ impl Proof {
params: &Params,
prover_set: &[Element],
retry_counter: u64,
) -> (u64, Option<Self>) {
) -> (u64, Result<Self, ProofGenerationError>) {
// Initialize set_size bins
let mut bins: Vec<Vec<Element>> = Vec::with_capacity(set_size as usize);
for _ in 0..set_size {
Expand All @@ -163,11 +199,8 @@ impl Proof {
// 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),
if let Some(bin_index) = Proof::bin_hash(set_size, retry_counter, element) {
bins[bin_index as usize].push(element);
}
}

Expand All @@ -176,21 +209,21 @@ impl Proof {
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);
return (step, Err(ProofGenerationError::NotFoundInBounds));
}
// 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) = Self::dfs(params, &bins, &r, step.saturating_add(1));
let (dfs_calls, proof) = Self::dfs(params, &bins, &r, step.saturating_add(1));
// Return proof if found
if proof_opt.is_some() {
return (dfs_calls, proof_opt);
if proof.is_ok() {
return (dfs_calls, proof);
}
// Update step, that is the number of DFS calls
step = dfs_calls;
}
}
(step, None)
(step, Err(ProofGenerationError::NotFound))
}

/// Depth-First Search (DFS) algorithm which goes through all potential
Expand All @@ -205,43 +238,43 @@ impl Proof {
bins: &[Vec<Element>],
round: &Round,
mut step: u64,
) -> (u64, Option<Self>) {
) -> (u64, Result<Self, ProofGenerationError>) {
// 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(Self {
let result = if Proof::proof_hash(params.valid_proof_probability, round) {
Ok(Self {
retry_counter: round.retry_counter,
search_counter: round.search_counter,
element_sequence: round.element_sequence.clone(),
})
} else {
None
Err(ProofGenerationError::NotFound)
};
return (step, proof_opt);
return (step, result);
}

// For each element in bin numbered id
for &element in &bins[round.id as usize] {
// If DFS was called more than params.dfs_bound times, abort this
// round
if step == params.dfs_bound {
return (step, None);
if step >= params.dfs_bound {
return (step, Err(ProofGenerationError::NotFoundInBounds));
}
// 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) = Self::dfs(params, bins, &r, step.saturating_add(1));
let (dfs_calls, proof) = Self::dfs(params, bins, &r, step.saturating_add(1));
// Return proof if found
if proof_opt.is_some() {
return (dfs_calls, proof_opt);
if proof.is_ok() {
return (dfs_calls, proof);
}
// Update step, i.e. is the number of DFS calls
step = dfs_calls;
}
}
// If no proof was found, return number of steps and None
(step, None)
(step, Err(ProofGenerationError::NotFound))
}

/// Oracle producing a uniformly random value in [0, set_size[ used for
Expand Down
16 changes: 12 additions & 4 deletions src/centralized_telescope/telescope.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Customer facing Centralized Telescope structure
use super::params::Params;
use super::proof::Proof;
use crate::utils::types::Element;
use crate::utils::types::{Element, ProofGenerationError, VerificationError};

/// The main centralized Telescope struct with prove and verify functions.
#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -138,7 +138,11 @@ impl Telescope {
/// }
/// let proof = telescope.prove(&prover_set).unwrap();
/// ```
pub fn prove(&self, prover_set: &[Element]) -> Option<Proof> {
///
/// # Errors
///
/// Returns a `ProofGenerationError`
pub fn prove(&self, prover_set: &[Element]) -> Result<Proof, ProofGenerationError> {
Proof::new(self.set_size, &self.params, prover_set)
}

Expand All @@ -164,9 +168,13 @@ impl Telescope {
/// prover_set.push([(i % 256) as u8 ; 48]);
/// }
/// let proof = telescope.prove(&prover_set).unwrap();
/// assert!(telescope.verify(&proof));
/// assert!(telescope.verify(&proof).is_ok());
/// ```
pub fn verify(&self, proof: &Proof) -> bool {
///
/// # Errors
///
/// Returns a `VerificationError`
pub fn verify(&self, proof: &Proof) -> Result<(), VerificationError> {
proof.verify(self.set_size, &self.params)
}
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// #![deny(missing_docs)]
#![doc = include_str!("../README.md")]

mod utils;
pub mod utils;

pub mod centralized_telescope;
pub mod simple_lottery;
Expand Down
Loading
Loading