From ca0a72fe9a5720012d9b7e5ac64295d858bb2898 Mon Sep 17 00:00:00 2001 From: Maxim Urschumzew Date: Tue, 12 Sep 2023 13:58:54 +0200 Subject: [PATCH] Squashed commit of the following: commit 3d5f759325915cc16308cf5236661ab21064e177 Author: ovi Date: Fri Sep 8 17:57:46 2023 +0200 ordering ZCdpBudget commit d6a99859a069a75858aaeb35e8fd74531df2041c Author: ovi Date: Fri Sep 8 17:53:18 2023 +0200 ordering ZCdpDiscreteGaussians commit d2cdd4cb91863c538f0112dc12f4dc2048d9962b Author: ovi Date: Mon Sep 4 16:17:38 2023 +0200 non-pub epsilon commit cfef6a7644fe02f302cf0f99a5c8233959c4e6f9 Author: ovi Date: Mon Sep 4 15:07:01 2023 +0200 pub budget commit eae7e4e23168e913e631126edbb798d509b57c22 Author: ovi Date: Mon Sep 4 14:32:57 2023 +0200 Display for error commit 410427ed10b8942781b1a8730591af9528540c13 Author: ovi Date: Mon Sep 4 13:53:37 2023 +0200 FromStr for Rational commit 59f552219d0d2c5d8f26951bc8aab853671ee822 Author: ovi Date: Sun Sep 3 14:13:20 2023 +0200 Display Rational commit 3ac128d3cb9d3bfc6e0b39314e55a49cd7f5fd76 Author: ovi Date: Sun Sep 3 13:11:47 2023 +0200 trying a thing commit 42e6cad9a9744f1a61ee7b277b44a2904c10d64d Author: ovi Date: Sat Sep 2 03:07:45 2023 +0200 yet more derives commit d43961af9cf82d38fa99b82d0ff146b68ec101e9 Author: ovi Date: Sat Sep 2 01:39:16 2023 +0200 yet more derives commit 76d20d9db954913d6b8e492af0cc358a58582baf Author: Maxim Urschumzew Date: Thu Aug 31 08:59:19 2023 +0200 Add more derives. commit 7bced484dccc3e84f8e3defb41f305721c9f873a Author: Maxim Urschumzew Date: Thu Aug 31 08:53:04 2023 +0200 Add derive. commit fcdc568416bdd314496f108e1e38a7af1cb7b78a Author: Maxim Urschumzew Date: Tue Aug 29 11:51:53 2023 +0200 Add serialize for rational. commit bd41119c4c3b2d1a2bc363ba055d9cd99002a8f4 Author: Maxim Urschumzew Date: Sun Aug 27 18:25:33 2023 +0200 Add default impl for poplar. commit 243736496f466d530e5b2b8e389978efd0f4ea01 Author: Maxim Urschumzew Date: Sun Aug 27 18:21:15 2023 +0200 Add default implementations. commit 7c4546035e29f076b0069bd7c4ec2aff6b2c44ec Author: Maxim Urschumzew Date: Sun Aug 27 17:47:41 2023 +0200 Add default implementation for `TypeWithNoise`. commit e5bdff38027543820eb147f742302d8d1faafce0 Author: Maxim Urschumzew Date: Mon Aug 14 13:34:03 2023 +0200 Add differential privacy to `FixedPointBoundedL2VecSum` (#578). Co-Authored-By: Olivia Co-Authored-By: Maxim Urschumzew --- Cargo.lock | 1 + Cargo.toml | 2 +- src/dp.rs | 36 +++++++++++++++++++++++++++++++++++- src/dp/distributions.rs | 6 ++++-- src/flp/types.rs | 5 +++++ src/vdaf/poplar1.rs | 4 +++- 6 files changed, 49 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 830c4e26f..e4ce70174 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -694,6 +694,7 @@ dependencies = [ "num-bigint", "num-integer", "num-traits", + "serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 0020ce2ef..60e2362b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ hmac = { version = "0.12.1", optional = true } num-bigint = { version = "0.4.4", optional = true, features = ["rand", "serde"] } num-integer = { version = "0.1.45", optional = true } num-iter = { version = "0.1.43", optional = true } -num-rational = { version = "0.4.1", optional = true } +num-rational = { version = "0.4.1", optional = true, features = ["serde"] } num-traits = { version = "0.2.16", optional = true } rand = { version = "0.8", optional = true } rand_core = "0.6.4" diff --git a/src/dp.rs b/src/dp.rs index d51a7dffd..f00a51421 100644 --- a/src/dp.rs +++ b/src/dp.rs @@ -16,6 +16,8 @@ //! use num_bigint::{BigInt, BigUint, TryFromBigIntError}; use num_rational::{BigRational, Ratio}; +use serde::{Deserialize, Serialize}; +use std::{fmt, str::FromStr}; /// Errors propagated by methods in this module. #[derive(Debug, thiserror::Error)] @@ -38,9 +40,35 @@ pub enum DpError { /// Positive arbitrary precision rational number to represent DP and noise distribution parameters in /// protocol messages and manipulate them without rounding errors. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct Rational(Ratio); +impl fmt::Display for Rational { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +/// An error indicating a string could not be parsed as Rational. +#[derive(Debug)] +pub struct RationalParseError; + +impl fmt::Display for RationalParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "RationalParseError") + } +} + +impl FromStr for Rational { + type Err = RationalParseError; + fn from_str(s: &str) -> Result { + match Ratio::::from_str(s) { + Ok(r) => Ok(Rational(r)), + Err(_) => Err(RationalParseError), + } + } +} + impl Rational { /// Construct a [`Rational`] number from numerator `n` and denominator `d`. Errors if denominator is zero. pub fn from_unsigned(n: T, d: T) -> Result @@ -83,6 +111,7 @@ pub trait DifferentialPrivacyDistribution {} /// Zero-concentrated differential privacy (ZCDP) budget as defined in [[BS16]]. /// /// [BS16]: https://arxiv.org/pdf/1605.02065.pdf +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Ord, PartialOrd)] pub struct ZCdpBudget { epsilon: Ratio, } @@ -95,6 +124,11 @@ impl ZCdpBudget { pub fn new(epsilon: Rational) -> Self { Self { epsilon: epsilon.0 } } + + /// Return the `epsilon` parameter of this strategy. + pub fn get_epsilon(&self) -> Rational { + Rational(self.epsilon.clone()) + } } impl DifferentialPrivacyBudget for ZCdpBudget {} diff --git a/src/dp/distributions.rs b/src/dp/distributions.rs index d3fdf035a..51e0315d2 100644 --- a/src/dp/distributions.rs +++ b/src/dp/distributions.rs @@ -56,6 +56,7 @@ use num_iter::range_inclusive; use num_rational::Ratio; use num_traits::{One, Zero}; use rand::{distributions::uniform::UniformSampler, distributions::Distribution, Rng}; +use serde::{Deserialize, Serialize}; use super::{ DifferentialPrivacyBudget, DifferentialPrivacyDistribution, DifferentialPrivacyStrategy, @@ -252,11 +253,12 @@ impl Distribution for DiscreteGaussian { impl DifferentialPrivacyDistribution for DiscreteGaussian {} /// A DP strategy using the discrete gaussian distribution. +#[derive(Clone, PartialEq, Serialize, Deserialize, Eq, Debug, Ord, PartialOrd)] pub struct DiscreteGaussianDpStrategy where - B: DifferentialPrivacyBudget, + B: DifferentialPrivacyBudget + std::fmt::Debug, { - budget: B, + pub budget: B, } /// A DP strategy using the discrete gaussian distribution providing zero-concentrated DP. diff --git a/src/flp/types.rs b/src/flp/types.rs index 18c290355..341c29376 100644 --- a/src/flp/types.rs +++ b/src/flp/types.rs @@ -2,6 +2,9 @@ //! A collection of [`Type`] implementations. + +#[cfg(feature = "experimental")] +use crate::dp::distributions::ZCdpDiscreteGaussian; use crate::field::{FftFriendlyFieldElement, FieldElementWithIntegerExt}; use crate::flp::gadgets::{Mul, ParallelSumGadget, PolyEval}; use crate::flp::{FlpError, Gadget, Type}; @@ -9,6 +12,7 @@ use crate::polynomial::poly_range_check; use std::convert::TryInto; use std::fmt::{self, Debug}; use std::marker::PhantomData; + /// The counter data type. Each measurement is `0` or `1` and the aggregate result is the sum of the measurements (i.e., the total number of `1s`). #[derive(Clone, PartialEq, Eq)] pub struct Count { @@ -569,6 +573,7 @@ impl Clone for SumVec { } } + impl Type for SumVec where F: FftFriendlyFieldElement, diff --git a/src/vdaf/poplar1.rs b/src/vdaf/poplar1.rs index 727e6f739..cd653bd97 100644 --- a/src/vdaf/poplar1.rs +++ b/src/vdaf/poplar1.rs @@ -12,7 +12,7 @@ use crate::{ vdaf::{ xof::{Seed, Xof, XofShake128}, Aggregatable, Aggregator, Client, Collector, PrepareTransition, Vdaf, VdafError, - }, + }, dp::distributions::ZCdpDiscreteGaussian, }; use bitvec::{prelude::Lsb0, vec::BitVec}; use rand_core::RngCore; @@ -27,6 +27,8 @@ use std::{ }; use subtle::{Choice, ConditionallyNegatable, ConditionallySelectable, ConstantTimeEq}; +use super::AggregatorWithNoise; + const DST_SHARD_RANDOMNESS: u16 = 1; const DST_CORR_INNER: u16 = 2; const DST_CORR_LEAF: u16 = 3;