-
Notifications
You must be signed in to change notification settings - Fork 30
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
API changes for Aggregator-side differential privacy #607
Conversation
src/vdaf/prio2.rs
Outdated
@@ -21,7 +21,6 @@ use std::{ | |||
convert::{TryFrom, TryInto}, | |||
io::Cursor, | |||
}; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: please back out the unrelated whitespace changes in this directory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- nit: Block comments should break lines at 100 characters, for consistency.
8ba9d5e
to
f16ef97
Compare
We have a remark regarding the name Usually, the privacy budget is calculated by summing up the privacy parameters of each round, which makes the distinction somewhat vacuous - the privacy parameter is effectively just the privacy budget of a single differentially private mechanism. We would be happy to leave the code as is, but wanted to give a heads-up regarding this. Of course, I assume there might be communities where using the term "budget" is more customary? |
Thinking further about the discussed direction for this PR, we concluded the following:
As a sketch, this might look as follows: // We need a trait which inherits from `rand::Distribution`
trait ParametrizedDistribution<DPBudget : DifferentialPrivacyBudget> : Distribution<BigInt>
{
fn new_with_budget(budget: DPBudget, sensitivity: Rational) -> Self;
} And the pub trait AggregatorWithNoise<DPBudget, PDistribution>: Aggregator
where
DPBudget: DifferentialPrivacyBudget,
PDistribution: ParametrizedDistribution<DPBudget>,
{
/// Adds noise to an aggregate share such that the aggregate result
/// is `DPBudget`-differentially private as long as one Aggregator is honest.
fn add_noise_to_agg_share(
&self,
budget: &DPBudget,
agg_param: &Self::AggregationParam,
agg_share: &mut Self::AggregateShare,
num_measurements: usize,
) -> Result<(), VdafError>;
} Then implementations of |
I like this proposal @MxmUrw. One concern I have is that your sketch hardcodes the type of the distribution to be Another note: Regarding the name: I tend to use "privacy budget" more often than "privacy parameters" (as do some practitioners like this survey, the Programming DP book or even theory papers like the RDP definition). Both terms seem pretty interchangeable. I just like the concrete feel of "budget" compared to generic "parameters" that could represent many things for the non-expert. I agree that "privacy parameters" might be more widespread though, so I don't have strong feelings. Edit: here is how an implementation could look like impl DifferentialPrivacyDistribution<ZeroConcentratedDifferentialPrivacyBudget, BigInt>
for DiscreteGaussian
{
/// Uses Theorem 4 from [[CKS20]]
///
/// [CKS20]: https://arxiv.org/pdf/2004.00010.pdf
fn from(
privacy_budget: &ZeroConcentratedDifferentialPrivacyBudget,
sensitivity: Rational,
) -> Self {
let sigma = Rational {
numerator: privacy_budget.epsilon.denominator * sensitivity.numerator,
denominator: privacy_budget.epsilon.numerator * sensitivity.denominator,
};
Self { sigma }
}
} |
@MxmUrw @ooovi @divergentdave do you have more changes to suggest? If not, I can rebase and squash so you can merge. |
Looks good to us! I think parametrizing over |
I would prefer that we take the correspondence from DP budgets to DP noise distributions out of the type system. As a motivating thought experiment, if noise needs to be non-identically distributed for some future combination of DP budget and VDAF, then we could still write all the code needed to do so by ignoring With the current trait definitions, we would need to specify So long as our conception of the |
If I understand correctly, this means that it would become unpractical to implement VDAFs generically over the choice of distribution. That is, the VDAF would hard-code the choice of distribution in OTOH, it may not be necessary for the EDIT: I am sympathetic with the rest of the argument, I think this is just a matter of figuring out the proper parametrization. I do agree that |
Yes. For instance,
Let me try to summarize some desired properties (they might not be all required, actually 1 and 3 seem incompatible):
And I think that we have two solutions:
|
The Regarding non-i.i.d. noise, I was only considering sampling noise from multiple distributions of the same kind, i.e. two different discrete Gaussian distributions for a VDAF that computes both a sum and a sum of squares. (not combining discrete Gaussian and Laplace) Thus, a |
Ah indeed, this would be a realistic VDAF, and it's unclear if we can build it with The new implementation should be extensible enough to support non i.i.d VDAFs or other changes, and does static dispatch. The drawback is that we might have to implement multiple combinations of accounting methods & distributions, as @MxmUrw pointed out. An alternative would be to pass a |
src/dp.rs
Outdated
/// | ||
/// [CKS20]: https://arxiv.org/pdf/2004.00010.pdf | ||
pub fn create_distribution( | ||
budget: ZeroConcentratedDifferentialPrivacyBudget, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this could take a reference instead
budget: ZeroConcentratedDifferentialPrivacyBudget, | |
budget: &ZeroConcentratedDifferentialPrivacyBudget, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
@divergentdave @tgeoghegan is there anything else I can do before merging? Thank you! |
src/dp.rs
Outdated
numerator: u32, | ||
denominator: u32, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If these aren't pub
then there's no way to construct a Rational
from outside the crate. Additionally, if there are any restrictions on what a valid Rational
is (for instance, is it OK for numerator > denominator
?) then we should provide a constructor that enforces that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed. I actually had a constructor but we removed it since it wasn't used. We don't have any constraint on the fields, so I'll just stick to public fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me!
- AggregatorWithNoise trait with a method to add noise - DifferentialPrivacyStrategy trait to represent budgets and distributions - Partial example with DiscreteGaussian and ZeroConcentratedDifferentialPrivacy
As discussed yesterday, this PR makes some API changes required to add DP on aggregated shares (aka Server-DP, following the terminology from DPrio (https://petsymposium.org/popets/2023/popets-2023-0086.php). Once we settle on an API we can tackle DP implementations for specific VDAFs, such as #578.
cc/ @cjpatton