Closed MxmUrw closed 10 months ago
Aggregator
with AggregatorWithNoise
roughly everywhere that calls (directly or indirectly) into compute_aggregate_share
, correct? How would we deal with VDAFs that don't support DP at all -- a blanked implementation of AggregatorWithNoise
for NoDpStrategy
?To be clear, we would need to replace
Aggregator
withAggregatorWithNoise
roughly everywhere that calls (directly or indirectly) intocompute_aggregate_share
, correct?
Yes, though it seems at first glance that no indirect calls need to be replaced! The only calls into compute_aggregate_share
happen in aggregator::handle_aggregate_share_generic
and collection_job_driver::step_collection_job_generic
. In both cases the Aggregator
type parameter comes from the vdaf_dispatch!
macro, which means that it is "locally generated".
Note that currently compute_aggregate_share
does not take an argument of type Aggregator
, so in practice we either would have to add an AggregatorWithNoise
argument, or instead write our own function which is going to be called directly after compute_aggregate_share
at both call-sites I mentioned above.
How would we deal with VDAFs that don't support DP at all -- a blanked implementation of AggregatorWithNoise for NoDpStrategy?
Correct, any VDAF which doesn't support DP would need to implement AggregatorWithNoise<_,_,NoDpStrategy>
. EDIT: And yes, the implementation would essentially be the identity function.
We have implemented approach 1 here: #1892. Personally I think it fits quite well with the current janus architecture. See that PR for a summary of changes, comments welcome!
The related PRs have landed across libprio and Janus. I don't believe there's any further work to do here so I'm going to close. Maxim, Olivia, please feel free to re-open if there's more you want to discuss here.
Since https://github.com/divviup/libprio-rs/pull/578 is now merged, I would like to start the discussion about how to integrate dp into janus:
The architectural additions from that PR amount to:
which inherits from
Aggregator
but additionally takes a DP strategy as type parameter. It requires the following method to be implemented:This method has to be called from janus by both leader and helper, on aggregate shares, with an appropriate
dp_strategy
argument.ZCdpDiscreteGaussian
orApproximateDpLaplace
. Different VDAFs may choose to support different DP strategies. The runtime representation of a strategy is its budget, also called the privacy parameter(s). For example, the concept of zCDP-differential privacy has a single parameter $\epsilon$, while approximate differential privacy has two, $\epsilon$ and $\delta$.What I think we need to do is:
Task
with a field for DP strategy. Since implementers of theDPStrategy
trait are distinct types, we need to combine them into an enum, similar to howVdafOps
can contain any vdaf.add_noise_to_agg_share
needs to be done somewhere in janus after summing the shares. @tgeoghegan suggested to do it inaggregator::aggregate_share::compute_aggregate_share
.Question
The main question I have right now is: How do we dispatch the
add_noise_to_agg_share
call correctly?I see two possible approaches:
Aggregator<K,N>
byAggregatorWithNoise<K,N,S>
. Relevant places would includehandle_aggregate_share_generic
. Then the strategy parameter would be handled similarly to theVERIFY_KEY_SIZE
andNONCE_SIZE
parameters, and dispatch could be mostly handled by thevdaf_ops!
macro. This means that if a VDAF wanted to implement two different DP strategies, there would be one enum variant for each strategy. I assume that usually there is one preferable way to do dp for a given aggregation, so the dispatch blow-up should be minimal. Another consequence is that every VDAF would have to support at least one DP strategy. Thus we would create aNoDpStrategy
for VDAFs which do not need dp.AggregatorWithNoise
and instances ofDPStrategy
. I am not sure how this would exactly look like, but this would allowAggregatorWithNoise
to be opt-in, with VDAFs only having to implement it if they do need dp.Note that in both cases there has to be code which forwards the user chosen DP strategy (runtime enum value) to the
AggregatorWithNoise
(compiletime type), and throws an error if this particular strategy is not implemented by that VDAF. (This is implied by both approaches above, but I wanted to make it explicit.)Comments? Opinions?