-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Various methods on `Server` used to return `Option<T>`, making it possible for them to fail but not to indicate why. This means `prio-server` can't tell the difference between a packet being rejected due to a decryption error or because the decrypted payload was invalid, causing frustrating situations as described in [1]. We now return `Result<T, ServerError>` from `Server`'s methods. In support of this, this commit also includes some other cleanups: - various structs and functions are moved from `util.rs` (which will hopefully go away altogether in the near future) into the new `proof` module - the functions `unpack_proof` and `unpack_proof_mut` now also return errors, drawn from the new `proof::ProofError` enum. - a number of `use module::*` style statements are rewritten to be more explicit. [1] divviup/prio-server#550
- Loading branch information
1 parent
d7e93ae
commit 00db7ce
Showing
6 changed files
with
169 additions
and
114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,5 +17,6 @@ pub mod field; | |
mod fp; | ||
mod polynomial; | ||
mod prng; | ||
pub mod proof; | ||
pub mod server; | ||
pub mod util; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
//! Structs and utilities for working with proofs and proof shares | ||
use crate::field::FieldElement; | ||
|
||
/// Possible errors from proofs | ||
#[derive(Debug, thiserror::Error)] | ||
pub enum ProofError { | ||
/// Input sizes do not match | ||
#[error("input sizes do not match")] | ||
InputSizeMismatch, | ||
} | ||
|
||
/// Returns the number of field elements in the proof for given dimension of | ||
/// data elements | ||
/// | ||
/// Proof is a vector, where the first `dimension` elements are the data | ||
/// elements, the next 3 elements are the zero terms for polynomials f, g and h | ||
/// and the remaining elements are non-zero points of h(x). | ||
pub(crate) fn proof_length(dimension: usize) -> usize { | ||
// number of data items + number of zero terms + N | ||
dimension + 3 + (dimension + 1).next_power_of_two() | ||
} | ||
|
||
/// Unpacked proof with subcomponents | ||
#[derive(Debug)] | ||
pub(crate) struct UnpackedProof<'a, F: FieldElement> { | ||
/// Data | ||
pub data: &'a [F], | ||
/// Zeroth coefficient of polynomial f | ||
pub f0: &'a F, | ||
/// Zeroth coefficient of polynomial g | ||
pub g0: &'a F, | ||
/// Zeroth coefficient of polynomial h | ||
pub h0: &'a F, | ||
/// Non-zero points of polynomial h | ||
pub points_h_packed: &'a [F], | ||
} | ||
|
||
/// Unpacked proof with mutable subcomponents | ||
#[derive(Debug)] | ||
pub struct UnpackedProofMut<'a, F: FieldElement> { | ||
/// Data | ||
pub data: &'a mut [F], | ||
/// Zeroth coefficient of polynomial f | ||
pub f0: &'a mut F, | ||
/// Zeroth coefficient of polynomial g | ||
pub g0: &'a mut F, | ||
/// Zeroth coefficient of polynomial h | ||
pub h0: &'a mut F, | ||
/// Non-zero points of polynomial h | ||
pub points_h_packed: &'a mut [F], | ||
} | ||
|
||
/// Unpacks the proof vector into subcomponents | ||
pub(crate) fn unpack_proof<F: FieldElement>( | ||
proof: &[F], | ||
dimension: usize, | ||
) -> Result<UnpackedProof<F>, ProofError> { | ||
// check the proof length | ||
if proof.len() != proof_length(dimension) { | ||
return Err(ProofError::InputSizeMismatch); | ||
} | ||
// split share into components | ||
let (data, rest) = proof.split_at(dimension); | ||
if let ([f0, g0, h0], points_h_packed) = rest.split_at(3) { | ||
Ok(UnpackedProof { | ||
data, | ||
f0, | ||
g0, | ||
h0, | ||
points_h_packed, | ||
}) | ||
} else { | ||
Err(ProofError::InputSizeMismatch) | ||
} | ||
} | ||
|
||
/// Unpacks a mutable proof vector into mutable subcomponents | ||
// TODO(timg): This is public because it is used by tests/tweaks.rs. We should | ||
// refactor that test so it doesn't require the crate to expose this function or | ||
// UnpackedProofMut. | ||
pub fn unpack_proof_mut<F: FieldElement>( | ||
proof: &mut [F], | ||
dimension: usize, | ||
) -> Result<UnpackedProofMut<F>, ProofError> { | ||
// check the share length | ||
if proof.len() != proof_length(dimension) { | ||
return Err(ProofError::InputSizeMismatch); | ||
} | ||
// split share into components | ||
let (data, rest) = proof.split_at_mut(dimension); | ||
if let ([f0, g0, h0], points_h_packed) = rest.split_at_mut(3) { | ||
Ok(UnpackedProofMut { | ||
data, | ||
f0, | ||
g0, | ||
h0, | ||
points_h_packed, | ||
}) | ||
} else { | ||
Err(ProofError::InputSizeMismatch) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use crate::field::{Field32, Field64}; | ||
use assert_matches::assert_matches; | ||
|
||
#[test] | ||
fn test_unpack_share_mut() { | ||
let dim = 15; | ||
let len = proof_length(dim); | ||
|
||
let mut share = vec![Field32::from(0); len]; | ||
let unpacked = unpack_proof_mut(&mut share, dim).unwrap(); | ||
*unpacked.f0 = Field32::from(12); | ||
assert_eq!(share[dim], 12); | ||
|
||
let mut short_share = vec![Field32::from(0); len - 1]; | ||
assert_matches!( | ||
unpack_proof_mut(&mut short_share, dim), | ||
Err(ProofError::InputSizeMismatch) | ||
); | ||
} | ||
|
||
#[test] | ||
fn test_unpack_share() { | ||
let dim = 15; | ||
let len = proof_length(dim); | ||
|
||
let share = vec![Field64::from(0); len]; | ||
unpack_proof(&share, dim).unwrap(); | ||
|
||
let short_share = vec![Field64::from(0); len - 1]; | ||
assert_matches!( | ||
unpack_proof(&short_share, dim), | ||
Err(ProofError::InputSizeMismatch) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters