<?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-rfc2629 version 1.6.2 (Ruby 3.0.3) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-patton-cfrg-vdaf-01" category="info" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.12.3 -->
  <front>
    <title abbrev="VDAF">Verifiable Distributed Aggregation Functions</title>
    <seriesInfo name="Internet-Draft" value="draft-patton-cfrg-vdaf-01"/>
    <author initials="C." surname="Patton" fullname="Christopher Patton">
      <organization>Cloudflare, Inc.</organization>
      <address>
        <email>cpatton@cloudflare.com</email>
      </address>
    </author>
    <author initials="R. L." surname="Barnes" fullname="Richard L. Barnes">
      <organization>Cisco</organization>
      <address>
        <email>rlb@ipv.sx</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="March" day="05"/>
    <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: 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 inputs.</t>
      <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 applications like <xref target="I-D.draft-gpew-priv-ppm"/> 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 measurement collectors);</li>
            <li>Capabilities of a malicious coalition of servers attempting to divulge
information about client inputs; 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 allow new constructions
to be easily used by applications.</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 input 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 combine their additive shares to obtain
the final aggregate.</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 generalization of a 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>The remainder of this document is organized as follows: <xref target="overview"/> gives a
brief overview of VDAFs; <xref target="vdaf"/> defines the syntax for VDAFs; <xref target="prelim"/>
defines various functionalities that are common to our constructions; <xref target="poplar1"/>
describes the Poplar1 construction; <xref target="prio3"/> describes the Prio3 construction;
and <xref target="security"/> enumerates the security considerations for VDAFs.</t>
    </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>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>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 VDAF</name>
        <artwork><![CDATA[
                 +--------------+
           +---->| Aggregator 0 |----+
           |     +--------------+    |
           |             ^           |
           |             |           |
           |             V           |
           |     +--------------+    |
           | +-->| Aggregator 1 |--+ |
           | |   +--------------+  | |
+--------+-+ |           ^         | +->+-----------+
| Client |---+           |         +--->| Collector |--> Aggregate
+--------+-+                         +->+-----------+
           |            ...          |
           |                         |
           |             |           |
           |             V           |
           |    +----------------+   |
           +--->| Aggregator N-1 |---+
                +----------------+

      Input shares           Aggregate shares
]]></artwork>
      </figure>
      <t>In a 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>Clients are configured with public parameters for a set of Aggregators.</li>
        <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 verify the validity of the input shares, producing a set of
"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 the validation process, each aggregator holds one output share.</li>
            <li>In most 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 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 inputs.  Thus clients trust Aggregators not to collude
(typically it is required that at least one Aggregator is honest), and
Collectors trust Aggregators to properly verify Client inputs.</t>
      <t>Within the bounds of the non-collusion requirements of a given VDAF 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
Aggregators 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 applications 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="vdaf">
      <name>Definition of VDAFs</name>
      <t>A concrete VDAF specifies the algorithms involved in evaluating an aggregation
function across a batch of inputs. This section specifies the interfaces of
these algorithms as they would be exposed to applications.</t>
      <t>The overall execution of a VDAF comprises the following steps:</t>
      <ul spacing="normal">
        <li>Setup - Generating shared parameters for the Aggregators</li>
        <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>The setup algorithm is performed once for a given collection of Aggregators.
Sharding and preparation are done once per measurement input.  Aggregation and
unsharding are done over a batch of inputs (more precisely, over the output
shares recovered from those inputs).</t>
      <t>Note that the preparation step performs two functions: Verification and
conversion.  Conversion translates input shares into output shares that are
compatible with the aggregation function.  Verification ensures that aggregating
the recovered 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 in terms of an abstract
base class <tt>Vdaf</tt>. This class defines the set of methods and attributes a
concrete VDAF must provide. The attributes are listed in [{vdaf-param}}; the
methods are defined in the subsections that follow.</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>ROUNDS</tt></td>
            <td align="left">Number of rounds of communication during the preparation phase (<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>PublicParam</tt></td>
            <td align="left">Type of public parameter used by the Client during the sharding phase (<xref target="sec-vdaf-shard"/>)</td>
          </tr>
          <tr>
            <td align="left">
              <tt>VerifyParam</tt></td>
            <td align="left">Type of verification parameter used by each Aggregator during the preparation phase (<xref target="sec-vdaf-prepare"/>)</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 the preparation phase (<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>AggShare</tt></td>
            <td align="left">Type of each aggregate share</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggResult</tt></td>
            <td align="left">Type of the aggregate result</td>
          </tr>
        </tbody>
      </table>
      <section anchor="sec-vdaf-setup">
        <name>Setup</name>
        <t>Before execution of the VDAF can begin, it is necessary to distribute long-lived
parameters to the Client and Aggregators. The long-lived parameters are
generated by the following algorithm:</t>
        <ul spacing="normal">
          <li>
            <tt>Vdaf.setup() -&gt; (PublicParam, Vec[VerifyParam])</tt> is the randomized setup
algorithm used to generate the public parameter used by the Clients and the
verification parameters used by the Aggregators. The length of the latter <bcp14>MUST</bcp14>
be equal to <tt>SHARES</tt>. In general, an Aggregator's verification parameter is
considered secret and <bcp14>MUST NOT</bcp14> be revealed to the Clients, Collector or other
Aggregators. The parameters <bcp14>MAY</bcp14> be reused across multiple VDAF evaluations.
See <xref target="security"/> for a discussion of the security implications this has
depending on the threat model.</li>
        </ul>
      </section>
      <section anchor="sec-vdaf-shard">
        <name>Sharding</name>
        <t>In order to protect the privacy of its measurements, a VDAF Client splits its
measurements into "input shares".  The <tt>measurement_to_input_shares</tt> method is
used for this purpose.</t>
        <ul spacing="normal">
          <li>
            <tt>Vdaf.measurement_to_input_shares(public_param: PublicParam, input:
Measurement) -&gt; Vec[Bytes]</tt> is the randomized input-distribution algorithm run
by each Client. It consumes the public parameter and input measurement and
produces a sequence of input shares, one for each Aggregator. The length of
the output <bcp14>MUST</bcp14> be <tt>SHARES</tt>.</li>
        </ul>
        <figure anchor="shard-flow">
          <name>The Client divides its measurement input 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>
        <ul empty="true">
          <li>
            <t>CP The <tt>public_param</tt> is intended to allow for protocols that require the
Client to use a public key for sharding its measurement. When rotating the
<tt>verify_param</tt> for such a scheme, it would be necessary to also update the
<tt>public_param</tt> with which the clients are configured. For PPM it would be nice
if we could rotate the <tt>verify_param</tt> without also having to update the
clients. We should consider dropping this at some point. See
https://github.com/cjpatton/vdaf/issues/19.</t>
          </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>
            <tt>Vdaf.prep_init(verify_param: VerifyParam, agg_param: AggParam, nonce: 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 its verification parameter
(<tt>verify_param</tt>), the aggregation parameter (<tt>agg_param</tt>), the nonce provided
by the environment (<tt>nonce</tt>, see <xref target="run-vdaf"/>), and one of the input shares
generated by the client (<tt>input_share</tt>). Its output is the Aggregator's
initial preparation state.</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 Depending on what we do for issue#20, we may end up needing to
revise the above paragraph.</t>
          </li>
        </ul>
      </section>
      <section anchor="sec-vdaf-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.  This algorithm is performed locally at each
Aggregator, without communication with the other Aggregators.</t>
        <ul spacing="normal">
          <li>
            <tt>Vdaf.out_shares_to_agg_share(agg_param: AggParam, output_shares:
Vec[OutShare]) -&gt; agg_share: AggShare</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>
        <figure anchor="agg-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 and the unsharding algorithm
below in "one-shot" form, where all shares for a batch are provided at the same
time.  Some VDAFs may also support a "streaming" form, where shares are
processed one at a time.</t>
      </section>
      <section anchor="sec-vdaf-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>Vdaf.agg_shares_to_result(agg_param: AggParam, agg_shares: Vec[AggShare]) -&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>.
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="I-D.draft-gpew-priv-ppm"/>.) Or
is this out-of-scope of this document?</t>
          </li>
        </ul>
      </section>
      <section anchor="execution">
        <name>Execution of a VDAF</name>
        <t>Executing a VDAF involves the concurrent evaluation of the VDAF on individual
inputs and aggregation of the recovered output shares. This is captured by the
following example algorithm:</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]):
    # Distribute long-lived parameters.
    (public_param, verify_params) = Vdaf.setup()

    out_shares = []
    for (nonce, measurement) in zip(nonces, measurements):

        # Each Client shards its input into shares.
        input_shares = Vdaf.measurement_to_input_shares(public_param,
                                                        measurement)

        # Each Aggregator initializes its preparation state.
        prep_states = []
        for j in range(Vdaf.SHARES):
            state = Vdaf.prep_init(verify_params[j],
                                   agg_param,
                                   nonce,
                                   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 phasre are the output shares.
        out_shares.append(outbound)

    # Each Aggregator aggregates its output shares into an
    # aggregate share.
    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.
    agg_result = Vdaf.agg_shares_to_result(agg_param, agg_shares)
    return agg_result
]]></artwork>
        </figure>
        <t>The inputs to this algorithm are the aggregation parameter <tt>agg_param</tt>, a list
of nonces <tt>nonces</tt>, and a batch of Client inputs <tt>input_batch</tt>. The aggregation
parameter is chosen by the Aggregators prior to executing the VDAF. This
document does not specify how the nonces are chosen, but security requires that
the nonces be unique for each measurement. See <xref target="security"/> for details.</t>
        <t>Another important question this document leaves out of scope is how a VDAF is to
be executed by Aggregators distributed over a real network. Algorithm <tt>run_vdaf</tt>
prescribes the protocol's execution in a "benign" environment in which there is
no adversary and 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="I-D.draft-gpew-priv-ppm"/> that implements
suitable cryptographic functionalities. 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 VDAF in various
adversarial environments and what properties the wrapper protocol needs to
provide in each.</t>
        <!--
## VDAFs in the Literature

* Prio [CGB17] defines the composition of a linear secret sharing scheme and an
  affine-aggregatable encoding of a statistic.

* A special case of zero-knowledge proofs over distributed data [BBCGGI19] in
  which the client speaks once.

* The composition of an incremental distributed point function and the
  secure-sketching protocol for subset histograms defined in [BBCGGI21].

* Prio+ [AGJOP21] has the client upload XOR shares and then has the servers
  convert them to additive shares over a number of rounds.
-->

</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.
If <tt>integer &gt;= Field.MODULUS</tt>, then <tt>integer</tt> is first reduced modulo
<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 = Field(OS2IP(encoded_x))
        vec.append(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. (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.</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>. This value <bcp14>MUST</bcp14> be a power of 2.</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>
        </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 <xref target="prg-constructions"/>.</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)

# Expand a seed into a vector of Field elements.
def expand_into_vec(Prg,
                    Field,
                    seed: Bytes,
                    info: Bytes,
                    length: Unsigned):
    m = next_power_of_2(Field.MODULUS) - 1
    prg = Prg(seed, info)
    vec = []
    while len(vec) < length:
        x = OS2IP(prg.next(Field.ENCODED_SIZE))
        x &= m
        if x < Field.MODULUS:
            vec.append(Field(x))
    return vec
]]></artwork>
        </figure>
        <section anchor="prg-constructions">
          <name>Constructions</name>
          <section anchor="prgaes128">
            <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
https://github.com/cjpatton/vdaf/issues/32 for details.</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 anchor="prg-aes128">
              <name>Definition of PRG PrgBlockCipher(Aes128).</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>
    <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 "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>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 proof 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]) -&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.</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 "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>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)</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="prio3-instantiations"/>). 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>We remark that, taken together, these two 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>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>PublicParam</tt></td>
              <td align="left">
                <tt>None</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>VerifyParam</tt></td>
              <td align="left">
                <tt>Tuple[Unsigned, Bytes]</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>AggShare</tt></td>
              <td align="left">
                <tt>Vec[Flp.Field]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">
                <tt>Vec[Unsigned]</tt></td>
            </tr>
          </tbody>
        </table>
        <section anchor="setup">
          <name>Setup</name>
          <t>The setup algorithm generates a symmetric key shared by all of the Aggregators.
The key is used to derive query randomness for the FLP query-generation
algorithm run by the Aggregators during preparation. An Aggregator's
verification parameter also includes its "ID", a unique integer in <tt>[0,
SHARES)</tt>.</t>
          <figure anchor="prio3-eval-setup">
            <name>The setup algorithm for prio3.</name>
            <artwork><![CDATA[
def setup(Prio3):
    k_query_init = gen_rand(Prio3.Prg.SEED_SIZE)
    verify_param = [(j, k_query_init) for j in range(Prio3.SHARES)]
    return (None, verify_param)
]]></artwork>
          </figure>
        </section>
        <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 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 a pair of auxiliary functions for encoding the shares. These
are called <tt>encode_leader_share</tt> and <tt>encode_helper_share</tt> respectively and they
are described 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, _public_param, measurement):
    dst = b"vdaf-00 prio3"
    inp = Prio3.Flp.encode(measurement)
    k_joint_rand = zeros(Prio3.Prg.SEED_SIZE)

    # Generate input shares.
    leader_input_share = inp
    k_helper_input_shares = []
    k_helper_blinds = []
    k_helper_hints = []
    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_hint = Prio3.Prg.derive_seed(k_blind,
                                       byte(j+1) + encoded)
        k_joint_rand = xor(k_joint_rand, k_hint)
        k_helper_input_shares.append(k_share)
        k_helper_blinds.append(k_blind)
        k_helper_hints.append(k_hint)
    k_leader_blind = gen_rand(Prio3.Prg.SEED_SIZE)
    encoded = Prio3.Flp.Field.encode_vec(leader_input_share)
    k_leader_hint = Prio3.Prg.derive_seed(k_leader_blind,
                                          byte(0) + encoded)
    k_joint_rand = xor(k_joint_rand, k_leader_hint)

    # Finish joint randomness hints.
    for j in range(Prio3.SHARES-1):
        k_helper_hints[j] = xor(k_helper_hints[j], k_joint_rand)
    k_leader_hint = xor(k_leader_hint, k_joint_rand)

    # 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)

    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):
        input_shares.append(Prio3.encode_helper_share(
            k_helper_input_shares[j],
            k_helper_proof_shares[j],
            k_helper_blinds[j],
            k_helper_hints[j],
        ))
    return 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 an XOR secret share of this seed from its
input share and the "blind" generated by the client. Thus, before running the
query-generation algorithm, it must first gather the XOR secret shares derived
by the other Aggregators.</t>
          <t>In order to avoid extra round of communication, the Client sends each Aggregator
a "hint" equal to the XOR of the other Aggregators' shares 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 XOR shares of the PRG seed
along with their verifier shares.</t>
          <ul empty="true">
            <li>
              <t>NOTE This optimization somewhat diverges from Section 6.2.3 of <xref target="BBCGGI19"/>.
Security analysis is needed.</t>
            </li>
          </ul>
          <t>The algorithms required for preparation are defined as follows. These algorithms
make use of encoding and decoding 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_param, _agg_param, nonce, input_share):
    dst = b"vdaf-00 prio3"
    (j, k_query_init) = verify_param

    (input_share, proof_share, k_blind, k_hint) = \
        Prio3.decode_leader_share(input_share) if j == 0 else \
        Prio3.decode_helper_share(dst, j, input_share)

    out_share = Prio3.Flp.truncate(input_share)

    k_query_rand = Prio3.Prg.derive_seed(k_query_init,
                                         byte(255) + nonce)
    query_rand = Prio3.Prg.expand_into_vec(
        Prio3.Flp.Field,
        k_query_rand,
        dst,
        Prio3.Flp.QUERY_RAND_LEN
    )
    joint_rand, k_joint_rand, k_joint_rand_share = [], None, None
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        encoded = Prio3.Flp.Field.encode_vec(input_share)
        k_joint_rand_share = Prio3.Prg.derive_seed(k_blind,
                                                   byte(j) + encoded)
        k_joint_rand = xor(k_hint, k_joint_rand_share)
        joint_rand = Prio3.Prg.expand_into_vec(
            Prio3.Flp.Field,
            k_joint_rand,
            dst,
            Prio3.Flp.JOINT_RAND_LEN
        )
    verifier_share = Prio3.Flp.query(input_share,
                                     proof_share,
                                     query_rand,
                                     joint_rand,
                                     Prio3.SHARES)

    prep_msg = Prio3.encode_prepare_message(verifier_share,
                                            k_joint_rand_share)
    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)

    (verifier, k_joint_rand_check) = \
        Prio3.decode_prepare_message(inbound)

    if k_joint_rand_check != k_joint_rand or \
            not Prio3.Flp.decide(verifier):
        raise ERR_VERIFY

    return out_share

def prep_shares_to_prep(Prio3, _agg_param, prep_shares):
    verifier = Prio3.Flp.Field.zeros(Prio3.Flp.VERIFIER_LEN)
    k_joint_rand_check = zeros(Prio3.Prg.SEED_SIZE)
    for encoded in prep_shares:
        (verifier_share, k_joint_rand_share) = \
            Prio3.decode_prepare_message(encoded)

        verifier = vec_add(verifier, verifier_share)

        if Prio3.Flp.JOINT_RAND_LEN > 0:
            k_joint_rand_check = xor(k_joint_rand_check,
                                     k_joint_rand_share)

    return Prio3.encode_prepare_message(verifier,
                                        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 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):
    agg = Prio3.Flp.Field.zeros(Prio3.Flp.OUTPUT_LEN)
    for agg_share in agg_shares:
        agg = vec_add(agg, agg_share)
    return list(map(lambda x: x.as_unsigned(), agg))
]]></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 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 += 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, encoded = encoded[:l], encoded[l:]
    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 += k_hint
    return encoded

def decode_helper_share(Prio3, dst, j, 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(j),
                                            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(j),
                                            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, encoded = encoded[:l], encoded[l:]
    if len(encoded) != 0:
        raise ERR_DECODE
    return (input_share, proof_share, k_blind, k_hint)

def encode_prepare_message(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_prepare_message(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)
]]></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/cjpatton/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>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 and truncating an input vector to the length of an aggregatable
output:</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>
          </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/cjpatton/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>
          <t><br/></t>
          <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>
                  <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> and
<tt>Valid.truncate</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/cjpatton/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> (see <xref target="prg-constructions"/>) 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 as a singleton vector in the natural way. The
parameters for this circuit are summarized below.</t>
          <t><br/></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>Field</tt></td>
                <td align="left">
                  <tt>Field64</tt> (<xref target="field64"/>)</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section anchor="prio3-sum">
          <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> (see <xref target="prg-constructions"/>) 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]
]]></artwork>
          <t>The validity circuit checks that the input comprised 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>
          <t><br/></t>
          <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>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> (see <xref target="prg-constructions"/>) 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
]]></artwork>
          <t>The validity circuit uses <tt>Range2</tt> (see <xref target="prio3-sum"/>) 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>
          <t><br/></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>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 The spec for Poplar1 is still a work-in-progress. A partial
implementation can be found at
https://github.com/abetterinternet/libprio-rs/blob/main/src/vdaf/poplar1.rs.
The verification logic is nearly complete, however as of this draft the code
is missing the IDPF. An implementation of the IDPF can be found at
https://github.com/google/distributed_point_functions/.</t>
        </li>
      </ul>
      <t>This section specifies Poplar1, a VDAF for the following task. Each Client holds
a <tt>BITS</tt>-bit string 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 Poplar <xref target="BBCGGI21"/>. At a high level,
the protocol works as follows.</t>
      <ol spacing="normal" type="1"><li>Each Clients runs the input-distribution algorithm on its <tt>n</tt>-bit string and
sends an input 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 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>Our VDAF 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>
      <section anchor="incremental-distributed-point-functions-idpfs">
        <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. The Client specifies an index <tt>alpha</tt> and values <tt>beta</tt>,
one for each "level" <tt>1 &lt;= l &lt;= BITS</tt>. The key generation generates two IDPF
keys, one for each Aggregator. When evaluated at index <tt>0 &lt;= x &lt; 2^l</tt>, each
IDPF share returns an additive share of <tt>beta[l]</tt> if <tt>x</tt> is the <tt>l</tt>-bit prefix
of <tt>alpha</tt> and shares of zero otherwise.</t>
        <ul empty="true">
          <li>
            <t>CP What does it mean for <tt>x</tt> to be the <tt>l</tt>-bit prefix of <tt>alpha</tt>? We need to
be a bit more precise here.</t>
          </li>
        </ul>
        <ul empty="true">
          <li>
            <t>CP Why isn't the domain size actually <tt>2^(BITS+1)</tt>, i.e., the number of nodes
in a binary tree of height <tt>BITS</tt> (excluding the root)?</t>
          </li>
        </ul>
        <t>Each <tt>beta[l]</tt> is a pair of elements of a finite field. Each level <bcp14>MAY</bcp14> have
different field parameters. Thus a concrete IDPF specifies associated types
<tt>Field[1]</tt>, <tt>Field[2]</tt>, ..., and <tt>Field[BITS]</tt> defining, respectively, the field
parameters at level 1, level 2, ..., and level <tt>BITS</tt>.</t>
        <t>An IDPF is comprised of the following algorithms (let type <tt>Value[l]</tt> denote
<tt>(Field[l], Field[l])</tt> for each level <tt>l</tt>):</t>
        <ul spacing="normal">
          <li>
            <tt>idpf_gen(alpha: Unsigned, beta: (Value[1], ..., Value[BITS])) -&gt; key:
(IDPFKey, IDPFKey)</tt> is the randomized key-generation algorithm run by the
client. 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>.</li>
          <li>
            <tt>IDPFKey.eval(l: Unsigned, x: Unsigned) -&gt; value: Value[l])</tt> is deterministic,
stateless key-evaluation algorithm run by each Aggregator. It returns the
value corresponding to index <tt>x</tt>. The value of <tt>l</tt> <bcp14>MUST</bcp14> be in <tt>[1, BITS]</tt> and
the value of <tt>x</tt> <bcp14>MUST</bcp14> be in range <tt>[2^(l-1), 2^l)</tt>.</li>
        </ul>
        <t>A concrete IDPF specifies a single associated constant:</t>
        <ul spacing="normal">
          <li>
            <tt>BITS: Unsigned</tt> is the length of each Client input.</li>
        </ul>
        <t>A concrete IDPF also specifies the following associated types:</t>
        <ul spacing="normal">
          <li>
            <tt>Field[l]</tt> for each level <tt>1 &lt;= l &lt;= BITS</tt>. Each defines the same methods and
associated constants as <tt>Field</tt> in <xref target="prio3"/>.</li>
        </ul>
        <t>Note that IDPF construction of <xref target="BBCGGI21"/> uses one field for the inner nodes of
the tree and a different, larger field for the leaf nodes. See <xref target="BBCGGI21"/>,
Section 4.3.</t>
        <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.</t>
      </section>
      <section anchor="poplar1-construction">
        <name>Construction</name>
        <t>The VDAF involves two rounds of communication (<tt>ROUNDS == 2</tt>) and is defined for
two Aggregators (<tt>SHARES == 2</tt>).</t>
        <section anchor="setup-1">
          <name>Setup</name>
          <t>The verification parameter is a symmetric key shared by both Aggregators. This
VDAF has no public parameter.</t>
          <figure anchor="poplar1-eval-setup">
            <name>The setup algorithm for poplar1.</name>
            <artwork><![CDATA[
def vdaf_setup():
  k_verify_init = gen_rand(SEED_SIZE)
  return (None, [(0, k_verify_init), (1, k_verify_init)])
]]></artwork>
          </figure>
          <section anchor="client">
            <name>Client</name>
            <t>The client's input is an IDPF index, denoted <tt>alpha</tt>. The 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"/>. After evaluating
their IDPF key shares on the set 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*a + 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_share</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(_, alpha):
  if alpha < 2**BITS: raise ERR_INVALID_INPUT

  # Prepare IDPF values.
  beta = []
  correlation_shares_0, correlation_shares_1 = [], []
  for l in range(1,BITS+1):
    (k, a, b, c) = Field[l].rand_vec(4)

    # Construct values of the form (1, k), where k
    # is a random field element.
    beta += [(1, k)]

    # Create secret shares of correlations to aid
    # the Aggregators' computation.
    A = -2*a+k
    B = a*a + b - a * k + c
    correlation_share = Field[l].rand_vec(5)
    correlation_shares_1.append(correlation_share)
    correlation_shares_0.append(
      [a, b, c, A, B] - correlation_share)

  # Generate IDPF shares.
  (key_0, key_1) = idpf_gen(input, beta)

  input_shares = [
    encode_input_share(key_0, correlation_shares_0),
    encode_input_share(key_1, correlation_shares_1),
  ]

  return input_shares
]]></artwork>
            </figure>
            <ul empty="true">
              <li>
                <t>TODO It would be more efficient to represent the correlation shares using PRG
seeds as suggested in <xref target="BBCGGI21"/>.</t>
              </li>
            </ul>
          </section>
        </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 pair of vectors of field
elements <tt>data_share</tt> and <tt>auth_share</tt>, The Aggregators use <tt>auth_share</tt> and the
correlation shares provided by the Client to verify that their <tt>data_share</tt>
vectors are additive shares of a one-hot vector.</t>
          <ul empty="true">
            <li>
              <t>CP Consider adding aggregation parameter as input to <tt>k_verify_rand</tt>
derivation.</t>
            </li>
          </ul>
          <figure anchor="poplar1-prep-state">
            <name>Preparation state for poplar1.</name>
            <artwork><![CDATA[
class PrepState:
  def __init__(verify_param, agg_param, nonce, input_share):
    (self.l, self.candidate_prefixes) = decode_indexes(agg_param)
    (self.idpf_key,
     self.correlation_shares) = decode_input_share(input_share)
    (self.party_id, k_verify_init) = verify_param
    self.k_verify_rand = get_key(k_verify_init, nonce)
    self.step = "ready"

  def next(self, inbound: Optional[Bytes]):
    l = self.l
    (a_share, b_share, c_share,
     A_share, B_share) = correlation_shares[l-1]

    if self.step == "ready" and inbound == None:
      # Evaluate IDPF on candidate prefixes.
      data_share, auth_share = [], []
      for x in self.candidate_prefixes:
        value = kdpf_key.eval(l, x)
        data_share.append(value[0])
        auth_share.append(value[1])

      # Prepare first sketch verification message.
      r = Prg.expand_into_vec(Field[l], self.k_verify_rand, len(data_share))
      verifier_share_1 = [
         a_share + inner_product(data_share, r),
         b_share + inner_product(data_share, r * r),
         c_share + inner_product(auth_share, r),
      ]

      self.output_share = data_share
      self.step = "sketch round 1"
      return verifier_share_1

    elif self.step == "sketch round 1" and inbound != None:
      verifier_1 = Field[l].decode_vec(inbound)
      verifier_share_2 = [
        (verifier_1[0] * verifier_1[0] \
         - verifier_1[1] \
         - verifier_1[2]) * self.party_id \
        + A_share * verifier_1[0] \
        + B_share
      ]

      self.step = "sketch round 2"
      return Field[l].encode_vec(verifier_share_2)

    elif self.step == "sketch round 2" and inbound != None:
      verifier_2 = Field[l].decode_vec(inbound)
      if verifier_2 != 0: raise ERR_INVALID
      return Field[l].encode_vec(self.output_share)

    else: raise ERR_INVALID_STATE

def prep_shares_to_prep(agg_param, inbound: Vec[Bytes]):
  if len(inbound) != 2:
    raise ERR_INVALID_INPUT

  (l, _) = decode_indexes(agg_param)
  verifier = Field[l].decode_vec(inbound[0]) + \
             Field[l].decode_vec(inbound[1])

  return Field[l].encode_vec(verifier)
]]></artwork>
          </figure>
        </section>
        <section anchor="aggregation-1">
          <name>Aggregation</name>
          <figure anchor="poplar1-out2agg">
            <name>Aggregation algorithm for poplar1.</name>
            <artwork><![CDATA[
def out_shares_to_agg_share(agg_param, output_shares: Vec[Bytes]):
  (l, candidate_prefixes) = decode_indexes(agg_param)
  if len(output_shares) != len(candidate_prefixes):
    raise ERR_INVALID_INPUT

  agg_share = Field[l].zeros(len(candidate_prefixes))
  for output_share in output_shares:
    agg_share += Field[l].decode_vec(output_share)

  return Field[l].encode_vec(agg_share)
]]></artwork>
          </figure>
        </section>
        <section anchor="unsharding-1">
          <name>Unsharding</name>
          <figure anchor="poplar1-agg-output">
            <name>Computation of the aggregate result for poplar1.</name>
            <artwork><![CDATA[
def agg_shares_to_result(agg_param, agg_shares: Vec[Bytes]):
  (l, _) = decode_indexes(agg_param)
  if len(agg_shares) != 2:
    raise ERR_INVALID_INPUT

  agg = Field[l].decode_vec(agg_shares[0]) + \
        Field[l].decode_vec(agg_shares[1]J)

  return Field[l].encode_vec(agg)
]]></artwork>
          </figure>
        </section>
        <section anchor="poplar1-helper-functions">
          <name>Helper Functions</name>
          <ul empty="true">
            <li>
              <t>TODO Specify the following functionalities:</t>
            </li>
          </ul>
          <ul spacing="normal">
            <li>
              <tt>encode_input_share</tt> is used to encode an input share, consisting of an IDPF
key share and correlation shares.</li>
            <li>
              <tt>decode_input_share</tt> is used to decode an input share.</li>
            <li>
              <tt>decode_indexes(encoded: Bytes) -&gt; (l: Unsigned, indexes: Vec[Unsigned])</tt>
decodes a sequence of indexes, i.e., candidate indexes for IDPF evaluation.
The value of <tt>l</tt> <bcp14>MUST</bcp14> be in range <tt>[1, BITS]</tt> and <tt>indexes[i]</tt> <bcp14>MUST</bcp14> be in range
<tt>[2^(l-1), 2^l)</tt> for all <tt>i</tt>. An error is raised if <tt>encoded</tt> cannot be
decoded.</li>
          </ul>
        </section>
      </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 parameters distributed to the Aggregators (<tt>verify_params</tt>, see
<xref target="setup"/>) 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 parameters with the Clients. It is
therefore <bcp14>RECOMMENDED</bcp14> that the Aggregators generate <tt>verify_params</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>This document makes no request of IANA.</t>
    </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="Vad16" target="https://link.springer.com/chapter/10.1007/978-3-319-57048-8_7">
          <front>
            <title>The Complexity of Differential Privacy</title>
            <author initials="S." surname="Vadhan">
              <organization/>
            </author>
            <date year="2016"/>
          </front>
        </reference>
        <reference anchor="I-D.draft-gpew-priv-ppm">
          <front>
            <title>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="25" month="October" year="2021"/>
            <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 privacy preserving measurement (PPM)
   protocol which can be used to collect aggregate data without
   revealing any individual user's data.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-gpew-priv-ppm-00"/>
        </reference>
      </references>
    </references>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>Thanks to Henry Corrigan-Gibbs, Armando Faz-Hernandez, Mariana Raykova, and
Christopher Wood for useful feedback on and contributions to the spec.</t>
    </section>
    <section numbered="false" anchor="test-vectors">
      <name>Test Vectors</name>
      <t>Test vectors cover the generation input shares and the conversion of input shares
into output shares. Vectors specify the public and verification parameters, the
measurement, the aggregation parameter, the expected input shares, the prepare
messages, and the expected output shares.</t>
      <t>Test vectors are encoded in JSON. Input shares and prepare messages are
represented as hexadecimal streams. 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="prio3aes128count-1">
        <name>Prio3Aes128Count</name>
        <t>For this test, the value of <tt>SHARES</tt> is <tt>2</tt>.</t>
        <artwork><![CDATA[
{
    "public_param": null,
    "verify_params": [
        [
            0,
            "01010101010101010101010101010101"
        ],
        [
            1,
            "01010101010101010101010101010101"
        ]
    ],
    "agg_param": null,
    "prep": [
        {
            "measurement": 1,
            "nonce": "01010101010101010101010101010101",
            "input_shares": [
                "05ac22db75e9b262e9642de9ec1ec37990625f92bf426c52e12c88d7c6e53ed673a3a8a3c7944170e09a52b96573259d",
                "0101010101010101010101010101010101010101010101010101010101010101"
            ],
            "prep_shares": [
                [
                    "48771012eeda70a056cf2fd53022cf7b2edf45090eaa765c2b6cefb7a4abc524",
                    "b788efec11258f61fa53dd238a164da076bfd3f2e4bd966634b24bb64c2fa160"
                ]
            ],
            "out_shares": [
                [
                    408739992155304546
                ],
                [
                    18038004077259279776
                ]
            ]
        }
    ]
}
]]></artwork>
      </section>
      <section numbered="false" anchor="prio3aes128sum">
        <name>Prio3Aes128Sum</name>
        <t>For this test:</t>
        <ul spacing="normal">
          <li>The value of <tt>SHARES</tt> is <tt>2</tt>.</li>
          <li>The value of <tt>bits</tt> is <tt>8</tt>.</li>
        </ul>
        <artwork><![CDATA[
{
    "public_param": null,
    "verify_params": [
        [
            0,
            "01010101010101010101010101010101"
        ],
        [
            1,
            "01010101010101010101010101010101"
        ]
    ],
    "agg_param": null,
    "prep": [
        {
            "measurement": 100,
            "nonce": "01010101010101010101010101010101",
            "input_shares": [
                "05ac22dc75e9b243140aab68977b81a3958c5e79d27edaa00c6b33842dc57724c50207f8c00abf4aaa8ac6a09b5c684d0e59db99532526f582b7524f30d800486ec480e493439573ec2eff20748556c94d7e446de9717ff49ddcfa6fd0ad0a1a9d6de6270bd7ea53092a7e8205b312344bae6f4b6b9456d87695dba9c28514a4e9642deaec1ec35b90625f93bf426c52069601a28cc673c1f0dc7109dee4ca90e0ff309abc86571f3509a1bb33b9e896edd08f984ca3e301e945a8fa1665e19311ae9976f0e8ec34714740fc23cd88500902c8557088fa5acbde164aa52a6e118dff362e6b0b5f784a9c7260312d3b2a1f1a54d8233e4c56bcf5c2f5484fa1460af85fc46fdcdba9bbad76589159c4d6c49c786a160d9dbbd18100c52fe81ba838a57b45d13c764ff9efa7b451235a51384935e831635714ee447bbc02473cb26d536e274c701416619abb2c743ced75c9928483c926ae3ab0f0e3328c79338dd2a496c9468fe9e470aee30b94150f7356e7b19c668175df4f978736e7d3a7c710aa38a446ed62022bcb5ff783d05b428d5a16cdeae0b98268e9ded44a1f7fc734a9baafae0f029dfe79a7c176d58baf68cef928b502b5e59e4fb1925c690745ea06264fa20fa47217120d4343b9a360cad2b5424760e6df18c1214937928e1ef17005cb32815a105f471dff2bbced99f2708ddd70e28bcab86e71dde3d891ea9156b271ab9d025fabcceba3b24c673774e4f474e869c32e818f80c387c1e2197f6612c627287cd9e0a193e70a64ad4546dc0573de3c8b99a0002e67707f58974b8c40bb09f974938b96e14f901084b455f1f4ee3ec4f3b7ce02d42fe0cac452e35b4ff8e5d38e5e99c132b88d122e8ae2b6b97a62206e6f39ba74de00cbb69501010101010101010101010101010101dfed32c071cc6899645ab72c36bd3670",
                "0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010b9e7430cc7a71a356d6bd09d36d1fdb"
            ],
            "prep_shares": [
                [
                    "2bcc0144c56fcf120a7aab22d57cde99fd2ee2301be4c59983d5e68e79f04cd8978b2c4598eafab7b1e8b0af8ba4bda20b9e7430cc7a71a356d6bd09d36d1fdb",
                    "d433febb3a9030d1f58554dd2a8321682eff019a7a26e88471ed622fbd956e5e0af1c04b5573400ed13ae90b325aed4edfed32c071cc6899645ab72c36bd3670"
                ]
            ],
            "out_shares": [
                [
                    178602842237398423407215704739732627917
                ],
                [
                    161679524683540039539650068628168138392
                ]
            ]
        }
    ]
}
]]></artwork>
      </section>
      <section numbered="false" anchor="prio3aes128histogram-1">
        <name>Prio3Aes128Histogram</name>
        <t>For this test:</t>
        <ul spacing="normal">
          <li>The value of <tt>SHARES</tt> is <tt>2</tt>.</li>
          <li>The value of <tt>buckets</tt> is <tt>[1, 10, 100]</tt>.</li>
        </ul>
        <artwork><![CDATA[
{
    "public_param": null,
    "verify_params": [
        [
            0,
            "01010101010101010101010101010101"
        ],
        [
            1,
            "01010101010101010101010101010101"
        ]
    ],
    "agg_param": null,
    "prep": [
        {
            "measurement": 50,
            "nonce": "01010101010101010101010101010101",
            "input_shares": [
                "05ac22dc75e9b243140aab68977b81a3958c5e79d27edaa00c6b33842dc57724c50207f8c00abf4aaa8ac6a09b5c684d0e59db99532526f582b7524f30d80048e9642deaec1ec35b90625f93bf426c52f7ee6bcda3008ff165f5a4dda4bf3382726b89e1455450fb07187cc5b1f4e5b8076d88ca6a52fc73893f179286ed2293f2ba224171991de5cad6ec008bfb16d0990681811a5d149cad81d5177733e8dbabf41f2912442107c7600326e510c0d4a17daddb4577dda42dc84334e51821bb48542744f26726abec63e901571c2841a53f4e93c9bac99d39f87c3773f8173d93465cd2d31f7513516566b9d3aa7a4088d9fb35185b7d6233a9306f40f834c5c3dea78561a999332ab95825a559a131bad2b5cd6a32ed918564d534513aac896d2da35f81b74c226d75f832957209f6df24dc1c9ddf93d4e28a0b30df4a873401010101010101010101010101010101688dfdc50bd6d3a9ecf1613c58b7ced1",
                "0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101014a3951bdbf7a4564e422499e59351ba7"
            ],
            "prep_shares": [
                [
                    "03faf09f79624d05e3a1e17bf1e5117ea6eec816dbd047641506a0c1b1e817fa1ebb27507cea09b00b47e0615ba82ff64a3951bdbf7a4564e422499e59351ba7",
                    "fc050f60869db2de1c5e1e840e1aee830a99091f9a820099b6b9591984046f48b6b6d58ddb1675ef43101aa8773f3025688dfdc50bd6d3a9ecf1613c58b7ced1"
                ]
            ],
            "out_shares": [
                [
                    7539922107207114695252505926366364067,
                    198783809130402957557687312006462666532,
                    261868461448231140209796284667530078285,
                    19075760356742656327154126012204712008
                ],
                [
                    332742444813731348251613267441534402142,
                    141498557790535505389178461361438099677,
                    78413905472707322737069488700370687925,
                    321206606564195806619711647355696054201
                ]
            ]
        }
    ]
}
]]></artwork>
      </section>
    </section>
  </back>
  <!-- ##markdown-source:
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

-->

</rfc>
