<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.6.16 (Ruby 3.1.2) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-irtf-cfrg-vdaf-03" category="info" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.14.0 -->
  <front>
    <title abbrev="VDAF">Verifiable Distributed Aggregation Functions</title>
    <seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-vdaf-03"/>
    <author initials="R. L." surname="Barnes" fullname="Richard L. Barnes">
      <organization>Cisco</organization>
      <address>
        <email>rlb@ipv.sx</email>
      </address>
    </author>
    <author initials="C." surname="Patton" fullname="Christopher Patton">
      <organization>Cloudflare</organization>
      <address>
        <email>chrispatton+ietf@gmail.com</email>
      </address>
    </author>
    <author initials="P." surname="Schoppmann" fullname="Phillipp Schoppmann">
      <organization>Google</organization>
      <address>
        <email>schoppmann@google.com</email>
      </address>
    </author>
    <date year="2022" month="August" day="24"/>
    <area>IRTF</area>
    <workgroup>CFRG</workgroup>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <t>This document describes Verifiable Distributed Aggregation Functions (VDAFs), a
family of multi-party protocols for computing aggregate statistics over user
measurements. These protocols are designed to ensure that, as long as at least
one aggregation server executes the protocol honestly, individual measurements
are never seen by any server in the clear. At the same time, VDAFs allow the
servers to detect if a malicious or misconfigured client submitted an
input that would result in an incorrect aggregate result.</t>
    </abstract>
    <note removeInRFC="true">
      <name>Discussion Venues</name>
      <t>Discussion of this document takes place on the
    Crypto Forum Research Group mailing list (cfrg@ietf.org),
    which is archived at <eref target="https://mailarchive.ietf.org/arch/search/?email_list=cfrg"/>.</t>
      <t>Source for this draft and an issue tracker can be found at
    <eref target="https://github.com/cjpatton/vdaf"/>.</t>
    </note>
  </front>
  <middle>
    <section anchor="introduction">
      <name>Introduction</name>
      <t>The ubiquity of the Internet makes it an ideal platform for measurement of
large-scale phenomena, whether public health trends or the behavior of computer
systems at scale. There is substantial overlap, however, between information
that is valuable to measure and information that users consider private.</t>
      <t>For example, consider an application that provides health information to users.
The operator of an application might want to know which parts of their
application are used most often, as a way to guide future development of the
application.  Specific users' patterns of usage, though, could reveal sensitive
things about them, such as which users are researching a given health condition.</t>
      <t>In many situations, the measurement collector is only interested in aggregate
statistics, e.g., which portions of an application are most used or what
fraction of people have experienced a given disease.  Thus systems that provide
aggregate statistics while protecting individual measurements can deliver the
value of the measurements while protecting users' privacy.</t>
      <t>Most prior approaches to this problem fall under the rubric of "differential
privacy (DP)" <xref target="Dwo06"/>. Roughly speaking, a data aggregation system that is
differentially private ensures that the degree to which any individual
measurement influences the value of the aggregate result can be precisely
controlled. For example, in systems like RAPPOR <xref target="EPK14"/>, each user samples
noise from a well-known distribution and adds it to their input before
submitting to the aggregation server. The aggregation server then adds up the
noisy inputs, and because it knows the distribution from whence the noise was
sampled, it can estimate the true sum with reasonable precision.</t>
      <t>Differentially private systems like RAPPOR are easy to deploy and provide a
useful guarantee. On its own, however, DP falls short of the strongest privacy
property one could hope for. Specifically, depending on the "amount" of noise a
client adds to its input, it may be possible for a curious aggregator to make a
reasonable guess of the input's true value. Indeed, the more noise the clients
add, the less reliable will be the server's estimate of the output. Thus systems
employing DP techniques alone must strike a delicate balance between privacy and
utility.</t>
      <t>The ideal goal for a privacy-preserving measurement system is that of secure
multi-party computation (MPC): No participant in the protocol should learn
anything about an individual input beyond what it can deduce from the aggregate.
In this document, we describe Verifiable Distributed Aggregation Functions
(VDAFs) as a general class of protocols that achieve this goal.</t>
      <t>VDAF schemes achieve their privacy goal by distributing the computation of the
aggregate among a number of non-colluding aggregation servers. As long as a
subset of the servers executes the protocol honestly, VDAFs guarantee that no
input is ever accessible to any party besides the client that submitted it. At
the same time, VDAFs are "verifiable" in the sense that malformed inputs that
would otherwise garble the output of the computation can be detected and removed
from the set of input measurements.</t>
      <t>In addition to these MPC-style security goals, VDAFs can be composed with
various mechanisms for differential privacy, thereby providing the added
assurance that the aggregate result itself does not leak too much information
about any one measurement.</t>
      <ul empty="true">
        <li>
          <t>TODO(issue #94) Provide guidance for local and central DP and point to it
here.</t>
        </li>
      </ul>
      <t>The cost of achieving these security properties is the need for multiple servers
to participate in the protocol, and the need to ensure they do not collude to
undermine the VDAF's privacy guarantees.  Recent implementation experience has
shown that practical challenges of coordinating multiple servers can be
overcome.  The Prio system <xref target="CGB17"/> (essentially a VDAF) has been deployed in
systems supporting hundreds of millions of users: The Mozilla Origin Telemetry
project <xref target="OriginTelemetry"/> and the Exposure Notification Private Analytics
collaboration among the Internet Security Research Group (ISRG), Google, Apple,
and others <xref target="ENPA"/>.</t>
      <t>The VDAF abstraction laid out in <xref target="vdaf"/> represents a class of multi-party
protocols for privacy-preserving measurement proposed in the literature. These
protocols vary in their operational and security considerations, sometimes in
subtle but consequential ways. This document therefore has two important goals:</t>
      <ol spacing="normal" type="1"><li>
          <t>Providing higher-level protocols like <xref target="DAP"/> with a
simple, uniform interface for accessing privacy-preserving measurement
schemes, and documenting relevant operational and security bounds for that
interface:  </t>
          <ol spacing="normal" type="1"><li>General patterns of communications among the various actors involved in
the system (clients, aggregation servers, and the collector of the
aggregate result);</li>
            <li>Capabilities of a malicious coalition of servers attempting to divulge
information about client measurements; and</li>
            <li>Conditions that are necessary to ensure that malicious clients cannot
corrupt the computation.</li>
          </ol>
        </li>
        <li>Providing cryptographers with design criteria that provide a clear
deployment roadmap for new constructions.</li>
      </ol>
      <t>This document also specifies two concrete VDAF schemes, each based on a protocol
from the literature.</t>
      <ul spacing="normal">
        <li>
          <t>The aforementioned Prio system <xref target="CGB17"/> allows for the privacy-preserving
computation of a variety aggregate statistics. The basic idea underlying Prio
is fairly simple:
          </t>
          <ol spacing="normal" type="1"><li>Each client shards its measurement into a sequence of additive shares and
distributes the shares among the aggregation servers.</li>
            <li>Next, each server adds up its shares locally, resulting in an additive
share of the aggregate.</li>
            <li>Finally, the aggregation servers send their aggregate shares to the data
collector, who combines them to obtain the aggregate result.</li>
          </ol>
          <t>
The difficult part of this system is ensuring that the servers hold shares of
a valid input, e.g., the input is an integer in a specific range. Thus Prio
specifies a multi-party protocol for accomplishing this task.  </t>
          <t>
In <xref target="prio3"/> we describe Prio3, a VDAF that follows the same overall framework
as the original Prio protocol, but incorporates techniques introduced in
<xref target="BBCGGI19"/> that result in significant performance gains.</t>
        </li>
        <li>
          <t>More recently, Boneh et al. <xref target="BBCGGI21"/> described a protocol called Poplar
for solving the <tt>t</tt>-heavy-hitters problem in a privacy-preserving manner. Here
each client holds a bit-string of length <tt>n</tt>, and the goal of the aggregation
servers is to compute the set of inputs that occur at least <tt>t</tt> times. The
core primitive used in their protocol is a specialized Distributed Point
Function (DPF) <xref target="GI14"/> that allows the servers to "query" their DPF shares on
any bit-string of length shorter than or equal to <tt>n</tt>. As a result of this
query, each of the servers has an additive share of a bit indicating whether
the string is a prefix of the client's input. The protocol also specifies a
multi-party computation for verifying that at most one string among a set of
candidates is a prefix of the client's input.  </t>
          <t>
In <xref target="poplar1"/> we describe a VDAF called Poplar1 that implements this
functionality.</t>
        </li>
      </ul>
      <t>Finally, perhaps the most complex aspect of schemes like Prio3 and Poplar1 is
the process by which the client-generated measurements are prepared for
aggregation. Because these constructions are based on secret sharing, the
servers will be required to exchange some amount of information in order to
verify the measurement is valid and can be aggregated. Depending on the
construction, this process may require multiple round trips over the network.</t>
      <t>There are applications in which this verification step may not be necessary,
e.g., when the client's software is run a trusted execution environment. To
support these applications, this document also defines Distributed Aggregation
Functions (DAFs) as a simpler class of protocols that aim to provide the same
privacy guarantee as VDAFs but fall short of being verifiable.</t>
      <ul empty="true">
        <li>
          <t>OPEN ISSUE Decide if we should give one or two example DAFs. There are natural
variants of Prio3 and Poplar1 that might be worth describing.</t>
        </li>
      </ul>
      <t>The remainder of this document is organized as follows: <xref target="overview"/> gives a
brief overview of DAFs and VDAFs; <xref target="daf"/> defines the syntax for DAFs; <xref target="vdaf"/>
defines the syntax for VDAFs; <xref target="prelim"/> defines various functionalities that
are common to our constructions; <xref target="prio3"/> describes the Prio3 construction;
<xref target="poplar1"/> describes the Poplar1 construction; and <xref target="security"/> enumerates the
security considerations for VDAFs.</t>
      <section anchor="change-log">
        <name>Change Log</name>
        <t>(*) Indicates a change that breaks wire compatibility with the previous draft.</t>
        <t>03:</t>
        <ul spacing="normal">
          <li>Define codepoints for (V)DAFs and use them for domain separation in Prio3 and
Poplar1. (*)</li>
          <li>Prio3: Align joint randomness computation with revised paper <xref target="BBCGGI19"/>.
This change mitigates an attack on robustness. (*)</li>
          <li>Prio3: Remove an intermediate PRG evaluation from query randomness generation.
(*)</li>
          <li>Add additional guidance for choosing FFT-friendly fields.</li>
        </ul>
        <t>02:</t>
        <ul spacing="normal">
          <li>Complete the initial specification of Poplar1.</li>
          <li>Extend (V)DAF syntax to include a "public share" output by the Client and
distributed to all of the Aggregators. This is to accommodate "extractable"
IDPFs as required for Poplar1. (See <xref target="BBCGGI21"/>, Section 4.3 for details.)</li>
          <li>Extend (V)DAF syntax to allow the unsharding step to take into account the
number of measurements aggregated.</li>
          <li>Extend FLP syntax by adding a method for decoding the aggregate result from a
vector of field elements. The new method takes into account the number of
measurements.</li>
          <li>Prio3: Align aggregate result computation with updated FLP syntax.</li>
          <li>Prg: Add a method for statefully generating a vector of field elements.</li>
          <li>Field: Require that field elements are fully reduced before decoding. (*)</li>
          <li>Define new field Field255.</li>
        </ul>
        <t>01:</t>
        <ul spacing="normal">
          <li>Require that VDAFs specify serialization of aggregate shares.</li>
          <li>Define Distributed Aggregation Functions (DAFs).</li>
          <li>Prio3: Move proof verifier check from <tt>prep_next()</tt> to
<tt>prep_shares_to_prep()</tt>. (*)</li>
          <li>Remove public parameter and replace verification parameter with a
"verification key" and "Aggregator ID".</li>
        </ul>
      </section>
    </section>
    <section anchor="conventions-and-definitions">
      <name>Conventions and Definitions</name>
      <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>
      <t>Algorithms in this document are written in Python 3. Type hints are used to
define input and output types. A fatal error in a program (e.g., failure to
parse one of the function parameters) is usually handled by raising an
exception.</t>
      <t>A variable with type <tt>Bytes</tt> is a byte string. This document defines several
byte-string constants. When comprised of printable ASCII characters, they are
written as Python 3 byte-string literals (e.g., <tt>b'some constant string'</tt>).</t>
      <t>A global constant <tt>VERSION</tt> is defined, which algorithms are free to use as
desired. Its value <bcp14>SHALL</bcp14> be <tt>b'vdaf-03'</tt>.</t>
      <t>This document describes algorithms for multi-party computations in which the
parties typically communicate over a network. Wherever a quantity is defined
that must be be transmitted from one party to another, this document prescribes
a particular encoding of that quantity as a byte string.</t>
      <ul empty="true">
        <li>
          <t>OPEN ISSUE It might be better to not be prescriptive about how quantities are
encoded on the wire. See issue #58.</t>
        </li>
      </ul>
      <t>Some common functionalities:</t>
      <ul spacing="normal">
        <li>
          <tt>zeros(len: Unsigned) -&gt; Bytes</tt> returns an array of zero bytes. The length of
<tt>output</tt> <bcp14>MUST</bcp14> be <tt>len</tt>.</li>
        <li>
          <tt>gen_rand(len: Unsigned) -&gt; Bytes</tt> returns an array of random bytes. The
length of <tt>output</tt> <bcp14>MUST</bcp14> be <tt>len</tt>.</li>
        <li>
          <tt>byte(int: Unsigned) -&gt; Bytes</tt> returns the representation of <tt>int</tt> as a byte
string. The value of <tt>int</tt> <bcp14>MUST</bcp14> be in <tt>[0,256)</tt>.</li>
        <li>
          <tt>concat(parts: Vec[Bytes]) -&gt; Bytes</tt> returns the concatenation of the input
byte strings, i.e., <tt>parts[0] || ... || parts[len(parts)-1]</tt>.</li>
        <li>
          <tt>xor(left: Bytes, right: Bytes) -&gt; Bytes</tt> returns the bitwise XOR of <tt>left</tt>
and <tt>right</tt>. An exception is raised if the inputs are not the same length.</li>
        <li>
          <tt>I2OSP</tt> and <tt>OS2IP</tt> from <xref target="RFC8017"/>, which are used, respectively, to
convert a non-negative integer to a byte string and convert a byte string to a
non-negative integer.</li>
        <li>
          <tt>next_power_of_2(n: Unsigned) -&gt; Unsigned</tt> returns the smallest integer
greater than or equal to <tt>n</tt> that is also a power of two.</li>
      </ul>
    </section>
    <section anchor="overview">
      <name>Overview</name>
      <figure anchor="overall-flow">
        <name>Overall data flow of a (V)DAF</name>
        <artwork><![CDATA[
                 +--------------+
           +---->| Aggregator 0 |----+
           |     +--------------+    |
           |             ^           |
           |             |           |
           |             V           |
           |     +--------------+    |
           | +-->| Aggregator 1 |--+ |
           | |   +--------------+  | |
+--------+-+ |           ^         | +->+-----------+
| Client |---+           |         +--->| Collector |--> Aggregate
+--------+-+                         +->+-----------+
           |            ...          |
           |                         |
           |             |           |
           |             V           |
           |    +----------------+   |
           +--->| Aggregator N-1 |---+
                +----------------+

      Input shares           Aggregate shares
]]></artwork>
      </figure>
      <t>In a DAF- or VDAF-based private measurement system, we distinguish three types
of actors: Clients, Aggregators, and Collectors.  The overall flow of the
measurement process is as follows:</t>
      <ul spacing="normal">
        <li>To submit an individual measurement, the Client shards the measurement into
"input shares" and sends one input share to each Aggregator.</li>
        <li>
          <t>The Aggregators convert their input shares into "output shares".
          </t>
          <ul spacing="normal">
            <li>Output shares are in one-to-one correspondence with the input shares.</li>
            <li>Just as each Aggregator receives one input share of each input, at the end
of this process, each aggregator holds one output share.</li>
            <li>In VDAFs, Aggregators will need to exchange information among themselves
as part of the validation process.</li>
          </ul>
        </li>
        <li>Each Aggregator combines the output shares across inputs in the batch to
compute the "aggregate share" for that batch, i.e., its share of the desired
aggregate result.</li>
        <li>The Aggregators submit their aggregate shares to the Collector, who combines
them to obtain the aggregate result over the batch.</li>
      </ul>
      <t>Aggregators are a new class of actor relative to traditional measurement systems
where clients submit measurements to a single server.  They are critical for
both the privacy properties of the system and, in the case of VDAFs, the
correctness of the measurements obtained.  The privacy properties of the system
are assured by non-collusion among Aggregators, and Aggregators are the entities
that perform validation of Client measurements.  Thus clients trust Aggregators
not to collude (typically it is required that at least one Aggregator is
honest), and Collectors trust Aggregators to correctly run the protocol.</t>
      <t>Within the bounds of the non-collusion requirements of a given (V)DAF instance,
it is possible for the same entity to play more than one role.  For example, the
Collector could also act as an Aggregator, effectively using the other
Aggregator(s) to augment a basic client-server protocol.</t>
      <t>In this document, we describe the computations performed by the actors in this
system. It is up to the higher-level protocol making use of the (V)DAF to
arrange for the required information to be delivered to the proper actors in the
proper sequence. In general, we assume that all communications are confidential
and mutually authenticated, with the exception that Clients submitting
measurements may be anonymous.</t>
    </section>
    <section anchor="daf">
      <name>Definition of DAFs</name>
      <t>By way of a gentle introduction to VDAFs, this section describes a simpler class
of schemes called Distributed Aggregation Functions (DAFs). Unlike VDAFs, DAFs
do not provide verifiability of the computation. Clients must therefore be
trusted to compute their input shares correctly. Because of this fact, the use
of a DAF is <bcp14>NOT RECOMMENDED</bcp14> for most applications. See <xref target="security"/> for
additional discussion.</t>
      <t>A DAF scheme is used to compute a particular "aggregation function" over a set
of measurements generated by Clients. Depending on the aggregation function, the
Collector might select an "aggregation parameter" and disseminates it to the
Aggregators. The semantics of this parameter is specific to the aggregation
function, but in general it is used to represent the set of "queries" that can
be made on the measurement set. For example, the aggregation parameter is used
to represent the candidate prefixes in Poplar1 <xref target="poplar1"/>.</t>
      <t>Execution of a DAF has four distinct stages:</t>
      <ul spacing="normal">
        <li>Sharding - Each Client generates input shares from its measurement and
distributes them among the Aggregators.</li>
        <li>Preparation - Each Aggregator converts each input share into an output share
compatible with the aggregation function. This computation involves the
aggregation parameter. In general, each aggregation parameter may result in a
different an output share.</li>
        <li>Aggregation - Each Aggregator combines a sequence of output shares into its
aggregate share and sends the aggregate share to the Collector.</li>
        <li>Unsharding - The Collector combines the aggregate shares into the aggregate
result.</li>
      </ul>
      <t>Sharding and Preparation are done once per measurement. Aggregation and
Unsharding are done over a batch of measurements (more precisely, over the
recovered output shares).</t>
      <t>A concrete DAF specifies an algorithm for the computation needed in each of
these stages. The interface of each algorithm is defined in the remainder of
this section. In addition, a concrete DAF defines the associated constants and
types enumerated in the following table.</t>
      <table anchor="daf-param">
        <name>Constants and types defined by each concrete DAF.</name>
        <thead>
          <tr>
            <th align="left">Parameter</th>
            <th align="left">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>ID</tt></td>
            <td align="left">Algorithm identifier for this DAF.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>SHARES</tt></td>
            <td align="left">Number of input shares into which each measurement is sharded</td>
          </tr>
          <tr>
            <td align="left">
              <tt>Measurement</tt></td>
            <td align="left">Type of each measurement</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggParam</tt></td>
            <td align="left">Type of aggregation parameter</td>
          </tr>
          <tr>
            <td align="left">
              <tt>OutShare</tt></td>
            <td align="left">Type of each output share</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggResult</tt></td>
            <td align="left">Type of the aggregate result</td>
          </tr>
        </tbody>
      </table>
      <t>These types define some of the inputs and outputs of DAF methods at various
stages of the computation. Observe that only the measurements, output shares,
the aggregate result, and the aggregation parameter have an explicit type. All
other values --- in particular, the input shares and the aggregate shares ---
have type <tt>Bytes</tt> and are treated as opaque byte strings. This is because these
values must be transmitted between parties over a network.</t>
      <ul empty="true">
        <li>
          <t>OPEN ISSUE It might be cleaner to define a type for each value, then have that
type implement an encoding where necessary. This way each method parameter has
a meaningful type hint. See issue#58.</t>
        </li>
      </ul>
      <t>Each DAF is identified by a unique, 32-bit integer <tt>ID</tt>. Identifiers for each
(V)DAF specified in this document are defined in <xref target="codepoints"/>.</t>
      <section anchor="sec-daf-shard">
        <name>Sharding</name>
        <t>In order to protect the privacy of its measurements, a DAF Client shards its
measurements into a sequence of input shares. The <tt>measurement_to_input_shares</tt>
method is used for this purpose.</t>
        <ul spacing="normal">
          <li>
            <tt>Daf.measurement_to_input_shares(input: Measurement) -&gt; (Bytes, Vec[Bytes])</tt>
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 sequence of input shares, one for each
Aggregator. The length of the output vector <bcp14>MUST</bcp14> be <tt>SHARES</tt>.</li>
        </ul>
        <figure anchor="shard-flow">
          <name>The Client divides its measurement into input shares and distributes them to the Aggregators.</name>
          <artwork><![CDATA[
    Client
    ======

    measurement
      |
      V
    +----------------------------------------------+
    | measurement_to_input_shares                  |
    +----------------------------------------------+
      |              |              ...  |
      V              V                   V
     input_share_0  input_share_1       input_share_[SHARES-1]
      |              |              ...  |
      V              V                   V
    Aggregator 0   Aggregator 1        Aggregator SHARES-1
]]></artwork>
        </figure>
      </section>
      <section anchor="sec-daf-prepare">
        <name>Preparation</name>
        <t>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:</t>
        <ul spacing="normal">
          <li>
            <tt>Daf.prep(agg_id: Unsigned, agg_param: AggParam, public_share: Bytes,
input_share: Bytes) -&gt; OutShare</tt> 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.</li>
        </ul>
        <t>The protocol in which the DAF is used <bcp14>MUST</bcp14> ensure that the Aggregator's
identifier is equal to the integer in range <tt>[0, SHARES)</tt> that matches the index
of <tt>input_share</tt> in the sequence of input shares output by the Client.</t>
      </section>
      <section anchor="sec-daf-aggregate">
        <name>Aggregation</name>
        <t>Once an Aggregator holds output shares for a batch of measurements (where
batches are defined by the application), it combines them into a share of the
desired aggregate result:</t>
        <ul spacing="normal">
          <li>
            <tt>Daf.out_shares_to_agg_share(agg_param: AggParam, out_shares: Vec[OutShare])
-&gt; agg_share: Bytes</tt> is the deterministic aggregation algorithm. It is run by
each Aggregator a set of recovered output shares.</li>
        </ul>
        <figure anchor="aggregate-flow">
          <name>Aggregation of output shares. `B` indicates the number of measurements in the batch.</name>
          <artwork><![CDATA[
    Aggregator 0    Aggregator 1        Aggregator SHARES-1
    ============    ============        ===================

    out_share_0_0   out_share_1_0       out_share_[SHARES-1]_0
    out_share_0_1   out_share_1_1       out_share_[SHARES-1]_1
    out_share_0_2   out_share_1_2       out_share_[SHARES-1]_2
         ...             ...                     ...
    out_share_0_B   out_share_1_B       out_share_[SHARES-1]_B
      |               |                   |
      V               V                   V
    +-----------+   +-----------+       +-----------+
    | out2agg   |   | out2agg   |   ... | out2agg   |
    +-----------+   +-----------+       +-----------+
      |               |                   |
      V               V                   V
    agg_share_0     agg_share_1         agg_share_[SHARES-1]
]]></artwork>
        </figure>
        <t>For simplicity, we have written this algorithm in a "one-shot" form, where all
output shares for a batch are provided at the same time. Many DAFs may also
support a "streaming" form, where shares are processed one at a time.</t>
        <ul empty="true">
          <li>
            <t>OPEN ISSUE It may be worthwhile to explicitly define the "streaming" API. See
issue#47.</t>
          </li>
        </ul>
      </section>
      <section anchor="sec-daf-unshard">
        <name>Unsharding</name>
        <t>After the Aggregators have aggregated a sufficient number of output shares, each
sends its aggregate share to the Collector, who runs the following algorithm to
recover the following output:</t>
        <ul spacing="normal">
          <li>
            <tt>Daf.agg_shares_to_result(agg_param: AggParam,
agg_shares: Vec[Bytes], num_measurements: Unsigned) -&gt; AggResult</tt> is
run by the Collector in order to compute the aggregate result from
the Aggregators' shares. The length of <tt>agg_shares</tt> <bcp14>MUST</bcp14> be <tt>SHARES</tt>.
<tt>num_measurements</tt> is the number of measurements that contributed to
each of the aggregate shares. This algorithm is deterministic.</li>
        </ul>
        <figure anchor="unshard-flow">
          <name>Computation of the final aggregate result from aggregate shares.</name>
          <artwork><![CDATA[
    Aggregator 0    Aggregator 1        Aggregator SHARES-1
    ============    ============        ===================

    agg_share_0     agg_share_1         agg_share_[SHARES-1]
      |               |                   |
      V               V                   V
    +-----------------------------------------------+
    | agg_shares_to_result                          |
    +-----------------------------------------------+
      |
      V
    agg_result

    Collector
    =========
]]></artwork>
        </figure>
        <ul empty="true">
          <li>
            <t>QUESTION Maybe the aggregation algorithms should be randomized in order to
allow the Aggregators (or the Collector) to add noise for differential
privacy. (See the security considerations of <xref target="DAP"/>.)
Or is this out-of-scope of this document? See
https://github.com/ietf-wg-ppm/ppm-specification/issues/19.</t>
          </li>
        </ul>
      </section>
      <section anchor="daf-execution">
        <name>Execution of a DAF</name>
        <t>Securely executing a DAF involves emulating the following procedure.</t>
        <!--
Simon Friedberger: I think this would be easier to understand (also a bit
longer) if there was an Aggregator class which behaved like an actual aggregator
but with messages being sent by calling functions.
-->
<figure anchor="run-daf">
          <name>Execution of a DAF.</name>
          <artwork><![CDATA[
def run_daf(Daf,
            agg_param: Daf.AggParam,
            measurements: Vec[Daf.Measurement]):
    out_shares = [ [] for j in range(Daf.SHARES) ]
    for measurement in measurements:
        # Each Client shards its measurement into input shares and
        # distributes them among the Aggregators.
        (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, public_share, input_shares[j]))

    # Each Aggregator aggregates its output shares into an aggregate
    # share and sends it to the Collector.
    agg_shares = []
    for j in range(Daf.SHARES):
        agg_share_j = Daf.out_shares_to_agg_share(agg_param,
                                                  out_shares[j])
        agg_shares.append(agg_share_j)

    # Collector unshards the aggregate result.
    num_measurements = len(measurements)
    agg_result = Daf.agg_shares_to_result(agg_param, agg_shares,
                                          num_measurements)
    return agg_result
]]></artwork>
        </figure>
        <t>The inputs to this procedure are the same as the aggregation function computed by
the DAF: An aggregation parameter and a sequence of measurements. The procedure
prescribes how a DAF is executed in a "benign" environment in which there is no
adversary and the messages are passed among the protocol participants over
secure point-to-point channels. In reality, these channels need to be
instantiated by some "wrapper protocol", such as <xref target="DAP"/>,
that realizes these channels using suitable cryptographic mechanisms. Moreover,
some fraction of the Aggregators (or Clients) may be malicious and diverge from
their prescribed behaviors. <xref target="security"/> describes the execution of the DAF in
various adversarial environments and what properties the wrapper protocol needs
to provide in each.</t>
      </section>
    </section>
    <section anchor="vdaf">
      <name>Definition of VDAFs</name>
      <t>Like DAFs described in the previous section, a VDAF scheme is used to compute a
particular aggregation function over a set of Client-generated measurements.
Evaluation of a VDAF involves the same four stages as for DAFs: Sharding,
Preparation, Aggregation, and Unsharding. However, the Preparation stage will
require interaction among the Aggregators in order to facilitate verifiability
of the computation's correctness. Accommodating this interaction will require
syntactic changes.</t>
      <t>Overall execution of a VDAF comprises the following stages:</t>
      <ul spacing="normal">
        <li>Sharding - Computing input shares from an individual measurement</li>
        <li>Preparation - Conversion and verification of input shares to output shares
compatible with the aggregation function being computed</li>
        <li>Aggregation - Combining a sequence of output shares into an aggregate share</li>
        <li>Unsharding - Combining a sequence of aggregate shares into an aggregate
result</li>
      </ul>
      <t>In contrast to DAFs, the Preparation stage for VDAFs now performs an additional
task: Verification of the validity of the recovered output shares. This process
ensures that aggregating the output shares will not lead to a garbled aggregate
result.</t>
      <!--
For some VDAFs, like Prio3 ({{prio3}}) or Poplar1 ({{poplar1}}), the output
shares are recovered first, then validated. For other protocols, like Prio+
[AGJOP21], there is no explicit verification step.
-->

<t>The remainder of this section defines the VDAF interface. The attributes are
listed in <xref target="vdaf-param"/> are defined by each concrete VDAF.</t>
      <table anchor="vdaf-param">
        <name>Constants and types defined by each concrete VDAF.</name>
        <thead>
          <tr>
            <th align="left">Parameter</th>
            <th align="left">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>ID</tt></td>
            <td align="left">Algorithm identifier for this VDAF.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>VERIFY_KEY_SIZE</tt></td>
            <td align="left">Size (in bytes) of the verification key (<xref target="sec-vdaf-prepare"/>)</td>
          </tr>
          <tr>
            <td align="left">
              <tt>ROUNDS</tt></td>
            <td align="left">Number of rounds of communication during the Preparation stage (<xref target="sec-vdaf-prepare"/>)</td>
          </tr>
          <tr>
            <td align="left">
              <tt>SHARES</tt></td>
            <td align="left">Number of input shares into which each measurement is sharded (<xref target="sec-vdaf-shard"/>)</td>
          </tr>
          <tr>
            <td align="left">
              <tt>Measurement</tt></td>
            <td align="left">Type of each measurement</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggParam</tt></td>
            <td align="left">Type of aggregation parameter</td>
          </tr>
          <tr>
            <td align="left">
              <tt>Prep</tt></td>
            <td align="left">State of each Aggregator during Preparation (<xref target="sec-vdaf-prepare"/>)</td>
          </tr>
          <tr>
            <td align="left">
              <tt>OutShare</tt></td>
            <td align="left">Type of each output share</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggResult</tt></td>
            <td align="left">Type of the aggregate result</td>
          </tr>
        </tbody>
      </table>
      <t>Similarly to DAFs (see {[sec-daf}}), any output of a VDAF method that must be
transmitted from one party to another is treated as an opaque byte string. All
other quantities are given a concrete type.</t>
      <ul empty="true">
        <li>
          <t>OPEN ISSUE It might be cleaner to define a type for each value, then have that
type implement an encoding where necessary. See issue#58.</t>
        </li>
      </ul>
      <t>Each VDAF is identified by a unique, 32-bit integer <tt>ID</tt>. Identifiers for each
(V)DAF specified in this document are defined in <xref target="codepoints"/>.</t>
      <section anchor="sec-vdaf-shard">
        <name>Sharding</name>
        <t>Sharding is syntactically identical to DAFs (cf. <xref target="sec-daf-shard"/>):</t>
        <ul spacing="normal">
          <li>
            <tt>Vdaf.measurement_to_input_shares(measurement: Measurement) -&gt; (Bytes,
Vec[Bytes])</tt> 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 <xref target="prio3"/>). The length of the output vector <bcp14>MUST</bcp14> be
<tt>SHARES</tt>.</li>
        </ul>
      </section>
      <section anchor="sec-vdaf-prepare">
        <name>Preparation</name>
        <t>To recover and verify output shares, the Aggregators interact with one another
over <tt>ROUNDS</tt> rounds. Prior to each round, each Aggregator constructs an
outbound message. Next, the sequence of outbound messages is combined into a
single message, called a "preparation message". (Each of the outbound messages
are called "preparation-message shares".) Finally, the preparation message is
distributed to the Aggregators to begin the next round.</t>
        <t>An Aggregator begins the first round with its input share and it begins each
subsequent round with the previous preparation message. Its output in the last
round is its output share and its output in each of the preceding rounds is a
preparation-message share.</t>
        <t>This process involves a value called the "aggregation parameter" used to map the
input shares to output shares. The Aggregators need to agree on this parameter
before they can begin preparing inputs for aggregation.</t>
        <figure anchor="prep-flow">
          <name>VDAF preparation process on the input shares for a single measurement. At the end of the computation, each Aggregator holds an output share or an error.</name>
          <artwork><![CDATA[
    Aggregator 0   Aggregator 1        Aggregator SHARES-1
    ============   ============        ===================

    input_share_0  input_share_1       input_share_[SHARES-1]
      |              |              ...  |
      V              V                   V
    +-----------+  +-----------+       +-----------+
    | prep_init |  | prep_init |       | prep_init |
    +-----------+  +------------+      +-----------+
      |              |              ...  |             \
      V              V                   V             |
    +-----------+  +-----------+       +-----------+   |
    | prep_next |  | prep_next |       | prep_next |   |
    +-----------+  +-----------+       +-----------+   |
      |              |              ...  |             |
      V              V                   V             | x ROUNDS
    +----------------------------------------------+   |
    | prep_shares_to_prep                          |   |
    +----------------------------------------------+   |
                     |                                 |
      +--------------+-------------------+             |
      |              |              ...  |             |
      V              V                   V             /
     ...            ...                 ...
      |              |                   |
      V              V                   V
    +-----------+  +-----------+       +-----------+
    | prep_next |  | prep_next |       | prep_next |
    +-----------+  +-----------+       +-----------+
      |              |              ...  |
      V              V                   V
    out_share_0    out_share_1         out_share_[SHARES-1]
]]></artwork>
        </figure>
        <t>To facilitate the preparation process, a concrete VDAF implements the following
class methods:</t>
        <ul spacing="normal">
          <li>
            <t><tt>Vdaf.prep_init(verify_key: Bytes, agg_id: Unsigned, agg_param: AggParam,
nonce: Bytes, public_share: Bytes, input_share: Bytes) -&gt; Prep</tt> 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 (<tt>verify_key</tt>), the Aggregator's unique
identifier (<tt>agg_id</tt>), the aggregation parameter (<tt>agg_param</tt>), the nonce
provided by the environment (<tt>nonce</tt>, see <xref target="run-vdaf"/>), and the public share
(<tt>public_share</tt>) and one of the input shares generated by the client
(<tt>input_share</tt>). Its output is the Aggregator's initial preparation state.  </t>
            <t>
The length of <tt>verify_key</tt> <bcp14>MUST</bcp14> be <tt>VERIFY_KEY_SIZE</tt>. It is up to the high
level protocol in which the VDAF is used to arrange for the distribution of
the verification key among the Aggregators prior to the start of this phase of
VDAF evaluation.  </t>
            <ul empty="true">
              <li>
                <t>OPEN ISSUE What security properties do we need for this key exchange? See
issue#18.</t>
              </li>
            </ul>
            <t>
Protocols using the VDAF <bcp14>MUST</bcp14> ensure that the Aggregator's identifier is equal
to the integer in range <tt>[0, SHARES)</tt> that matches the index of <tt>input_share</tt>
in the sequence of input shares output by the Client. In addition, protocols
<bcp14>MUST</bcp14> ensure that public share consumed by each of the Aggregators is
identical. This is security critical for VDAFs such as Poplar1 that require an
extractable distributed point function. (See <xref target="poplar1"/> for details.)</t>
          </li>
          <li>
            <tt>Vdaf.prep_next(prep: Prep, inbound: Optional[Bytes]) -&gt; Union[Tuple[Prep,
Bytes], OutShare]</tt> is the deterministic preparation-state update algorithm run
by each Aggregator. It updates the Aggregator's preparation state (<tt>prep</tt>) and
returns either its next preparation state and its message share for the
current round or, if this is the last round, its output share. An exception is
raised if a valid output share could not be recovered. The input of this
algorithm is the inbound preparation message or, if this is the first round,
<tt>None</tt>.</li>
          <li>
            <tt>Vdaf.prep_shares_to_prep(agg_param: AggParam, prep_shares: Vec[Bytes]) -&gt;
Bytes</tt> is the deterministic preparation-message pre-processing algorithm. It
combines the preparation-message shares generated by the Aggregators in the
previous round into the preparation message consumed by each in the next
round.</li>
        </ul>
        <t>In effect, each Aggregator moves through a linear state machine with <tt>ROUNDS+1</tt>
states.  The Aggregator enters the first state on using the initialization
algorithm, and the update algorithm advances the Aggregator to the next state.
Thus, in addition to defining the number of rounds (<tt>ROUNDS</tt>), a VDAF instance
defines the state of the Aggregator after each round.</t>
        <ul empty="true">
          <li>
            <t>TODO Consider how to bake this "linear state machine" condition into the
syntax. Given that Python 3 is used as our pseudocode, it's easier to specify
the preparation state using a class.</t>
          </li>
        </ul>
        <t>The preparation-state update accomplishes two tasks: recovery of output shares
from the input shares and ensuring that the recovered output shares are valid.
The abstraction boundary is drawn so that an Aggregator only recovers an output
share if it is deemed valid (at least, based on the Aggregator's view of the
protocol). Another way to draw this boundary would be to have the Aggregators
recover output shares first, then verify that they are valid. However, this
would allow the possibility of misusing the API by, say, aggregating an invalid
output share. Moreover, in protocols like Prio+ <xref target="AGJOP21"/> based on oblivious
transfer, it is necessary for the Aggregators to interact in order to recover
aggregatable output shares at all.</t>
        <t>Note that it is possible for a VDAF to specify <tt>ROUNDS == 0</tt>, in which case each
Aggregator runs the preparation-state update algorithm once and immediately
recovers its output share without interacting with the other Aggregators.
However, most, if not all, constructions will require some amount of interaction
in order to ensure validity of the output shares (while also maintaining
privacy).</t>
        <ul empty="true">
          <li>
            <t>OPEN ISSUE accommodating 0-round VDAFs may require syntax changes if, for
example, public keys are required. On the other hand, we could consider
defining this class of schemes as a different primitive. See issue#77.</t>
          </li>
        </ul>
      </section>
      <section anchor="sec-vdaf-aggregate">
        <name>Aggregation</name>
        <t>VDAF Aggregation is identical to DAF Aggregation (cf. <xref target="sec-daf-aggregate"/>):</t>
        <ul spacing="normal">
          <li>
            <tt>Vdaf.out_shares_to_agg_share(agg_param: AggParam, out_shares: Vec[OutShare])
-&gt; agg_share: Bytes</tt> is the deterministic aggregation algorithm. It is run by
each Aggregator over the output shares it has computed over a batch of
measurement inputs.</li>
        </ul>
        <t>The data flow for this stage is illustrated in <xref target="aggregate-flow"/>. Here again,
we have the aggregation algorithm in a "one-shot" form, where all shares for a
batch are provided at the same time. VDAFs typically also support a "streaming"
form, where shares are processed one at a time.</t>
      </section>
      <section anchor="sec-vdaf-unshard">
        <name>Unsharding</name>
        <t>VDAF Unsharding is identical to DAF Unsharding (cf. <xref target="sec-daf-unshard"/>):</t>
        <ul spacing="normal">
          <li>
            <tt>Vdaf.agg_shares_to_result(agg_param: AggParam,
agg_shares: Vec[Bytes], num_measurements: Unsigned) -&gt; AggResult</tt> is
run by the Collector in order to compute the aggregate result from
the Aggregators' shares. The length of <tt>agg_shares</tt> <bcp14>MUST</bcp14> be <tt>SHARES</tt>.
<tt>num_measurements</tt> is the number of measurements that contributed to
each of the aggregate shares. This algorithm is deterministic.</li>
        </ul>
        <t>The data flow for this stage is illustrated in <xref target="unshard-flow"/>.</t>
      </section>
      <section anchor="vdaf-execution">
        <name>Execution of a VDAF</name>
        <t>Secure execution of a VDAF involves simulating the following procedure.</t>
        <figure anchor="run-vdaf">
          <name>Execution of a VDAF.</name>
          <artwork><![CDATA[
def run_vdaf(Vdaf,
             agg_param: Vdaf.AggParam,
             nonces: Vec[Bytes],
             measurements: Vec[Vdaf.Measurement]):
    # Generate the long-lived verification key.
    verify_key = gen_rand(Vdaf.VERIFY_KEY_SIZE)

    out_shares = []
    for (nonce, measurement) in zip(nonces, measurements):
        # Each Client shards its measurement into input shares.
        (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)

        # Aggregators recover their output shares.
        inbound = None
        for i in range(Vdaf.ROUNDS+1):
            outbound = []
            for j in range(Vdaf.SHARES):
                out = Vdaf.prep_next(prep_states[j], inbound)
                if i < Vdaf.ROUNDS:
                    (prep_states[j], out) = out
                outbound.append(out)
            # This is where we would send messages over the
            # network in a distributed VDAF computation.
            if i < Vdaf.ROUNDS:
                inbound = Vdaf.prep_shares_to_prep(agg_param,
                                                   outbound)

        # The final outputs of prepare phase are the output shares.
        out_shares.append(outbound)

    # Each Aggregator aggregates its output shares into an
    # aggregate share. In a distributed VDAF computation, the
    # aggregate shares are sent over the network.
    agg_shares = []
    for j in range(Vdaf.SHARES):
        out_shares_j = [out[j] for out in out_shares]
        agg_share_j = Vdaf.out_shares_to_agg_share(agg_param,
                                                   out_shares_j)
        agg_shares.append(agg_share_j)

    # Collector unshards the aggregate.
    num_measurements = len(measurements)
    agg_result = Vdaf.agg_shares_to_result(agg_param, agg_shares,
                                           num_measurements)
    return agg_result
]]></artwork>
        </figure>
        <t>The inputs to this algorithm are the aggregation parameter, a list of
measurements, and a nonce for each measurement. This document does not specify
how the nonces are chosen, but security requires that the nonces be unique. See
<xref target="security"/> for details. As explained in <xref target="daf-execution"/>, the secure
execution of a VDAF requires the application to instantiate secure channels
between each of the protocol participants.</t>
      </section>
    </section>
    <section anchor="prelim">
      <name>Preliminaries</name>
      <t>This section describes the primitives that are common to the VDAFs specified in
this document.</t>
      <section anchor="field">
        <name>Finite Fields</name>
        <t>Both Prio3 and Poplar1 use finite fields of prime order. Finite field
elements are represented by a class <tt>Field</tt> with the following associated
parameters:</t>
        <ul spacing="normal">
          <li>
            <tt>MODULUS: Unsigned</tt> is the prime modulus that defines the field.</li>
          <li>
            <tt>ENCODED_SIZE: Unsigned</tt> is the number of bytes used to encode a field element
as a byte string.</li>
        </ul>
        <t>A concrete <tt>Field</tt> also implements the following class methods:</t>
        <ul spacing="normal">
          <li>
            <tt>Field.zeros(length: Unsigned) -&gt; output: Vec[Field]</tt> returns a vector of
zeros. The length of <tt>output</tt> <bcp14>MUST</bcp14> be <tt>length</tt>.</li>
          <li>
            <tt>Field.rand_vec(length: Unsigned) -&gt; output: Vec[Field]</tt> returns a vector of
random field elements. The length of <tt>output</tt> <bcp14>MUST</bcp14> be <tt>length</tt>.</li>
        </ul>
        <t>A field element is an instance of a concrete <tt>Field</tt>. The concrete class defines
the usual arithmetic operations on field elements. In addition, it defines the
following instance method for converting a field element to an unsigned integer:</t>
        <ul spacing="normal">
          <li>
            <tt>elem.as_unsigned() -&gt; Unsigned</tt> returns the integer representation of
field element <tt>elem</tt>.</li>
        </ul>
        <t>Likewise, each concrete <tt>Field</tt> implements a constructor for converting an
unsigned integer into a field element:</t>
        <ul spacing="normal">
          <li>
            <tt>Field(integer: Unsigned)</tt> returns <tt>integer</tt> represented as a field element.
The value of <tt>integer</tt> <bcp14>MUST</bcp14> be less than <tt>Field.MODULUS</tt>.</li>
        </ul>
        <t>Finally, each concrete <tt>Field</tt> has two derived class methods, one for encoding
a vector of field elements as a byte string and another for decoding a vector of
field elements.</t>
        <figure anchor="field-derived-methods">
          <name>Derived class methods for finite fields.</name>
          <artwork><![CDATA[
def encode_vec(Field, data: Vec[Field]) -> Bytes:
    encoded = Bytes()
    for x in data:
        encoded += I2OSP(x.as_unsigned(), Field.ENCODED_SIZE)
    return encoded

def decode_vec(Field, encoded: Bytes) -> Vec[Field]:
    L = Field.ENCODED_SIZE
    if len(encoded) % L != 0:
        raise ERR_DECODE

    vec = []
    for i in range(0, len(encoded), L):
        encoded_x = encoded[i:i+L]
        x = OS2IP(encoded_x)
        if x >= Field.MODULUS:
            raise ERR_DECODE # Integer is larger than modulus
        vec.append(Field(x))
    return vec
]]></artwork>
        </figure>
        <section anchor="auxiliary-functions">
          <name>Auxiliary Functions</name>
          <t>The following auxiliary functions on vectors of field elements are used in the
remainder of this document. Note that an exception is raised by each function if
the operands are not the same length.</t>
          <figure anchor="field-helper-functions">
            <name>Common functions for finite fields.</name>
            <artwork><![CDATA[
# Compute the inner product of the operands.
def inner_product(left: Vec[Field], right: Vec[Field]) -> Field:
    return sum(map(lambda x: x[0] * x[1], zip(left, right)))

# Subtract the right operand from the left and return the result.
def vec_sub(left: Vec[Field], right: Vec[Field]):
    return list(map(lambda x: x[0] - x[1], zip(left, right)))

# Add the right operand to the left and return the result.
def vec_add(left: Vec[Field], right: Vec[Field]):
    return list(map(lambda x: x[0] + x[1], zip(left, right)))
]]></artwork>
          </figure>
        </section>
        <section anchor="field-fft-friendly">
          <name>FFT-Friendly Fields</name>
          <t>Some VDAFs require fields that are suitable for efficient computation of the
discrete Fourier transform, as this allows for fast polynomial interpolation.
(One example is Prio3 (<xref target="prio3"/>) when instantiated with the generic FLP of
<xref target="flp-generic-construction"/>.) Specifically, a field is said to be
"FFT-friendly" if, in addition to satisfying the interface described in
<xref target="field"/>, it implements the following method:</t>
          <ul spacing="normal">
            <li>
              <tt>Field.gen() -&gt; Field</tt> returns the generator of a large subgroup of the
multiplicative group. To be FFT-friendly, the order of this subgroup NUST be a
power of 2. In addition, the size of the subgroup dictates how large
interpolated polynomials can be. It is <bcp14>RECOMMENDED</bcp14> that a generator is chosen
with order at least <tt>2^20</tt>.</li>
          </ul>
          <t>FFT-friendly fields also define the following parameter:</t>
          <ul spacing="normal">
            <li>
              <tt>GEN_ORDER: Unsigned</tt> is the order of a multiplicative subgroup generated by
<tt>Field.gen()</tt>.</li>
          </ul>
        </section>
        <section anchor="parameters">
          <name>Parameters</name>
          <t>The tables below define finite fields used in the remainder of this document.</t>
          <table anchor="field64">
            <name>Field64, an FFT-friendly field.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">MODULUS</td>
                <td align="left">2^32 * 4294967295 + 1</td>
              </tr>
              <tr>
                <td align="left">ENCODED_SIZE</td>
                <td align="left">8</td>
              </tr>
              <tr>
                <td align="left">Generator</td>
                <td align="left">7^4294967295</td>
              </tr>
              <tr>
                <td align="left">GEN_ORDER</td>
                <td align="left">2^32</td>
              </tr>
            </tbody>
          </table>
          <table anchor="field128">
            <name>Field128, an FFT-friendly field.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">MODULUS</td>
                <td align="left">2^66 * 4611686018427387897 + 1</td>
              </tr>
              <tr>
                <td align="left">ENCODED_SIZE</td>
                <td align="left">16</td>
              </tr>
              <tr>
                <td align="left">Generator</td>
                <td align="left">7^4611686018427387897</td>
              </tr>
              <tr>
                <td align="left">GEN_ORDER</td>
                <td align="left">2^66</td>
              </tr>
            </tbody>
          </table>
          <table anchor="field255">
            <name>Field255.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">MODULUS</td>
                <td align="left">2^255 - 19</td>
              </tr>
              <tr>
                <td align="left">ENCODED_SIZE</td>
                <td align="left">32</td>
              </tr>
            </tbody>
          </table>
          <ul empty="true">
            <li>
              <t>OPEN ISSUE We currently use big-endian for encoding field elements. However,
for implementations of <tt>GF(2^255-19)</tt>, little endian is more common. See
issue#90.</t>
            </li>
          </ul>
        </section>
      </section>
      <section anchor="prg">
        <name>Pseudorandom Generators</name>
        <t>A pseudorandom generator (PRG) is used to expand a short, (pseudo)random seed
into a long string of pseudorandom bits. A PRG suitable for this document
implements the interface specified in this section. Concrete constructions are
described in the subsections that follow.</t>
        <t>PRGs are defined by a class <tt>Prg</tt> with the following associated parameter:</t>
        <ul spacing="normal">
          <li>
            <tt>SEED_SIZE: Unsigned</tt> is the size (in bytes) of a seed.</li>
        </ul>
        <t>A concrete <tt>Prg</tt> implements the following class method:</t>
        <ul spacing="normal">
          <li>
            <tt>Prg(seed: Bytes, info: Bytes)</tt> constructs an instance of <tt>Prg</tt> from the given
seed and info string. The seed <bcp14>MUST</bcp14> be of length <tt>SEED_SIZE</tt> and <bcp14>MUST</bcp14> be
generated securely (i.e., it is either the output of <tt>gen_rand</tt> or a previous
invocation of the PRG). The info string is used for domain separation.</li>
          <li>
            <tt>prg.next(length: Unsigned)</tt> returns the next <tt>length</tt> bytes of output of PRG.
If the seed was securely generated, the output can be treated as pseudorandom.</li>
        </ul>
        <t>Each <tt>Prg</tt> has two derived class methods. The first is used to derive a fresh
seed from an existing one. The second is used to compute a sequence of
pseudorandom field elements. For each method, the seed <bcp14>MUST</bcp14> be of length
<tt>SEED_SIZE</tt> and <bcp14>MUST</bcp14> be generated securely (i.e., it is either the output of
<tt>gen_rand</tt> or a previous invocation of the PRG).</t>
        <figure anchor="prg-derived-methods">
          <name>Derived class methods for PRGs.</name>
          <artwork><![CDATA[
# Derive a new seed.
def derive_seed(Prg, seed: Bytes, info: Bytes) -> bytes:
    prg = Prg(seed, info)
    return prg.next(Prg.SEED_SIZE)

# Output the next `length` pseudorandom elements of `Field`.
def next_vec(self, Field, length: Unsigned):
    m = next_power_of_2(Field.MODULUS) - 1
    vec = []
    while len(vec) < length:
        x = OS2IP(self.next(Field.ENCODED_SIZE))
        x &= m
        if x < Field.MODULUS:
            vec.append(Field(x))
    return vec

# Expand the input `seed` into vector of `length` field elements.
def expand_into_vec(Prg,
                    Field,
                    seed: Bytes,
                    info: Bytes,
                    length: Unsigned):
    prg = Prg(seed, info)
    return prg.next_vec(Field, length)
]]></artwork>
        </figure>
        <section anchor="prg-aes128">
          <name>PrgAes128</name>
          <ul empty="true">
            <li>
              <t>OPEN ISSUE Phillipp points out that a fixed-key mode of AES may be more
performant (https://eprint.iacr.org/2019/074.pdf). See issue#32.</t>
            </li>
          </ul>
          <ul empty="true">
            <li>
              <t>TODO(issue #106) Decide if it's safe to model this construction as a random
oracle. <tt>PrgAes128.derive_seed()</tt> is used for the Fiat-Shamir heuristic in
Prio3 (<xref target="prio3"/>). A fixed-key is used for this step (the all-zero string). A
reasonable starting point would be to model AES as an ideal cipher.</t>
            </li>
          </ul>
          <t>Our first construction, <tt>PrgAes128</tt>, converts a blockcipher, namely AES-128,
into a PRG. Seed expansion involves two steps. In the first step, CMAC
<xref target="RFC4493"/> is applied to the seed and info string to get a fresh key. In the
second step, the fresh key is used in CTR-mode to produce a key stream for
generating the output. A fixed initialization vector (IV) is used.</t>
          <figure>
            <name>Definition of PRG PrgAes128.</name>
            <artwork><![CDATA[
class PrgAes128:

    SEED_SIZE: Unsigned = 16

    def __init__(self, seed, info):
        self.length_consumed = 0

        # Use CMAC as a pseudorandom function to derive a key.
        self.key = AES128-CMAC(seed, info)

    def next(self, length):
        self.length_consumed += length

        # CTR-mode encryption of the all-zero string of the desired
        # length and using a fixed, all-zero IV.
        stream = AES128-CTR(key, zeros(16), zeros(self.length_consumed))
        return stream[-length:]
]]></artwork>
          </figure>
        </section>
      </section>
    </section>
    <section anchor="prio3">
      <name>Prio3</name>
      <ul empty="true">
        <li>
          <t>NOTE This construction has not undergone significant security analysis.</t>
        </li>
      </ul>
      <t>This section describes Prio3, a VDAF for Prio <xref target="CGB17"/>. Prio is suitable for
a wide variety of aggregation functions, including (but not limited to) sum,
mean, standard deviation, estimation of quantiles (e.g., median), and linear
regression. In fact, the scheme described in this section is compatible with any
aggregation function that has the following structure:</t>
      <ul spacing="normal">
        <li>Each measurement is encoded as a vector over some finite field.</li>
        <li>Input validity is determined by an arithmetic circuit evaluated over the
encoded input. (An "arithmetic circuit" is a function comprised of arithmetic
operations in the field.) The circuit's output is a single field element: if
zero, then the input is said to be "valid"; otherwise, if the output is
non-zero, then the input is said to be "invalid".</li>
        <li>The aggregate result is obtained by summing up the encoded input vectors and
computing some function of the sum.</li>
      </ul>
      <t>At a high level, Prio3 distributes this computation as follows. Each Client
first shards its measurement by first encoding it, then splitting the vector into
secret shares and sending a share to each Aggregator. Next, in the preparation
phase, the Aggregators carry out a multi-party computation to determine if their
shares correspond to a valid input (as determined by the arithmetic circuit).
This computation involves a "proof" of validity generated by the Client. Next,
each Aggregator sums up its input shares locally. Finally, the Collector sums up
the aggregate shares and computes the aggregate result.</t>
      <t>This VDAF does not have an aggregation parameter. Instead, the output share is
derived from the input share by applying a fixed map. See <xref target="poplar1"/> for an
example of a VDAF that makes meaningful use of the aggregation parameter.</t>
      <t>As the name implies, Prio3 is a descendant of the original Prio construction.
A second iteration was deployed in the <xref target="ENPA"/> system, and like the VDAF
described here, the ENPA system was built from techniques introduced in
<xref target="BBCGGI19"/> that significantly improve communication cost. That system was
specialized for a particular aggregation function; the goal of Prio3 is to
provide the same level of generality as the original construction.</t>
      <t>The core component of Prio3 is a "Fully Linear Proof (FLP)" system. Introduced
by <xref target="BBCGGI19"/>, the FLP encapsulates the functionality required for encoding
and validating inputs. Prio3 can be thought of as a transformation of a
particular class of FLPs into a VDAF.</t>
      <t>The remainder of this section is structured as follows. The syntax for FLPs is
described in <xref target="flp"/>. The generic transformation of an FLP into Prio3 is
specified in <xref target="prio3-construction"/>. Next, a concrete FLP suitable for any
validity circuit is specified in <xref target="flp-generic"/>. Finally, instantiations of
Prio3 for various types of measurements are specified in
<xref target="prio3-instantiations"/>. Test vectors can be found in <xref target="test-vectors"/>.</t>
      <section anchor="flp">
        <name>Fully Linear Proof (FLP) Systems</name>
        <t>Conceptually, an FLP is a two-party protocol executed by a prover and a
verifier. In actual use, however, the prover's computation is carried out by the
Client, and the verifier's computation is distributed among the Aggregators. The
Client generates a "proof" of its input's validity and distributes shares of the
proof to the Aggregators. Each Aggregator then performs some a computation on
its input share and proof share locally and sends the result to the other
Aggregators. Combining the exchanged messages allows each Aggregator to decide
if it holds a share of a valid input. (See <xref target="prio3-construction"/> for details.)</t>
        <t>As usual, we will describe the interface implemented by a concrete FLP in terms
of an abstract base class <tt>Flp</tt> that specifies the set of methods and parameters
a concrete FLP must provide.</t>
        <t>The parameters provided by a concrete FLP are listed in <xref target="flp-param"/>.</t>
        <table anchor="flp-param">
          <name>Constants and types defined by a concrete FLP.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>PROVE_RAND_LEN</tt></td>
              <td align="left">Length of the prover randomness, the number of random field elements consumed by the prover when generating a proof</td>
            </tr>
            <tr>
              <td align="left">
                <tt>QUERY_RAND_LEN</tt></td>
              <td align="left">Length of the query randomness, the number of random field elements consumed by the verifier</td>
            </tr>
            <tr>
              <td align="left">
                <tt>JOINT_RAND_LEN</tt></td>
              <td align="left">Length of the joint randomness, the number of random field elements consumed by both the prover and verifier</td>
            </tr>
            <tr>
              <td align="left">
                <tt>INPUT_LEN</tt></td>
              <td align="left">Length of the encoded measurement (<xref target="flp-encode"/>)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>OUTPUT_LEN</tt></td>
              <td align="left">Length of the aggregatable output (<xref target="flp-encode"/>)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>PROOF_LEN</tt></td>
              <td align="left">Length of the proof</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VERIFIER_LEN</tt></td>
              <td align="left">Length of the verifier message generated by querying the input and proof</td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">Type of the measurement</td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">Type of the aggregate result</td>
            </tr>
            <tr>
              <td align="left">
                <tt>Field</tt></td>
              <td align="left">As defined in (<xref target="field"/>)</td>
            </tr>
          </tbody>
        </table>
        <t>An FLP specifies the following algorithms for generating and verifying proofs of
validity (encoding is described below in <xref target="flp-encode"/>):</t>
        <ul spacing="normal">
          <li>
            <tt>Flp.prove(input: Vec[Field], prove_rand: Vec[Field], joint_rand: Vec[Field])
-&gt; Vec[Field]</tt> is the deterministic proof-generation algorithm run by the
prover. Its inputs are the encoded input, the "prover randomness"
<tt>prove_rand</tt>, and the "joint randomness" <tt>joint_rand</tt>. The prover randomness is
used only by the prover, but the joint randomness is shared by both the prover
and verifier.</li>
          <li>
            <tt>Flp.query(input: Vec[Field], proof: Vec[Field], query_rand: Vec[Field],
joint_rand: Vec[Field], num_shares: Unsigned) -&gt; Vec[Field]</tt> is the
query-generation algorithm run by the verifier. This is used to "query" the
input and proof. The result of the query (i.e., the output of this function)
is called the "verifier message". In addition to the input and proof, this
algorithm takes as input the query randomness <tt>query_rand</tt> and the joint
randomness <tt>joint_rand</tt>. The former is used only by the verifier. <tt>num_shares</tt>
specifies how many input and proof shares were generated.</li>
          <li>
            <tt>Flp.decide(verifier: Vec[Field]) -&gt; Bool</tt> is the deterministic decision
algorithm run by the verifier. It takes as input the verifier message and
outputs a boolean indicating if the input from which it was generated is
valid.</li>
        </ul>
        <t>Our application requires that the FLP is "fully linear" in the sense defined in
<xref target="BBCGGI19"/>. As a practical matter, what this property implies is that, when
run on a share of the input and proof, the query-generation algorithm outputs a
share of the verifier message. Furthermore, the "strong zero-knowledge" property
of the FLP system ensures that the verifier message reveals nothing about the
input's validity. Therefore, to decide if an input is valid, the Aggregators
will run the query-generation algorithm locally, exchange verifier shares,
combine them to recover the verifier message, and run the decision algorithm.</t>
        <t>The query-generation algorithm includes a parameter <tt>num_shares</tt> that specifies
the number of shares of the input and proof that were generated. If these data
are not secret shared, then <tt>num_shares == 1</tt>. This parameter is useful for
certain FLP constructions. For example, the FLP in <xref target="flp-generic"/> is defined in
terms of an arithmetic circuit; when the circuit contains constants, it is
sometimes necessary to normalize those constants to ensure that the circuit's
output, when run on a valid input, is the same regardless of the number of
shares.</t>
        <t>An FLP is executed by the prover and verifier as follows:</t>
        <figure anchor="run-flp">
          <name>Execution of an FLP.</name>
          <artwork><![CDATA[
def run_flp(Flp, inp: Vec[Flp.Field], num_shares: Unsigned):
    joint_rand = Flp.Field.rand_vec(Flp.JOINT_RAND_LEN)
    prove_rand = Flp.Field.rand_vec(Flp.PROVE_RAND_LEN)
    query_rand = Flp.Field.rand_vec(Flp.QUERY_RAND_LEN)

    # Prover generates the proof.
    proof = Flp.prove(inp, prove_rand, joint_rand)

    # Verifier queries the input and proof.
    verifier = Flp.query(inp, proof, query_rand, joint_rand, num_shares)

    # Verifier decides if the input is valid.
    return Flp.decide(verifier)
]]></artwork>
        </figure>
        <t>The proof system is constructed so that, if <tt>input</tt> is a valid input, then
<tt>run_flp(Flp, input, 1)</tt> always returns <tt>True</tt>. On the other hand, if <tt>input</tt> is
invalid, then as long as <tt>joint_rand</tt> and <tt>query_rand</tt> are generated uniform
randomly, the output is <tt>False</tt> with overwhelming probability.</t>
        <t>We remark that <xref target="BBCGGI19"/> defines a much larger class of fully linear proof
systems than we consider here. In particular, what is called an "FLP" here is
called a 1.5-round, public-coin, interactive oracle proof system in their paper.</t>
        <section anchor="flp-encode">
          <name>Encoding the Input</name>
          <t>The type of measurement being aggregated is defined by the FLP. Hence, the FLP
also specifies a method of encoding raw measurements as a vector of field
elements:</t>
          <ul spacing="normal">
            <li>
              <tt>Flp.encode(measurement: Measurement) -&gt; Vec[Field]</tt> encodes a raw measurement
as a vector of field elements. The return value <bcp14>MUST</bcp14> be of length <tt>INPUT_LEN</tt>.</li>
          </ul>
          <t>For some FLPs, the encoded input also includes redundant field elements that are
useful for checking the proof, but which are not needed after the proof has been
checked. An example is the "integer sum" data type from <xref target="CGB17"/> in which an
integer in range <tt>[0, 2^k)</tt> is encoded as a vector of <tt>k</tt> field elements (this
type is also defined in <xref target="prio3aes128sum"/>). After consuming this vector,
all that is needed is the integer it represents. Thus the FLP defines an
algorithm for truncating the input to the length of the aggregated output:</t>
          <ul spacing="normal">
            <li>
              <tt>Flp.truncate(input: Vec[Field]) -&gt; Vec[Field]</tt> maps an encoded input to an
aggregatable output. The length of the input <bcp14>MUST</bcp14> be <tt>INPUT_LEN</tt> and the length
of the output <bcp14>MUST</bcp14> be <tt>OUTPUT_LEN</tt>.</li>
          </ul>
          <t>Once the aggregate shares have been computed and combined together, their sum
can be converted into the aggregate result. This could be a projection from
the FLP's field to the integers, or it could include additional
post-processing.</t>
          <ul spacing="normal">
            <li>
              <tt>Flp.decode(output: Vec[Field], num_measurements: Unsigned) -&gt; AggResult</tt>
maps a sum of aggregate shares to an aggregate result. The length of the
input <bcp14>MUST</bcp14> be <tt>OUTPUT_LEN</tt>. <tt>num_measurements</tt> is the number of measurements
that contributed to the aggregated output.</li>
          </ul>
          <t>We remark that, taken together, these three functionalities correspond roughly
to the notion of "Affine-aggregatable encodings (AFEs)" from <xref target="CGB17"/>.</t>
        </section>
      </section>
      <section anchor="prio3-construction">
        <name>Construction</name>
        <t>This section specifies <tt>Prio3</tt>, an implementation of the <tt>Vdaf</tt> interface
(<xref target="vdaf"/>). It has two generic parameters: an <tt>Flp</tt> (<xref target="flp"/>) and a <tt>Prg</tt>
(<xref target="prg"/>). The associated constants and types required by the <tt>Vdaf</tt> interface
are defined in <xref target="prio3-param"/>. The methods required for sharding, preparation,
aggregation, and unsharding are described in the remaining subsections.</t>
        <table anchor="prio3-param">
          <name>Associated parameters for the Prio3 VDAF.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>VERIFY_KEY_SIZE</tt></td>
              <td align="left">
                <tt>Prg.SEED_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>ROUNDS</tt></td>
              <td align="left">
                <tt>1</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>SHARES</tt></td>
              <td align="left">in <tt>[2, 255)</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">
                <tt>Flp.Measurement</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggParam</tt></td>
              <td align="left">
                <tt>None</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>Prep</tt></td>
              <td align="left">
                <tt>Tuple[Vec[Flp.Field], Optional[Bytes], Bytes]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>OutShare</tt></td>
              <td align="left">
                <tt>Vec[Flp.Field]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">
                <tt>Flp.AggResult</tt></td>
            </tr>
          </tbody>
        </table>
        <section anchor="sharding">
          <name>Sharding</name>
          <t>Recall from <xref target="flp"/> that the FLP syntax calls for "joint randomness" shared by
the prover (i.e., the Client) and the verifier (i.e., the Aggregators). VDAFs
have no such notion. Instead, the Client derives the joint randomness from its
input in a way that allows the Aggregators to reconstruct it from their input
shares. (This idea is based on the Fiat-Shamir heuristic and is described in
Section 6.2.3 of <xref target="BBCGGI19"/>.)</t>
          <t>The input-distribution algorithm involves the following steps:</t>
          <ol spacing="normal" type="1"><li>Encode the Client's raw measurement as an input for the FLP</li>
            <li>Shard the input into a sequence of input shares</li>
            <li>Derive the joint randomness from the input shares</li>
            <li>Run the FLP proof-generation algorithm using the derived joint randomness</li>
            <li>Shard the proof into a sequence of proof shares</li>
          </ol>
          <t>The algorithm is specified below. Notice that only one set of input and proof
shares (called the "leader" shares below) are vectors of field elements. The
other shares (called the "helper" shares) are represented instead by PRG seeds,
which are expanded into vectors of field elements.</t>
          <t>The code refers to auxiliary functions for encoding the shares and deriving the
joint randomness. In particular, <tt>encode_leader_share</tt> and
<tt>encode_helper_share</tt> are used for encoding and <tt>joint_rand</tt> is used for joint
randomness. These are defined in <xref target="prio3-helper-functions"/>.</t>
          <figure anchor="prio3-eval-input">
            <name>Input-distribution algorithm for Prio3.</name>
            <artwork><![CDATA[
def measurement_to_input_shares(Prio3, measurement):
    # Domain separation tag for PRG info string
    dst = VERSION + I2OSP(Prio3.ID, 4)
    inp = Prio3.Flp.encode(measurement)

    # Generate input shares.
    leader_input_share = inp
    k_helper_input_shares = []
    k_helper_blinds = []
    k_joint_rand_parts = []
    for j in range(Prio3.SHARES-1):
        k_blind = gen_rand(Prio3.Prg.SEED_SIZE)
        k_share = gen_rand(Prio3.Prg.SEED_SIZE)
        helper_input_share = Prio3.Prg.expand_into_vec(
            Prio3.Flp.Field,
            k_share,
            dst + byte(j+1),
            Prio3.Flp.INPUT_LEN
        )
        leader_input_share = vec_sub(leader_input_share,
                                     helper_input_share)
        encoded = Prio3.Flp.Field.encode_vec(helper_input_share)
        k_joint_rand_part = Prio3.Prg.derive_seed(
            k_blind, dst + byte(j+1) + encoded)
        k_helper_input_shares.append(k_share)
        k_helper_blinds.append(k_blind)
        k_joint_rand_parts.append(k_joint_rand_part)
    k_leader_blind = gen_rand(Prio3.Prg.SEED_SIZE)
    encoded = Prio3.Flp.Field.encode_vec(leader_input_share)
    k_leader_joint_rand_part = Prio3.Prg.derive_seed(
        k_leader_blind, dst + byte(0) + encoded)
    k_joint_rand_parts.insert(0, k_leader_joint_rand_part)

    # Compute joint randomness seed.
    k_joint_rand = Prio3.joint_rand(k_joint_rand_parts)

    # Generate the proof shares.
    prove_rand = Prio3.Prg.expand_into_vec(
        Prio3.Flp.Field,
        gen_rand(Prio3.Prg.SEED_SIZE),
        dst,
        Prio3.Flp.PROVE_RAND_LEN
    )
    joint_rand = Prio3.Prg.expand_into_vec(
        Prio3.Flp.Field,
        k_joint_rand,
        dst,
        Prio3.Flp.JOINT_RAND_LEN
    )
    proof = Prio3.Flp.prove(inp, prove_rand, joint_rand)
    leader_proof_share = proof
    k_helper_proof_shares = []
    for j in range(Prio3.SHARES-1):
        k_share = gen_rand(Prio3.Prg.SEED_SIZE)
        k_helper_proof_shares.append(k_share)
        helper_proof_share = Prio3.Prg.expand_into_vec(
            Prio3.Flp.Field,
            k_share,
            dst + byte(j+1),
            Prio3.Flp.PROOF_LEN
        )
        leader_proof_share = vec_sub(leader_proof_share,
                                     helper_proof_share)

    # The Leader's "hint" consists of the joint randomness parts of the
    # other Aggregators.
    k_leader_hint = k_joint_rand_parts[1:]
    input_shares = []
    input_shares.append(Prio3.encode_leader_share(
        leader_input_share,
        leader_proof_share,
        k_leader_blind,
        k_leader_hint,
    ))
    for j in range(Prio3.SHARES-1):
        # Each Helper's hint consists of the joint randomness part of the
        # other Aggregators.
        k_helper_hint = k_joint_rand_parts[:j+1] + \
                        k_joint_rand_parts[j+2:]
        input_shares.append(Prio3.encode_helper_share(
            k_helper_input_shares[j],
            k_helper_proof_shares[j],
            k_helper_blinds[j],
            k_helper_hint,
        ))
    return (b'', input_shares)
]]></artwork>
          </figure>
        </section>
        <section anchor="preparation">
          <name>Preparation</name>
          <t>This section describes the process of recovering output shares from the input
shares. The high-level idea is that each Aggregator first queries its input and
proof share locally, then exchanges its verifier share with the other
Aggregators. The verifier shares are then combined into the verifier message,
which is used to decide whether to accept.</t>
          <t>In addition, the Aggregators must ensure that they have all used the same joint
randomness for the query-generation algorithm. The joint randomness is generated
by a PRG seed. Each Aggregator derives a "part" of this seed from its input
share and the "blind" generated by the client. The seed is derived by hashing
together the parts, so before running the query-generation algorithm, it must
first gather the parts derived by the other Aggregators.</t>
          <t>In order to avoid extra round of communication, the Client sends each Aggregator
a "hint" consisting of the other Aggregators' parts of the joint randomness
seed. This leaves open the possibility that the Client cheated by, say, forcing
the Aggregators to use joint randomness that biases the proof check procedure
some way in its favor. To mitigate this, the Aggregators also check that they
have all computed the same joint randomness seed before accepting their output
shares. To do so, they exchange their parts of the joint randomness along with
their verifier shares.</t>
          <t>The algorithms required for preparation are defined as follows. These algorithms
make use of methods defined in <xref target="prio3-helper-functions"/>.</t>
          <figure anchor="prio3-prep-state">
            <name>Preparation state for Prio3.</name>
            <artwork><![CDATA[
def prep_init(Prio3, verify_key, agg_id, _agg_param,
              nonce, _public_share, input_share):
    # Domain separation tag for PRG info string
    dst = VERSION + I2OSP(Prio3.ID, 4)

    (input_share, proof_share, k_blind, k_hint) = \
        Prio3.decode_leader_share(input_share) if agg_id == 0 else \
        Prio3.decode_helper_share(dst, agg_id, input_share)
    out_share = Prio3.Flp.truncate(input_share)

    # Compute joint randomness.
    joint_rand, k_joint_rand, k_joint_rand_part = [], None, None
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        encoded = Prio3.Flp.Field.encode_vec(input_share)
        k_joint_rand_part = Prio3.Prg.derive_seed(
            k_blind, dst + byte(agg_id) + encoded)
        k_joint_rand_parts = k_hint[:agg_id] + \
                             [k_joint_rand_part] + \
                             k_hint[agg_id:]
        k_joint_rand = Prio3.joint_rand(k_joint_rand_parts)
        joint_rand = Prio3.Prg.expand_into_vec(
            Prio3.Flp.Field,
            k_joint_rand,
            dst,
            Prio3.Flp.JOINT_RAND_LEN
        )

    # Query the input and proof share.
    query_rand = Prio3.Prg.expand_into_vec(
        Prio3.Flp.Field,
        verify_key,
        dst + byte(255) + nonce,
        Prio3.Flp.QUERY_RAND_LEN
    )
    verifier_share = Prio3.Flp.query(input_share,
                                     proof_share,
                                     query_rand,
                                     joint_rand,
                                     Prio3.SHARES)

    prep_msg = Prio3.encode_prep_share(verifier_share,
                                       k_joint_rand_part)
    return (out_share, k_joint_rand, prep_msg)

def prep_next(Prio3, prep, inbound):
    (out_share, k_joint_rand, prep_msg) = prep

    if inbound is None:
        return (prep, prep_msg)

    k_joint_rand_check = Prio3.decode_prep_msg(inbound)
    if k_joint_rand_check != k_joint_rand:
        raise ERR_VERIFY # joint randomness check failed

    return out_share

def prep_shares_to_prep(Prio3, _agg_param, prep_shares):
    dst = VERSION + I2OSP(Prio3.ID, 4)
    verifier = Prio3.Flp.Field.zeros(Prio3.Flp.VERIFIER_LEN)
    k_joint_rand_parts = []
    for encoded in prep_shares:
        (verifier_share, k_joint_rand_part) = \
            Prio3.decode_prep_share(encoded)

        verifier = vec_add(verifier, verifier_share)

        if Prio3.Flp.JOINT_RAND_LEN > 0:
            k_joint_rand_parts.append(k_joint_rand_part)

    if not Prio3.Flp.decide(verifier):
        raise ERR_VERIFY # proof verifier check failed

    k_joint_rand_check = None
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        k_joint_rand_check = Prio3.joint_rand(k_joint_rand_parts)
    return Prio3.encode_prep_msg(k_joint_rand_check)
]]></artwork>
          </figure>
        </section>
        <section anchor="aggregation">
          <name>Aggregation</name>
          <t>Aggregating a set of output shares is simply a matter of adding up the vectors
element-wise.</t>
          <figure anchor="prio3-out2agg">
            <name>Aggregation algorithm for Prio3.</name>
            <artwork><![CDATA[
def out_shares_to_agg_share(Prio3, _agg_param, out_shares):
    agg_share = Prio3.Flp.Field.zeros(Prio3.Flp.OUTPUT_LEN)
    for out_share in out_shares:
        agg_share = vec_add(agg_share, out_share)
    return Prio3.Flp.Field.encode_vec(agg_share)
]]></artwork>
          </figure>
        </section>
        <section anchor="unsharding">
          <name>Unsharding</name>
          <t>To unshard a set of aggregate shares, the Collector first adds up the vectors
element-wise. It then converts each element of the vector into an integer.</t>
          <figure anchor="prio3-agg-output">
            <name>Computation of the aggregate result for Prio3.</name>
            <artwork><![CDATA[
def agg_shares_to_result(Prio3, _agg_param, agg_shares,
                         num_measurements):
    agg = Prio3.Flp.Field.zeros(Prio3.Flp.OUTPUT_LEN)
    for agg_share in agg_shares:
        agg = vec_add(agg, Prio3.Flp.Field.decode_vec(agg_share))
    return Prio3.Flp.decode(agg, num_measurements)
]]></artwork>
          </figure>
        </section>
        <section anchor="prio3-helper-functions">
          <name>Auxiliary Functions</name>
          <figure anchor="prio3-helpers">
            <name>Helper functions required for Prio3.</name>
            <artwork><![CDATA[
def joint_rand(Prio3, k_joint_rand_parts):
    dst = VERSION + I2OSP(Prio3.ID, 4)
    return Prio3.Prg.derive_seed(
        zeros(Prio3.Prg.SEED_SIZE),
        dst + byte(255) + concat(k_joint_rand_parts))

def encode_leader_share(Prio3,
                        input_share,
                        proof_share,
                        k_blind,
                        k_hint):
    encoded = Bytes()
    encoded += Prio3.Flp.Field.encode_vec(input_share)
    encoded += Prio3.Flp.Field.encode_vec(proof_share)
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        encoded += k_blind
        encoded += concat(k_hint)
    return encoded

def decode_leader_share(Prio3, encoded):
    l = Prio3.Flp.Field.ENCODED_SIZE * Prio3.Flp.INPUT_LEN
    encoded_input_share, encoded = encoded[:l], encoded[l:]
    input_share = Prio3.Flp.Field.decode_vec(encoded_input_share)
    l = Prio3.Flp.Field.ENCODED_SIZE * Prio3.Flp.PROOF_LEN
    encoded_proof_share, encoded = encoded[:l], encoded[l:]
    proof_share = Prio3.Flp.Field.decode_vec(encoded_proof_share)
    l = Prio3.Prg.SEED_SIZE
    k_blind, k_hint = None, None
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        k_blind, encoded = encoded[:l], encoded[l:]
        k_hint = []
        for _ in range(Prio3.SHARES-1):
            k_joint_rand_part, encoded = encoded[:l], encoded[l:]
            k_hint.append(k_joint_rand_part)
    if len(encoded) != 0:
        raise ERR_DECODE
    return (input_share, proof_share, k_blind, k_hint)

def encode_helper_share(Prio3,
                        k_input_share,
                        k_proof_share,
                        k_blind,
                        k_hint):
    encoded = Bytes()
    encoded += k_input_share
    encoded += k_proof_share
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        encoded += k_blind
        encoded += concat(k_hint)
    return encoded

def decode_helper_share(Prio3, dst, agg_id, encoded):
    l = Prio3.Prg.SEED_SIZE
    k_input_share, encoded = encoded[:l], encoded[l:]
    input_share = Prio3.Prg.expand_into_vec(Prio3.Flp.Field,
                                            k_input_share,
                                            dst + byte(agg_id),
                                            Prio3.Flp.INPUT_LEN)
    k_proof_share, encoded = encoded[:l], encoded[l:]
    proof_share = Prio3.Prg.expand_into_vec(Prio3.Flp.Field,
                                            k_proof_share,
                                            dst + byte(agg_id),
                                            Prio3.Flp.PROOF_LEN)
    k_blind, k_hint = None, None
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        k_blind, encoded = encoded[:l], encoded[l:]
        k_hint = []
        for _ in range(Prio3.SHARES-1):
            k_joint_rand_part, encoded = encoded[:l], encoded[l:]
            k_hint.append(k_joint_rand_part)
    if len(encoded) != 0:
        raise ERR_DECODE
    return (input_share, proof_share, k_blind, k_hint)

def encode_prep_share(Prio3, verifier, k_joint_rand):
    encoded = Bytes()
    encoded += Prio3.Flp.Field.encode_vec(verifier)
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        encoded += k_joint_rand
    return encoded

def decode_prep_share(Prio3, encoded):
    l = Prio3.Flp.Field.ENCODED_SIZE * Prio3.Flp.VERIFIER_LEN
    encoded_verifier, encoded = encoded[:l], encoded[l:]
    verifier = Prio3.Flp.Field.decode_vec(encoded_verifier)
    k_joint_rand = None
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        l = Prio3.Prg.SEED_SIZE
        k_joint_rand, encoded = encoded[:l], encoded[l:]
    if len(encoded) != 0:
        raise ERR_DECODE
    return (verifier, k_joint_rand)

def encode_prep_msg(Prio3, k_joint_rand_check):
    encoded = Bytes()
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        encoded += k_joint_rand_check
    return encoded

def decode_prep_msg(Prio3, encoded):
    k_joint_rand_check = None
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        l = Prio3.Prg.SEED_SIZE
        k_joint_rand_check, encoded = encoded[:l], encoded[l:]
    if len(encoded) != 0:
        raise ERR_DECODE
    return k_joint_rand_check
]]></artwork>
          </figure>
        </section>
      </section>
      <section anchor="flp-generic">
        <name>A General-Purpose FLP</name>
        <t>This section describes an FLP based on the construction from in <xref target="BBCGGI19"/>,
Section 4.2. We begin in <xref target="flp-generic-overview"/> with an overview of their proof
system and the extensions to their proof system made here. The construction is
specified in <xref target="flp-generic-construction"/>.</t>
        <ul empty="true">
          <li>
            <t>OPEN ISSUE We're not yet sure if specifying this general-purpose FLP is
desirable. It might be preferable to specify specialized FLPs for each data
type that we want to standardize, for two reasons. First, clear and concise
specifications are likely easier to write for specialized FLPs rather than the
general one. Second, we may end up tailoring each FLP to the measurement type
in a way that improves performance, but breaks compatibility with the
general-purpose FLP.</t>
            <t>In any case, we can't make this decision until we know which data types to
standardize, so for now, we'll stick with the general-purpose construction.
The reference implementation can be found at
https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc.</t>
          </li>
        </ul>
        <ul empty="true">
          <li>
            <t>OPEN ISSUE Chris Wood points out that the this section reads more like a paper
than a standard. Eventually we'll want to work this into something that is
readily consumable by the CFRG.</t>
          </li>
        </ul>
        <section anchor="flp-generic-overview">
          <name>Overview</name>
          <t>In the proof system of <xref target="BBCGGI19"/>, validity is defined via an arithmetic
circuit evaluated over the input: If the circuit output is zero, then the input
is deemed valid; otherwise, if the circuit output is non-zero, then the input is
deemed invalid. Thus the goal of the proof system is merely to allow the
verifier to evaluate the validity circuit over the input. For our application
(<xref target="prio3"/>), this computation is distributed among multiple Aggregators, each of
which has only a share of the input.</t>
          <t>Suppose for a moment that the validity circuit <tt>C</tt> is affine, meaning its only
operations are addition and multiplication-by-constant. In particular, suppose
the circuit does not contain a multiplication gate whose operands are both
non-constant. Then to decide if an input <tt>x</tt> is valid, each Aggregator could
evaluate <tt>C</tt> on its share of <tt>x</tt> locally, broadcast the output share to its
peers, then combine the output shares locally to recover <tt>C(x)</tt>. This is true
because for any <tt>SHARES</tt>-way secret sharing of <tt>x</tt> it holds that</t>
          <artwork><![CDATA[
C(x_shares[0] + ... + x_shares[SHARES-1]) =
    C(x_shares[0]) + ... + C(x_shares[SHARES-1])
]]></artwork>
          <t>(Note that, for this equality to hold, it may be necessary to scale any
constants in the circuit by <tt>SHARES</tt>.) However this is not the case if <tt>C</tt> is
not-affine (i.e., it contains at least one multiplication gate whose operands
are non-constant). In the proof system of <xref target="BBCGGI19"/>, the proof is designed to
allow the (distributed) verifier to compute the non-affine operations using only
linear operations on (its share of) the input and proof.</t>
          <t>To make this work, the proof system is restricted to validity circuits that
exhibit a special structure. Specifically, an arithmetic circuit with "G-gates"
(see <xref target="BBCGGI19"/>, Definition 5.2) is composed of affine gates and any number of
instances of a distinguished gate <tt>G</tt>, which may be non-affine. We will refer to
this class of circuits as 'gadget circuits' and to <tt>G</tt> as the "gadget".</t>
          <t>As an illustrative example, consider a validity circuit <tt>C</tt> that recognizes the
set <tt>L = set([0], [1])</tt>. That is, <tt>C</tt> takes as input a length-1 vector <tt>x</tt> and
returns 0 if <tt>x[0]</tt> is in <tt>[0,2)</tt> and outputs something else otherwise. This
circuit can be expressed as the following degree-2 polynomial:</t>
          <artwork><![CDATA[
C(x) = (x[0] - 1) * x[0] = x[0]^2 - x[0]
]]></artwork>
          <t>This polynomial recognizes <tt>L</tt> because <tt>x[0]^2 = x[0]</tt> is only true if <tt>x[0] ==
0</tt> or <tt>x[0] == 1</tt>. Notice that the polynomial involves a non-affine operation,
<tt>x[0]^2</tt>. In order to apply <xref target="BBCGGI19"/>, Theorem 4.3, the circuit needs to be
rewritten in terms of a gadget that subsumes this non-affine operation. For
example, the gadget might be multiplication:</t>
          <artwork><![CDATA[
Mul(left, right) = left * right
]]></artwork>
          <t>The validity circuit can then be rewritten in terms of <tt>Mul</tt> like so:</t>
          <artwork><![CDATA[
C(x[0]) = Mul(x[0], x[0]) - x[0]
]]></artwork>
          <t>The proof system of <xref target="BBCGGI19"/> allows the verifier to evaluate each instance
of the gadget (i.e., <tt>Mul(x[0], x[0])</tt> in our example) using a linear function
of the input and proof. The proof is constructed roughly as follows. Let <tt>C</tt> be
the validity circuit and suppose the gadget is arity-<tt>L</tt> (i.e., it has <tt>L</tt> input
wires.). Let <tt>wire[j-1,k-1]</tt> denote the value of the <tt>j</tt>th wire of the <tt>k</tt>th
call to the gadget during the evaluation of <tt>C(x)</tt>. Suppose there are <tt>M</tt> such
calls and fix distinct field elements <tt>alpha[0], ..., alpha[M-1]</tt>. (We will
require these points to have a special property, as we'll discuss in
<xref target="flp-generic-overview-extensions"/>; but for the moment it is only important
that they are distinct.)</t>
          <t>The prover constructs from <tt>wire</tt> and <tt>alpha</tt> a polynomial that, when evaluated
at <tt>alpha[k-1]</tt>, produces the output of the <tt>k</tt>th call to the gadget. Let us
call this the "gadget polynomial". Polynomial evaluation is linear, which means
that, in the distributed setting, the Client can disseminate additive shares of
the gadget polynomial that the Aggregators then use to compute additive shares
of each gadget output, allowing each Aggregator to compute its share of <tt>C(x)</tt>
locally.</t>
          <t>There is one more wrinkle, however: It is still possible for a malicious prover
to produce a gadget polynomial that would result in <tt>C(x)</tt> being computed
incorrectly, potentially resulting in an invalid input being accepted. To
prevent this, the verifier performs a probabilistic test to check that the
gadget polynomial is well-formed. This test, and the procedure for constructing
the gadget polynomial, are described in detail in <xref target="flp-generic-construction"/>.</t>
          <section anchor="flp-generic-overview-extensions">
            <name>Extensions</name>
            <t>The FLP described in the next section extends the proof system <xref target="BBCGGI19"/>,
Section 4.2 in three ways.</t>
            <t>First, the validity circuit in our construction includes an additional, random
input (this is the "joint randomness" derived from the input shares in Prio3;
see <xref target="prio3-construction"/>). This allows for circuit optimizations that trade a
small soundness error for a shorter proof. For example, consider a circuit that
recognizes the set of length-<tt>N</tt> vectors for which each element is either one or
zero. A deterministic circuit could be constructed for this language, but it
would involve a large number of multiplications that would result in a large
proof. (See the discussion in <xref target="BBCGGI19"/>, Section 5.2 for details). A much
shorter proof can be constructed for the following randomized circuit:</t>
            <artwork><![CDATA[
C(inp, r) = r * Range2(inp[0]) + ... + r^N * Range2(inp[N-1])
]]></artwork>
            <t>(Note that this is a special case of <xref target="BBCGGI19"/>, Theorem 5.2.) Here <tt>inp</tt> is
the length-<tt>N</tt> input and <tt>r</tt> is a random field element. The gadget circuit
<tt>Range2</tt> is the "range-check" polynomial described above, i.e., <tt>Range2(x) = x^2 -
x</tt>. The idea is that, if <tt>inp</tt> is valid (i.e., each <tt>inp[j]</tt> is in <tt>[0,2)</tt>),
then the circuit will evaluate to 0 regardless of the value of <tt>r</tt>; but if
<tt>inp[j]</tt> is not in <tt>[0,2)</tt> for some <tt>j</tt>, the output will be non-zero with high
probability.</t>
            <t>The second extension implemented by our FLP allows the validity circuit to
contain multiple gadget types. (This generalization was suggested in
<xref target="BBCGGI19"/>, Remark 4.5.) For example, the following circuit is allowed, where
<tt>Mul</tt> and <tt>Range2</tt> are the gadgets defined above (the input has length <tt>N+1</tt>):</t>
            <artwork><![CDATA[
C(inp, r) = r * Range2(inp[0]) + ... + r^N * Range2(inp[N-1]) + \
            2^0 * inp[0]       + ... + 2^(N-1) * inp[N-1]     - \
            Mul(inp[N], inp[N])
]]></artwork>
            <t>Finally, <xref target="BBCGGI19"/>, Theorem 4.3 makes no restrictions on the choice of the
fixed points <tt>alpha[0], ..., alpha[M-1]</tt>, other than to require that the points
are distinct. In this document, the fixed points are chosen so that the gadget
polynomial can be constructed efficiently using the Cooley-Tukey FFT ("Fast
Fourier Transform") algorithm. Note that this requires the field to be
"FFT-friendly" as defined in <xref target="field-fft-friendly"/>.</t>
          </section>
        </section>
        <section anchor="flp-generic-valid">
          <name>Validity Circuits</name>
          <t>The FLP described in <xref target="flp-generic-construction"/> is defined in terms of a
validity circuit <tt>Valid</tt> that implements the interface described here.</t>
          <t>A concrete <tt>Valid</tt> defines the following parameters:</t>
          <table>
            <name>Validity circuit parameters.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Description</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">A list of gadgets</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">Number of times each gadget is called</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>INPUT_LEN</tt></td>
                <td align="left">Length of the input</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">Length of the aggregatable output</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">Length of the random input</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">The type of measurement</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">Type of the aggregate result</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">An FFT-friendly finite field as defined in <xref target="field-fft-friendly"/></td>
              </tr>
            </tbody>
          </table>
          <t>Each gadget <tt>G</tt> in <tt>GADGETS</tt> defines a constant <tt>DEGREE</tt> that specifies the
circuit's "arithmetic degree". This is defined to be the degree of the
polynomial that computes it. For example, the <tt>Mul</tt> circuit in
<xref target="flp-generic-overview"/> is defined by the polynomial <tt>Mul(x) = x * x</tt>, which
has degree <tt>2</tt>. Hence, the arithmetic degree of this gadget is <tt>2</tt>.</t>
          <t>Each gadget also defines a parameter <tt>ARITY</tt> that specifies the circuit's arity
(i.e., the number of input wires).</t>
          <t>A concrete <tt>Valid</tt> provides the following methods for encoding a measurement as
an input vector, truncating an input vector to the length of an aggregatable
output, and converting an aggregated output to an aggregate result:</t>
          <ul spacing="normal">
            <li>
              <tt>Valid.encode(measurement: Measurement) -&gt; Vec[Field]</tt> returns a vector of
length <tt>INPUT_LEN</tt> representing a measurement.</li>
            <li>
              <tt>Valid.truncate(input: Vec[Field]) -&gt; Vec[Field]</tt> returns a vector of length
<tt>OUTPUT_LEN</tt> representing an aggregatable output.</li>
            <li>
              <tt>Valid.decode(output: Vec[Field], num_measurements: Unsigned) -&gt; AggResult</tt>
returns an aggregate result.</li>
          </ul>
          <t>Finally, the following class methods are derived for each concrete <tt>Valid</tt>:</t>
          <figure>
            <name>Derived methods for validity circuits.</name>
            <artwork><![CDATA[
# Length of the prover randomness.
def prove_rand_len(Valid):
    return sum(map(lambda g: g.ARITY, Valid.GADGETS))

# Length of the query randomness.
def query_rand_len(Valid):
    return len(Valid.GADGETS)

# Length of the proof.
def proof_len(Valid):
    length = 0
    for (g, g_calls) in zip(Valid.GADGETS, Valid.GADGET_CALLS):
        P = next_power_of_2(1 + g_calls)
        length += g.ARITY + g.DEGREE * (P - 1) + 1
    return length

# Length of the verifier message.
def verifier_len(Valid):
    length = 1
    for g in Valid.GADGETS:
        length += g.ARITY + 1
    return length
]]></artwork>
          </figure>
        </section>
        <section anchor="flp-generic-construction">
          <name>Construction</name>
          <t>This section specifies <tt>FlpGeneric</tt>, an implementation of the <tt>Flp</tt> interface
(<xref target="flp"/>). It has as a generic parameter a validity circuit <tt>Valid</tt> implementing
the interface defined in <xref target="flp-generic-valid"/>.</t>
          <ul empty="true">
            <li>
              <t>NOTE A reference implementation can be found in
https://github.com/cfrg/draft-irtf-cfrg-vdaf/blob/main/poc/flp_generic.sage.</t>
            </li>
          </ul>
          <t>The FLP parameters for <tt>FlpGeneric</tt> are defined in <xref target="flp-generic-param"/>. The
required methods for generating the proof, generating the verifier, and deciding
validity are specified in the remaining subsections.</t>
          <t>In the remainder, we let <tt>[n]</tt> denote the set <tt>{1, ..., n}</tt> for positive integer
<tt>n</tt>. We also define the following constants:</t>
          <ul spacing="normal">
            <li>Let <tt>H = len(Valid.GADGETS)</tt></li>
            <li>
              <t>For each <tt>i</tt> in <tt>[H]</tt>:
              </t>
              <ul spacing="normal">
                <li>Let <tt>G_i = Valid.GADGETS[i]</tt></li>
                <li>Let <tt>L_i = Valid.GADGETS[i].ARITY</tt></li>
                <li>Let <tt>M_i = Valid.GADGET_CALLS[i]</tt></li>
                <li>Let <tt>P_i = next_power_of_2(M_i+1)</tt></li>
                <li>Let <tt>alpha_i = Field.gen()^(Field.GEN_ORDER / P_i)</tt></li>
              </ul>
            </li>
          </ul>
          <table anchor="flp-generic-param">
            <name>FLP Parameters of FlpGeneric.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>PROVE_RAND_LEN</tt></td>
                <td align="left">
                  <tt>Valid.prove_rand_len()</tt> (see <xref target="flp-generic-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>QUERY_RAND_LEN</tt></td>
                <td align="left">
                  <tt>Valid.query_rand_len()</tt> (see <xref target="flp-generic-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>Valid.JOINT_RAND_LEN</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>INPUT_LEN</tt></td>
                <td align="left">
                  <tt>Valid.INPUT_LEN</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>Valid.OUTPUT_LEN</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOF_LEN</tt></td>
                <td align="left">
                  <tt>Valid.proof_len()</tt> (see <xref target="flp-generic-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>VERIFIER_LEN</tt></td>
                <td align="left">
                  <tt>Valid.verifier_len()</tt> (see <xref target="flp-generic-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>Valid.Measurement</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Valid.Field</tt></td>
              </tr>
            </tbody>
          </table>
          <section anchor="flp-generic-construction-prove">
            <name>Proof Generation</name>
            <t>On input <tt>inp</tt>, <tt>prove_rand</tt>, and <tt>joint_rand</tt>, the proof is computed as
follows:</t>
            <ol spacing="normal" type="1"><li>For each <tt>i</tt> in <tt>[H]</tt> create an empty table <tt>wire_i</tt>.</li>
              <li>Partition the prover randomness <tt>prove_rand</tt> into subvectors <tt>seed_1, ...,
seed_H</tt> where <tt>len(seed_i) == L_i</tt> for all <tt>i</tt> in <tt>[H]</tt>. Let us call these
the "wire seeds" of each gadget.</li>
              <li>Evaluate <tt>Valid</tt> on input of <tt>inp</tt> and <tt>joint_rand</tt>, recording the inputs of
each gadget in the corresponding table. Specifically, for every <tt>i</tt> in <tt>[H]</tt>,
set <tt>wire_i[j-1,k-1]</tt> to the value on the <tt>j</tt>th wire into the <tt>k</tt>th call to
gadget <tt>G_i</tt>.</li>
              <li>
                <t>Compute the "wire polynomials". That is, for every <tt>i</tt> in <tt>[H]</tt> and <tt>j</tt> in
<tt>[L_i]</tt>, construct <tt>poly_wire_i[j-1]</tt>, the <tt>j</tt>th wire polynomial for the
<tt>i</tt>th gadget, as follows:  </t>
                <ul spacing="normal">
                  <li>Let <tt>w = [seed_i[j-1], wire_i[j-1,0], ..., wire_i[j-1,M_i-1]]</tt>.</li>
                  <li>Let <tt>padded_w = w + Field.zeros(P_i - len(w))</tt>.</li>
                </ul>
                <ul empty="true">
                  <li>
                    <t>NOTE We pad <tt>w</tt> to the nearest power of 2 so that we can use FFT for
interpolating the wire polynomials. Perhaps there is some clever math for
picking <tt>wire_inp</tt> in a way that avoids having to pad.</t>
                  </li>
                </ul>
                <ul spacing="normal">
                  <li>Let <tt>poly_wire_i[j-1]</tt> be the lowest degree polynomial for which
<tt>poly_wire_i[j-1](alpha_i^k) == padded_w[k]</tt> for all <tt>k</tt> in <tt>[P_i]</tt>.</li>
                </ul>
              </li>
              <li>
                <t>Compute the "gadget polynomials". That is, for every <tt>i</tt> in <tt>[H]</tt>:  </t>
                <ul spacing="normal">
                  <li>Let <tt>poly_gadget_i = G_i(poly_wire_i[0], ..., poly_wire_i[L_i-1])</tt>. That
is, evaluate the circuit <tt>G_i</tt> on the wire polynomials for the <tt>i</tt>th
gadget. (Arithmetic is in the ring of polynomials over <tt>Field</tt>.)</li>
                </ul>
              </li>
            </ol>
            <t>The proof is the vector <tt>proof = seed_1 + coeff_1 + ... + seed_H + coeff_H</tt>,
where <tt>coeff_i</tt> is the vector of coefficients of <tt>poly_gadget_i</tt> for each <tt>i</tt> in
<tt>[H]</tt>.</t>
          </section>
          <section anchor="flp-generic-construction-query">
            <name>Query Generation</name>
            <t>On input of <tt>inp</tt>, <tt>proof</tt>, <tt>query_rand</tt>, and <tt>joint_rand</tt>, the verifier message
is generated as follows:</t>
            <ol spacing="normal" type="1"><li>For every <tt>i</tt> in <tt>[H]</tt> create an empty table <tt>wire_i</tt>.</li>
              <li>Partition <tt>proof</tt> into the subvectors <tt>seed_1</tt>, <tt>coeff_1</tt>, ..., <tt>seed_H</tt>,
<tt>coeff_H</tt> defined in <xref target="flp-generic-construction-prove"/>.</li>
              <li>Evaluate <tt>Valid</tt> on input of <tt>inp</tt> and <tt>joint_rand</tt>, recording the inputs of
each gadget in the corresponding table. This step is similar to the prover's
step (3.) except the verifier does not evaluate the gadgets. Instead, it
computes the output of the <tt>k</tt>th call to <tt>G_i</tt> by evaluating
<tt>poly_gadget_i(alpha_i^k)</tt>. Let <tt>v</tt> denote the output of the circuit
evaluation.</li>
              <li>Compute the wire polynomials just as in the prover's step (4.).</li>
              <li>
                <t>Compute the tests for well-formedness of the gadget polynomials. That is, for
every <tt>i</tt> in <tt>[H]</tt>:  </t>
                <ul spacing="normal">
                  <li>Let <tt>t = query_rand[i]</tt>. Check if <tt>t^(P_i) == 1</tt>: If so, then raise
ERR_ABORT and halt. (This prevents the verifier from inadvertently leaking
a gadget output in the verifier message.)</li>
                  <li>Let <tt>y_i = poly_gadget_i(t)</tt>.</li>
                  <li>For each <tt>j</tt> in <tt>[0,L_i)</tt> let <tt>x_i[j-1] = poly_wire_i[j-1](t)</tt>.</li>
                </ul>
              </li>
            </ol>
            <t>The verifier message is the vector <tt>verifier = [v] + x_1 + [y_1] + ... + x_H +
[y_H]</tt>.</t>
          </section>
          <section anchor="decision">
            <name>Decision</name>
            <t>On input of vector <tt>verifier</tt>, the verifier decides if the input is valid as
follows:</t>
            <ol spacing="normal" type="1"><li>Parse <tt>verifier</tt> into <tt>v</tt>, <tt>x_1</tt>, <tt>y_1</tt>, ..., <tt>x_H</tt>, <tt>y_H</tt> as defined in
<xref target="flp-generic-construction-query"/>.</li>
              <li>
                <t>Check for well-formedness of the gadget polynomials. For every <tt>i</tt> in <tt>[H]</tt>:  </t>
                <ul spacing="normal">
                  <li>Let <tt>z = G_i(x_i)</tt>. That is, evaluate the circuit <tt>G_i</tt> on <tt>x_i</tt> and set
<tt>z</tt> to the output.</li>
                  <li>If <tt>z != y_i</tt>, then return <tt>False</tt> and halt.</li>
                </ul>
              </li>
              <li>Return <tt>True</tt> if <tt>v == 0</tt> and <tt>False</tt> otherwise.</li>
            </ol>
          </section>
          <section anchor="encoding">
            <name>Encoding</name>
            <t>The FLP encoding and truncation methods invoke <tt>Valid.encode</tt>,
<tt>Valid.truncate</tt>, and <tt>Valid.decode</tt> in the natural way.</t>
          </section>
        </section>
      </section>
      <section anchor="prio3-instantiations">
        <name>Instantiations</name>
        <t>This section specifies instantiations of Prio3 for various measurement types.
Each uses <tt>FlpGeneric</tt> as the FLP (<xref target="flp-generic"/>) and is determined by a
validity circuit (<xref target="flp-generic-valid"/>) and a PRG (<xref target="prg"/>). Test vectors for
each can be found in <xref target="test-vectors"/>.</t>
        <ul empty="true">
          <li>
            <t>NOTE Reference implementations of each of these VDAFs can be found in
https://github.com/cfrg/draft-irtf-cfrg-vdaf/blob/main/poc/vdaf_prio3.sage.</t>
          </li>
        </ul>
        <section anchor="prio3aes128count">
          <name>Prio3Aes128Count</name>
          <t>Our first instance of Prio3 is for a simple counter: Each measurement is either
one or zero and the aggregate result is the sum of the measurements.</t>
          <t>This instance uses <tt>PrgAes128</tt> (<xref target="prg-aes128"/>) as its PRG. Its validity
circuit, denoted <tt>Count</tt>, uses <tt>Field64</tt> (<xref target="field64"/>) as its finite field. Its
gadget, denoted <tt>Mul</tt>, is the degree-2, arity-2 gadget defined as</t>
          <artwork><![CDATA[
def Mul(x, y):
    return x * y
]]></artwork>
          <t>The validity circuit is defined as</t>
          <artwork><![CDATA[
def Count(inp: Vec[Field64]):
    return Mul(inp[0], inp[0]) - inp[0]
]]></artwork>
          <t>The measurement is encoded and decoded as a singleton vector in the natural
way. The parameters for this circuit are summarized below.</t>
          <table>
            <name>Parameters of validity circuit Count.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">
                  <tt>[Mul]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[1]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>INPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>0</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>Unsigned</tt>, in range <tt>[0,2)</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">
                  <tt>Unsigned</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field64</tt> (<xref target="field64"/>)</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section anchor="prio3aes128sum">
          <name>Prio3Aes128Sum</name>
          <t>The next instance of Prio3 supports summing of integers in a pre-determined
range. Each measurement is an integer in range <tt>[0, 2^bits)</tt>, where <tt>bits</tt> is an
associated parameter.</t>
          <t>This instance of Prio3 uses <tt>PrgAes128</tt> (<xref target="prg-aes128"/>) as its PRG.
Its validity circuit, denoted <tt>Sum</tt>, uses <tt>Field128</tt> (<xref target="field128"/>) as its
finite field. The measurement is encoded as a length-<tt>bits</tt> vector of field
elements, where the <tt>l</tt>th element of the vector represents the <tt>l</tt>th bit of the
summand:</t>
          <artwork><![CDATA[
def encode(Sum, measurement: Integer):
    if 0 > measurement or measurement >= 2^Sum.INPUT_LEN:
        raise ERR_INPUT

    encoded = []
    for l in range(Sum.INPUT_LEN):
        encoded.append(Sum.Field((measurement >> l) & 1))
    return encoded

def truncate(Sum, inp):
    decoded = Sum.Field(0)
    for (l, b) in enumerate(inp):
        w = Sum.Field(1 << l)
        decoded += w * b
    return [decoded]

def decode(Sum, output, _num_measurements):
    return output[0].as_unsigned()
]]></artwork>
          <t>The validity circuit checks that the input consists of ones and zeros. Its
gadget, denoted <tt>Range2</tt>, is the degree-2, arity-1 gadget defined as</t>
          <artwork><![CDATA[
def Range2(x):
    return x^2 - x
]]></artwork>
          <t>The validity circuit is defined as</t>
          <artwork><![CDATA[
def Sum(inp: Vec[Field128], joint_rand: Vec[Field128]):
    out = Field128(0)
    r = joint_rand[0]
    for x in inp:
        out += r * Range2(x)
        r *= joint_rand[0]
    return out
]]></artwork>
          <table>
            <name>Parameters of validity circuit Sum.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">
                  <tt>[Range2]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[bits]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>INPUT_LEN</tt></td>
                <td align="left">
                  <tt>bits</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>Unsigned</tt>, in range <tt>[0, 2^bits)</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">
                  <tt>Unsigned</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="field128"/>)</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section anchor="prio3aes128histogram">
          <name>Prio3Aes128Histogram</name>
          <t>This instance of Prio3 allows for estimating the distribution of the
measurements by computing a simple histogram. Each measurement is an arbitrary
integer and the aggregate result counts the number of measurements that fall in
a set of fixed buckets.</t>
          <t>This instance of Prio3 uses <tt>PrgAes128</tt> (<xref target="prg-aes128"/>) as its PRG. Its
validity circuit, denoted <tt>Histogram</tt>, uses <tt>Field128</tt> (<xref target="field128"/>) as its
finite field. The measurement is encoded as a one-hot vector representing the
bucket into which the measurement falls (let <tt>bucket</tt> denote a sequence of
monotonically increasing integers):</t>
          <artwork><![CDATA[
def encode(Histogram, measurement: Integer):
    boundaries = buckets + [Infinity]
    encoded = [Field128(0) for _ in range(len(boundaries))]
    for i in range(len(boundaries)):
        if measurement <= boundaries[i]:
            encoded[i] = Field128(1)
            return encoded

def truncate(Histogram, inp: Vec[Field128]):
    return inp

def decode(Histogram, output: Vec[Field128], _num_measurements):
    return [bucket_count.as_unsigned() for bucket_count in output]
]]></artwork>
          <t>The validity circuit uses <tt>Range2</tt> (see <xref target="prio3aes128sum"/>) as its single gadget. It
checks for one-hotness in two steps, as follows:</t>
          <artwork><![CDATA[
def Histogram(inp: Vec[Field128],
              joint_rand: Vec[Field128],
              num_shares: Unsigned):
    # Check that each bucket is one or zero.
    range_check = Field128(0)
    r = joint_rand[0]
    for x in inp:
        range_check += r * Range2(x)
        r *= joint_rand[0]

    # Check that the buckets sum to 1.
    sum_check = -Field128(1) * Field128(num_shares).inv()
    for b in inp:
        sum_check += b

    out = joint_rand[1]   * range_check + \
          joint_rand[1]^2 * sum_check
    return out
]]></artwork>
          <t>Note that this circuit depends on the number of shares into which the input is
sharded. This is provided to the FLP by Prio3.</t>
          <table>
            <name>Parameters of validity circuit Histogram.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">
                  <tt>[Range2]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[buckets + 1]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>INPUT_LEN</tt></td>
                <td align="left">
                  <tt>buckets + 1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>buckets + 1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>2</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>Integer</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">
                  <tt>Vec[Unsigned]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="field128"/>)</td>
              </tr>
            </tbody>
          </table>
        </section>
      </section>
    </section>
    <section anchor="poplar1">
      <name>Poplar1</name>
      <ul empty="true">
        <li>
          <t>NOTE This construction has not undergone significant security analysis.</t>
        </li>
      </ul>
      <t>This section specifies Poplar1, a VDAF for the following task. Each Client holds
a string of length <tt>BITS</tt> and the Aggregators hold a set of <tt>l</tt>-bit strings,
where <tt>l &lt;= BITS</tt>. We will refer to the latter as the set of "candidate
prefixes". The Aggregators' goal is to count how many inputs are prefixed by
each candidate prefix.</t>
      <t>This functionality is the core component of the Poplar protocol <xref target="BBCGGI21"/>. At
a high level, the protocol works as follows.</t>
      <ol spacing="normal" type="1"><li>Each Client splits its input string into input shares and sends one share to
each Aggregator.</li>
        <li>The Aggregators agree on an initial set of candidate prefixes, say <tt>0</tt> and
<tt>1</tt>.</li>
        <li>The Aggregators evaluate the VDAF on each set of input shares and aggregate
the recovered output shares. The aggregation parameter is the set of
candidate prefixes.</li>
        <li>The Aggregators send their aggregate shares to the Collector, who combines
them to recover the counts of each candidate prefix.</li>
        <li>Let <tt>H</tt> denote the set of prefixes that occurred at least <tt>t</tt> times. If the
prefixes all have length <tt>BITS</tt>, then <tt>H</tt> is the set of <tt>t</tt>-heavy-hitters.
Otherwise compute the next set of candidate prefixes as follows. For each <tt>p</tt>
in <tt>H</tt>, add add <tt>p || 0</tt> and <tt>p || 1</tt> to the set. Repeat step 3 with the new
set of candidate prefixes.</li>
      </ol>
      <t>Poplar1 is constructed from an "Incremental Distributed Point Function (IDPF)",
a primitive described by <xref target="BBCGGI21"/> that generalizes the notion of a
Distributed Point Function (DPF) <xref target="GI14"/>. Briefly, a DPF is used to distribute
the computation of a "point function", a function that evaluates to zero on
every input except at a programmable "point". The computation is distributed in
such a way that no one party knows either the point or what it evaluates to.</t>
      <t>An IDPF generalizes this "point" to a path on a full binary tree from the root
to one of the leaves. It is evaluated on an "index" representing a unique node
of the tree. If the node is on the programmed path, then function evaluates to
to a non-zero value; otherwise it evaluates to zero. This structure allows an
IDPF to provide the functionality required for the above protocol, while at the
same time ensuring the same degree of privacy as a DPF.</t>
      <t>Poplar1 composes an IDPF with the "secure sketching" protocol of <xref target="BBCGGI21"/>.
This protocol ensures that evaluating a set of input shares on a unique set of
candidate prefixes results in shares of a "one-hot" vector, i.e., a vector that
is zero everywhere except for one element, which is equal to one.</t>
      <t>The remainder of this section is structured as follows. IDPFs are defined in
<xref target="idpf"/>; a concrete instantiation is given <xref target="idpf-poplar"/>. The Poplar1 VDAF is
defined in <xref target="poplar1-construction"/> in terms of a generic IDPF. Finally, a
concrete instantiation of Poplar1 is specified in <xref target="poplar1aes128"/>;
test vectors can be found in <xref target="test-vectors"/>.</t>
      <section anchor="idpf">
        <name>Incremental Distributed Point Functions (IDPFs)</name>
        <t>An IDPF is defined over a domain of size <tt>2^BITS</tt>, where <tt>BITS</tt> is constant
defined by the IDPF. Indexes into the IDPF tree are encoded as integers in range
<tt>[0, 2^BITS)</tt>. The Client specifies an index <tt>alpha</tt> and a vector of
values <tt>beta</tt>, one for each "level" <tt>L</tt> in range <tt>[0, BITS)</tt>. The key generation
algorithm generates one IDPF "key" for each Aggregator. When evaluated at level
<tt>L</tt> and index <tt>0 &lt;= prefix &lt; 2^L</tt>, each IDPF key returns an additive share of
<tt>beta[L]</tt> if <tt>prefix</tt> is the <tt>L</tt>-bit prefix of <tt>alpha</tt> and shares of zero
otherwise.</t>
        <t>An index <tt>x</tt> is defined to be a prefix of another index <tt>y</tt> as follows. Let
<tt>LSB(x, N)</tt> denote the least significant <tt>N</tt> bits of positive integer <tt>x</tt>. By
definition, a positive integer <tt>0 &lt;= x &lt; 2^L</tt> is said to be the length-<tt>L</tt>
prefix of positive integer <tt>0 &lt;= y &lt; 2^BITS</tt> if <tt>LSB(x, L)</tt> is equal to the most
significant <tt>L</tt> bits of <tt>LSB(y, BITS)</tt>, For example, 6 (110 in binary) is the
length-3 prefix of 25 (11001), but 7 (111) is not.</t>
        <t>Each of the programmed points <tt>beta</tt> is a vector of elements of some finite
field. We distinguish two types of fields: One for inner nodes (denoted
<tt>Idpf.FieldInner</tt>), and one for leaf nodes (<tt>Idpf.FieldLeaf</tt>). (Our
instantiation of Poplar1 (<xref target="poplar1aes128"/>) will use a much larger
field for leaf nodes than for inner nodes. This is to ensure the IDPF is
"extractable" as defined in <xref target="BBCGGI21"/>, Definition 1.)</t>
        <t>A concrete IDPF defines the types and constants enumerated in <xref target="idpf-param"/>. In
the remainder we write <tt>Idpf.Vec</tt> as shorthand for the type
<tt>Union[Vec[Vec[Idpf.FieldInner]], Vec[Vec[Idpf.FieldLeaf]]]</tt>. (This type denotes
either a vector of inner node field elements or leaf node field elements.) The
scheme is comprised of the following algorithms:</t>
        <ul spacing="normal">
          <li>
            <tt>Idpf.gen(alpha: Unsigned, beta_inner: Vec[Vec[Idpf.FieldInner]], beta_leaf:
Vec[Idpf.FieldLeaf]) -&gt; (Bytes, Vec[Bytes])</tt> is the randomized IDPF-key
generation algorithm. Its inputs are the index <tt>alpha</tt> and the values <tt>beta</tt>.
The value of <tt>alpha</tt> <bcp14>MUST</bcp14> be in range <tt>[0, 2^BITS)</tt>. The output is a public
part that is sent to all Aggregators and a vector of private IDPF keys, one
for each aggregator.</li>
          <li>
            <t><tt>Idpf.eval(agg_id: Unsigned, public_share: Bytes, key: Bytes, level: Unsigned,
prefixes: Vec[Unsigned]) -&gt; Idpf.Vec</tt> is the deterministic, stateless
IDPF-key evaluation algorithm run by each Aggregator. Its inputs are the
Aggregator's unique identifier, the public share distributed to all of the
Aggregators, the Aggregator's IDPF key, the "level" at which to evaluate the
IDPF, and the sequence of candidate prefixes. It returns the share of the
value corresponding to each candidate prefix.  </t>
            <t>
The output type depends on the value of <tt>level</tt>: If <tt>level &lt; Idpf.BITS-1</tt>, the
output is the value for an inner node, which has type
<tt>Vec[Vec[Idpf.FieldInner]]</tt>; otherwise, if <tt>level == Idpf.BITS-1</tt>, then the
output is the value for a leaf node, which has type
<tt>Vec[Vec[Idpf.FieldLeaf]]</tt>.  </t>
            <t>
The value of <tt>level</tt> <bcp14>MUST</bcp14> be in range <tt>[0, BITS)</tt>. The indexes in <tt>prefixes</tt>
              <bcp14>MUST</bcp14> all be distinct and in range <tt>[0, 2^level)</tt>.  </t>
            <t>
Applications <bcp14>MUST</bcp14> ensure that the Aggregator's identifier is equal to the
integer in range <tt>[0, SHARES)</tt> that matches the index of <tt>key</tt> in the sequence
of IDPF keys output by the Client.</t>
          </li>
        </ul>
        <t>In addition, the following method is derived for each concrete <tt>Idpf</tt>:</t>
        <artwork><![CDATA[
def current_field(Idpf, level):
    return Idpf.FieldInner if level < Idpf.BITS-1 \
                else Idpf.FieldLeaf
]]></artwork>
        <t>Finally, an implementation note. The interface for IDPFs specified here is
stateless, in the sense that there is no state carried between IDPF evaluations.
This is to align the IDPF syntax with the VDAF abstraction boundary, which does
not include shared state across across VDAF evaluations. In practice, of course,
it will often be beneficial to expose a stateful API for IDPFs and carry the
state across evaluations. See <xref target="idpf-poplar"/> for details.</t>
        <table anchor="idpf-param">
          <name>Constants and types defined by a concrete IDPF.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">SHARES</td>
              <td align="left">Number of IDPF keys output by IDPF-key generator</td>
            </tr>
            <tr>
              <td align="left">BITS</td>
              <td align="left">Length in bits of each input string</td>
            </tr>
            <tr>
              <td align="left">VALUE_LEN</td>
              <td align="left">Number of field elements of each output value</td>
            </tr>
            <tr>
              <td align="left">KEY_SIZE</td>
              <td align="left">Size in bytes of each IDPF key</td>
            </tr>
            <tr>
              <td align="left">FieldInner</td>
              <td align="left">Implementation of <tt>Field</tt> (<xref target="field"/>) used for values of inner nodes</td>
            </tr>
            <tr>
              <td align="left">FieldLeaf</td>
              <td align="left">Implementation of <tt>Field</tt> used for values of leaf nodes</td>
            </tr>
            <tr>
              <td align="left">Prg</td>
              <td align="left">Implementation of <tt>Prg</tt> (<xref target="prg"/>)</td>
            </tr>
          </tbody>
        </table>
      </section>
      <section anchor="poplar1-construction">
        <name>Construction</name>
        <t>This section specifies <tt>Poplar1</tt>, an implementation of the <tt>Vdaf</tt> interface
(<xref target="vdaf"/>). It is defined in terms of any <tt>Idpf</tt> (<xref target="idpf"/>) for which
<tt>Idpf.SHARES == 2</tt> and <tt>Idpf.VALUE_LEN == 2</tt>. The associated constants and types
required by the <tt>Vdaf</tt> interface are defined in <xref target="poplar1-param"/>. The methods
required for sharding, preparation, aggregation, and unsharding are described in
the remaining subsections.</t>
        <table anchor="poplar1-param">
          <name>Associated parameters for the Poplar1 VDAF.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>VERIFY_KEY_SIZE</tt></td>
              <td align="left">
                <tt>Idpf.Prg.SEED_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>ROUNDS</tt></td>
              <td align="left">
                <tt>2</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>SHARES</tt></td>
              <td align="left">
                <tt>2</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">
                <tt>Unsigned</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggParam</tt></td>
              <td align="left">
                <tt>Tuple[Unsigned, Vec[Unsigned]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>Prep</tt></td>
              <td align="left">
                <tt>Tuple[Bytes, Unsigned, Idpf.Vec]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>OutShare</tt></td>
              <td align="left">
                <tt>Idpf.Vec</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">
                <tt>Vec[Unsigned]</tt></td>
            </tr>
          </tbody>
        </table>
        <section anchor="client">
          <name>Client</name>
          <t>The client's input is an IDPF index, denoted <tt>alpha</tt>. The programmed IDPF values
are pairs of field elements <tt>(1, k)</tt> where each <tt>k</tt> is chosen at random. This
random value is used as part of the secure sketching protocol of <xref target="BBCGGI21"/>,
Appendix C.4. After evaluating their IDPF key shares on a given sequence of
candidate prefixes, the sketching protocol is used by the Aggregators to verify
that they hold shares of a one-hot vector. In addition, for each level of the
tree, the prover generates random elements <tt>a</tt>, <tt>b</tt>, and <tt>c</tt> and computes</t>
          <artwork><![CDATA[
    A = -2*a + k
    B = a^2 + b - k*a + c
]]></artwork>
          <t>and sends additive shares of <tt>a</tt>, <tt>b</tt>, <tt>c</tt>, <tt>A</tt> and <tt>B</tt> to the Aggregators.
Putting everything together, the input-distribution algorithm is defined as
follows. Function <tt>encode_input_shares</tt> is defined in <xref target="poplar1-helper-functions"/>.</t>
          <figure anchor="poplar1-mes2inp">
            <name>The input-distribution algorithm for Poplar1.</name>
            <artwork><![CDATA[
def measurement_to_input_shares(Poplar1, measurement):
    dst = VERSION + I2OSP(Poplar1.ID, 4)
    prg = Poplar1.Idpf.Prg(
        gen_rand(Poplar1.Idpf.Prg.SEED_SIZE), dst + byte(255))

    # Construct the IDPF values for each level of the IDPF tree.
    # Each "data" value is 1; in addition, the Client generates
    # a random "authenticator" value used by the Aggregators to
    # compute the sketch during preparation. This sketch is used
    # to verify the one-hotness of their output shares.
    beta_inner = [
        [Poplar1.Idpf.FieldInner(1), k] \
            for k in prg.next_vec(Poplar1.Idpf.FieldInner,
                                  Poplar1.Idpf.BITS - 1) ]
    beta_leaf = [Poplar1.Idpf.FieldLeaf(1)] + \
        prg.next_vec(Poplar1.Idpf.FieldLeaf, 1)

    # Generate the IDPF keys.
    (public_share, keys) = \
        Poplar1.Idpf.gen(measurement, beta_inner, beta_leaf)

    # Generate correlated randomness used by the Aggregators to
    # compute a sketch over their output shares. PRG seeds are
    # used to encode shares of the `(a, b, c)` triples.
    # (See [BBCGGI21, Appendix C.4].)
    corr_seed = [
        gen_rand(Poplar1.Idpf.Prg.SEED_SIZE),
        gen_rand(Poplar1.Idpf.Prg.SEED_SIZE),
    ]
    corr_prg = [
        Poplar1.Idpf.Prg(corr_seed[0], dst + byte(0)),
        Poplar1.Idpf.Prg(corr_seed[1], dst + byte(1)),
    ]

    # For each level of the IDPF tree, shares of the `(A, B)`
    # pairs are computed from the corresponding `(a, b, c)`
    # triple and authenticator value `k`.
    corr_inner = [[], []]
    for level in range(Poplar1.Idpf.BITS):
        Field = Poplar1.Idpf.current_field(level)
        k = beta_inner[level][1] if level < Poplar1.Idpf.BITS - 1 \
            else beta_leaf[1]
        (a, b, c) = vec_add(corr_prg[0].next_vec(Field, 3),
                            corr_prg[1].next_vec(Field, 3))
        A = -Field(2) * a + k
        B = a^2 + b - a * k + c
        corr1 = prg.next_vec(Field, 2)
        corr0 = vec_sub([A, B], corr1)
        if level < Poplar1.Idpf.BITS - 1:
            corr_inner[0] += corr0
            corr_inner[1] += corr1
        else:
            corr_leaf = [corr0, corr1]

    # Each input share consists of the Aggregator's IDPF key
    # and a share of the correlated randomness.
    return (public_share,
            Poplar1.encode_input_shares(
                keys, corr_seed, corr_inner, corr_leaf))
]]></artwork>
          </figure>
        </section>
        <section anchor="preparation-1">
          <name>Preparation</name>
          <t>The aggregation parameter encodes a sequence of candidate prefixes. When an
Aggregator receives an input share from the Client, it begins by evaluating its
IDPF share on each candidate prefix, recovering a <tt>data_share</tt> and <tt>auth_share</tt>
for each. The Aggregators use these and the correlation shares provided by the
Client to verify that the sequence of <tt>data_share</tt> values are additive shares of
a one-hot vector.</t>
          <t>The algorithms below make use of auxiliary functions <tt>verify_context()</tt> and
<tt>decode_input_share()</tt> defined in <xref target="poplar1-helper-functions"/>.</t>
          <figure anchor="poplar1-prep-state">
            <name>Preparation state for Poplar1.</name>
            <artwork><![CDATA[
def prep_init(Poplar1, verify_key, agg_id, agg_param,
              nonce, public_share, input_share):
    dst = VERSION + I2OSP(Poplar1.ID, 4)
    (level, prefixes) = agg_param
    (key, corr_seed, corr_inner, corr_leaf) = \
        Poplar1.decode_input_share(input_share)

    # Evaluate the IDPF key at the given set of prefixes.
    value = Poplar1.Idpf.eval(
        agg_id, public_share, key, level, prefixes)

    # Get correlation shares for the given level of the IDPF tree.
    #
    # Implementation note: Computing the shares of `(a, b, c)`
    # requires expanding PRG seeds into a vector of field elements
    # of length proportional to the level of the tree. Typically
    # the IDPF will be evaluated incrementally beginning with
    # `level == 0`. Implementations can save computation by
    # storing the intermediate PRG state between evaluations.
    corr_prg = Poplar1.Idpf.Prg(corr_seed, dst + byte(agg_id))
    for current_level in range(level+1):
        Field = Poplar1.Idpf.current_field(current_level)
        (a_share, b_share, c_share) = corr_prg.next_vec(Field, 3)
    (A_share, B_share) = corr_inner[2*level:2*(level+1)] \
        if level < Poplar1.Idpf.BITS - 1 else corr_leaf

    # Compute the Aggregator's first round of the sketch. These are
    # called the "masked input values" [BBCGGI21, Appendix C.4].
    Field = Poplar1.Idpf.current_field(level)
    verify_rand_prg = Poplar1.Idpf.Prg(verify_key,
        dst + Poplar1.verify_context(nonce, level, prefixes))
    verify_rand = verify_rand_prg.next_vec(Field, len(prefixes))
    sketch_share = [a_share, b_share, c_share]
    out_share = []
    for (i, r) in enumerate(verify_rand):
        (data_share, auth_share) = value[i]
        sketch_share[0] += data_share * r
        sketch_share[1] += data_share * r^2
        sketch_share[2] += auth_share * r
        out_share.append(data_share)

    prep_mem = sketch_share \
                + [A_share, B_share, Field(agg_id)] \
                + out_share
    return (b'ready', level, prep_mem)

def prep_next(Poplar1, prep_state, opt_sketch):
    (step, level, prep_mem) = prep_state
    Field = Poplar1.Idpf.current_field(level)

    # Aggregators exchange masked input values (step (3.)
    # of [BBCGGI21, Appendix C.4]).
    if step == b'ready' and opt_sketch == None:
        sketch_share, prep_mem = prep_mem[:3], prep_mem[3:]
        return ((b'sketch round 1', level, prep_mem),
                Field.encode_vec(sketch_share))

    # Aggregators exchange evaluated shares (step (4.)).
    elif step == b'sketch round 1' and opt_sketch != None:
        prev_sketch = Field.decode_vec(opt_sketch)
        if len(prev_sketch) == 0:
            prev_sketch = Field.zeros(3)
        elif len(prev_sketch) != 3:
            raise ERR_INPUT # prep message malformed
        (A_share, B_share, agg_id), prep_mem = \
            prep_mem[:3], prep_mem[3:]
        sketch_share = [
            agg_id * (prev_sketch[0]^2 \
                        - prev_sketch[1]
                        - prev_sketch[2]) \
                + A_share * prev_sketch[0] \
                + B_share
        ]
        return ((b'sketch round 2', level, prep_mem),
                Field.encode_vec(sketch_share))

    elif step == b'sketch round 2' and opt_sketch != None:
        prev_sketch = Field.decode_vec(opt_sketch)
        if len(prev_sketch) == 0:
            prev_sketch = Field.zeros(1)
        elif len(prev_sketch) != 1:
            raise ERR_INPUT # prep message malformed
        if prev_sketch[0] != Field(0):
            raise ERR_VERIFY
        return prep_mem # Output shares

    raise ERR_INPUT # unexpected input

def prep_shares_to_prep(Poplar1, agg_param, prep_shares):
    if len(prep_shares) != 2:
        raise ERR_INPUT # unexpected number of prep shares
    (level, _) = agg_param
    Field = Poplar1.Idpf.current_field(level)
    sketch = vec_add(Field.decode_vec(prep_shares[0]),
                     Field.decode_vec(prep_shares[1]))
    if sketch == Field.zeros(len(sketch)):
        # In order to reduce communication overhead, let the
        # empty string denote the zero vector of the required
        # length.
        return b''
    return Field.encode_vec(sketch)
]]></artwork>
          </figure>
        </section>
        <section anchor="aggregation-1">
          <name>Aggregation</name>
          <t>Aggregation involves simply adding up the output shares.</t>
          <figure anchor="poplar1-out2agg">
            <name>Aggregation algorithm for Poplar1.</name>
            <artwork><![CDATA[
def out_shares_to_agg_share(Poplar1, agg_param, out_shares):
    (level, prefixes) = agg_param
    Field = Poplar1.Idpf.current_field(level)
    agg_share = Field.zeros(len(prefixes))
    for out_share in out_shares:
        agg_share = vec_add(agg_share, out_share)
    return Field.encode_vec(agg_share)
]]></artwork>
          </figure>
        </section>
        <section anchor="unsharding-1">
          <name>Unsharding</name>
          <t>Finally, the Collector unshards the aggregate result by adding up the aggregate
shares.</t>
          <figure anchor="poplar1-agg-output">
            <name>Computation of the aggregate result for Poplar1.</name>
            <artwork><![CDATA[
def agg_shares_to_result(Poplar1, agg_param,
                         agg_shares, _num_measurements):
    (level, prefixes) = agg_param
    Field = Poplar1.Idpf.current_field(level)
    agg = Field.zeros(len(prefixes))
    for agg_share in agg_shares:
        agg = vec_add(agg, Field.decode_vec(agg_share))
    return list(map(lambda x: x.as_unsigned(), agg))
]]></artwork>
          </figure>
        </section>
        <section anchor="poplar1-helper-functions">
          <name>Auxiliary Functions</name>
          <figure anchor="poplar1-helpers">
            <name>Helper functions for Poplar1.</name>
            <artwork><![CDATA[
def encode_input_shares(Poplar1, keys,
                        corr_seed, corr_inner, corr_leaf):
    input_shares = []
    for (key, seed, inner, leaf) in zip(keys,
                                        corr_seed,
                                        corr_inner,
                                        corr_leaf):
        encoded = Bytes()
        encoded += key
        encoded += seed
        encoded += Poplar1.Idpf.FieldInner.encode_vec(inner)
        encoded += Poplar1.Idpf.FieldLeaf.encode_vec(leaf)
        input_shares.append(encoded)
    return input_shares

def decode_input_share(Poplar1, encoded):
    l = Poplar1.Idpf.KEY_SIZE
    key, encoded = encoded[:l], encoded[l:]
    l = Poplar1.Idpf.Prg.SEED_SIZE
    corr_seed, encoded = encoded[:l], encoded[l:]
    l = Poplar1.Idpf.FieldInner.ENCODED_SIZE \
        * 2 * (Poplar1.Idpf.BITS - 1)
    encoded_corr_inner, encoded = encoded[:l], encoded[l:]
    corr_inner = Poplar1.Idpf.FieldInner.decode_vec(
        encoded_corr_inner)
    l = Poplar1.Idpf.FieldLeaf.ENCODED_SIZE * 2
    encoded_corr_leaf, encoded = encoded[:l], encoded[l:]
    corr_leaf = Poplar1.Idpf.FieldLeaf.decode_vec(
        encoded_corr_leaf)
    if len(encoded) != 0:
        raise ERR_INPUT
    return (key, corr_seed, corr_inner, corr_leaf)

def encode_agg_param(Poplar1, level, prefixes):
    if level > 2^16 - 1:
        raise ERR_INPUT # level too deep
    if len(prefixes) > 2^16 - 1:
        raise ERR_INPUT # too many prefixes
    encoded = Bytes()
    encoded += I2OSP(level, 2)
    encoded += I2OSP(len(prefixes), 2)
    packed = 0
    for (i, prefix) in enumerate(prefixes):
        packed |= prefix << ((level+1) * i)
    l = floor(((level+1) * len(prefixes) + 7) / 8)
    encoded += I2OSP(packed, l)
    return encoded

def verify_context(Poplar1, nonce, level, prefixes):
    if len(nonce) > 255:
        raise ERR_INPUT # nonce too long
    context = Bytes()
    context += byte(254)
    context += byte(len(nonce))
    context += nonce
    context += Poplar1.encode_agg_param(level, prefixes)
    return context
]]></artwork>
          </figure>
        </section>
      </section>
      <section anchor="idpf-poplar">
        <name>The IDPF scheme of <xref target="BBCGGI21"/></name>
        <t>In this section we specify a concrete IDPF, called IdpfPoplar, suitable for
instantiating Poplar1. The scheme gets its name from the name of the protocol of
<xref target="BBCGGI21"/>.</t>
        <ul empty="true">
          <li>
            <t>TODO We should consider giving <tt>IdpfPoplar</tt> a more distinctive name.</t>
          </li>
        </ul>
        <t>The constant and type definitions required by the <tt>Idpf</tt> interface are given in
<xref target="idpf-poplar-param"/>.</t>
        <table anchor="idpf-poplar-param">
          <name>Constants and type definitions for IdpfPoplar.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">SHARES</td>
              <td align="left">
                <tt>2</tt></td>
            </tr>
            <tr>
              <td align="left">BITS</td>
              <td align="left">any positive integer</td>
            </tr>
            <tr>
              <td align="left">VALUE_LEN</td>
              <td align="left">any positive integer</td>
            </tr>
            <tr>
              <td align="left">KEY_SIZE</td>
              <td align="left">
                <tt>Prg.SEED_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">FieldInner</td>
              <td align="left">
                <tt>Field64</tt> (<xref target="field64"/>)</td>
            </tr>
            <tr>
              <td align="left">FieldLeaf</td>
              <td align="left">
                <tt>Field255</tt> (<xref target="field255"/>)</td>
            </tr>
            <tr>
              <td align="left">Prg</td>
              <td align="left">any implementation of <tt>Prg</tt> (<xref target="prg"/>)</td>
            </tr>
          </tbody>
        </table>
        <section anchor="key-generation">
          <name>Key Generation</name>
          <ul empty="true">
            <li>
              <t>TODO Describe the construction in prose, beginning with a gentle introduction
to the high level idea.</t>
            </li>
          </ul>
          <t>The description of the IDPF-key generation algorithm makes use of auxiliary
functions <tt>extend()</tt>, <tt>convert()</tt>, and <tt>encode_public_share()</tt> defined in
<xref target="idpf-poplar-helper-functions"/>. In the following, we let <tt>Field2</tt> denote the
field <tt>GF(2)</tt>.</t>
          <figure anchor="idpf-poplar-gen">
            <name>IDPF-key generation algorithm of IdpfPoplar.</name>
            <artwork><![CDATA[
def gen(IdpfPoplar, alpha, beta_inner, beta_leaf):
    if alpha >= 2^IdpfPoplar.BITS:
        raise ERR_INPUT # alpha too long
    if len(beta_inner) != IdpfPoplar.BITS - 1:
        raise ERR_INPUT # beta_inner vector is the wrong size

    init_seed = [
        gen_rand(IdpfPoplar.Prg.SEED_SIZE),
        gen_rand(IdpfPoplar.Prg.SEED_SIZE),
    ]

    seed = init_seed.copy()
    ctrl = [Field2(0), Field2(1)]
    correction_words = []
    for level in range(IdpfPoplar.BITS):
        keep = (alpha >> (IdpfPoplar.BITS - level - 1)) & 1
        lose = 1 - keep
        bit = Field2(keep)

        (s0, t0) = IdpfPoplar.extend(seed[0])
        (s1, t1) = IdpfPoplar.extend(seed[1])
        seed_cw = xor(s0[lose], s1[lose])
        ctrl_cw = (
            t0[0] + t1[0] + bit + Field2(1),
            t0[1] + t1[1] + bit,
        )

        x0 = xor(s0[keep], seed_cw) if ctrl[0] == Field2(1) \
                else s0[keep]
        x1 = xor(s1[keep], seed_cw) if ctrl[1] == Field2(1) \
                else s1[keep]
        (seed[0], w0) = IdpfPoplar.convert(level, x0)
        (seed[1], w1) = IdpfPoplar.convert(level, x1)
        ctrl[0] = t0[keep] + ctrl[0] * ctrl_cw[keep]
        ctrl[1] = t1[keep] + ctrl[1] * ctrl_cw[keep]

        b = beta_inner[level] if level < IdpfPoplar.BITS-1 \
                else beta_leaf
        if len(b) != IdpfPoplar.VALUE_LEN:
            raise ERR_INPUT # beta too long or too short

        w_cw = vec_add(vec_sub(b, w0), w1)
        if ctrl[1] == Field2(1):
            w_cw = vec_neg(w_cw)
        correction_words.append((seed_cw, ctrl_cw, w_cw))

    public_share = IdpfPoplar.encode_public_share(correction_words)
    return (public_share, init_seed)
]]></artwork>
          </figure>
        </section>
        <section anchor="key-evaluation">
          <name>Key Evaluation</name>
          <ul empty="true">
            <li>
              <t>TODO Describe in prose how IDPF-key evaluation algorithm works.</t>
            </li>
          </ul>
          <t>The description of the IDPF-evaluation algorithm makes use of auxiliary
functions <tt>extend()</tt>, <tt>convert()</tt>, and <tt>decode_public_share()</tt> defined in
<xref target="idpf-poplar-helper-functions"/>.</t>
          <figure anchor="idpf-poplar-eval">
            <name>IDPF-evaluation generation algorithm of IdpfPoplar.</name>
            <artwork><![CDATA[
def eval(IdpfPoplar, agg_id, public_share, init_seed,
         level, prefixes):
    if agg_id >= IdpfPoplar.SHARES:
        raise ERR_INPUT # invalid aggregator ID
    if level >= IdpfPoplar.BITS:
        raise ERR_INPUT # level too deep
    if len(set(prefixes)) != len(prefixes):
        raise ERR_INPUT # candidate prefixes are non-unique

    correction_words = IdpfPoplar.decode_public_share(public_share)
    out_share = []
    for prefix in prefixes:
        if prefix >= 2^(level+1):
            raise ERR_INPUT # prefix too long

        # The Aggregator's output share is the value of a node of
        # the IDPF tree at the given `level`. The node's value is
        # computed by traversing the path defined by the candidate
        # `prefix`. Each node in the tree is represented by a seed
        # (`seed`) and a set of control bits (`ctrl`).
        seed = init_seed
        ctrl = Field2(agg_id)
        for current_level in range(level+1):
            bit = (prefix >> (level - current_level)) & 1

            # Implementation note: Typically the current round of
            # candidate prefixes would have been derived from
            # aggregate results computed during previous rounds. For
            # example, when using `IdpfPoplar` to compute heavy
            # hitters, a string whose hit count exceeded the given
            # threshold in the last round would be the prefix of each
            # `prefix` in the current round. (See [BBCGGI21,
            # Section 5.1].) In this case, part of the path would
            # have already been traversed.
            #
            # Re-computing nodes along previously traversed paths is
            # wasteful. Implementations can eliminate this added
            # complexity by caching nodes (i.e., `(seed, ctrl)`
            # pairs) output by previous calls to `eval_next()`.
            (seed, ctrl, y) = IdpfPoplar.eval_next(seed, ctrl,
                correction_words[current_level], current_level, bit)
        out_share.append(y if agg_id == 0 else vec_neg(y))
    return out_share

# Compute the next node in the IDPF tree along the path determined by
# a candidate prefix. The next node is determined by `bit`, the bit
# of the prefix corresponding to the next level of the tree.
#
# TODO Consider implementing some version of the optimization
# discussed at the end of [BBCGGI21, Appendix C.2]. This could on
# average reduce the number of AES calls by a constant factor.
def eval_next(IdpfPoplar, prev_seed, prev_ctrl,
              correction_word, level, bit):
    (seed_cw, ctrl_cw, w_cw) = correction_word
    (s, t) = IdpfPoplar.extend(prev_seed)
    if prev_ctrl == Field2(1):
        s[0] = xor(s[0], seed_cw)
        s[1] = xor(s[1], seed_cw)
        t[0] = t[0] + ctrl_cw[0]
        t[1] = t[1] + ctrl_cw[1]

    next_ctrl = t[bit]
    (next_seed, y) = IdpfPoplar.convert(level, s[bit])
    if next_ctrl == Field2(1):
        y = vec_add(y, w_cw)
    return (next_seed, next_ctrl, y)
]]></artwork>
          </figure>
        </section>
        <section anchor="idpf-poplar-helper-functions">
          <name>Auxiliary Functions</name>
          <figure anchor="idpf-poplar-helpers">
            <name>Helper functions for IdpfPoplar.</name>
            <artwork><![CDATA[
def extend(IdpfPoplar, seed):
    dst = VERSION + b' idpf poplar extend'
    prg = IdpfPoplar.Prg(seed, dst)
    s = [
        prg.next(IdpfPoplar.Prg.SEED_SIZE),
        prg.next(IdpfPoplar.Prg.SEED_SIZE),
    ]
    b = OS2IP(prg.next(1))
    t = [Field2(b & 1), Field2((b >> 1) & 1)]
    return (s, t)

def convert(IdpfPoplar, level, seed):
    dst = VERSION + b' idpf poplar convert'
    prg = IdpfPoplar.Prg(seed, dst)
    next_seed = prg.next(IdpfPoplar.Prg.SEED_SIZE)
    Field = IdpfPoplar.current_field(level)
    w = prg.next_vec(Field, IdpfPoplar.VALUE_LEN)
    return (next_seed, w)

def encode_public_share(IdpfPoplar, correction_words):
    encoded = Bytes()
    packed_ctrl = 0
    for (level, (_, ctrl_cw, _)) \
        in enumerate(correction_words):
        packed_ctrl |= ctrl_cw[0].as_unsigned() << (2*level)
        packed_ctrl |= ctrl_cw[1].as_unsigned() << (2*level+1)
    l = floor((2*IdpfPoplar.BITS + 7) / 8)
    encoded += I2OSP(packed_ctrl, l)
    for (level, (seed_cw, _, w_cw)) \
        in enumerate(correction_words):
        Field = IdpfPoplar.current_field(level)
        encoded += seed_cw
        encoded += Field.encode_vec(w_cw)
    return encoded

def decode_public_share(IdpfPoplar, encoded):
    l = floor((2*IdpfPoplar.BITS + 7) / 8)
    encoded_ctrl, encoded = encoded[:l], encoded[l:]
    packed_ctrl = OS2IP(encoded_ctrl)
    correction_words = []
    for level in range(IdpfPoplar.BITS):
        Field = IdpfPoplar.current_field(level)
        ctrl_cw = (Field2(packed_ctrl & 1),
                   Field2((packed_ctrl >> 1) & 1))
        packed_ctrl >>= 2
        l = IdpfPoplar.Prg.SEED_SIZE
        seed_cw, encoded = encoded[:l], encoded[l:]
        l = Field.ENCODED_SIZE * IdpfPoplar.VALUE_LEN
        encoded_w_cw, encoded = encoded[:l], encoded[l:]
        w_cw = Field.decode_vec(encoded_w_cw)
        correction_words.append((seed_cw, ctrl_cw, w_cw))
    if len(encoded) != 0:
        raise ERR_DECODE
    return correction_words
]]></artwork>
          </figure>
        </section>
      </section>
      <section anchor="poplar1aes128">
        <name>Poplar1Aes128</name>
        <t>We refer to Poplar1 instantiated with IdpfPoplar (<tt>VALUE_LEN == 2</tt>)
and PrgAes128 (<xref target="prg-aes128"/>) as Poplar1Aes128. This VDAF is suitable
for any positive value of <tt>BITS</tt>. Test vectors can be found in
<xref target="test-vectors"/>.</t>
      </section>
    </section>
    <section anchor="security">
      <name>Security Considerations</name>
      <ul empty="true">
        <li>
          <t>NOTE: This is a brief outline of the security considerations.  This section
will be filled out more as the draft matures and security analyses are
completed.</t>
        </li>
      </ul>
      <t>VDAFs have two essential security goals:</t>
      <ol spacing="normal" type="1"><li>Privacy: An attacker that controls the network, the Collector, and a subset
of Clients and Aggregators learns nothing about the measurements of honest
Clients beyond what it can deduce from the aggregate result.</li>
        <li>Robustness: An attacker that controls the network and a subset of Clients
cannot cause the Collector to compute anything other than the aggregate of
the measurements of honest Clients.</li>
      </ol>
      <t>Note that, to achieve robustness, it is important to ensure that the
verification key distributed to the Aggregators (<tt>verify_key</tt>, see <xref target="sec-vdaf-prepare"/>) is
never revealed to the Clients.</t>
      <t>It is also possible to consider a stronger form of robustness, where the
attacker also controls a subset of Aggregators (see <xref target="BBCGGI19"/>, Section 6.3).
To satisfy this stronger notion of robustness, it is necessary to prevent the
attacker from sharing the verification key with the Clients. It is therefore
<bcp14>RECOMMENDED</bcp14> that the Aggregators generate <tt>verify_key</tt> only after a set of
Client inputs has been collected for verification, and re-generate them for each
such set of inputs.</t>
      <t>In order to achieve robustness, the Aggregators <bcp14>MUST</bcp14> ensure that the nonces used
to process the measurements in a batch are all unique.</t>
      <t>A VDAF is the core cryptographic primitive of a protocol that achieves
the above privacy and robustness goals. It is not sufficient on its own,
however. The application will need to assure a few security properties,
for example:</t>
      <ul spacing="normal">
        <li>Securely distributing the long-lived parameters.</li>
        <li>
          <t>Establishing secure channels:
          </t>
          <ul spacing="normal">
            <li>Confidential and authentic channels among Aggregators, and between the
Aggregators and the Collector; and</li>
            <li>Confidential and Aggregator-authenticated channels between Clients and
Aggregators.</li>
          </ul>
        </li>
        <li>Enforcing the non-collusion properties required of the specific VDAF in use.</li>
      </ul>
      <t>In such an environment, a VDAF provides the high-level privacy property
described above: The Collector learns only the aggregate measurement, and
nothing about individual measurements aside from what can be inferred from the
aggregate result.  The Aggregators learn neither individual measurements nor the
aggregate result.  The Collector is assured that the aggregate statistic
accurately reflects the inputs as long as the Aggregators correctly executed
their role in the VDAF.</t>
      <t>On their own, VDAFs do not mitigate Sybil attacks <xref target="Dou02"/>. In this attack, the
adversary observes a subset of input shares transmitted by a Client it is
interested in. It allows the input shares to be processed, but corrupts and
picks bogus inputs for the remaining Clients.  Applications can guard against
these risks by adding additional controls on measurement submission, such as
client authentication and rate limits.</t>
      <t>VDAFs do not inherently provide differential privacy <xref target="Dwo06"/>.  The VDAF approach
to private measurement can be viewed as complementary to differential privacy,
relying on non-collusion instead of statistical noise to protect the privacy of
the inputs.  It is possible that a future VDAF could incorporate differential
privacy features, e.g., by injecting noise before the sharding stage and
removing it after unsharding.</t>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>A codepoint for each (V)DAF in this document is defined in the table below. Note
that <tt>0xFFFF0000</tt> through <tt>0xFFFFFFFF</tt> are reserved for private use.</t>
      <table anchor="codepoints">
        <name>Unique identifiers for (V)DAFs.</name>
        <thead>
          <tr>
            <th align="left">Value</th>
            <th align="left">Scheme</th>
            <th align="left">Type</th>
            <th align="left">Reference</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>0x00000000</tt></td>
            <td align="left">Prio3Aes128Count</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3aes128count"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000001</tt></td>
            <td align="left">Prio3Aes128Sum</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3aes128sum"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000002</tt></td>
            <td align="left">Prio3Aes128Histogram</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3aes128histogram"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000003</tt> to <tt>0x00000FFF</tt></td>
            <td align="left">reserved for Prio3</td>
            <td align="left">VDAF</td>
            <td align="left">n/a</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00001000</tt></td>
            <td align="left">Poplar1Aes128</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="poplar1aes128"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0xFFFF0000</tt> to <tt>0xFFFFFFFF</tt></td>
            <td align="left">reserved</td>
            <td align="left">n/a</td>
            <td align="left">n/a</td>
          </tr>
        </tbody>
      </table>
      <ul empty="true">
        <li>
          <t>TODO Add IANA considerations for the codepoints summarized in <xref target="codepoints"/>.</t>
        </li>
      </ul>
      <ul empty="true">
        <li>
          <t>OPEN ISSUE Currently the scheme includes the PRG. This means that we need bits
of the codepoint to differentiate between PRGs. We could instead make the PRG
generic (e.g., Prio3Count(Aes128) instead of Prio3Aes128Count) and define a
separate codepoint.</t>
        </li>
      </ul>
    </section>
  </middle>
  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner">
              <organization/>
            </author>
            <date month="March" year="1997"/>
            <abstract>
              <t>In many standards track documents several words are used to signify the requirements in the specification.  These words are often capitalized. This document defines these words as they should be interpreted in IETF documents.  This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        <reference anchor="RFC8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba">
              <organization/>
            </author>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol  specifications.  This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the  defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
        <reference anchor="RFC8017">
          <front>
            <title>PKCS #1: RSA Cryptography Specifications Version 2.2</title>
            <author fullname="K. Moriarty" initials="K." role="editor" surname="Moriarty">
              <organization/>
            </author>
            <author fullname="B. Kaliski" initials="B." surname="Kaliski">
              <organization/>
            </author>
            <author fullname="J. Jonsson" initials="J." surname="Jonsson">
              <organization/>
            </author>
            <author fullname="A. Rusch" initials="A." surname="Rusch">
              <organization/>
            </author>
            <date month="November" year="2016"/>
            <abstract>
              <t>This document provides recommendations for the implementation of public-key cryptography based on the RSA algorithm, covering cryptographic primitives, encryption schemes, signature schemes with appendix, and ASN.1 syntax for representing keys and for identifying the schemes.</t>
              <t>This document represents a republication of PKCS #1 v2.2 from RSA Laboratories' Public-Key Cryptography Standards (PKCS) series.  By publishing this RFC, change control is transferred to the IETF.</t>
              <t>This document also obsoletes RFC 3447.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8017"/>
          <seriesInfo name="DOI" value="10.17487/RFC8017"/>
        </reference>
        <reference anchor="RFC4493">
          <front>
            <title>The AES-CMAC Algorithm</title>
            <author fullname="JH. Song" initials="JH." surname="Song">
              <organization/>
            </author>
            <author fullname="R. Poovendran" initials="R." surname="Poovendran">
              <organization/>
            </author>
            <author fullname="J. Lee" initials="J." surname="Lee">
              <organization/>
            </author>
            <author fullname="T. Iwata" initials="T." surname="Iwata">
              <organization/>
            </author>
            <date month="June" year="2006"/>
            <abstract>
              <t>The National Institute of Standards and Technology (NIST) has recently specified the Cipher-based Message Authentication Code (CMAC), which is equivalent to the One-Key CBC MAC1 (OMAC1) submitted by Iwata and Kurosawa.  This memo specifies an authentication algorithm based on CMAC with the 128-bit Advanced Encryption Standard (AES). This new authentication algorithm is named AES-CMAC. The purpose of this document is to make the AES-CMAC algorithm conveniently available to the Internet Community.  This memo provides information for the Internet community.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="4493"/>
          <seriesInfo name="DOI" value="10.17487/RFC4493"/>
        </reference>
      </references>
      <references>
        <name>Informative References</name>
        <reference anchor="AGJOP21" target="https://ia.cr/2021/576">
          <front>
            <title>Prio+: Privacy Preserving Aggregate Statistics via Boolean Shares</title>
            <author initials="S." surname="Addanki">
              <organization/>
            </author>
            <author initials="K." surname="Garbe">
              <organization/>
            </author>
            <author initials="E." surname="Jaffe">
              <organization/>
            </author>
            <author initials="R." surname="Ostrovsky">
              <organization/>
            </author>
            <author initials="A." surname="Polychroniadou">
              <organization/>
            </author>
            <date year="2021"/>
          </front>
        </reference>
        <reference anchor="BBCGGI19" target="https://ia.cr/2019/188">
          <front>
            <title>Zero-Knowledge Proofs on Secret-Shared Data via Fully Linear PCPs</title>
            <author initials="D." surname="Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2019"/>
          </front>
          <seriesInfo name="CRYPTO 2019" value=""/>
        </reference>
        <reference anchor="BBCGGI21" target="https://ia.cr/2021/017">
          <front>
            <title>Lightweight Techniques for Private Heavy Hitters</title>
            <author initials="D." surname="Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2021"/>
          </front>
          <seriesInfo name="IEEE S&amp;P 2021" value=""/>
        </reference>
        <reference anchor="CGB17" target="https://dl.acm.org/doi/10.5555/3154630.3154652">
          <front>
            <title>Prio: Private, Robust, and Scalable Computation of Aggregate Statistics</title>
            <author initials="H." surname="Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="D." surname="Boneh">
              <organization/>
            </author>
            <date year="2017"/>
          </front>
          <seriesInfo name="NSDI 2017" value=""/>
        </reference>
        <reference anchor="Dou02" target="https://doi.org/10.1007/3-540-45748-8_24">
          <front>
            <title>The Sybil Attack</title>
            <author initials="J." surname="Douceur">
              <organization/>
            </author>
            <date year="2002"/>
          </front>
          <seriesInfo name="IPTPS 2002" value=""/>
        </reference>
        <reference anchor="Dwo06" target="https://link.springer.com/chapter/10.1007/11787006_1">
          <front>
            <title>Differential Privacy</title>
            <author initials="C." surname="Dwork">
              <organization/>
            </author>
            <date year="2006"/>
          </front>
          <seriesInfo name="ICALP 2006" value=""/>
        </reference>
        <reference anchor="EPK14" target="https://dl.acm.org/doi/10.1145/2660267.2660348">
          <front>
            <title>RAPPOR: Randomized Aggregatable Privacy-Preserving Ordinal Response</title>
            <author initials="Ú." surname="Erlingsson">
              <organization/>
            </author>
            <author initials="V." surname="Pihur">
              <organization/>
            </author>
            <author initials="A." surname="Korolova">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <seriesInfo name="CCS 2014" value=""/>
        </reference>
        <reference anchor="ENPA" target="https://covid19-static.cdn-apple.com/applications/covid19/current/static/contact-tracing/pdf/ENPA_White_Paper.pdf">
          <front>
            <title>Exposure Notification Privacy-preserving Analytics (ENPA) White Paper</title>
            <author>
              <organization/>
            </author>
            <date year="2021"/>
          </front>
        </reference>
        <reference anchor="GI14" target="https://link.springer.com/chapter/10.1007/978-3-642-55220-5_35">
          <front>
            <title>Distributed Point Functions and Their Applications</title>
            <author initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <seriesInfo name="EUROCRYPT 2014" value=""/>
        </reference>
        <reference anchor="OriginTelemetry" target="https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/collection/origin.html">
          <front>
            <title>Origin Telemetry</title>
            <author>
              <organization/>
            </author>
            <date year="2020"/>
          </front>
        </reference>
        <reference anchor="DAP">
          <front>
            <title>Distributed Aggregation Protocol for Privacy Preserving Measurement</title>
            <author fullname="Tim Geoghegan">
              <organization>ISRG</organization>
            </author>
            <author fullname="Christopher Patton">
              <organization>Cloudflare</organization>
            </author>
            <author fullname="Eric Rescorla">
              <organization>Mozilla</organization>
            </author>
            <author fullname="Christopher A. Wood">
              <organization>Cloudflare</organization>
            </author>
            <date day="11" month="July" year="2022"/>
            <abstract>
              <t>   There are many situations in which it is desirable to take
   measurements of data which people consider sensitive.  In these
   cases, the entity taking the measurement is usually not interested in
   people's individual responses but rather in aggregated data.
   Conventional methods require collecting individual responses and then
   aggregating them, thus representing a threat to user privacy and
   rendering many such measurements difficult and impractical.  This
   document describes a multi-party distributed aggregation protocol
   (DAP) for privacy preserving measurement (PPM) which can be used to
   collect aggregate data without revealing any individual user's data.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-ppm-dap-01"/>
        </reference>
      </references>
    </references>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>Thanks to David Cook, Henry Corrigan-Gibbs, Armando Faz-Hernandez, Simon
Friedberger, Tim Geoghegan, Mariana Raykova, Jacob Rothstein, and Christopher
Wood for useful feedback on and contributions to the spec.</t>
    </section>
    <section numbered="false" anchor="test-vectors">
      <name>Test Vectors</name>
      <ul empty="true">
        <li>
          <t>NOTE Machine-readable test vectors can be found at
https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec.</t>
        </li>
      </ul>
      <t>Test vectors cover the generation of input shares and the conversion of input
shares into output shares. Vectors specify the verification key, measurements,
aggregation parameter, and any parameters needed to construct the VDAF. (For
example, for <tt>Prio3Aes128Sum</tt>, the user specifies the number of bits for
representing each summand.)</t>
      <t>Byte strings are encoded in hexadecimal To make the tests deterministic,
<tt>gen_rand()</tt> was replaced with a function that returns the requested number of
<tt>0x01</tt> octets.</t>
      <section numbered="false" anchor="testvec-prio3aes128count">
        <name>Prio3Aes128Count</name>
        <artwork><![CDATA[
verify_key: "01010101010101010101010101010101"
upload_0:
  measurement: 1
  nonce: "01010101010101010101010101010101"
  public_share: >-
  input_share_0: >-
    ad8bb894e3222b47b70eb67d4f70cb78644826d67d31129e422b910cf0aab70c0b78
    fa57b4a7b3aaafae57bd1012e813
  input_share_1: >-
    0101010101010101010101010101010101010101010101010101010101010101
  round_0:
    prep_share_0: >-
      38d535dd68f3c02ed6681f7ff24239d46fde93c8402d24ebbafa25c77ca3535d
    prep_share_1: >-
      c72aca21970c3fd35274476a1cddd4bb4efa24ee0d71473e4a0a23713a347d78
    prep_message: >-
  out_share_0:
    - 12505291739929652039
  out_share_1:
    - 5941452329484932283
agg_share_0: >-
  ad8bb894e3222b47
agg_share_1: >-
  5274476a1cddd4bb
agg_result: 1
]]></artwork>
      </section>
      <section numbered="false" anchor="testvec-prio3aes128sum">
        <name>Prio3Aes128Sum</name>
        <artwork><![CDATA[
bits: 8
verify_key: "01010101010101010101010101010101"
upload_0:
  measurement: 100
  nonce: "01010101010101010101010101010101"
  public_share: >-
  input_share_0: >-
    fc1e42a024e3d8b45f63f485ebe2dc8a356c5e5780a0bd751184e6a02a96c0767f51
    8e87282ebdc039590aef02e40e5492c9eb69dd22b6b4f1d630e7ca8612b7a7e090b3
    9460bc4036345f5ef537d691fd585bc05a2ea580c7e354680afd0fd49f3d083d5e38
    3b97755a842cf5e69870a970b14a10595c0c639ad2e7bda42c7146c4b69fd79e7403
    d89dac5816d0dc6f2bb987fccca4c4aee64444b7f46431433c59c6e7f2839fe2b7ad
    9316d31a52dcc0df07f1da14aa38e0cd88de380fda29b33704e8c3439376762739aa
    5b5cff9e925939773d24ca0e75bcf87149c9bcc2f8462afa6b50513ab003ac00c9ae
    3685ea52bdee3c814ffd5afc8357d93454b3ffaf0b5e9fd351730f0d55aed54a9cfa
    86f9119601ce9857ee0af3f579251bcc7ffe51b8393adc36ab6142eb0e0d07c9b2d5
    ab71d8d5639f32c61f7d59b45a95129cbc76d7e30c02a1329454f843553413d4e84b
    cab2c3ba1a0150292026dfa37488da5dd639c53edd51bf4eb5aa54d5b165fcd55d10
    f3496008f4e3b6d3eb200c19c5b9c42ad4f12977a857d02f787b14ced27fc5eefb05
    722b372a7d48c1891d30a32d84ec8d1f9a783a38bfac2793f0da6796cff90521e1d7
    3f497f7d2c910b7fbbea2ba4b906d437a53bcbed16986f5646fd238e736f1c3e9d3a
    910218ce7f48dea3e9a1a848c580a1c506a80edb0c0a973a269667475ce88f442467
    4b14a3a8f2b71ef529d2ca96a3c5e4da384545749a55188d4de0074ad601695e934c
    9fe71d27c139b7678ead7f904cd2ae2a3aafa96d8211579e391507df96bf42c383f2
    ac71d7a558ebf1e3d5ab086b65422415bd24be9c979ca5b4f381d51b06ec4f6740b1
    a084999cd95fe63fec4a019f635640ba18d42312de7d1994947502b9010101010101
    010101010101010101015f0721f50826593dc3908dad39353846
  input_share_1: >-
    01010101010101010101010101010101010101010101010101010101010101010101
    0101010101010101010101010101094240ceae2d63ba1bdda997fa0bcbd8
  round_0:
    prep_share_0: >-
      0a85b5e51cacf514ee9e9bbe5d3ac023795e910b765411e5cea8ff187973640694
      bd740cc15bc9cad60bc85785206062094240ceae2d63ba1bdda997fa0bcbd8
    prep_share_1: >-
      f57a4a1ae3530acf11616441a2c53fde804d262dc42e15e556ee02c588c3ca9d92
      4eefa735a95f6e420f2c5161706e025f0721f50826593dc3908dad39353846
    prep_message: >-
      60af733578d766f2305c1d53c840b4b5
  out_share_0:
    - 227608477929192160221239678567201956832
  out_share_1:
    - 112673888991746302725626094800698809477
agg_share_0: >-
  ab3bcc5ef693737a7a3e76cd9face3e0
agg_share_1: >-
  54c433a1096c8c6985c1893260531c85
agg_result: 100
]]></artwork>
      </section>
      <section numbered="false" anchor="testvec-prio3aes128histogram">
        <name>Prio3Aes128Histogram</name>
        <artwork><![CDATA[
buckets: [1, 10, 100]
verify_key: "01010101010101010101010101010101"
upload_0:
  measurement: 50
  nonce: "01010101010101010101010101010101"
  public_share: >-
  input_share_0: >-
    ee1076c1ebc2d48a557a71031bc9dd5c9cd5e91180bbb51f4ac366946bcbfa93b908
    792bd15d402f4ac8da264e24a20f645ef68472180c5894bac704ae0675d7f16776df
    4f93852a40b514593a73be51ad64d8c28322a47af92c92223dd489998a3c6687861c
    dc2e4d834885d03d8d3273af0bf742c47985ae8fec6d16c31216792bb0cdca0d1d1f
    a2287414cd069f8caa42dc08f78dd43e14c4095e2ef9d9609937caebcd534e813136
    e79a4233e873397a6c7fd164928d43673b32e061139dc6650152d8433e2342f59514
    9418929b74c9e23f1469ed1eebdaa57d0b5c62f90cb5a53dc68c8e030448bb2d9c07
    aeed50d82c93e1afe8febd68918933ed9b2dd36b9d8a35fd6c57cd76707011fca775
    26437aeb8392a2013f829c1e395f7f8ddef030f5bc869833f528ae2137a2e667aa64
    8d8643f6c13e8d76e8832ab9ef7d0101010101010101010101010101010194c3f0f1
    061c8f440b51f806ad822510
  input_share_1: >-
    01010101010101010101010101010101010101010101010101010101010101010101
    01010101010101010101010101016195ec204fd5d65c14fac36b73723cde
  round_0:
    prep_share_0: >-
      f2dc9e823b867d760b2169644633804eabec10e5869fe8f3030c5da6dc0fce03a4
      33572cb8aaa7ca3559959f7bad68306195ec204fd5d65c14fac36b73723cde
    prep_share_1: >-
      0d23617dc479826df4de969bb9cc7fb3f5e934542e987db0271aee33551b28a4c1
      6f7ad00127c43df9c433a1c224594d94c3f0f1061c8f440b51f806ad822510
    prep_message: >-
      7912f1157c2ce3a4dca6456224aeaeea
  out_share_0:
    - 316441748434879643753815489063091297628
    - 208470253761472213750543248431791209107
    - 245951175238245845331446316072865931791
    - 133415875449384174923011884997795018199
  out_share_1:
    - 23840618486058819193050284304809468581
    - 131812113159466249196322524936109557102
    - 94331191682692617615419457295034834419
    - 206866491471554288023853888370105748010
agg_share_0: >-
  ee1076c1ebc2d48a557a71031bc9dd5c9cd5e91180bbb51f4ac366946bcbfa93b90879
  2bd15d402f4ac8da264e24a20f645ef68472180c5894bac704ae0675d7
agg_share_1: >-
  11ef893e143d2b59aa858efce43622a5632a16ee7f444ac4b53c996b9434056e46f786
  d42ea2bfb4b53725d9b1db5df39ba1097b8de7f38b6b4538fb51f98a2a
agg_result: [0, 0, 1, 0]
]]></artwork>
      </section>
      <section numbered="false" anchor="testvec-poplar1aes128">
        <name>Poplar1Aes128</name>
        <section numbered="false" anchor="sharding-1">
          <name>Sharding</name>
          <artwork><![CDATA[
bits: 4
verify_key: "01010101010101010101010101010101"
agg_param: (0, [0, 1])
upload_0:
  measurement: 13
  nonce: "01010101010101010101010101010101"
  public_share: >-
    9a000000000000000000000000000000000000000000000001eb3a1bd6b5fa4a4500
    000000000000000000000000000000ffffffff0000000022522c3fd5a33cac000000
    00000000000000000000000000ffffffff0000000069f41eee46542b690000000000
    00000000000000000000000000000000000000000000000000000000000000000000
    0000000000000000017d1fd6df94280145a0dcc933ceb706e9219d50e7c4f92fd8ca
    9a0ffb7d819646
  input_share_0: >-
    0101010101010101010101010101010101010101010101010101010101010101c226
    c4542c79eafa04ece4b493baadd00114dd7a8f91b9a25b767f43733c467d2cbb7fb5
    fe9782d0a51919f2bc2b6aa57442f7b923b9a700c7ab7a6c0aaff428ee671e1ed22f
    12dbb4714b53b11f3e0354cd5709f04c6bb9b0563499a7bd94c11d6d48c24ddc68a4
    b6477c2847d8218a
  input_share_1: >-
    01010101010101010101010101010101010101010101010101010101010101010e6b
    27437d25adc6b565aa093dcc0d27507481df2f19d80abebe750f4b0ab4b6eb20a7de
    2aebb5f610e65647225d4a1851709e3b8c95c38eccf85ffebf320fae04f6826999af
    0782036a9671411b0676717cc6a0b8fd87177836f1fd980d49e4ad23f31e83a99cea
    313c614e7106ec80
]]></artwork>
        </section>
        <section numbered="false" anchor="preparation-aggregation-and-unsharding">
          <name>Preparation, Aggregation, and Unsharding</name>
          <artwork><![CDATA[
verify_key: "01010101010101010101010101010101"
agg_param: (0, [0, 1])
upload_0:
  round_0:
    prep_share_0: >-
      d15f37fd8d2de10c3eec340265f8bfaa6ea7b79536b4d12a
    prep_share_1: >-
      7e02697276b506ca402eca93b7dcf770877dff591d6fd9c5
    prep_message: >-
      4f61a17103e2e7d57f1afe961dd5b71af625b6ee5424aaef
  round_1:
    prep_share_0: >-
      cba373c9458c26ee
    prep_share_1: >-
      345c8c35ba73d913
    prep_message: >-
  out_share_0:
    - 18188801410092473065
    - 309938393258542164
  out_share_1:
    - 257942659322111256
    - 18136805676156042158
agg_share_0: >-
  fc6b9a839aaf9ae9044d1f53986e4454
agg_share_1: >-
  0394657b65506518fbb2e0ab6791bbae
agg_result: [0, 1]
]]></artwork>
          <artwork><![CDATA[
verify_key: "01010101010101010101010101010101"
agg_param: (1, [0, 1, 2, 3])
upload_0:
  round_0:
    prep_share_0: >-
      9b0474605d77d4791a43cb86dc332a15b8b5f67496aa4b8d
    prep_share_1: >-
      92b13576b734a956e93851d81193d503bae64c3cda971dfb
    prep_message: >-
      2db5a9d814ac7dce037c1d5fedc6ff17739c42b271416987
  round_1:
    prep_share_0: >-
      aecb3ecaafff0dbe
    prep_share_1: >-
      5134c1345000f243
    prep_message: >-
  out_share_0:
    - 16639637265869957457
    - 1807457878431656707
    - 14875784335609201424
    - 8515527061577716649
  out_share_1:
    - 1807106803544626864
    - 16639286190982927614
    - 3570959733805382897
    - 9931217007836867673
agg_share_0: >-
  e6ebddeec787e9511915615d36666b03ce716709b74e8310762d3abecc90d3a9
agg_share_1: >-
  19142210387816b0e6ea9ea1c99994fe318e98f548b17cf189d2c540336f2c59
agg_result: [0, 0, 0, 1]
]]></artwork>
          <artwork><![CDATA[
verify_key: "01010101010101010101010101010101"
agg_param: (2, [0, 2, 4, 6])
upload_0:
  round_0:
    prep_share_0: >-
      93df236f6e786bca97233e32224a1941f6dd3a9511e01acc
    prep_share_1: >-
      2ab413234f2bec549b6546e4d96fee4bad6957e433768506
    prep_message: >-
      be933692bda4581e32888517fbba078ba446927a45569fd1
  round_1:
    prep_share_0: >-
      c36e1270495f5aa6
    prep_share_1: >-
      3c91ed8eb6a0a55b
    prep_message: >-
  out_share_0:
    - 3024081010823632913
    - 6306522542811675542
    - 2996392641000911092
    - 7890625214403888205
  out_share_1:
    - 15422663058590951408
    - 12140221526602908779
    - 15450351428413673229
    - 10556118855010696117
agg_share_0: >-
  29f7b1a836259811578544d6dc487b962995533b3e7430f46d8121d38048c44d
agg_share_1: >-
  d6084e56c9da67f0a87abb2823b7846bd66aacc3c18bcf0d927ede2b7fb73bb5
agg_result: [0, 0, 0, 1]
]]></artwork>
          <artwork><![CDATA[
verify_key: "01010101010101010101010101010101"
agg_param: (3, [1, 3, 5, 7, 9, 13, 15])
upload_0:
upload_0:
  measurement: 13
  nonce: "01010101010101010101010101010101"
  public_share: >-
    9a000000000000000000000000000000000000000000000001eb3a1bd6b5fa4a4500
    000000000000000000000000000000ffffffff0000000022522c3fd5a33cac000000
    00000000000000000000000000ffffffff0000000069f41eee46542b690000000000
    00000000000000000000000000000000000000000000000000000000000000000000
    0000000000000000017d1fd6df94280145a0dcc933ceb706e9219d50e7c4f92fd8ca
    9a0ffb7d819646
  input_share_0: >-
    0101010101010101010101010101010101010101010101010101010101010101c226
    c4542c79eafa04ece4b493baadd00114dd7a8f91b9a25b767f43733c467d2cbb7fb5
    fe9782d0a51919f2bc2b6aa57442f7b923b9a700c7ab7a6c0aaff428ee671e1ed22f
    12dbb4714b53b11f3e0354cd5709f04c6bb9b0563499a7bd94c11d6d48c24ddc68a4
    b6477c2847d8218a
  input_share_1: >-
    01010101010101010101010101010101010101010101010101010101010101010e6b
    27437d25adc6b565aa093dcc0d27507481df2f19d80abebe750f4b0ab4b6eb20a7de
    2aebb5f610e65647225d4a1851709e3b8c95c38eccf85ffebf320fae04f6826999af
    0782036a9671411b0676717cc6a0b8fd87177836f1fd980d49e4ad23f31e83a99cea
    313c614e7106ec80
  round_0:
    prep_share_0: >-
      0940b06b287f0232397df2414c00cd0ccfb08f955bf4089651f019458cd7da2204
      c997d78134341745669b19da58cbef280f712d12900475ac2c4de486e9870774ba
      3c9d024245e7866528e37b9a931e61b794ab12a4bf74b41de50cec5f1214
    prep_share_1: >-
      605b876c915cb4b2d94c5999ab0642e81eefe4b06ac936b2cd9608ffeb9a6c8a45
      a9faa5b4940cdc375043075990f115770cbb762f2baf1bf9024c36685cf3051607
      a3331e036072b0202bb89be78d7ad8f8c07fbf2761884dcb4f414e966562
    prep_message: >-
      699c37d7b9dbb6e512ca4bdaf7070ff4eea07445c6bd3f491f862245787246ac4a
      73927d35c840f37cb6de2133e9bd049f1c2ca341bbb391a52e9a1aef467a0c0ac1
      dfd02045a65a3685549c178220993ab0552ad1cc20fd01e9344e3af57789
  round_1:
    prep_share_0: >-
      69ac4b4219b647d08579ebc1d61e15a87684c817b8e9e2f599dec39dd42c60e0
    prep_share_1: >-
      1653b4bde649b82f7a86143e29e1ea57897b37e847161d0a66213c622bd39f0d
    prep_message: >-
  out_share_0:
    - 31266787981623073345438631450097917412029050287225674733758559830914037991840
    - 26393661814069127500656687560668964619575440551355825110935075749282733430112
    - 29174096716912605985872100661347047626133976434476959088535854022406688824676
    - 37302603208117590782775952507020589026342905631492315271787751917771005617295
    - 55309420117672678173715719521410144937198418175813304907316032334662803449360
    - 29174390317706805594521496894406843472816744180092642437922410411508000504883
    - 21223279146307403682071881696710510174726527474394063793607036387613816968277
  out_share_1:
    - 26629256637035024366346861054246036514605942045594607285970232173042526828109
    - 31502382804588970211128804943674989307059551781464456908793716254673831389837
    - 28721947901745491725913391842996906300501015898343322931192937981549875995273
    - 20593441410540506929009539997323364900292086701327966747941040086185559202654
    - 2586624500985419538069772982933808989436574157006977112412759669293761370589
    - 28721654300951292117263995609937110453818248152727639581806381592448564315067
    - 36672765472350694029713610807633443751908464858426218226121755616342747851672
agg_share_0: >-
  45205ff6efcf67961cc100e880f3c58d5ce283585caf7fb58e09c24ba9bc49a03a5a48
  7f662ab7b240b41b6c3ac345c3754b43cbb1a5d8158e8859d1994d1560407ff41dd4ca
  cc470b3c428a61fa974d6cf9b1d14c6db9401f0e174ffce55d64527886748fe09c86af
  d58b7e7717c47ee97309fefeda64830940348d97e3e48f7a4805bcea0d023dffa0d3cb
  1bda898326421778e72467244acb17f472a4e61040801ea8170611e914421029a53aa0
  1b494ff834cf2e01239409a37b99623c332eebf34778eee2356d44b95a1681d1f394f7
  fe66cad88d59fcb458283e84d455
agg_share_1: >-
  3adfa00910309869e33eff177f0c3a72a31d7ca7a350804a71f63db45643b64d45a5b7
  8099d5484dbf4be493c53cba3c8ab4bc344e5a27ea7177a62e66b2ea8d3f800be22b35
  33b8f4c3bd759e0568b293064e2eb39246bfe0f1e8b0031aa2892d87798b701f637950
  2a748188e83b81168cf60101259b7cf6bfcb72681c1b5e05b7fa4315f2fdc2005f2c34
  e425767cd9bde88718db98dbb534e80b8d5b19dd3f7fe157e8f9ee16ebbdefd65ac55f
  e4b6b007cb30d1fedc6bf65c84669dc3bb51140cb887111dca92bb46a5e97e2e0c6b08
  0199352772a6034ba7d7c17b2b98
agg_result: [0, 0, 0, 0, 0, 1, 0]
]]></artwork>
        </section>
      </section>
    </section>
  </back>
  <!-- ##markdown-source:
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
42eHxy16nYNXUge0272N1UOXnTlZTvq942t1CLuju4fGCXSnyRJDTdlwtJaK
I0YtbxYC+Ry/I9G2veqH/wZLMIhg4WSKz/Huz9/sAt94sPvdg+8ePd797iFQ
uR0q12CFKn72W/r+hTsuHePxz+Z1ekQhHE7z2ZPIRw+UJj7nj2g8ipvHSvTw
99/zo0e450c7O4++fbS98+2D3cfffPv42+8eb9j8zqP1u28ZaB0YHj2yYNjZ
/TaAA3z+rwXE7sOHwIJ3vluz6fDQ8GG7WvgsZXNtfH+qccjU1zmNR9lZH3P8
YVtWFWoozhqKBMOR5K1U1Ve2Hb543qEl93e+6w6xwk+FHYJlcLgn1IaRLV1h
ffLvtiUdn8Igxc7gjpLtamdYoFwCJeUJT5k6R8cvuja1Iv24lHKC53kBkkCH
X+zKm2UKqo2ot+jzVZ0OLWJ2hlGGW9+PYfiQSQf3PqqxGM+WmmUyXOPGA2fS
CAK5ME+mUSqOss9VVkGqzMQTgAYLa7QAcda5o+LsC7a5Ou19e7jeplY26wUl
BMiarYxmvZGRjOeE57HSy8Rkck1zVSyHYd2DwFjEMznZmMqxRDEtiUPyYBxX
xeWErMXaYWZEA4jVyu+ae/P5YhGel5Ra/LiTDdKBxjlKToBxW+GyNCxgSEl3
LiycmPBlHpYJQ7zViHy32qAVG6AhsBtYgHrL2bQHF2JAftCGUS8UWyjGWm1w
Yg31Qb7wL1gBtRwSIQJBhDWU3YYdDGz5L5EabPUce2+07Ayf0EYjzEB8gxh0
bu4vP4tyIqgM2EhA6/iQpkjNi7EmSaoHiwHY7X2vTWJPFNztOoF77j0iuLKe
h0cDZaI1KPNVCBOtQ5h16KLK7TOF0SK9kovIxhr8+hS/6AD8KT2v/XKhpDvy
BiZAqfhJrNeRHw0MEQ7n4JmBgwBpgm94N02MC0DurAR4TcS+S2vGd8i8VKaz
qdimenEDtXmdc1glvUCi8Wk+Pd3tBIaZLvLMpsGII1nRSARfd+M/6/gtJiBc
Bm+1xUzWNS/805N4HlqJ/rzJSHQTU0+EsVlLzangEJ4hnsiQDbLeQumAXLcy
koGRxjjFVwiyiAqtjk0GdutPFnNaHzDY1P7AmiO8MapZmyOP5ZV5eOb2ljBk
mE6LhwXspyVKeSRh9BP6UBeZjgBvZtlyyblyFEiguhF2YJ/0MRpsjn4lrMR0
+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
pUPYql0OZ8zGFIZ062HSSsxauTlc+vPpFb3Jy0+dA6o4FxfnJ0vvl+o0Gcvp
fXVmHB7UdB1ox/QVx9fZnXMsBwtm/Ojkxe/NWSwkZZOBaIY5fvOubmNT3P8+
ZXPbyBusGCWemQ/oNlfrV+uNjeVf861uMx0+DeHKvKV0yFTZSttL8C6fos3v
e7ly/nSwoIuHj+/zHb2TJE1MIL2O6y5R1XDSmjbc8uRyvCZJy1TudgKNwmvJ
UwfQc6o6no0YmO6DpX+fEudHuXEQwnqbaGQKerLI1mPB2/FJcAw+XYyDsTlb
fCozE3nOW5yI4qQu9YJuUx+kP7PCPrY4LWZNZeVcsXf8tvggujSZaQ6SrIUB
Ht44WHyA1xnhfeF9nMHFxUlHKL8nq5MI3LaAca/W/7AA8QNyfHY3+73NWEvf
GxuDPh+rKi/OfTEQYndugSieor5cLA8PNwQ5PfrqqSMsn9HG+lMHbe8ZeZBm
6SZFajZejAmJf52jpgktheMBohkfCTyP8124f/KyexwbM2+uh/GEY68wrCPG
yd5ahGzesh3qTdvkCRGfEHNPXDur0trz3iTMLpIHrAVpbXj/gL+qyBHzThVf
UwlE++KKP7eLO+XiiZW757fCnJMGZ+d8m1h2t26tR9ZQ0nNoiwYxaw0RZYzM
ocTgeA+raD764k4jIjEh7PaPjjNMODWfXhVrP1xSu0vbrnvZRpfZCxRj39oq
3KVxoXsj552/83Af5919n3WpCdDPk6fy8Xer8J4vQ3ud+O1aLk8bfHf4G8hL
2KK1o8Kglm/sCZ4noHTFPDHde+FcI/dfuUBXyUXk42vBr/hYppT4j0UyvTly
v3nOSXKU4N+MD7NH9lG6Wgf+hId3HCLbM1XP5MkZsFvz1fNE9j0/Sf1no6Ph
I51Ou/j100QKTYr00cmxuzl18q6XxR0vfywOjpzlR1O/7r2Omp14uTo5XJag
GJ57189vWJn3IaHJMF3/c18dhC8eiNHRkfmcuZ2S02Gcz/stqlvEe0aXjOnR
Cpm0oZhk4w9w/7/v+ieOcyfT0uGysDsArL4byL/04SgJ52n9M3JRxLOGAwE2
iYiin0CS91xq37Cll0mU0JxkmhLb8zfv251zth7EXqYN/h7vKzPfPSOKvvyK
JpyyxbS/WVBxn3CJAxDh4xRsCd7F4m8m1oVzXyVFQbCWfFwbm1muLic5Dk84
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

-->

</rfc>
