Skip to content

Commit

Permalink
Merge pull request #25 from abetterinternet/timg/return-result-2
Browse files Browse the repository at this point in the history
Return `Result` from `Server` methods
  • Loading branch information
tgeoghegan authored Apr 8, 2021
2 parents 85feeb8 + 24ac8dd commit b68a16b
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 41 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "prio"
version = "0.3.0"
version = "0.4.0"
authors = ["Josh Aas <jaas@kflag.net>", "Karl Tarbe <tarbe@apple.com>"]
edition = "2018"
description = "Implementation of the Prio aggregation system core: https://crypto.stanford.edu/prio/"
Expand Down
10 changes: 6 additions & 4 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@

//! Prio client

use crate::encrypt::*;
use crate::field::FieldElement;
use crate::polynomial::*;
use crate::util::*;
use crate::{
encrypt::{encrypt_share, EncryptError, PublicKey},
field::FieldElement,
polynomial::{poly_fft, PolyAuxMemory},
util::{proof_length, serialize, unpack_proof_mut, vector_with_length},
};

use std::convert::TryFrom;

Expand Down
8 changes: 0 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,3 @@ mod polynomial;
mod prng;
pub mod server;
pub mod util;

#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
9 changes: 4 additions & 5 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ impl<F: FieldElement> Server<F> {
&mut self,
eval_at: F,
share: &[u8],
) -> Option<VerificationMessage<F>> {
let share_field = self.deserialize_share(share).ok()?;
) -> Result<VerificationMessage<F>, ServerError> {
let share_field = self.deserialize_share(share)?;
generate_verification_message(
self.dimension,
eval_at,
Expand Down Expand Up @@ -182,7 +182,7 @@ pub fn generate_verification_message<F: FieldElement>(
proof: &[F],
is_first_server: bool,
mem: &mut ValidationMemory<F>,
) -> Option<VerificationMessage<F>> {
) -> Result<VerificationMessage<F>, ServerError> {
let unpacked = unpack_proof(proof, dimension)?;
let proof_length = 2 * (dimension + 1).next_power_of_two();

Expand Down Expand Up @@ -235,8 +235,7 @@ pub fn generate_verification_message<F: FieldElement>(
&mut mem.poly_mem.fft_memory,
);

let vm = VerificationMessage { f_r, g_r, h_r };
Some(vm)
Ok(VerificationMessage { f_r, g_r, h_r })
}

/// Decides if the distributed proof is valid
Expand Down
65 changes: 47 additions & 18 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ pub enum SerializeError {
/// element of the field.
#[error("last chunk of bytes is incomplete")]
IncompleteChunk,
/// Emitted by `unpack_proof[_mut]` if the serialized share+proof has the wrong length
#[error("serialized input has wrong length")]
UnpackInputSizeMismatch,
/// Finite field operation error.
#[error("finite field operation error")]
Field(#[from] FieldError),
Expand All @@ -34,6 +37,7 @@ pub fn vector_with_length<F: FieldElement>(len: usize) -> Vec<F> {
}

/// Unpacked proof with subcomponents
#[derive(Debug)]
pub struct UnpackedProof<'a, F: FieldElement> {
/// Data
pub data: &'a [F],
Expand All @@ -48,6 +52,7 @@ pub struct UnpackedProof<'a, F: FieldElement> {
}

/// Unpacked proof with mutable subcomponents
#[derive(Debug)]
pub struct UnpackedProofMut<'a, F: FieldElement> {
/// Data
pub data: &'a mut [F],
Expand All @@ -62,51 +67,53 @@ pub struct UnpackedProofMut<'a, F: FieldElement> {
}

/// Unpacks the proof vector into subcomponents
pub fn unpack_proof<F: FieldElement>(proof: &[F], dimension: usize) -> Option<UnpackedProof<F>> {
pub(crate) fn unpack_proof<F: FieldElement>(
proof: &[F],
dimension: usize,
) -> Result<UnpackedProof<F>, SerializeError> {
// check the proof length
if proof.len() != proof_length(dimension) {
return None;
return Err(SerializeError::UnpackInputSizeMismatch);
}
// split share into components
let (data, rest) = proof.split_at(dimension);
let (zero_terms, points_h_packed) = rest.split_at(3);
if let [f0, g0, h0] = zero_terms {
let unpacked = UnpackedProof {
if let ([f0, g0, h0], points_h_packed) = rest.split_at(3) {
Ok(UnpackedProof {
data,
f0,
g0,
h0,
points_h_packed,
};
Some(unpacked)
})
} else {
None
Err(SerializeError::UnpackInputSizeMismatch)
}
}

/// 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,
) -> Option<UnpackedProofMut<F>> {
) -> Result<UnpackedProofMut<F>, SerializeError> {
// check the share length
if proof.len() != proof_length(dimension) {
return None;
return Err(SerializeError::UnpackInputSizeMismatch);
}
// split share into components
let (data, rest) = proof.split_at_mut(dimension);
let (zero_terms, points_h_packed) = rest.split_at_mut(3);
if let [f0, g0, h0] = zero_terms {
let unpacked = UnpackedProofMut {
if let ([f0, g0, h0], points_h_packed) = rest.split_at_mut(3) {
Ok(UnpackedProofMut {
data,
f0,
g0,
h0,
points_h_packed,
};
Some(unpacked)
})
} else {
None
Err(SerializeError::UnpackInputSizeMismatch)
}
}

Expand Down Expand Up @@ -154,7 +161,8 @@ pub fn reconstruct_shares<F: FieldElement>(share1: &[F], share2: &[F]) -> Option
#[cfg(test)]
pub mod tests {
use super::*;
use crate::field::Field32;
use crate::field::{Field32, Field64};
use assert_matches::assert_matches;

pub fn secret_share(share: &mut [Field32]) -> Vec<Field32> {
use rand::Rng;
Expand All @@ -176,14 +184,35 @@ pub mod tests {
}

#[test]
fn test_unpack_share() {
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(SerializeError::UnpackInputSizeMismatch)
);
}

#[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(SerializeError::UnpackInputSizeMismatch)
);
}

#[test]
Expand Down
12 changes: 7 additions & 5 deletions tests/tweaks.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// Copyright (c) 2020 Apple Inc.
// SPDX-License-Identifier: MPL-2.0

use prio::client::*;
use prio::encrypt::*;
use prio::field::Field32;
use prio::server::*;
use prio::util::*;
use prio::{
client::Client,
encrypt::{decrypt_share, encrypt_share, PrivateKey, PublicKey},
field::Field32,
server::Server,
util::{deserialize, serialize, unpack_proof_mut, vector_with_length},
};

#[derive(Debug, Clone, Copy, PartialEq)]
enum Tweak {
Expand Down

0 comments on commit b68a16b

Please sign in to comment.