diff --git a/Cargo.toml b/Cargo.toml index ffdbd48cd..8628a13b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,6 @@ zipf = "7.0.1" default = ["crypto-dependencies"] experimental = ["bitvec", "fiat-crypto", "fixed", "num-bigint", "num-rational", "num-traits", "num-integer", "num-iter", "rand"] multithreaded = ["rayon"] -prio2 = ["crypto-dependencies"] crypto-dependencies = ["aes", "ctr", "hmac", "sha2"] test-util = ["hex", "rand", "serde_json"] diff --git a/README.md b/README.md index 5d9541bad..e2390f25b 100644 --- a/README.md +++ b/README.md @@ -75,4 +75,3 @@ This crate defines the following feature flags: |`crypto-dependencies`|Yes|Enables dependencies on various RustCrypto crates, and uses them to implement `XofTurboShake128` to support VDAFs.| |`experimental`|No|Certain experimental APIs are guarded by this feature. They may undergo breaking changes in future patch releases, as an exception to semantic versioning.| |`multithreaded`|No|Enables certain Prio3 VDAF implementations that use `rayon` for parallelization of gadget evaluations.| -|`prio2`|No|Enables the Prio v2 API, and a VDAF based on the Prio2 system.| diff --git a/benches/cycle_counts.rs b/benches/cycle_counts.rs index 0bac3a7fd..5ab704cd4 100644 --- a/benches/cycle_counts.rs +++ b/benches/cycle_counts.rs @@ -5,15 +5,12 @@ use iai::black_box; #[cfg(feature = "experimental")] use prio::{ codec::{Decode, Encode, ParameterizedDecode}, - field::{Field255, FieldElement}, + field::{Field255, FieldElement, FieldPrio2}, idpf::{Idpf, IdpfInput, IdpfPublicShare, RingBufferCache}, - vdaf::{poplar1::Poplar1IdpfValue, xof::Seed}, -}; -#[cfg(feature = "prio2")] -use prio::{ - field::FieldPrio2, vdaf::{ + poplar1::Poplar1IdpfValue, prio2::{Prio2, Prio2PrepareShare}, + xof::Seed, Aggregator, Share, }, }; @@ -45,7 +42,7 @@ fn prng_4096() -> Vec { prng(4096) } -#[cfg(feature = "prio2")] +#[cfg(feature = "experimental")] fn prio2_client(size: usize) -> Vec> { let prio2 = Prio2::new(size).unwrap(); let input = vec![0u32; size]; @@ -53,22 +50,22 @@ fn prio2_client(size: usize) -> Vec> { prio2.shard(&black_box(input), &black_box(nonce)).unwrap().1 } -#[cfg(feature = "prio2")] +#[cfg(feature = "experimental")] fn prio2_client_10() -> Vec> { prio2_client(10) } -#[cfg(feature = "prio2")] +#[cfg(feature = "experimental")] fn prio2_client_100() -> Vec> { prio2_client(100) } -#[cfg(feature = "prio2")] +#[cfg(feature = "experimental")] fn prio2_client_1000() -> Vec> { prio2_client(1000) } -#[cfg(feature = "prio2")] +#[cfg(feature = "experimental")] fn prio2_shard_and_prepare(size: usize) -> Prio2PrepareShare { let prio2 = Prio2::new(size).unwrap(); let input = vec![0u32; size]; @@ -80,17 +77,17 @@ fn prio2_shard_and_prepare(size: usize) -> Prio2PrepareShare { .1 } -#[cfg(feature = "prio2")] +#[cfg(feature = "experimental")] fn prio2_shard_and_prepare_10() -> Prio2PrepareShare { prio2_shard_and_prepare(10) } -#[cfg(feature = "prio2")] +#[cfg(feature = "experimental")] fn prio2_shard_and_prepare_100() -> Prio2PrepareShare { prio2_shard_and_prepare(100) } -#[cfg(feature = "prio2")] +#[cfg(feature = "experimental")] fn prio2_shard_and_prepare_1000() -> Prio2PrepareShare { prio2_shard_and_prepare(1000) } @@ -261,34 +258,10 @@ macro_rules! main_base { }; } -#[cfg(feature = "prio2")] -macro_rules! main_add_prio2 { - ( $( $func_name:ident ),* $(,)* ) => { - main_base!( - prio2_client_10, - prio2_client_100, - prio2_client_1000, - prio2_shard_and_prepare_10, - prio2_shard_and_prepare_100, - prio2_shard_and_prepare_1000, - $( $func_name, )* - ); - }; -} - -#[cfg(not(feature = "prio2"))] -macro_rules! main_add_prio2 { - ( $( $func_name:ident ),* $(,)* ) => { - main_base!( - $( $func_name, )* - ); - }; -} - #[cfg(feature = "multithreaded")] macro_rules! main_add_multithreaded { ( $( $func_name:ident ),* $(,)* ) => { - main_add_prio2!( + main_base!( prio3_client_count_vec_multithreaded_1000, $( $func_name, )* ); @@ -298,7 +271,7 @@ macro_rules! main_add_multithreaded { #[cfg(not(feature = "multithreaded"))] macro_rules! main_add_multithreaded { ( $( $func_name:ident ),* $(,)* ) => { - main_add_prio2!( + main_base!( $( $func_name, )* ); }; @@ -308,6 +281,12 @@ macro_rules! main_add_multithreaded { macro_rules! main_add_experimental { ( $( $func_name:ident ),* $(,)* ) => { main_add_multithreaded!( + prio2_client_10, + prio2_client_100, + prio2_client_1000, + prio2_shard_and_prepare_10, + prio2_shard_and_prepare_100, + prio2_shard_and_prepare_1000, idpf_codec, idpf_poplar_gen_8, idpf_poplar_gen_128, diff --git a/benches/speed_tests.rs b/benches/speed_tests.rs index 78b9ffabc..f10ef5c83 100644 --- a/benches/speed_tests.rs +++ b/benches/speed_tests.rs @@ -15,7 +15,7 @@ use num_rational::Ratio; use num_traits::ToPrimitive; #[cfg(feature = "experimental")] use prio::dp::distributions::DiscreteGaussian; -#[cfg(feature = "prio2")] +#[cfg(feature = "experimental")] use prio::vdaf::prio2::Prio2; use prio::{ benchmarked::*, @@ -116,7 +116,7 @@ fn poly_mul(c: &mut Criterion) { } /// Benchmark prio2. -#[cfg(feature = "prio2")] +#[cfg(feature = "experimental")] fn prio2(c: &mut Criterion) { let mut group = c.benchmark_group("prio2_shard"); for input_length in [10, 100, 1_000] { @@ -864,13 +864,9 @@ fn poplar1_generate_zipf_distributed_batch( (samples, prefix_tree) } -#[cfg(all(feature = "prio2", feature = "experimental"))] +#[cfg(feature = "experimental")] criterion_group!(benches, poplar1, prio3, prio2, poly_mul, prng, idpf, dp_noise); -#[cfg(all(not(feature = "prio2"), feature = "experimental"))] -criterion_group!(benches, poplar1, prio3, poly_mul, prng, idpf, dp_noise); -#[cfg(all(feature = "prio2", not(feature = "experimental")))] -criterion_group!(benches, prio3, prio2, prng, poly_mul); -#[cfg(all(not(feature = "prio2"), not(feature = "experimental")))] +#[cfg(not(feature = "experimental"))] criterion_group!(benches, prio3, prng, poly_mul); criterion_main!(benches); diff --git a/binaries/Cargo.toml b/binaries/Cargo.toml index fa11ab488..87c78a18a 100644 --- a/binaries/Cargo.toml +++ b/binaries/Cargo.toml @@ -10,4 +10,4 @@ repository = "https://github.com/divviup/libprio-rs" base64 = "0.21.6" fixed = "1.23" fixed-macro = "1.2.0" -prio = { path = "..", features = ["prio2", "experimental"] } +prio = { path = "..", features = ["experimental"] } diff --git a/src/flp.rs b/src/flp.rs index f2dc85a86..5fd956155 100644 --- a/src/flp.rs +++ b/src/flp.rs @@ -545,6 +545,7 @@ pub trait Type: Sized + Eq + Clone + Debug { /// A type which supports adding noise to aggregate shares for Server Differential Privacy. #[cfg(feature = "experimental")] +#[cfg_attr(docsrs, doc(cfg(feature = "experimental")))] pub trait TypeWithNoise: Type where S: DifferentialPrivacyStrategy, @@ -749,11 +750,13 @@ pub(crate) fn gadget_poly_len(gadget_degree: usize, wire_poly_len: usize) -> usi /// Utilities for testing FLPs. #[cfg(feature = "test-util")] +#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))] pub mod test_utils { use super::*; use crate::field::{random_vector, FieldElement, FieldElementWithInteger}; /// Various tests for an FLP. + #[cfg_attr(docsrs, doc(cfg(feature = "test-util")))] pub struct FlpTest<'a, T: Type> { /// The FLP. pub flp: &'a T, diff --git a/src/lib.rs b/src/lib.rs index c9d4e22c4..deb9bc102 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,7 @@ pub mod benchmarked; pub mod codec; #[cfg(feature = "experimental")] +#[cfg_attr(docsrs, doc(cfg(feature = "experimental")))] pub mod dp; mod fft; pub mod field; diff --git a/src/polynomial.rs b/src/polynomial.rs index 89d8a9140..272266f53 100644 --- a/src/polynomial.rs +++ b/src/polynomial.rs @@ -3,7 +3,7 @@ //! Functions for polynomial interpolation and evaluation -#[cfg(feature = "prio2")] +#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] use crate::fft::{discrete_fourier_transform, discrete_fourier_transform_inv_finish}; use crate::field::FftFriendlyFieldElement; @@ -204,7 +204,7 @@ pub fn poly_mul(p: &[F], q: &[F]) -> Vec { out } -#[cfg(feature = "prio2")] +#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] #[inline] pub fn poly_interpret_eval( points: &[F], diff --git a/src/prng.rs b/src/prng.rs index 0a0c796c9..2c3f5b664 100644 --- a/src/prng.rs +++ b/src/prng.rs @@ -6,7 +6,7 @@ //! NOTE: The public API for this module is a work in progress. use crate::field::{FieldElement, FieldElementExt}; -#[cfg(feature = "prio2")] +#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] use crate::vdaf::xof::SeedStreamAes128; use crate::vdaf::xof::{Seed, SeedStreamTurboShake128, Xof, XofTurboShake128}; use rand_core::RngCore; @@ -35,7 +35,7 @@ pub(crate) struct Prng { buffer_index: usize, } -#[cfg(feature = "prio2")] +#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] impl Prng { /// Create a [`Prng`] from a seed for Prio 2. The first 16 bytes of the seed and the last 16 /// bytes of the seed are used, respectively, for the key and initialization vector for AES128 @@ -131,21 +131,19 @@ where mod tests { use super::*; #[cfg(feature = "experimental")] - use crate::field::Field128; - #[cfg(feature = "prio2")] - use crate::field::{encode_fieldvec, FieldPrio2}; + use crate::field::{encode_fieldvec, Field128, FieldPrio2}; use crate::{ codec::Decode, field::Field64, vdaf::xof::{Seed, SeedStreamTurboShake128, Xof, XofTurboShake128}, }; - #[cfg(feature = "prio2")] + #[cfg(feature = "experimental")] use base64::{engine::Engine, prelude::BASE64_STANDARD}; - #[cfg(feature = "prio2")] + #[cfg(feature = "experimental")] use sha2::{Digest, Sha256}; #[test] - #[cfg(feature = "prio2")] + #[cfg(feature = "experimental")] fn secret_sharing_interop() { let seed = [ 0xcd, 0x85, 0x5b, 0xd4, 0x86, 0x48, 0xa4, 0xce, 0x52, 0x5c, 0x36, 0xee, 0x5a, 0x71, @@ -167,7 +165,7 @@ mod tests { } /// takes a seed and hash as base64 encoded strings - #[cfg(feature = "prio2")] + #[cfg(feature = "experimental")] fn random_data_interop(seed_base64: &str, hash_base64: &str, len: usize) { let seed = BASE64_STANDARD.decode(seed_base64).unwrap(); let random_data = extract_share_from_seed::(len, &seed); @@ -175,14 +173,14 @@ mod tests { let mut random_bytes = Vec::new(); encode_fieldvec(&random_data, &mut random_bytes).unwrap(); - let mut hasher = Sha256::new(); + let mut hasher = ::new(); hasher.update(&random_bytes); let digest = hasher.finalize(); assert_eq!(BASE64_STANDARD.encode(digest), hash_base64); } #[test] - #[cfg(feature = "prio2")] + #[cfg(feature = "experimental")] fn test_hash_interop() { random_data_interop( "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=", @@ -216,7 +214,7 @@ mod tests { ); } - #[cfg(feature = "prio2")] + #[cfg(feature = "experimental")] fn extract_share_from_seed(length: usize, seed: &[u8]) -> Vec { assert_eq!(seed.len(), 32); Prng::from_prio2_seed(seed.try_into().unwrap()) diff --git a/src/vdaf.rs b/src/vdaf.rs index 610ca571e..8c9fd9afd 100644 --- a/src/vdaf.rs +++ b/src/vdaf.rs @@ -72,18 +72,6 @@ pub enum Share { Helper(Seed), } -impl Share { - /// Truncate the Leader's share to the given length. If this is the Helper's share, then this - /// method clones the input without modifying it. - #[cfg(feature = "prio2")] - pub(crate) fn truncated(&self, len: usize) -> Self { - match self { - Self::Leader(ref data) => Self::Leader(data[..len].to_vec()), - Self::Helper(ref seed) => Self::Helper(seed.clone()), - } - } -} - impl PartialEq for Share { fn eq(&self, other: &Self) -> bool { self.ct_eq(other).into() @@ -300,6 +288,7 @@ pub trait Aggregator: Vda /// Aggregator that implements differential privacy with Aggregator-side noise addition. #[cfg(feature = "experimental")] +#[cfg_attr(docsrs, doc(cfg(feature = "experimental")))] pub trait AggregatorWithNoise< const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize, @@ -712,6 +701,7 @@ mod tests { } #[cfg(feature = "test-util")] +#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))] pub mod dummy; #[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] #[cfg_attr( @@ -719,10 +709,14 @@ pub mod dummy; doc(cfg(all(feature = "crypto-dependencies", feature = "experimental"))) )] pub mod poplar1; -#[cfg(feature = "prio2")] -#[cfg_attr(docsrs, doc(cfg(feature = "prio2")))] +#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] +#[cfg_attr( + docsrs, + doc(cfg(all(feature = "crypto-dependencies", feature = "experimental"))) +)] pub mod prio2; pub mod prio3; #[cfg(any(test, feature = "test-util"))] +#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))] pub mod prio3_test; pub mod xof; diff --git a/src/vdaf/prio2.rs b/src/vdaf/prio2.rs index 081980c4b..c34f92e64 100644 --- a/src/vdaf/prio2.rs +++ b/src/vdaf/prio2.rs @@ -88,8 +88,13 @@ impl Prio2 { ) .map_err(|e| VdafError::Uncategorized(e.to_string()))?; + let truncated_share = match input_share { + Share::Leader(data) => Share::Leader(data[..self.input_len].to_vec()), + Share::Helper(seed) => Share::Helper(seed.clone()), + }; + Ok(( - Prio2PrepareState(input_share.truncated(self.input_len)), + Prio2PrepareState(truncated_share), Prio2PrepareShare(verifier_share), )) } diff --git a/src/vdaf/prio3_test.rs b/src/vdaf/prio3_test.rs index 4a6931fcd..9a3dfd85f 100644 --- a/src/vdaf/prio3_test.rs +++ b/src/vdaf/prio3_test.rs @@ -194,6 +194,7 @@ where /// This version allows customizing the deserialization of measurements, via an additional type /// parameter. #[cfg(feature = "test-util")] +#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))] pub fn check_test_vec_custom_de( test_vec_json_str: &str, new_vdaf: impl Fn(&HashMap, u8) -> Prio3, @@ -213,6 +214,7 @@ pub fn check_test_vec_custom_de( /// Evaluate a Prio3 test vector. The instance of Prio3 is constructed from the `new_vdaf` callback, /// which takes in the VDAF parameters encoded by the test vectors and the number of shares. #[cfg(feature = "test-util")] +#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))] pub fn check_test_vec( test_vec_json_str: &str, new_vdaf: impl Fn(&HashMap, u8) -> Prio3, diff --git a/src/vdaf/xof.rs b/src/vdaf/xof.rs index 61bf1a7a0..67881419d 100644 --- a/src/vdaf/xof.rs +++ b/src/vdaf/xof.rs @@ -452,6 +452,7 @@ impl RngCore for SeedStreamFixedKeyAes128 { /// XOF based on HMAC-SHA256 and AES128. This XOF is not part of the VDAF spec. #[cfg(feature = "crypto-dependencies")] +#[cfg_attr(docsrs, doc(cfg(feature = "crypto-dependencies")))] #[derive(Clone, Debug)] pub struct XofHmacSha256Aes128(Hmac);