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

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

    measurement
      |
      V
    +----------------------------------------------+
    | measurement_to_input_shares                  |
    +----------------------------------------------+
      |              |              ...  |
      V              V                   V
     input_share_0  input_share_1       input_share_[SHARES-1]
      |              |              ...  |
      V              V                   V
    Aggregator 0   Aggregator 1        Aggregator SHARES-1
]]></artwork>
        </figure>
      </section>
      <section anchor="sec-daf-prepare">
        <name>Preparation</name>
        <t>Once an Aggregator has received the public share and one of the input shares,
the next step is to prepare the input share for aggregation. This is
accomplished using the following algorithm:</t>
        <ul spacing="normal">
          <li>
            <tt>Daf.prep(agg_id: Unsigned, agg_param: AggParam, public_share: Bytes,
input_share: Bytes) -&gt; OutShare</tt> is the deterministic preparation algorithm.
It takes as input the public share and one of the input shares generated by a
Client, the Aggregator's unique identifier, and the aggregation parameter
selected by the Collector and returns an output share.</li>
        </ul>
        <t>The protocol in which the DAF is used <bcp14>MUST</bcp14> ensure that the Aggregator's
identifier is equal to the integer in range <tt>[0, SHARES)</tt> that matches the index
of <tt>input_share</tt> in the sequence of input shares output by the Client.</t>
      </section>
      <section anchor="sec-daf-validity-scopes">
        <name>Validity of Aggregation Parameters</name>
        <t>Concrete DAFs implementations <bcp14>MAY</bcp14> impose certain restrictions for input shares
and aggregation parameters. Protocols using a DAF <bcp14>MUST</bcp14> ensure that for each
input share and aggregation parameter <tt>agg_param</tt>, <tt>Daf.prep</tt> is only called if
<tt>Daf.is_valid(agg_param, previous_agg_params)</tt> returns True, where
<tt>previous_agg_params</tt> contains all aggregation parameters that have previously
been used with the same input share.</t>
        <t>DAFs <bcp14>MUST</bcp14> implement the following function:</t>
        <ul spacing="normal">
          <li>
            <tt>Daf.is_valid(agg_param: AggParam, previous_agg_params: Vec[AggParam]) -&gt;
Bool</tt>: Checks if the <tt>agg_param</tt> is compatible with all elements of
<tt>previous_agg_params</tt>.</li>
        </ul>
      </section>
      <section anchor="sec-daf-aggregate">
        <name>Aggregation</name>
        <t>Once an Aggregator holds output shares for a batch of measurements (where
batches are defined by the application), it combines them into a share of the
desired aggregate result:</t>
        <ul spacing="normal">
          <li>
            <tt>Daf.out_shares_to_agg_share(agg_param: AggParam, out_shares: Vec[OutShare])
-&gt; agg_share: Bytes</tt> is the deterministic aggregation algorithm. It is run by
each Aggregator a set of recovered output shares.</li>
        </ul>
        <figure anchor="aggregate-flow">
          <name>Aggregation of output shares. `B` indicates the number of measurements in the batch.</name>
          <artwork><![CDATA[
    Aggregator 0    Aggregator 1        Aggregator SHARES-1
    ============    ============        ===================

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

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

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

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

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

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

<t>The remainder of this section defines the VDAF interface. The attributes are
listed in <xref target="vdaf-param"/> are defined by each concrete VDAF.</t>
      <table anchor="vdaf-param">
        <name>Constants and types defined by each concrete VDAF.</name>
        <thead>
          <tr>
            <th align="left">Parameter</th>
            <th align="left">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>ID</tt></td>
            <td align="left">Algorithm identifier for this VDAF</td>
          </tr>
          <tr>
            <td align="left">
              <tt>VERIFY_KEY_SIZE</tt></td>
            <td align="left">Size (in bytes) of the verification key (<xref target="sec-vdaf-prepare"/>)</td>
          </tr>
          <tr>
            <td align="left">
              <tt>NONCE_SIZE</tt>    `</td>
            <td align="left">Size (in bytes) of the nonce</td>
          </tr>
          <tr>
            <td align="left">
              <tt>ROUNDS</tt></td>
            <td align="left">Number of rounds of communication during the Preparation stage (<xref target="sec-vdaf-prepare"/>)</td>
          </tr>
          <tr>
            <td align="left">
              <tt>SHARES</tt></td>
            <td align="left">Number of input shares into which each measurement is sharded (<xref target="sec-vdaf-shard"/>)</td>
          </tr>
          <tr>
            <td align="left">
              <tt>Measurement</tt></td>
            <td align="left">Type of each measurement</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggParam</tt></td>
            <td align="left">Type of aggregation parameter</td>
          </tr>
          <tr>
            <td align="left">
              <tt>Prep</tt></td>
            <td align="left">State of each Aggregator during Preparation (<xref target="sec-vdaf-prepare"/>)</td>
          </tr>
          <tr>
            <td align="left">
              <tt>OutShare</tt></td>
            <td align="left">Type of each output share</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggResult</tt></td>
            <td align="left">Type of the aggregate result</td>
          </tr>
        </tbody>
      </table>
      <t>Similarly to DAFs (see {[sec-daf}}), any output of a VDAF method that must be
transmitted from one party to another is treated as an opaque byte string. All
other quantities are given a concrete type.</t>
      <ul empty="true">
        <li>
          <t>OPEN ISSUE It might be cleaner to define a type for each value, then have that
type implement an encoding where necessary. See issue#58.</t>
        </li>
      </ul>
      <t>Each VDAF is identified by a unique, 32-bit integer <tt>ID</tt>. Identifiers for each
(V)DAF specified in this document are defined in <xref target="codepoints"/>. The following
method is defined for every VDAF:</t>
      <artwork><![CDATA[
def custom(Vdaf, usage: Unsigned) -> Bytes:
    return format_custom(0, Vdaf.ID, usage)
]]></artwork>
      <t>It is used to construct a customization string for an instance of <tt>Prg</tt> used by
the VDAF. (See <xref target="prg"/>.)</t>
      <section anchor="sec-vdaf-shard">
        <name>Sharding</name>
        <t>Sharding transforms a measurement into input shares as it does in DAFs
(cf. <xref target="sec-daf-shard"/>); in addition, it takes a nonce as input and
produces a public share:</t>
        <ul spacing="normal">
          <li>
            <tt>Vdaf.measurement_to_input_shares(measurement: Measurement, nonce:
Bytes[Vdaf.NONCE_SIZE]) -&gt; (Bytes, Vec[Bytes])</tt> is the randomized
input-distribution algorithm run by each Client. It consumes the measurement
and the nonce and produces a public share, distributed to each of Aggregators,
and the corresponding sequence of input shares, one for each Aggregator.
Depending on the VDAF, the input shares may encode additional information used
to verify the recovered output shares (e.g., the "proof shares" in Prio3
<xref target="prio3"/>). The length of the output vector <bcp14>MUST</bcp14> be <tt>SHARES</tt>.</li>
        </ul>
        <t>In order to ensure privacy of the measurement, the Client <bcp14>MUST</bcp14> generate the
nonce using a cryptographically secure pseudorandom number generator (CSPRNG).
(See <xref target="security"/> for details.)</t>
      </section>
      <section anchor="sec-vdaf-prepare">
        <name>Preparation</name>
        <t>To recover and verify output shares, the Aggregators interact with one another
over <tt>ROUNDS</tt> rounds. Prior to each round, each Aggregator constructs an
outbound message. Next, the sequence of outbound messages is combined into a
single message, called a "preparation message". (Each of the outbound messages
are called "preparation-message shares".) Finally, the preparation message is
distributed to the Aggregators to begin the next round.</t>
        <t>An Aggregator begins the first round with its input share and it begins each
subsequent round with the previous preparation message. Its output in the last
round is its output share and its output in each of the preceding rounds is a
preparation-message share.</t>
        <t>This process involves a value called the "aggregation parameter" used to map the
input shares to output shares. The Aggregators need to agree on this parameter
before they can begin preparing inputs for aggregation.</t>
        <figure anchor="prep-flow">
          <name>VDAF preparation process on the input shares for a single measurement. At the end of the computation, each Aggregator holds an output share or an error.</name>
          <artwork><![CDATA[
    Aggregator 0   Aggregator 1        Aggregator SHARES-1
    ============   ============        ===================

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

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

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

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

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

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

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

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

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

# Add the right operand to the left and return the result.
def vec_add(left: Vec[Field], right: Vec[Field]):
    return list(map(lambda x: x[0] + x[1], zip(left, right)))
]]></artwork>
          </figure>
        </section>
        <section anchor="field-fft-friendly">
          <name>FFT-Friendly Fields</name>
          <t>Some VDAFs require fields that are suitable for efficient computation of the
discrete Fourier transform, as this allows for fast polynomial interpolation.
(One example is Prio3 (<xref target="prio3"/>) when instantiated with the generic FLP of
<xref target="flp-generic-construction"/>.) Specifically, a field is said to be
"FFT-friendly" if, in addition to satisfying the interface described in
<xref target="field"/>, it implements the following method:</t>
          <ul spacing="normal">
            <li>
              <tt>Field.gen() -&gt; Field</tt> returns the generator of a large subgroup of the
multiplicative group. To be FFT-friendly, the order of this subgroup <bcp14>MUST</bcp14> be a
power of 2. In addition, the size of the subgroup dictates how large
interpolated polynomials can be. It is <bcp14>RECOMMENDED</bcp14> that a generator is chosen
with order at least <tt>2^20</tt>.</li>
          </ul>
          <t>FFT-friendly fields also define the following parameter:</t>
          <ul spacing="normal">
            <li>
              <tt>GEN_ORDER: Unsigned</tt> is the order of a multiplicative subgroup generated by
<tt>Field.gen()</tt>.</li>
          </ul>
        </section>
        <section anchor="parameters">
          <name>Parameters</name>
          <t>The tables below define finite fields used in the remainder of this document.</t>
          <table anchor="field64">
            <name>Field64, an FFT-friendly field.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">MODULUS</td>
                <td align="left">2^32 * 4294967295 + 1</td>
              </tr>
              <tr>
                <td align="left">ENCODED_SIZE</td>
                <td align="left">8</td>
              </tr>
              <tr>
                <td align="left">Generator</td>
                <td align="left">7^4294967295</td>
              </tr>
              <tr>
                <td align="left">GEN_ORDER</td>
                <td align="left">2^32</td>
              </tr>
            </tbody>
          </table>
          <table anchor="field128">
            <name>Field128, an FFT-friendly field.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">MODULUS</td>
                <td align="left">2^66 * 4611686018427387897 + 1</td>
              </tr>
              <tr>
                <td align="left">ENCODED_SIZE</td>
                <td align="left">16</td>
              </tr>
              <tr>
                <td align="left">Generator</td>
                <td align="left">7^4611686018427387897</td>
              </tr>
              <tr>
                <td align="left">GEN_ORDER</td>
                <td align="left">2^66</td>
              </tr>
            </tbody>
          </table>
          <table anchor="field255">
            <name>Field255.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">MODULUS</td>
                <td align="left">2^255 - 19</td>
              </tr>
              <tr>
                <td align="left">ENCODED_SIZE</td>
                <td align="left">32</td>
              </tr>
            </tbody>
          </table>
          <ul empty="true">
            <li>
              <t>OPEN ISSUE We currently use big-endian for encoding field elements. However,
for implementations of <tt>GF(2^255-19)</tt>, little endian is more common. See
issue#90.</t>
            </li>
          </ul>
        </section>
      </section>
      <section anchor="prg">
        <name>Pseudorandom Generators</name>
        <t>A pseudorandom generator (PRG) is used to expand a short, (pseudo)random seed
into a long string of pseudorandom bits. A PRG suitable for this document
implements the interface specified in this section.</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[Prg.SEED_SIZE], custom: Bytes, binder: Bytes)</tt> constructs an
instance of <tt>Prg</tt> from the given seed and customization and binder strings.
(See below for definitions of these.) 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).</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[Prg.SEED_SIZE], custom: Bytes, binder: Bytes):
    prg = Prg(seed, custom, binder)
    return prg.next(Prg.SEED_SIZE)

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

# Expand the input `seed` into vector of `length` field elements.
def expand_into_vec(Prg,
                    Field,
                    seed: Bytes[Prg.SEED_SIZE],
                    custom: Bytes,
                    binder: Bytes,
                    length: Unsigned):
    prg = Prg(seed, custom, binder)
    return prg.next_vec(Field, length)
]]></artwork>
        </figure>
        <section anchor="prg-sha3">
          <name>PrgSha3</name>
          <t>This section describes PrgSha3, a PRG based on the Keccak permutation of SHA-3
<xref target="FIPS202"/>. Keccak is used in the cSHAKE128 mode of operation <xref target="SP800-185"/>.</t>
          <figure>
            <name>Definition of PRG PrgSha3.</name>
            <artwork><![CDATA[
class PrgSha3(Prg):
    # Associated parameters
    SEED_SIZE = 16

    def __init__(self, seed, custom, binder):
        self.l = 0
        self.x = seed + binder
        self.s = custom

    def next(self, length: Unsigned) -> Bytes:
        self.l += length

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

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

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

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

    # Generate measurement shares.
    leader_meas_share = inp
    k_helper_meas_shares = []
    k_helper_blinds = []
    k_joint_rand_parts = []
    for j in range(Prio3.SHARES-1):
        k_blind = gen_rand(Prio3.Prg.SEED_SIZE)
        k_share = gen_rand(Prio3.Prg.SEED_SIZE)
        helper_meas_share = Prio3.Prg.expand_into_vec(
            Prio3.Flp.Field,
            k_share,
            Prio3.custom(DST_MEASUREMENT_SHARE),
            byte(j+1),
            Prio3.Flp.INPUT_LEN
        )
        leader_meas_share = vec_sub(leader_meas_share,
                                    helper_meas_share)
        encoded = Prio3.Flp.Field.encode_vec(helper_meas_share)
        k_joint_rand_part = Prio3.Prg.derive_seed(k_blind,
            Prio3.custom(DST_JOINT_RAND_PART),
            byte(j+1) + nonce + encoded)
        k_helper_meas_shares.append(k_share)
        k_helper_blinds.append(k_blind)
        k_joint_rand_parts.append(k_joint_rand_part)
    k_leader_blind = gen_rand(Prio3.Prg.SEED_SIZE)
    encoded = Prio3.Flp.Field.encode_vec(leader_meas_share)
    k_leader_joint_rand_part = Prio3.Prg.derive_seed(k_leader_blind,
        Prio3.custom(DST_JOINT_RAND_PART),
        byte(0) + nonce + encoded)
    k_joint_rand_parts.insert(0, k_leader_joint_rand_part)

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

    # Generate the proof shares.
    prove_rand = Prio3.Prg.expand_into_vec(
        Prio3.Flp.Field,
        gen_rand(Prio3.Prg.SEED_SIZE),
        Prio3.custom(DST_PROVE_RANDOMNESS),
        b'',
        Prio3.Flp.PROVE_RAND_LEN,
    )
    joint_rand = Prio3.Prg.expand_into_vec(
        Prio3.Flp.Field,
        k_joint_rand,
        Prio3.custom(DST_JOINT_RANDOMNESS),
        b'',
        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,
            Prio3.custom(DST_PROOF_SHARE),
            byte(j+1),
            Prio3.Flp.PROOF_LEN,
        )
        leader_proof_share = vec_sub(leader_proof_share,
                                     helper_proof_share)

    # Each Aggregator's input share contains its measurement share,
    # proof share, and blind. The public share contains the
    # Aggregators' joint randomness parts.
    input_shares = []
    input_shares.append(Prio3.encode_leader_share(
        leader_meas_share,
        leader_proof_share,
        k_leader_blind,
    ))
    for j in range(Prio3.SHARES-1):
        input_shares.append(Prio3.encode_helper_share(
            k_helper_meas_shares[j],
            k_helper_proof_shares[j],
            k_helper_blinds[j],
        ))
    public_share = Prio3.encode_public_share(k_joint_rand_parts)
    return (public_share, input_shares)
]]></artwork>
          </figure>
        </section>
        <section anchor="preparation">
          <name>Preparation</name>
          <t>This section describes the process of recovering output shares from the input
shares. The high-level idea is that each Aggregator first queries its input and
proof share locally, then exchanges its verifier share with the other
Aggregators. The verifier shares are then combined into the verifier message,
which is used to decide whether to accept.</t>
          <t>In addition, the Aggregators must ensure that they have all used the same joint
randomness for the query-generation algorithm. The joint randomness is generated
by a PRG seed. Each Aggregator derives a "part" of this seed from its input
share and the "blind" generated by the client. The seed is derived by hashing
together the parts, so before running the query-generation algorithm, it must
first gather the parts derived by the other Aggregators.</t>
          <t>In order to avoid extra round of communication, the Client sends each Aggregator
a "hint" consisting of the other Aggregators' parts of the joint randomness
seed. This leaves open the possibility that the Client cheated by, say, forcing
the Aggregators to use joint randomness that biases the proof check procedure
some way in its favor. To mitigate this, the Aggregators also check that they
have all computed the same joint randomness seed before accepting their output
shares. To do so, they exchange their parts of the joint randomness along with
their verifier shares.</t>
          <t>The definitions of constants and a few auxiliary functions are defined in
<xref target="prio3-auxiliary"/>.</t>
          <figure anchor="prio3-prep-state">
            <name>Preparation state for Prio3.</name>
            <artwork><![CDATA[
def prep_init(Prio3, verify_key, agg_id, _agg_param,
              nonce, public_share, input_share):
    k_joint_rand_parts = Prio3.decode_public_share(public_share)
    (meas_share, proof_share, k_blind) = \
        Prio3.decode_leader_share(input_share) if agg_id == 0 else \
        Prio3.decode_helper_share(agg_id, input_share)
    out_share = Prio3.Flp.truncate(meas_share)

    # Compute joint randomness.
    joint_rand = []
    k_corrected_joint_rand, k_joint_rand_part = None, None
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        encoded = Prio3.Flp.Field.encode_vec(meas_share)
        k_joint_rand_part = Prio3.Prg.derive_seed(k_blind,
            Prio3.custom(DST_JOINT_RAND_PART),
            byte(agg_id) + nonce + encoded)
        k_joint_rand_parts[agg_id] = k_joint_rand_part
        k_corrected_joint_rand = Prio3.joint_rand(k_joint_rand_parts)
        joint_rand = Prio3.Prg.expand_into_vec(
            Prio3.Flp.Field,
            k_corrected_joint_rand,
            Prio3.custom(DST_JOINT_RANDOMNESS),
            b'',
            Prio3.Flp.JOINT_RAND_LEN,
        )

    # Query the measurement and proof share.
    query_rand = Prio3.Prg.expand_into_vec(
        Prio3.Flp.Field,
        verify_key,
        Prio3.custom(DST_QUERY_RANDOMNESS),
        nonce,
        Prio3.Flp.QUERY_RAND_LEN,
    )
    verifier_share = Prio3.Flp.query(meas_share,
                                     proof_share,
                                     query_rand,
                                     joint_rand,
                                     Prio3.SHARES)

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

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

    if inbound is None:
        return (prep, prep_msg)

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

    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_parts = []
    for encoded in prep_shares:
        (verifier_share, k_joint_rand_part) = \
            Prio3.decode_prep_share(encoded)

        verifier = vec_add(verifier, verifier_share)

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

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

    k_joint_rand_check = None
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        k_joint_rand_check = Prio3.joint_rand(k_joint_rand_parts)
    return Prio3.encode_prep_msg(k_joint_rand_check)
]]></artwork>
          </figure>
        </section>
        <section anchor="validity-of-aggregation-parameters">
          <name>Validity of Aggregation Parameters</name>
          <t>Every input share <bcp14>MUST</bcp14> only be used once, regardless of the aggregation
parameters used.</t>
          <figure anchor="prio3-validity-scope">
            <name>Validity of aggregation parameters for Prio3.</name>
            <artwork><![CDATA[
def is_valid(agg_param, previous_agg_params):
    return len(previous_agg_params) == 0
]]></artwork>
          </figure>
        </section>
        <section anchor="aggregation">
          <name>Aggregation</name>
          <t>Aggregating a set of output shares is simply a matter of adding up the vectors
element-wise.</t>
          <figure anchor="prio3-out2agg">
            <name>Aggregation algorithm for Prio3.</name>
            <artwork><![CDATA[
def out_shares_to_agg_share(Prio3, _agg_param, out_shares):
    agg_share = Prio3.Flp.Field.zeros(Prio3.Flp.OUTPUT_LEN)
    for out_share in out_shares:
        agg_share = vec_add(agg_share, out_share)
    return Prio3.Flp.Field.encode_vec(agg_share)
]]></artwork>
          </figure>
        </section>
        <section anchor="unsharding">
          <name>Unsharding</name>
          <t>To unshard a set of aggregate shares, the Collector first adds up the vectors
element-wise. It then converts each element of the vector into an integer.</t>
          <figure anchor="prio3-agg-output">
            <name>Computation of the aggregate result for Prio3.</name>
            <artwork><![CDATA[
def agg_shares_to_result(Prio3, _agg_param,
                         agg_shares, num_measurements):
    agg = Prio3.Flp.Field.zeros(Prio3.Flp.OUTPUT_LEN)
    for agg_share in agg_shares:
        agg = vec_add(agg, Prio3.Flp.Field.decode_vec(agg_share))
    return Prio3.Flp.decode(agg, num_measurements)
]]></artwork>
          </figure>
        </section>
        <section anchor="prio3-auxiliary">
          <name>Auxiliary Functions</name>
          <artwork><![CDATA[
def joint_rand(Prio3, k_joint_rand_parts):
    return Prio3.Prg.derive_seed(
        zeros(Prio3.Prg.SEED_SIZE),
        Prio3.custom(DST_JOINT_RAND_SEED),
        concat(k_joint_rand_parts),
    )
]]></artwork>
          <section anchor="message-serialization">
            <name>Message Serialization</name>
            <artwork><![CDATA[
def encode_leader_share(Prio3,
                        meas_share,
                        proof_share,
                        k_blind):
    encoded = Bytes()
    encoded += Prio3.Flp.Field.encode_vec(meas_share)
    encoded += Prio3.Flp.Field.encode_vec(proof_share)
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        encoded += k_blind
    return encoded

def decode_leader_share(Prio3, encoded):
    l = Prio3.Flp.Field.ENCODED_SIZE * Prio3.Flp.INPUT_LEN
    encoded_meas_share, encoded = encoded[:l], encoded[l:]
    meas_share = Prio3.Flp.Field.decode_vec(encoded_meas_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
    if Prio3.Flp.JOINT_RAND_LEN == 0:
        if len(encoded) != 0:
            raise ERR_DECODE
        return (meas_share, proof_share, None)
    k_blind, encoded = encoded[:l], encoded[l:]
    if len(encoded) != 0:
        raise ERR_DECODE
    return (meas_share, proof_share, k_blind)

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

def decode_helper_share(Prio3, agg_id, encoded):
    c_meas_share = Prio3.custom(DST_MEASUREMENT_SHARE)
    c_proof_share = Prio3.custom(DST_PROOF_SHARE)
    l = Prio3.Prg.SEED_SIZE
    k_meas_share, encoded = encoded[:l], encoded[l:]
    meas_share = Prio3.Prg.expand_into_vec(Prio3.Flp.Field,
                                           k_meas_share,
                                           c_meas_share,
                                           byte(agg_id),
                                           Prio3.Flp.INPUT_LEN)
    k_proof_share, encoded = encoded[:l], encoded[l:]
    proof_share = Prio3.Prg.expand_into_vec(Prio3.Flp.Field,
                                            k_proof_share,
                                            c_proof_share,
                                            byte(agg_id),
                                            Prio3.Flp.PROOF_LEN)
    if Prio3.Flp.JOINT_RAND_LEN == 0:
        if len(encoded) != 0:
            raise ERR_DECODE
        return (meas_share, proof_share, None)
    k_blind, encoded = encoded[:l], encoded[l:]
    if len(encoded) != 0:
        raise ERR_DECODE
    return (meas_share, proof_share, k_blind)

def encode_public_share(Prio3,
                        k_joint_rand_parts):
    encoded = Bytes()
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        encoded += concat(k_joint_rand_parts)
    return encoded

def decode_public_share(Prio3, encoded):
    l = Prio3.Prg.SEED_SIZE
    if Prio3.Flp.JOINT_RAND_LEN == 0:
        if len(encoded) != 0:
            raise ERR_DECODE
        return None
    k_joint_rand_parts = []
    for i in range(Prio3.SHARES):
        k_joint_rand_part, encoded = encoded[:l], encoded[l:]
        k_joint_rand_parts.append(k_joint_rand_part)
    if len(encoded) != 0:
        raise ERR_DECODE
    return k_joint_rand_parts

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

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

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

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

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

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

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

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

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

def decode(Sum, output, _num_measurements):
    return output[0].as_unsigned()
]]></artwork>
          <t>The validity circuit checks that the input consists of ones and zeros. Its
gadget, denoted <tt>Range2</tt>, is the degree-2, arity-1 gadget defined as</t>
          <artwork><![CDATA[
def Range2(x):
    return x^2 - x
]]></artwork>
          <t>The validity circuit is defined as</t>
          <artwork><![CDATA[
def Sum(inp: Vec[Field128], joint_rand: Vec[Field128]):
    out = Field128(0)
    r = joint_rand[0]
    for x in inp:
        out += r * Range2(x)
        r *= joint_rand[0]
    return out
]]></artwork>
          <table>
            <name>Parameters of validity circuit Sum.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">
                  <tt>[Range2]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[bits]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>INPUT_LEN</tt></td>
                <td align="left">
                  <tt>bits</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>Unsigned</tt>, in range <tt>[0, 2^bits)</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">
                  <tt>Unsigned</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="field128"/>)</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section anchor="prio3histogram">
          <name>Prio3Histogram</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 PrgSha3 (<xref target="prg-sha3"/>) as its PRG. Its validity
circuit, denoted <tt>Histogram</tt>, uses <tt>Field128</tt> (<xref target="field128"/>) as its finite
field. The measurement is encoded as a one-hot vector representing the bucket
into which the measurement falls (let <tt>bucket</tt> denote a sequence of
monotonically increasing integers):</t>
          <artwork><![CDATA[
def encode(Histogram, measurement: Integer):
    boundaries = buckets + [Infinity]
    encoded = [Field128(0) for _ in range(len(boundaries))]
    for i in range(len(boundaries)):
        if measurement <= boundaries[i]:
            encoded[i] = Field128(1)
            return encoded

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

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

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

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

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

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

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

    corr_offsets = vec_add(
        Poplar1.Idpf.Prg.expand_into_vec(
            Poplar1.Idpf.FieldInner,
            corr_seed[0],
            Poplar1.custom(DST_CORR_INNER),
            byte(0) + nonce,
            3 * (Poplar1.Idpf.BITS-1),
        ),
        Poplar1.Idpf.Prg.expand_into_vec(
            Poplar1.Idpf.FieldInner,
            corr_seed[1],
            Poplar1.custom(DST_CORR_INNER),
            byte(1) + nonce,
            3 * (Poplar1.Idpf.BITS-1),
        ),
    )
    corr_offsets += vec_add(
        Poplar1.Idpf.Prg.expand_into_vec(
            Poplar1.Idpf.FieldLeaf,
            corr_seed[0],
            Poplar1.custom(DST_CORR_LEAF),
            byte(0) + nonce,
            3,
        ),
        Poplar1.Idpf.Prg.expand_into_vec(
            Poplar1.Idpf.FieldLeaf,
            corr_seed[1],
            Poplar1.custom(DST_CORR_LEAF),
            byte(1) + nonce,
            3,
        ),
    )

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

    # Each input share consists of the Aggregator's IDPF key
    # and a share of the correlated randomness.
    return (public_share,
            Poplar1.encode_input_shares(
                keys, corr_seed, corr_inner, corr_leaf))
]]></artwork>
          </figure>
        </section>
        <section anchor="preparation-1">
          <name>Preparation</name>
          <t>The aggregation parameter encodes a sequence of candidate prefixes. When an
Aggregator receives an input share from the Client, it begins by evaluating its
IDPF share on each candidate prefix, recovering a <tt>data_share</tt> and <tt>auth_share</tt>
for each. The Aggregators use these and the correlation shares provided by the
Client to verify that the sequence of <tt>data_share</tt> values are additive shares of
a one-hot vector.</t>
          <t>Aggregators <bcp14>MUST</bcp14> ensure the candidate prefixes are all unique and appear in
lexicographic order. (This is enforced in the definition of <tt>prep_init()</tt>
below.) Uniqueness is necessary to ensure the refined measurement (i.e., the sum
of the output shares) is in fact a one-hot vector. Otherwise, sketch
verification might fail, causing the Aggregators to erroneously reject a report
that is actually valid. Note that enforcing the order is not strictly necessary,
but this does allow uniqueness to be determined more efficiently.</t>
          <t>The algorithms below make use of the auxiliary function <tt>decode_input_share()</tt>
defined in <xref target="poplar1-auxiliary"/>.</t>
          <figure anchor="poplar1-prep-state">
            <name>Preparation state for Poplar1.</name>
            <artwork><![CDATA[
def prep_init(Poplar1, verify_key, agg_id, agg_param,
              nonce, public_share, input_share):
    (level, prefixes) = agg_param
    (key, corr_seed, corr_inner, corr_leaf) = \
        Poplar1.decode_input_share(input_share)
    Field = Poplar1.Idpf.current_field(level)

    # Ensure that candidate prefixes are all unique and appear in
    # lexicographic order.
    for i in range(1,len(prefixes)):
        if prefixes[i-1] >= prefixes[i]:
            raise ERR_INPUT # out-of-order prefix

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

    # Get shares of the correlated randomness for computing the
    # Aggregator's share of the sketch for the given level of the IDPF
    # tree.
    if level < Poplar1.Idpf.BITS - 1:
        corr_prg = Poplar1.Idpf.Prg(corr_seed,
                                    Poplar1.custom(DST_CORR_INNER),
                                    byte(agg_id) + nonce)
        # Fast-forward the PRG state to the current level.
        corr_prg.next_vec(Field, 3 * level)
    else:
        corr_prg = Poplar1.Idpf.Prg(corr_seed,
                                    Poplar1.custom(DST_CORR_LEAF),
                                    byte(agg_id) + nonce)
    (a_share, b_share, c_share) = corr_prg.next_vec(Field, 3)
    (A_share, B_share) = corr_inner[2*level:2*(level+1)] \
        if level < Poplar1.Idpf.BITS - 1 else corr_leaf

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

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

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

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

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

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

    raise ERR_INPUT # unexpected input

def prep_shares_to_prep(Poplar1, agg_param, prep_shares):
    if len(prep_shares) != 2:
        raise ERR_INPUT # unexpected number of prep shares
    (level, _) = agg_param
    Field = Poplar1.Idpf.current_field(level)
    sketch = vec_add(Field.decode_vec(prep_shares[0]),
                     Field.decode_vec(prep_shares[1]))
    if sketch == Field.zeros(len(sketch)):
        # In order to reduce communication overhead, let the
        # empty string denote the zero vector of the required
        # length.
        return b''
    return Field.encode_vec(sketch)
]]></artwork>
          </figure>
        </section>
        <section anchor="validity-of-aggregation-parameters-1">
          <name>Validity of Aggregation Parameters</name>
          <t>Aggregation parameters are valid for a given input share if no aggregation
parameter with the same level has been used with the same input share before.
The whole preparation phase <bcp14>MUST NOT</bcp14> be run more than once for a given
combination of input share and level.</t>
          <figure anchor="poplar1-validity-scope">
            <name>Validity of aggregation parameters for Poplar1.</name>
            <artwork><![CDATA[
def is_valid(agg_param, previous_agg_params):
    (level, _) = agg_param
    return all(
        level != other_level
        for (other_level, _) in previous_agg_params
    )
]]></artwork>
          </figure>
        </section>
        <section anchor="aggregation-1">
          <name>Aggregation</name>
          <t>Aggregation involves simply adding up the output shares.</t>
          <figure anchor="poplar1-out2agg">
            <name>Aggregation algorithm for Poplar1.</name>
            <artwork><![CDATA[
def out_shares_to_agg_share(Poplar1, agg_param, out_shares):
    (level, prefixes) = agg_param
    Field = Poplar1.Idpf.current_field(level)
    agg_share = Field.zeros(len(prefixes))
    for out_share in out_shares:
        agg_share = vec_add(agg_share, out_share)
    return Field.encode_vec(agg_share)
]]></artwork>
          </figure>
        </section>
        <section anchor="unsharding-1">
          <name>Unsharding</name>
          <t>Finally, the Collector unshards the aggregate result by adding up the aggregate
shares.</t>
          <figure anchor="poplar1-agg-output">
            <name>Computation of the aggregate result for Poplar1.</name>
            <artwork><![CDATA[
def agg_shares_to_result(Poplar1, agg_param,
                         agg_shares, _num_measurements):
    (level, prefixes) = agg_param
    Field = Poplar1.Idpf.current_field(level)
    agg = Field.zeros(len(prefixes))
    for agg_share in agg_shares:
        agg = vec_add(agg, Field.decode_vec(agg_share))
    return list(map(lambda x: x.as_unsigned(), agg))
]]></artwork>
          </figure>
        </section>
        <section anchor="poplar1-auxiliary">
          <name>Auxiliary Functions</name>
          <section anchor="message-serialization-1">
            <name>Message Serialization</name>
            <t>This section defines methods for serializing input shares, as required by the
<tt>Vdaf</tt> interface. Optional serialization of the aggregation parameter is also
specified below.</t>
            <t>Implementation note: The aggregation parameter includes the level of the IDPF
tree and the sequence of indices to evaluate. For implementations that perform
per-report caching across executions of the VDAF, this may be more information
than is strictly needed. In particular, it may be sufficient to convey which
indices from the previous execution will have their children included in the
next. This would help reduce communication overhead.</t>
            <artwork><![CDATA[
def encode_input_shares(Poplar1, keys,
                        corr_seed, corr_inner, corr_leaf):
    input_shares = []
    for (key, seed, inner, leaf) in zip(keys,
                                        corr_seed,
                                        corr_inner,
                                        corr_leaf):
        encoded = Bytes()
        encoded += key
        encoded += seed
        encoded += Poplar1.Idpf.FieldInner.encode_vec(inner)
        encoded += Poplar1.Idpf.FieldLeaf.encode_vec(leaf)
        input_shares.append(encoded)
    return input_shares

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

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

def decode_agg_param(Poplar1, encoded):
    encoded_level, encoded = encoded[:2], encoded[2:]
    level = OS2IP(encoded_level)
    encoded_prefix_count, encoded = encoded[:4], encoded[4:]
    prefix_count = OS2IP(encoded_prefix_count)
    l = floor(((level+1) * prefix_count + 7) / 8)
    encoded_packed, encoded = encoded[:l], encoded[l:]
    packed = OS2IP(encoded_packed)
    prefixes = []
    m = 2^(level+1) - 1
    for i in range(prefix_count):
        prefixes.append(packed >> ((level+1) * i) & m)
    if len(encoded) != 0:
        raise ERR_INPUT
    return (level, prefixes)
]]></artwork>
          </section>
        </section>
      </section>
      <section anchor="idpf-poplar">
        <name>The IDPF scheme of <xref target="BBCGGI21"/></name>
        <ul empty="true">
          <li>
            <t>TODO(issue#32) Consider replacing the generic <tt>Prg</tt> object here with some
fixed-key mode for AES (something along the lines of ia.cr/2019/074). This
would allow us to take advantage of hardware acceleration, which would
significantly improve performance. We use SHA-3 primarily to instantiate
random oracles, but the random oracle model may not be required for IDPF. More
investigation is needed.</t>
          </li>
        </ul>
        <t>In this section we specify a concrete IDPF, called IdpfPoplar, suitable for
instantiating Poplar1. The scheme gets its name from the name of the protocol of
<xref target="BBCGGI21"/>.</t>
        <ul empty="true">
          <li>
            <t>TODO We should consider giving <tt>IdpfPoplar</tt> a more distinctive name.</t>
          </li>
        </ul>
        <t>The constant and type definitions required by the <tt>Idpf</tt> interface are given in
<xref target="idpf-poplar-param"/>.</t>
        <table anchor="idpf-poplar-param">
          <name>Constants and type definitions for IdpfPoplar.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">SHARES</td>
              <td align="left">
                <tt>2</tt></td>
            </tr>
            <tr>
              <td align="left">BITS</td>
              <td align="left">any positive integer</td>
            </tr>
            <tr>
              <td align="left">VALUE_LEN</td>
              <td align="left">any positive integer</td>
            </tr>
            <tr>
              <td align="left">KEY_SIZE</td>
              <td align="left">
                <tt>Prg.SEED_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">FieldInner</td>
              <td align="left">
                <tt>Field64</tt> (<xref target="field64"/>)</td>
            </tr>
            <tr>
              <td align="left">FieldLeaf</td>
              <td align="left">
                <tt>Field255</tt> (<xref target="field255"/>)</td>
            </tr>
            <tr>
              <td align="left">Prg</td>
              <td align="left">any implementation of <tt>Prg</tt> (<xref target="prg"/>)</td>
            </tr>
          </tbody>
        </table>
        <section anchor="key-generation">
          <name>Key Generation</name>
          <ul empty="true">
            <li>
              <t>TODO Describe the construction in prose, beginning with a gentle introduction
to the high level idea.</t>
            </li>
          </ul>
          <t>The description of the IDPF-key generation algorithm makes use of auxiliary
functions <tt>extend()</tt>, <tt>convert()</tt>, and <tt>encode_public_share()</tt> defined in
<xref target="idpf-poplar-helper-functions"/>. In the following, we let <tt>Field2</tt> denote the
field <tt>GF(2)</tt>.</t>
          <figure anchor="idpf-poplar-gen">
            <name>IDPF-key generation algorithm of IdpfPoplar.</name>
            <artwork><![CDATA[
def gen(IdpfPoplar, alpha, beta_inner, beta_leaf):
    if alpha >= 2^IdpfPoplar.BITS:
        raise ERR_INPUT # alpha too long
    if len(beta_inner) != IdpfPoplar.BITS - 1:
        raise ERR_INPUT # beta_inner vector is the wrong size

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

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

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

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

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

        w_cw = vec_add(vec_sub(b, w0), w1)
        # Implementation note: Here we negate the correction word if
        # the control bit `ctrl[1]` is set. We avoid branching on the
        # value in order to reduce leakage via timing side channels.
        mask = Field(1) - Field(2) * Field(ctrl[1].as_unsigned())
        for i in range(len(w_cw)):
            w_cw[i] *= mask

        correction_words.append((seed_cw, ctrl_cw, w_cw))

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

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

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

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

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

    next_ctrl = t[bit]
    (next_seed, y) = IdpfPoplar.convert(level, s[bit])
    # Implementation note: Here we add the correction word to the
    # output if `next_ctrl` is set. We avoid branching on the value of
    # the control bit in order to reduce side channel leakage.
    mask = Field(next_ctrl.as_unsigned())
    for i in range(len(y)):
        y[i] += w_cw[i] * mask

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

def convert(IdpfPoplar, level, seed):
    prg = IdpfPoplar.Prg(seed, format_custom(1, 0, 1), b'')
    next_seed = prg.next(IdpfPoplar.Prg.SEED_SIZE)
    Field = IdpfPoplar.current_field(level)
    w = prg.next_vec(Field, IdpfPoplar.VALUE_LEN)
    return (next_seed, w)

def encode_public_share(IdpfPoplar, correction_words):
    encoded = Bytes()
    control_bits = list(itertools.chain.from_iterable(
        cw[1] for cw in correction_words
    ))
    encoded += pack_bits(control_bits)
    for (level, (seed_cw, _, w_cw)) \
        in enumerate(correction_words):
        Field = IdpfPoplar.current_field(level)
        encoded += seed_cw
        encoded += Field.encode_vec(w_cw)
    return encoded

def decode_public_share(IdpfPoplar, encoded):
    l = floor((2*IdpfPoplar.BITS + 7) / 8)
    encoded_ctrl, encoded = encoded[:l], encoded[l:]
    control_bits = unpack_bits(encoded_ctrl, 2 * IdpfPoplar.BITS)
    correction_words = []
    for level in range(IdpfPoplar.BITS):
        Field = IdpfPoplar.current_field(level)
        ctrl_cw = (
            control_bits[level * 2],
            control_bits[level * 2 + 1],
        )
        l = IdpfPoplar.Prg.SEED_SIZE
        seed_cw, encoded = encoded[:l], encoded[l:]
        l = Field.ENCODED_SIZE * IdpfPoplar.VALUE_LEN
        encoded_w_cw, encoded = encoded[:l], encoded[l:]
        w_cw = Field.decode_vec(encoded_w_cw)
        correction_words.append((seed_cw, ctrl_cw, w_cw))
    leftover_bits = encoded_ctrl[-1] >> (
        ((IdpfPoplar.BITS + 3) % 4 + 1) * 2
    )
    if leftover_bits != 0 or len(encoded) != 0:
        raise ERR_DECODE
    return correction_words
]]></artwork>
          </figure>
          <t>Here, <tt>pack_bits()</tt> takes a list of bits, packs each group of eight bits into a
byte, in LSB to MSB order, padding the most significant bits of the last byte
with zeros as necessary, and returns the byte array. <tt>unpack_bits()</tt> performs
the reverse operation: it takes in a byte array and a number of bits, and
returns a list of bits, extracting eight bits from each byte in turn, in LSB to
MSB order, and stopping after the requested number of bits. If the byte array
has an incorrect length, or if unused bits in the last bytes are not zero, it
throws an error.</t>
        </section>
      </section>
      <section anchor="poplar1-inst">
        <name>Instantiation</name>
        <t>By default, Poplar1 is instantiated with IdpfPoplar (<tt>VALUE_LEN == 2</tt>) and
PrgSha3 (<xref target="prg-sha3"/>). This VDAF is suitable for any positive value of <tt>BITS</tt>.
Test vectors can be found in <xref target="test-vectors"/>.</t>
      </section>
    </section>
    <section anchor="security">
      <name>Security Considerations</name>
      <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>Formal definitions of privacy and robustness can be found in <xref target="DPRS23"/>. 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, in particular the
verification key.</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 measurements for the remaining Clients.  Applications can guard
against these risks by adding additional controls on report 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 anchor="requirements-for-the-verification-key">
        <name>Requirements for the Verification Key</name>
        <t>The Aggregators are responsible for exchanging the verification key in advance
of executing the VDAF. Any procedure is acceptable as long as the following
conditions are met:</t>
        <ol spacing="normal" type="1"><li>To ensure robustness of the computation, the Aggregators <bcp14>MUST NOT</bcp14> reveal the
verification key to the Clients. Otherwise, a malicious Client might be able
to exploit knowledge of this key to craft an invalid report that would be
accepted by the Aggregators.</li>
          <li>To ensure privacy of the measurements, the Aggregators <bcp14>MUST</bcp14> commit to the
verification key prior to processing reports generated by Clients. Otherwise,
a malicious Aggregator may be able to craft a verification key that, for a
given report, causes an honest Aggregator to leak information about the
measurement during preparation.</li>
        </ol>
        <t>Meeting these conditions is required in order to leverage security analysis in
the framework of <xref target="DPRS23"/>. Their definition of robustness allows the attacker,
playing the role of a cohort of malicious Clients, to submit arbitrary reports
to the Aggregators and eavesdrop on their communications as they process them.
Security in this model is achievable as long as the verification key is kept
secret from the attacker.</t>
        <t>The privacy definition of <xref target="DPRS23"/> considers an active attacker that controls
the network and a subset of Aggregators; in addition, the attacker is allowed to
choose the verification key used by each honest Aggregator over the course of
the experiment. Security is achievable in this model as long as the key is
picked at the start of the experiment, prior to any reports being generated.
(The model also requires nonces to be generated at random; see
<xref target="nonce-requirements"/> below.)</t>
        <t>Meeting these requirements is relatively straightforward. For example, the
Aggregators may designate one of their peers to generate the verification key
and distribute it to the others. To assure Clients of key commitment, the
Clients and (honest) Aggregators could bind reports to a shared context string
derived from the key. For instance, the "task ID" of DAP <xref target="DAP"/> could be set to
the hash of the verification key; then as long as honest Aggregators only
consume reports for the task indicated by the Client, forging a new key after
the fact would reduce to finding collisions in the underlying hash function.
(Keeping the key secret from the Clients would require the hash function to be
one-way.) However, since rotating the key implies rotating the task ID, this
scheme would not allow key rotation over the lifetime of a task.</t>
      </section>
      <section anchor="nonce-requirements">
        <name>Requirements for the Nonce</name>
        <t>The sharding and preparation steps of VDAF execution depend on a nonce
associated with the Client's report. To ensure privacy of the underlying
measurement, the Client <bcp14>MUST</bcp14> generate this nonce using a CSPRNG. This is
required in order to leverage security analysis for the privacy definition of
<xref target="DPRS23"/>, which assumes the nonce is chosen at random prior to generating the
report.</t>
        <t>Other security considerations may require the nonce to be non-repeating. For
example, to achieve differential privacy it is necessary to avoid "over
exposing" a measurement by including it too many times in a single batch or
across multiple batches. It is <bcp14>RECOMMENDED</bcp14> that the nonce generated by the
Client be used by the Aggregators for replay protection.</t>
      </section>
      <section anchor="requirements-for-the-aggregation-parameters">
        <name>Requirements for the Aggregation Parameters</name>
        <t>As described in <xref target="sec-daf-validity-scopes"/> and <xref target="sec-vdaf-validity-scopes"/>
respectively, DAFs and VDAFs may impose restrictions on the re-use of input
shares. This is to ensure that correlated randomness provided by the Client
through the input share is not used more than once, which might compromise
confidentiality of the Client's measurements.</t>
        <t>Protocols that make use of VDAFs therefore <bcp14>MUST</bcp14> call <tt>Vdaf.is_valid</tt>
on the set of all aggregation parameters used for a Client's input share, and
only proceed with the preparation and aggregation phases if that function call
returns <tt>True</tt>.</t>
      </section>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>A codepoint for each (V)DAF in this document is defined in the table below. Note
that <tt>0xFFFF0000</tt> through <tt>0xFFFFFFFF</tt> are reserved for private use.</t>
      <table anchor="codepoints">
        <name>Unique identifiers for (V)DAFs.</name>
        <thead>
          <tr>
            <th align="left">Value</th>
            <th align="left">Scheme</th>
            <th align="left">Type</th>
            <th align="left">Reference</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>0x00000000</tt></td>
            <td align="left">Prio3Count</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3count"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000001</tt></td>
            <td align="left">Prio3Sum</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3sum"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000002</tt></td>
            <td align="left">Prio3Histogram</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3histogram"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000003</tt> to <tt>0x00000FFF</tt></td>
            <td align="left">reserved for Prio3</td>
            <td align="left">VDAF</td>
            <td align="left">n/a</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00001000</tt></td>
            <td align="left">Poplar1</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="poplar1-inst"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0xFFFF0000</tt> to <tt>0xFFFFFFFF</tt></td>
            <td align="left">reserved</td>
            <td align="left">n/a</td>
            <td align="left">n/a</td>
          </tr>
        </tbody>
      </table>
      <ul empty="true">
        <li>
          <t>TODO Add IANA considerations for the codepoints summarized in <xref target="codepoints"/>.</t>
        </li>
      </ul>
      <ul empty="true">
        <li>
          <t>OPEN ISSUE Currently the scheme includes the PRG. This means that we need bits
of the codepoint to differentiate between PRGs. We could instead make the PRG
generic (e.g., Prio3Count(Aes128) instead of Prio3Aes128Count) and define a
separate codepoint.</t>
        </li>
      </ul>
    </section>
  </middle>
  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        <reference anchor="SP800-185">
          <front>
            <title>SHA-3 Derived Functions: cSHAKE, KMAC, TupleHash and ParallelHash</title>
            <author>
              <organization/>
            </author>
            <date year="2016" month="December"/>
          </front>
          <seriesInfo name="NIST Special Publication 800-185" value=""/>
        </reference>
        <reference anchor="FIPS202">
          <front>
            <title>SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions</title>
            <author>
              <organization/>
            </author>
            <date year="2015" month="August"/>
          </front>
          <seriesInfo name="NIST FIPS PUB 202" value=""/>
        </reference>
        <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>
      </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="DPRS23" target="https://ia.cr/2023/130">
          <front>
            <title>Verifiable Distributed Aggregation Functions</title>
            <author initials="H." surname="Davis">
              <organization/>
            </author>
            <author initials="C." surname="Patton">
              <organization/>
            </author>
            <author initials="M." surname="Rosulek">
              <organization/>
            </author>
            <author initials="P." surname="Schoppmann">
              <organization/>
            </author>
            <date>n.d.</date>
          </front>
        </reference>
        <reference anchor="Dwo06" target="https://link.springer.com/chapter/10.1007/11787006_1">
          <front>
            <title>Differential Privacy</title>
            <author initials="C." surname="Dwork">
              <organization/>
            </author>
            <date year="2006"/>
          </front>
          <seriesInfo name="ICALP 2006" value=""/>
        </reference>
        <reference anchor="EPK14" target="https://dl.acm.org/doi/10.1145/2660267.2660348">
          <front>
            <title>RAPPOR: Randomized Aggregatable Privacy-Preserving Ordinal Response</title>
            <author initials="Ú." surname="Erlingsson">
              <organization/>
            </author>
            <author initials="V." surname="Pihur">
              <organization/>
            </author>
            <author initials="A." surname="Korolova">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <seriesInfo name="CCS 2014" value=""/>
        </reference>
        <reference anchor="ENPA" target="https://covid19-static.cdn-apple.com/applications/covid19/current/static/contact-tracing/pdf/ENPA_White_Paper.pdf">
          <front>
            <title>Exposure Notification Privacy-preserving Analytics (ENPA) White Paper</title>
            <author>
              <organization/>
            </author>
            <date year="2021"/>
          </front>
        </reference>
        <reference anchor="GI14" target="https://link.springer.com/chapter/10.1007/978-3-642-55220-5_35">
          <front>
            <title>Distributed Point Functions and Their Applications</title>
            <author initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <seriesInfo name="EUROCRYPT 2014" value=""/>
        </reference>
        <reference anchor="OriginTelemetry" target="https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/collection/origin.html">
          <front>
            <title>Origin Telemetry</title>
            <author>
              <organization/>
            </author>
            <date year="2020"/>
          </front>
        </reference>
        <reference anchor="DAP">
          <front>
            <title>Distributed Aggregation Protocol for Privacy Preserving Measurement</title>
            <author fullname="Tim Geoghegan" initials="T." surname="Geoghegan">
              <organization>ISRG</organization>
            </author>
            <author fullname="Christopher Patton" initials="C." surname="Patton">
              <organization>Cloudflare</organization>
            </author>
            <author fullname="Eric Rescorla" initials="E." surname="Rescorla">
              <organization>Mozilla</organization>
            </author>
            <author fullname="Christopher A. Wood" initials="C. A." surname="Wood">
              <organization>Cloudflare</organization>
            </author>
            <date day="9" month="December" year="2022"/>
            <abstract>
              <t>   There are many situations in which it is desirable to take
   measurements of data which people consider sensitive.  In these
   cases, the entity taking the measurement is usually not interested in
   people's individual responses but rather in aggregated data.
   Conventional methods require collecting individual responses and then
   aggregating them, thus representing a threat to user privacy and
   rendering many such measurements difficult and impractical.  This
   document describes a multi-party distributed aggregation protocol
   (DAP) for privacy preserving measurement (PPM) which can be used to
   collect aggregate data without revealing any individual user's data.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-ppm-dap-03"/>
        </reference>
      </references>
    </references>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The security considerations in <xref target="security"/> are based largely on the security
analysis of <xref target="DPRS23"/>. Thanks to Hannah Davis and Mike Rosulek, who lent their
time to developing definitions and security proofs.</t>
      <t>Thanks to Henry Corrigan-Gibbs, Armando Faz-Hernández, Simon Friedberger, Tim
Geoghegan, Mariana Raykova, Jacob Rothstein, and Christopher Wood for useful
feedback on and contributions to the spec.</t>
    </section>
    <section numbered="false" anchor="test-vectors">
      <name>Test Vectors</name>
      <ul empty="true">
        <li>
          <t>NOTE Machine-readable test vectors can be found at
https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec.</t>
        </li>
      </ul>
      <t>Test vectors cover the generation of input shares and the conversion of input
shares into output shares. Vectors specify the verification key, measurements,
aggregation parameter, and any parameters needed to construct the VDAF. (For
example, for <tt>Prio3Sum</tt>, the user specifies the number of bits for representing
each summand.)</t>
      <t>Byte strings are encoded in hexadecimal To make the tests deterministic,
<tt>gen_rand()</tt> was replaced with a function that returns the requested number of
<tt>0x01</tt> octets.</t>
      <section numbered="false" anchor="testvec-prio3count">
        <name>Prio3Count</name>
        <artwork><![CDATA[
verify_key: "01010101010101010101010101010101"
upload_0:
  measurement: 1
  nonce: "01010101010101010101010101010101"
  public_share: >-
  input_share_0: >-
    d8700d17841945acb2891eaadb82b14c71098bcf4a708cf5bfff34c19f1fcb389524
    33062a90142b69f3de7e58566e86
  input_share_1: >-
    0101010101010101010101010101010101010101010101010101010101010101
  round_0:
    prep_share_0: >-
      bc5ed32148ccdfe8149c04ac5b2e26bbb74c2c01d26b8e9a4f26452740c8b6e9
    prep_share_1: >-
      43a12cddb7332019fa93469841dbb1aba89845e53745d13445a31850c99c4ea8
    prep_message: >-
  out_share_0:
    - d8700d17841945ac
  out_share_1:
    - 278ff2e77be6ba56
agg_share_0: >-
  d8700d17841945ac
agg_share_1: >-
  278ff2e77be6ba56
agg_result: 1
]]></artwork>
      </section>
      <section numbered="false" anchor="testvec-prio3sum">
        <name>Prio3Sum</name>
        <artwork><![CDATA[
bits: 8
verify_key: "01010101010101010101010101010101"
upload_0:
  measurement: 100
  nonce: "01010101010101010101010101010101"
  public_share: >-
    905f744fdd73d539b852697c311bcc977e2eef2723dabfbae02c93ce1f196ae8
  input_share_0: >-
    9129dfc509b86e7947f238dd725ae3cc8393f640c44fd72eb0dd39bf28fbbf8e9455
    f069ca3089119d684ae29c280e954061350c04c90916f27895fe374ebd6badc69ad0
    e1fda3e02a85750c9a27b4f34a4dd09ce0c2cef5599c0a0a40c2c3fdea329eaa925f
    a1a65b7f947e9ec0b395412e56245f4d9fa5993f3e6a7263d71d73ac5dbb78a3104f
    23f0c67893b390b1b14a6211c54651645548d145213de5c87acd21d6218248991394
    708b9d823c9d9d7e16996f32d4578c2ecec9b0c2673c4d1ee156ffac2415369c1583
    21482ba0d8fa021f3c00185a99c74d619637f463e6d5bb22bb45cf3d43a9ba332148
    a61b42c26567563b8d9d612a8e85be68dd542838a2e1bd03e471ccf5514e333b3837
    0a41c8df749dd43a86ee2708c1797dd10fb2d655700c3d74e4c9a9726eafa553035d
    846162f981925e83d8dac7f08784339c3b89f54461ae764239bb521b6e3419ebe8d5
    6638968479a53a9ec5453b3f94dad0e3b41e71bc273222733428a18f3e66bdb42081
    55aa11215ce9c91bbf7664e10992cc2d8c30aa0abf524b6fc545a599a43b66d676a0
    2be73e6fc8c24e0ad17eceba6e081d8d8e7882eae163cc2afcc1e76cb7b3936168e0
    a71ce3f73999e7769ec43108075657cc36f5108a0b1713777bc6b561fed05dd0869d
    596c8cc079628e94440df17b63486d5b1e6af79dd1378f45bbdf68497d064e0c9f63
    b768bdd7e0761ec441b1a529e742d4e13f4755cdc99569236592dae907aab4ba5304
    cb7224469fb8bd76f2b348026d5d6312fc8c52f891461b08c5b05fdae2e1c745ce94
    63b92efb59a12cca026c6afb195322ef69c5eb452788742075e41231991d324f24f6
    21f6b79d6da2472438b455379856f7623ca9a4419d61eababea02634010101010101
    01010101010101010101
  input_share_1: >-
    01010101010101010101010101010101010101010101010101010101010101010101
    0101010101010101010101010101
  round_0:
    prep_share_0: >-
      b11ad355381629c48921bae8ff502c7e9b214980f51d58fd3b7293542ddb43f83f
      f15e16a0d7b38ed62357f1dbae34d4905f744fdd73d539b852697c311bcc97
    prep_share_1: >-
      4ee52caac7e9d61f76de451700afd383f622613281a91f1113882cd7646c207484
      da515e63d02452fe32316648fd84277e2eef2723dabfbae02c93ce1f196ae8
    prep_message: >-
      fab4374d7e6549b8ae110e76b4eb315d
  out_share_0:
    - 36a9b3cc584eefb20e6f6eca8c54caaf
  out_share_1:
    - c9564c33a7b11031f190913573ab35b6
agg_share_0: >-
  36a9b3cc584eefb20e6f6eca8c54caaf
agg_share_1: >-
  c9564c33a7b11031f190913573ab35b6
agg_result: 100
]]></artwork>
      </section>
      <section numbered="false" anchor="testvec-prio3histogram">
        <name>Prio3Histogram</name>
        <artwork><![CDATA[
buckets: [1, 10, 100]
verify_key: "01010101010101010101010101010101"
upload_0:
  measurement: 50
  nonce: "01010101010101010101010101010101"
  public_share: >-
    d995029335b0240dbdca1cbfb1211ecc67fa8edb6f0f74882a626d290baa199c
  input_share_0: >-
    22d711113962f5ffe2f3119db262a76940036dd11c6ac7a0ea844da70ed1cb575ada
    ee861cb1075340a455a13bbadd6270e2ab78349dbf2f7aca71d9a77efb01ccff433b
    195d4e1f143bd7bb6f3502dde041a22ef5c262c67f79bc61f0364dedcd549842a047
    2c4edf77a3860b96444fd00e20d1e9b6fe42013e7104b608d1c7f5c5752f4f95b614
    de92bc377c1b7ee8c96bf3de4eca547a691b86463b94e94d0b5b44bcfc47a54cd0f9
    6391e9559ab065af59873f4a8cf9dd55597c02245c4dd5343414855127a44b579b40
    e5fa3a941bb0b65cd4403291d03ed043aae2a0ec43b0950a7d1c28fc80090f5cb834
    f8df88c7dbdfa1e7503aef1d2a1a3d41de25091ddb2984b5a89d4a576564a93fb529
    5844aa9360be4b164f8ab9c064a640afea30eaef8ee4522b1b3340d0819f4ad40f3f
    809b746f999c34c40564fd87448001010101010101010101010101010101
  input_share_1: >-
    01010101010101010101010101010101010101010101010101010101010101010101
    0101010101010101010101010101
  round_0:
    prep_share_0: >-
      2d3f3200d6afb340b09dfc30b92ea4146ad4f5e2677515ed1c4e6ebcc8b6809ef5
      762a4ee715e20e05b219f8529dbfc1d995029335b0240dbdca1cbfb1211ecc
    prep_share_1: >-
      d2c0cdff29504ca34f6203cf46d15bed9083e4170397a5da2d55754b9a7bbf3803
      0a54eebf540cd5ff5e6b07d451ce7067fa8edb6f0f74882a626d290baa199c
    prep_message: >-
      c3885ffa3a60ba7f6413596d328cfd27
  out_share_0:
    - 22d711113962f5ffe2f3119db262a769
    - 40036dd11c6ac7a0ea844da70ed1cb57
    - 5adaee861cb1075340a455a13bbadd62
    - 70e2ab78349dbf2f7aca71d9a77efb01
  out_share_1:
    - dd28eeeec69d09e41d0cee624d9d5898
    - bffc922ee3953843157bb258f12e34aa
    - a5251179e34ef890bf5baa5ec44522a0
    - 8f1d5487cb6240b485358e2658810500
agg_share_0: >-
  22d711113962f5ffe2f3119db262a76940036dd11c6ac7a0ea844da70ed1cb575adaee
  861cb1075340a455a13bbadd6270e2ab78349dbf2f7aca71d9a77efb01
agg_share_1: >-
  dd28eeeec69d09e41d0cee624d9d5898bffc922ee3953843157bb258f12e34aaa52511
  79e34ef890bf5baa5ec44522a08f1d5487cb6240b485358e2658810500
agg_result: [0, 0, 1, 0]
]]></artwork>
      </section>
      <section numbered="false" anchor="testvec-poplar1">
        <name>Poplar1</name>
        <section numbered="false" anchor="sharding-1">
          <name>Sharding</name>
          <artwork><![CDATA[
bits: 4
verify_key: "01010101010101010101010101010101"
agg_param: (0, [0, 1])
upload_0:
  measurement: 13
  nonce: "01010101010101010101010101010101"
  public_share: >-
    9a00000000000000000000000000000000ffffffff000000002925acd3fdadd65000
    000000000000000000000000000000ffffffff00000000a30477d49c635897000000
    00000000000000000000000000ffffffff00000000be1923f14c176f080000000000
    00000000000000000000007fffffffffffffffffffffffffffffffffffffffffffff
    ffffffffffffffffec2f05a6f445eda5468c2b3ee83fd3031e06bef0befa154c75ef
    08d68e559203fc
  input_share_0: >-
    01010101010101010101010101010101010101010101010101010101010101012829
    0055e1399e093ce757ec6febc3bc89a955aab0739c173a2d54cfe984f90bc9170ed9
    fa7be3d005feb7b32d1d87867f965e8e09e8dedee5fead6898a353e42d243e7b64e6
    db53a4d1e004d7dd23880d06ea70ceb5fc414eb742e39ddd30ca69689aff04bee551
    8956f318ccd148a8
  input_share_1: >-
    0101010101010101010101010101010101010101010101010101010101010101b84f
    b52b53729cff7f30537d822e188c24f328a9cbcf8a0c5dec0ba7935e426335334440
    0524965ab9925911875b5354328f383f015d117fda7cc41787a4ee1596864e0b15e3
    529a3834658b103b521e1d2a46275be79a4a5766d3bd9e7d22fe000404c9866dd3ec
    a0b381328f8305a3
]]></artwork>
        </section>
        <section numbered="false" anchor="preparation-aggregation-and-unsharding">
          <name>Preparation, Aggregation, and Unsharding</name>
          <artwork><![CDATA[
verify_key: "01010101010101010101010101010101"
agg_param: (0, [0, 1])
upload_0:
  round_0:
    prep_share_0: >-
      45d4d76583ff3d4bfadb0a1a136a6df5139a62a553367029
    prep_share_1: >-
      a3f8aa69980f13c2749bf9b3c23e21e19e39198fb3f8e2ed
    prep_message: >-
      e9cd81cf1c0e510d6f7703ced5a88fd5b1d37c35072f5316
  round_1:
    prep_share_0: >-
      23568c2a012e01c9
    prep_share_1: >-
      dca973d4fed1fe38
    prep_message: >-
  out_share_0:
    - fcf3039f72d70136
    - 7a930346dcd33ac4
  out_share_1:
    - 030cfc5f8d28fecb
    - 856cfcb8232cc53e
agg_share_0: >-
  fcf3039f72d701367a930346dcd33ac4
agg_share_1: >-
  030cfc5f8d28fecb856cfcb8232cc53e
agg_result: [0, 1]
]]></artwork>
          <artwork><![CDATA[
verify_key: "01010101010101010101010101010101"
agg_param: (1, [0, 1, 2, 3])
upload_0:
  round_0:
    prep_share_0: >-
      7ff2aa9b62d4699bb13b5d89054dc718ef0ef340d31e71e7
    prep_share_1: >-
      152587e270e3ad1f7166f605136db06284feef9e0c60ec4a
    prep_message: >-
      9518327dd3b816ba22a2538f18bb7779740de2dfdf7f5e30
  round_1:
    prep_share_0: >-
      edbf9effc5523ad6
    prep_share_1: >-
      124060ff3aadc52b
    prep_message: >-
  out_share_0:
    - e6b4675d5645143d
    - 6751646bdd854e4f
    - 782cd9dd3b220cbe
    - 07af78ced3d6e89f
  out_share_1:
    - 194b98a1a9baebc4
    - 98ae9b93227ab1b2
    - 87d32621c4ddf343
    - f85087302c291763
agg_share_0: >-
  e6b4675d5645143d6751646bdd854e4f782cd9dd3b220cbe07af78ced3d6e89f
agg_share_1: >-
  194b98a1a9baebc498ae9b93227ab1b287d32621c4ddf343f85087302c291763
agg_result: [0, 0, 0, 1]
]]></artwork>
          <artwork><![CDATA[
verify_key: "01010101010101010101010101010101"
agg_param: (2, [0, 2, 4, 6])
upload_0:
  round_0:
    prep_share_0: >-
      6d956ea3b01727f03e3c4b1cad1461c3fae8fc676763d8ef
    prep_share_1: >-
      9b8bfdb242f67c7aed868f197e62d46f4450ac65b089a5b6
    prep_message: >-
      09216c56f30da4692bc2da372b7736313f39a8ce17ed7ea4
  round_1:
    prep_share_0: >-
      a22d3f45a76cf4f3
    prep_share_1: >-
      5dd2c0b958930b0e
    prep_message: >-
  out_share_0:
    - bb4d5c8b44fea90f
    - 01c9989f7fa25aef
    - 46f355d9bc179269
    - 50600db413c684ce
  out_share_1:
    - 44b2a373bb0156f2
    - fe36675f805da512
    - b90caa2543e86d98
    - af9ff24aec397b34
agg_share_0: >-
  bb4d5c8b44fea90f01c9989f7fa25aef46f355d9bc17926950600db413c684ce
agg_share_1: >-
  44b2a373bb0156f2fe36675f805da512b90caa2543e86d98af9ff24aec397b34
agg_result: [0, 0, 0, 1]
]]></artwork>
          <artwork><![CDATA[
verify_key: "01010101010101010101010101010101"
agg_param: (3, [1, 3, 5, 7, 9, 13, 15])
upload_0:
  round_0:
    prep_share_0: >-
      21acceb054f9fe345aa353803f2debb5a307dad06b26dc6a7c7b79a1a665448b20
      88a892dad00cba3ab6ab9b9283b734937b281810100158daca6188dbbc4e155e3a
      0697f2291a6f723b6085dedf9a23817a554358e9f191aaa2a2425c938238
    prep_share_1: >-
      11fbc7788b2224efb1c760840c8ef96f400e6762e8bcfa000823120f2fb12e3838
      7ab34acd8cbbb78016048aaf737e167c8b7660581df35eb1af7b95de07d29526de
      fc2f23c59aff034e7feec503ae2e064db27e2c0f57ce905cfba9fcc3dab0
    prep_message: >-
      33a89628e01c23240c6ab4044bbce524e316423353e3d66a849e8bb0d61672c359
      035bdda85cc871baccb02641f7354b10069e78682df4b78c79dd1eb9c420aa0519
      02c715eeb56e7589e074a3e3485187c807c184f949603aff9dec59575cfb
  round_1:
    prep_share_0: >-
      3dc137d56f1e1eb3f09ea7300d66f972d74efd3f1efd667bd6079dc9b16179d6
    prep_share_1: >-
      423ec82a90e1e14c0f6158cff299068d28b102c0e102998429f862364e9e8617
    prep_message: >-
  out_share_0:
    - 5ea259ad47a621cc04bc4804ecc9d302ccd2225b37e82770912154e4c0495f6b
    - 6f8fb25f78167a93352cd07ca7bd6ea4f12f457b2968a62f4fc721fd12946030
    - 066e1fbff795f0eab7023023e8662c0d01804d169505f1f58bb005b1ae8d7906
    - 241a08089dd8e7c318987d598d3fe8cb2c7870b6d3a46228307f5cc50ee1b81b
    - 16d9502d5eb5ba9bd5e5c55e0385b35ee3a944585225848fd5cb82ce78ea0e77
    - 2ccf7b85827ba848284a28c82e5b8bb9c591b4b21628f374c3fc2cf79e3e8560
    - 5e16bb7dbf1ca16bf038dbc8702e4a1ee79074856c05d742e3d43e6f94d8022c
  out_share_1:
    - 215da652b859de33fb43b7fb13362cfd332ddda4c817d88f6edeab1b3fb6a082
    - 10704da087e9856ccad32f835842915b0ed0ba84d69759d0b038de02ed6b9fbd
    - 7991e040086a0f1548fdcfdc1799d3f2fe7fb2e96afa0e0a744ffa4e517286e7
    - 5be5f7f76227183ce76782a672c01734d3878f492c5b9dd7cf80a33af11e47d2
    - 6926afd2a14a45642a1a3aa1fc7a4ca11c56bba7adda7b702a347d318715f176
    - 5330847a7d8457b7d7b5d737d1a474463a6e4b4de9d70c8b3c03d30861c17a8e
    - 21e9448240e35e940fc724378fd1b5e1186f8b7a93fa28bd1c2bc1906b27fdc1
agg_share_0: >-
  5ea259ad47a621cc04bc4804ecc9d302ccd2225b37e82770912154e4c0495f6b6f8fb2
  5f78167a93352cd07ca7bd6ea4f12f457b2968a62f4fc721fd12946030066e1fbff795
  f0eab7023023e8662c0d01804d169505f1f58bb005b1ae8d7906241a08089dd8e7c318
  987d598d3fe8cb2c7870b6d3a46228307f5cc50ee1b81b16d9502d5eb5ba9bd5e5c55e
  0385b35ee3a944585225848fd5cb82ce78ea0e772ccf7b85827ba848284a28c82e5b8b
  b9c591b4b21628f374c3fc2cf79e3e85605e16bb7dbf1ca16bf038dbc8702e4a1ee790
  74856c05d742e3d43e6f94d8022c
agg_share_1: >-
  215da652b859de33fb43b7fb13362cfd332ddda4c817d88f6edeab1b3fb6a08210704d
  a087e9856ccad32f835842915b0ed0ba84d69759d0b038de02ed6b9fbd7991e040086a
  0f1548fdcfdc1799d3f2fe7fb2e96afa0e0a744ffa4e517286e75be5f7f76227183ce7
  6782a672c01734d3878f492c5b9dd7cf80a33af11e47d26926afd2a14a45642a1a3aa1
  fc7a4ca11c56bba7adda7b702a347d318715f1765330847a7d8457b7d7b5d737d1a474
  463a6e4b4de9d70c8b3c03d30861c17a8e21e9448240e35e940fc724378fd1b5e1186f
  8b7a93fa28bd1c2bc1906b27fdc1
agg_result: [0, 0, 0, 0, 0, 1, 0]
]]></artwork>
        </section>
      </section>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA+y923bbVpYo+o6vQMvjbJNlkpbkSxKlnd2yLDuqsi215KRO
bbdLBElQQkwSbACUrLLTH7Kfzrec82NnXteaCwBp2UlVd4+xNUZVTBJYl7nm
mvdLv9+PqqyapXvx1s9pkU2zZDRL42dZWRXZaFWlk3j/4qJIL5Iqyxfx89Vi
jP8ot6JkNCrSK3zt2f7zrWiSjxfJHIaZFMm06mdFNe2Pp8VF/2qSTPvbD6Nx
UqUXeXGzF2eLaR5F2bLYi6tiVVa729vfbe9GSZEme/HR6Zvn0XVevL8o8tVy
Lz54fvoiep/ewFcT+HVRpcUirfrPcJYoKqtkMTlPZvkCZr5Jy6icJ0V1/u+r
vErLvXiRR8tsL35b5eNeXOZFVaTTEv51M8d/vIuiZFVd5sVeFPejGP54B6fZ
+DIpJvHLQfw0gdlK+i0vLpJF9jeCAywrK8c5fZ/Ok2y2Fxez0b9ky6tB+SEc
7FlylU3igzx/3zLK0Rlszgwyya7S4iJdVJPkKv2XC/xyMM7n4YgHlwWcTr68
TIv4JKmqfNG2vlm+mkxnAFM7/hhfXdI797K0mq6b4uQym82y5TI+G1/my+U8
WbTN8SLPL2bB+KV7/F8u6EcaOlrkxRzeuUr3Inj67OTb7e3+zreP9uhVxb6z
H/f7D+JngINXgHQO0WDR8MufDnvxn17tH/TiN6vlLP0xKS9jOHnYf5HMZukM
v9ii4SaAZgD1dJzORwCg3e2dx/R9CQOnJaLeXvz66OxNfLZMx1kyi09Wo1k2
ZvSWheEqnx+dnO1u77at8QyRLkF0PEmL+aqid/tPkxLW7VZ2+KFK4Sm4TP3j
VbVcVfbu+IXury7gBuAyH7UvE9cRn/z0FB7ZhUsDP1hY7r/44/HJ7k64ypMi
y+/B4gCSyfgG/pvCqFfZ4sJd5RT3UAEWZeMyvsqS+Gmez9JkEZ8B4qeyQHc3
6K8P1xYO42wQ708myeJ9Fn7/p0H8IilGafjt4SD+YzKd1r49HcTHQF7yq/L9
TfjL/iA+yWc3gKb5Iksm+cpACva/w9tM4IpUe/FlVS3Lvfv3s2QwLu7jz/cf
ffMYofL06cGLF0c734Vg+V9pkff/tMivZ+nkIgWw5Pm0jOHUz9JxASSF9j6B
C1slBJPnq9nsJn6ZLdIELtrBySawPANSATTosrH9p/nNrLb9HwdADooig6vU
f5GNRmX482uAZDYb5Un49V8G8VF5mWQBRHa+ayDNwelfTt4c+9/WQWvnu/s7
337roVVHopfZxWV1neL/x2/S8eUi+/dVWsaAfoxYgEM/psnVTfxjVgFN/i8I
HEEXC5yjw8PD+Ox/nNwKmbZ3vkHwHLx4uvNN84LtKRh68Wk+gjvco2t/Nk5m
xEEP8vlSSEOcT1tv3gaQfQYMAUQdMnzTpCBnz478L/W9TmaDZDwfAFG/P8mz
+zvbg0fwd//BzqOHjx9sD+i/j3YRBs/yVZ0UvrmErdyMslm8X1XJ+P2Gzfxx
gAOM01URrBfoWeN8Tt4AtXM/NRacZ7RaWOnO9vY39x/0Hz3c7j989M3Db/vf
nu8+pKWenJ7tPgjX+mWCzaZDQW5eO4uDgeXC7utXA8CLcjVL34ffnwzqTHUt
Cj64v/Ngm/Z0nW8/Drf0LAOyWoCkQCyMKf2GpcMin6FQFR5AkzMeHey/PPE/
1Zc2yxbvB+WyAF6SFsjb74OktITr745kZ+ebb7+B1893cOGHJ3/aeRgu/HT/
5OT4FJgA3JZ8nv3NnAMdkOylb7jWcTHJFrDN07RcwgmlG/b5//3vQXxYwDIv
yrJ+Ij/DQWWXgoSW5fwpL/JZfpWEt+lhk7QenPkfPn+ZdnYePrq/+/jx9u7j
bwb43wcPid4evj7ZD2Fy+GEJqFKk8eu8AkQVYUQhsTT8G8BwQ0y7g6N04z9f
ZkBSTpJlWmwFy19D3sY5SKM73/VLJELjwXiy6CfLJctp9/FfMnmpT94frwpE
s/v8Bny9gNte9asiGcOK7i8n0/u4lHNayTmtZABf4kaBBT+sY62/fSd5tjBC
EVFPICpZEe+bdWw46y9ilM3TPPzp9JiY5foz/Ty6f/fNt/0H/ccPd/uPHu3u
bvcfnT8g6fEYSHe2eJPO0nlagc4TQIF/jN2vtZPbbl3LNAOVJf/QL/NVMU77
oG6Vg3n+N5DTE0K6CiS491kFBzSHSwInVt6vdAL4EoRkgvP9nCYfXFbzGS70
zs/JZIdoy52QtiP/mqUfsuoG2dc6cnPHns0dcwogJ8LIl8mCv3fn8Fhm+kpI
PwDcffTNNtF74M79fj9ORiUiIyiDby6zMgbArOaw0HiSlmPANZBZvoT8xx1U
Z8sucPNomsyzGW1/vppVWX8JquVNvCxyUCfzGctCY2LzeDcTx+FLL1vnoM/F
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
aJxA35ksMdSUDUdrqdJk1PJm8aRPGHOzwp6dbZWS/DdYgkYECydTfIp3//pg
F/jGw93vHn73+Jvd7x4BlduhcjVWqOJnv6XvX7jj0jG++at5nR5RCIfTfPIk
8vFDpYnP+SMaj+LmsRI9/P33/Pgx7vnxzs7jbx9v73z7cPebB99+8+1332zY
/M7j9btvGWgdGB4/tmDY2f02gAN8/scCYvfRI2DBO9+t2XR4aPiwXS18llLj
Jqztz6mG78PS0SQ0yi76WFojWQSqUENx1gg+GI4k71o/KtTcXjzv0JL7O991
h1gVrYLFxDI43BPqvMyWrrCnw3fbbNE6sXUp3FGyXe0CmzqElStMyYqT0xdd
mymUflhKCdbLvABJoMMvduXNMgXVRtRbLLutOh1axOwMowy3vh/D8CGTDu59
VGMxni01ywRpr+YogjEbHY+cYY0K6mw0q9XJ5tnhenNY2SxklhAMamYumvVW
9i2eE57HAEBVA9/C54FbB0hiXD9IEwcBmkg2VWcc1upxxC0lhZzgy7WmcC4S
KcPCRPgNj+365WIWH0Y/Mk1n9VxLm2qr4TIFueQNWZG12dyI5hZrlgcpplTh
JPqM5zGlFpLvZIN0oGHDkmJj3Fm4I3jrHPFqGFP6WuLzLDBsIiy5iPjMNjzA
/AE5PBvWu1A+oRwENbaJ2dMHwcO/YEhqJyjSAu4ZC8y7HbhN2dqIIh7YMmH2
gmh9LT6tjdYWqXxFSRnmovKzKBCCboBdVrRgGamEGN5CNX+kziEsNl9M7Puu
nKxNdouCS1ynZM+96wNX1vPwaOBAZHDgN2NAFGDArc6ftdhnCqNFei3Xlq0y
+PU5ftEB+FN26NddRVavANPiJ7HeaX1Fnw1MEg4pg2lIJzzm7TZRMjgTE2bp
LL20KXyHDE1lOpuKlaoXN3CfVzyH9dILJCSf59Pz3U5gouki92yajjgUHM1F
8HU3/mcdv8UYhMvgrbYYzLrmhf/xJJ6H9qJ/3mQuuo3RJ8KQrKUmJXFMzxDP
ZsimWW+rdECu2xvJ1EhjnOMrBFnElVYXJwO79acNqNX6fIhurY8EKNj+yJpj
/wpEtbZLHtUbBeCZL7eoIfd21gBYytll8oDlFCw492C9B1CeRR0YpYogoedP
6XicvMcCvXOj95/9uN9/AErt86OTs93tXYxjlQezUDMZw5N/OkShdY5eLqT+
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
AA==

-->

</rfc>
