Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
cjpatton committed Jun 22, 2022
1 parent b870e80 commit f2833bd
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 33 deletions.
67 changes: 38 additions & 29 deletions draft-irtf-cfrg-vdaf.md
Original file line number Diff line number Diff line change
Expand Up @@ -473,10 +473,11 @@ In order to protect the privacy of its measurements, a DAF Client shards its
measurements into a sequence of input shares. The `measurement_to_input_shares`
method is used for this purpose.

* `Daf.measurement_to_input_shares(input: Measurement) -> Vec[Bytes]` is the
randomized input-distribution algorithm run by each Client. It consumes the
measurement and produces a sequence of input shares, one for each Aggregator.
The length of the output vector MUST be `SHARES`.
* `Daf.measurement_to_input_shares(input: Measurement) -> (Bytes, Vec[Bytes])`
is the randomized input-distribution algorithm run by each Client. It consumes
the measurement and produces a "public share", distributed to each of the
Aggregators, and a corresponding eequence of input shares, one for each
Aggregator. The length of the output vector MUST be `SHARES`.

~~~~
Client
Expand All @@ -500,14 +501,15 @@ distributes them to the Aggregators."}

## Preparation {#sec-daf-prepare}

Once an Aggregator has received an input share form a Client, the next step is
to prepare the input share for aggregation. This is accomplished using the
following algorithm:
Once an Aggregator has received the public share and one of the input shares,
the next step is to prepare the input share for aggregation. This is
accomplished using the following algorithm:

* `Daf.prep(agg_id: Unsigned, agg_param: AggParam, input_share: Bytes) ->
OutShare` is the deterministic preparation algorithm. It takes as input an
input share generated by a Client, the Aggregator's unique identifier, and the
aggregation parameter selected by the Collector and returns an output share.
* `Daf.prep(agg_id: Unsigned, agg_param: AggParam, public_share: Bytes,
input_share: Bytes) -> OutShare` is the deterministic preparation algorithm.
It takes as input the public share and one of the input shares generated by a
Client, the Aggregator's unique identifier, and the aggregation parameter
selected by the Collector and returns an output share.

The protocol in which the DAF is used MUST ensure that the Aggregator's
identifier is equal to the integer in range `[0, SHARES)` that matches the index
Expand Down Expand Up @@ -605,12 +607,13 @@ def run_daf(Daf,
for measurement in measurements:
# Each Client shards its measurement into input shares and
# distributes them among the Aggregators.
input_shares = Daf.measurement_to_input_shares(measurement)
(public_share, input_shares) = \
Daf.measurement_to_input_shares(measurement)

# Each Aggregator prepares its input share for aggregation.
for j in range(Daf.SHARES):
out_shares[j].append(
Daf.prep(j, agg_param, input_shares[j]))
Daf.prep(j, agg_param, public_share, input_shares[j]))

# Each Aggregator aggregates its output shares into an aggregate
# share and it to the Collector.
Expand Down Expand Up @@ -694,12 +697,14 @@ other quantities are given a concrete type.

Sharding is syntactically identical to DAFs (cf. {{sec-daf-shard}}):

* `Vdaf.measurement_to_input_shares(measurement: Measurement) -> Vec[Bytes]` is
the randomized input-distribution algorithm run by each Client. It consumes
the measurement and produces a sequence of input shares, one for each
Aggregator. Depending on the VDAF, the input shares may encode additional
information used to verify the recovered output shares (e.g., the "proof
shares" in Prio3 {{prio3}}). The length of the output vector MUST be `SHARES`.
* `Vdaf.measurement_to_input_shares(measurement: Measurement) -> (Bytes,
Vec[Bytes])` is the randomized input-distribution algorithm run by each
Client. It consumes the measurement and produces a public share, distributed
to each of Aggregators, and the corresponding sequence of input shares, one
for each Aggregator. Depending on the VDAF, the input shares may encode
additional information used to verify the recovered output shares (e.g., the
"proof shares" in Prio3 {{prio3}}). The length of the output vector MUST be
`SHARES`.

## Preparation {#sec-vdaf-prepare}

Expand Down Expand Up @@ -761,14 +766,14 @@ To facilitate the preparation process, a concrete VDAF implements the following
class methods:

* `Vdaf.prep_init(verify_key: Bytes, agg_id: Unsigned, agg_param: AggParam,
nonce: Bytes, input_share: Bytes) -> Prep` is the deterministic
preparation-state initialization algorithm run by each Aggregator to begin
processing its input share into an output share. Its inputs are the shared
verification key (`verify_key`), the Aggregator's unique identifier
(`agg_id`), the aggregation parameter (`agg_param`), the nonce provided by the
environment (`nonce`, see {{run-vdaf}}), and one of the input shares generated
by the client (`input_share`). Its output is the Aggregator's initial
preparation state.
nonce: Bytes, public_share: Bytes, input_share: Bytes) -> Prep` is the
deterministic preparation-state initialization algorithm run by each
Aggregator to begin processing its input share into an output share. Its
inputs are the shared verification key (`verify_key`), the Aggregator's unique
identifier (`agg_id`), the aggregation parameter (`agg_param`), the nonce
provided by the environment (`nonce`, see {{run-vdaf}}), and the public share
(`public_share`) and one of the input shares generated by the client
(`input_share`). Its output is the Aggregator's initial preparation state.

The length of `verify_key` MUST be `VERIFY_KEY_SIZE`. It is up to the high
level protocol in which the VDAF is used to arrange for the distribution of
Expand All @@ -780,7 +785,9 @@ class methods:

Protocols using the VDAF MUST ensure that the Aggregator's identifier is equal
to the integer in range `[0, SHARES)` that matches the index of `input_share`
in the sequence of input shares output by the Client.
in the sequence of input shares output by the Client. In addition, protocols
MUST ensure that public share consumed by each of the Aggregators is
identical. See {{security}} for details.

* `Vdaf.prep_next(prep: Prep, inbound: Optional[Bytes]) -> Union[Tuple[Prep,
Bytes], OutShare]` is the deterministic preparation-state update algorithm run
Expand Down Expand Up @@ -869,14 +876,16 @@ def run_vdaf(Vdaf,
out_shares = []
for (nonce, measurement) in zip(nonces, measurements):
# Each Client shards its measurement into input shares.
input_shares = Vdaf.measurement_to_input_shares(measurement)
(public_share, input_shares) = \
Vdaf.measurement_to_input_shares(measurement)

# Each Aggregator initializes its preparation state.
prep_states = []
for j in range(Vdaf.SHARES):
state = Vdaf.prep_init(verify_key, j,
agg_param,
nonce,
public_share,
input_shares[j])
prep_states.append(state)

Expand Down
10 changes: 6 additions & 4 deletions poc/idpf.sage
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ class Idpf:
# The finite field used to represent the leaf nodes of the IDPF tree.
FieldLeaf: field.Field = None

# Generates a sequence of IDPF-keys of length `SHARES`. Value `alpha` is the
# input to encode. Values `beta_inner` and `beta_leaf` are assigned to the
# values of the nodes on the non-zero path of the IPDF tree.
# Generates an IDPF public share and sequence of IDPF-keys of length
# `SHARES`. Value `alpha` is the input to encode. Values `beta_inner` and
# `beta_leaf` are assigned to the values of the nodes on the non-zero path
# of the IPDF tree.
#
# An error is raised if integer `alpha` is larger than or equal to `2^BITS`,
# any elment of `beta_inner` has length other than `VALUE_LEN`, or if
Expand All @@ -35,7 +36,7 @@ class Idpf:
def gen(Ipdf,
alpha: Unsigned,
beta_inner: Vec[Vec[Idpf.FieldInner]],
beta_leaf: Vec[Idpf.FieldLeaf]) -> Vec[Bytes]:
beta_leaf: Vec[Idpf.FieldLeaf]) -> (Bytes, Vec[Bytes]):
raise Error('not implemented')

# Evaluate an IDPF key at a given level of the tree and with the given set
Expand All @@ -47,6 +48,7 @@ class Idpf:
# `2^level` or if `level` greater than `BITS`.
@classmethod
def eval(Idpf,
public_share: Bytes,
key: Bytes,
level: Unsigned,
prefixes: Vec[Unsigned]) -> Union[Vec[Vec[Idpf.FieldInner]],
Expand Down

0 comments on commit f2833bd

Please sign in to comment.