<?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.13 (Ruby 3.1.2) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-irtf-cfrg-vdaf-02" category="info" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.13.0 -->
  <front>
    <title abbrev="VDAF">Verifiable Distributed Aggregation Functions</title>
    <seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-vdaf-02"/>
    <author initials="R. L." surname="Barnes" fullname="Richard L. Barnes">
      <organization>Cisco</organization>
      <address>
        <email>rlb@ipv.sx</email>
      </address>
    </author>
    <author initials="C." surname="Patton" fullname="Christopher Patton">
      <organization>Cloudflare</organization>
      <address>
        <email>chrispatton+ietf@gmail.com</email>
      </address>
    </author>
    <author initials="P." surname="Schoppmann" fullname="Phillipp Schoppmann">
      <organization>Google</organization>
      <address>
        <email>schoppmann@google.com</email>
      </address>
    </author>
    <date year="2022" month="July" day="11"/>
    <area>IRTF</area>
    <workgroup>CFRG</workgroup>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <t>This document describes Verifiable Distributed Aggregation Functions (VDAFs), a
family of multi-party protocols for computing aggregate statistics over user
measurements. These protocols are designed to ensure that, as long as at least
one aggregation server executes the protocol honestly, individual measurements
are never seen by any server in the clear. At the same time, VDAFs allow the
servers to detect if a malicious or misconfigured client submitted an
input that would result in an incorrect aggregate result.</t>
    </abstract>
    <note removeInRFC="true">
      <name>Discussion Venues</name>
      <t>Discussion of this document takes place on the
    Crypto Forum Research Group mailing list (cfrg@ietf.org),
    which is archived at <eref target="https://mailarchive.ietf.org/arch/search/?email_list=cfrg"/>.</t>
      <t>Source for this draft and an issue tracker can be found at
    <eref target="https://github.com/cjpatton/vdaf"/>.</t>
    </note>
  </front>
  <middle>
    <section anchor="introduction">
      <name>Introduction</name>
      <t>The ubiquity of the Internet makes it an ideal platform for measurement of
large-scale phenomena, whether public health trends or the behavior of computer
systems at scale. There is substantial overlap, however, between information
that is valuable to measure and information that users consider private.</t>
      <t>For example, consider an application that provides health information to users.
The operator of an application might want to know which parts of their
application are used most often, as a way to guide future development of the
application.  Specific users' patterns of usage, though, could reveal sensitive
things about them, such as which users are researching a given health condition.</t>
      <t>In many situations, the measurement collector is only interested in aggregate
statistics, e.g., which portions of an application are most used or what
fraction of people have experienced a given disease.  Thus systems that provide
aggregate statistics while protecting individual measurements can deliver the
value of the measurements while protecting users' privacy.</t>
      <t>Most prior approaches to this problem fall under the rubric of "differential
privacy (DP)" <xref target="Dwo06"/>. Roughly speaking, a data aggregation system that is
differentially private ensures that the degree to which any individual
measurement influences the value of the aggregate result can be precisely
controlled. For example, in systems like RAPPOR <xref target="EPK14"/>, each user samples
noise from a well-known distribution and adds it to their input before
submitting to the aggregation server. The aggregation server then adds up the
noisy inputs, and because it knows the distribution from whence the noise was
sampled, it can estimate the true sum with reasonable precision.</t>
      <t>Differentially private systems like RAPPOR are easy to deploy and provide a
useful guarantee. On its own, however, DP falls short of the strongest privacy
property one could hope for. Specifically, depending on the "amount" of noise a
client adds to its input, it may be possible for a curious aggregator to make a
reasonable guess of the input's true value. Indeed, the more noise the clients
add, the less reliable will be the server's estimate of the output. Thus systems
employing DP techniques alone must strike a delicate balance between privacy and
utility.</t>
      <t>The ideal goal for a privacy-preserving measurement system is that of secure
multi-party computation: No participant in the protocol should learn anything
about an individual input beyond what it can deduce from the aggregate. In this
document, we describe Verifiable Distributed Aggregation Functions (VDAFs) as a
general class of protocols that achieve this goal.</t>
      <t>VDAF schemes achieve their privacy goal by distributing the computation of the
aggregate among a number of non-colluding aggregation servers. As long as a
subset of the servers executes the protocol honestly, VDAFs guarantee that no
input is ever accessible to any party besides the client that submitted it. At
the same time, VDAFs are "verifiable" in the sense that malformed inputs that
would otherwise garble the output of the computation can be detected and removed
from the set of inputs.</t>
      <t>The cost of achieving these security properties is the need for multiple servers
to participate in the protocol, and the need to ensure they do not collude to
undermine the VDAF's privacy guarantees.  Recent implementation experience has
shown that practical challenges of coordinating multiple servers can be
overcome.  The Prio system <xref target="CGB17"/> (essentially a VDAF) has been deployed in
systems supporting hundreds of millions of users: The Mozilla Origin Telemetry
project <xref target="OriginTelemetry"/> and the Exposure Notification Private Analytics
collaboration among the Internet Security Research Group (ISRG), Google, Apple,
and others <xref target="ENPA"/>.</t>
      <t>The VDAF abstraction laid out in <xref target="vdaf"/> represents a class of multi-party
protocols for privacy-preserving measurement proposed in the literature. These
protocols vary in their operational and security considerations, sometimes in
subtle but consequential ways. This document therefore has two important goals:</t>
      <ol spacing="normal" type="1"><li>
          <t>Providing 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>02:</t>
        <ul spacing="normal">
          <li>Complete the initial specification of Poplar1.</li>
          <li>Extend (V)DAF syntax to include a "public share" output by the Client and
distributed to all of the Aggregators. This is to accommodate "extractable"
IDPFs as required for Poplar1. (See <xref target="BBCGGI21"/>, Section 4.3 for details.)</li>
          <li>Extend (V)DAF syntax to allow the unsharding step to take into account the
number of measurements aggregated.</li>
          <li>Extend FLP syntax by adding a method for decoding the aggregate result from a
vector of field elements. The new method takes into account the number of
measurements.</li>
          <li>Prio3: Align aggregate result computation with updated FLP syntax.</li>
          <li>Prg: Add a method for statefully generating a vector of field elements.</li>
          <li>Field: Require that field elements are fully reduced before decoding. (*)</li>
          <li>Define new field Field255.</li>
        </ul>
        <t>01:</t>
        <ul spacing="normal">
          <li>Require that VDAFs specify serialization of aggregate shares.</li>
          <li>Define Distributed Aggregation Functions (DAFs).</li>
          <li>Prio3: Move proof verifier check from <tt>prep_next()</tt> to
<tt>prep_shares_to_prep()</tt>. (*)</li>
          <li>Remove public parameter and replace verification parameter with a
"verification key" and "Aggregator ID".</li>
        </ul>
      </section>
    </section>
    <section anchor="conventions-and-definitions">
      <name>Conventions and Definitions</name>
      <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>
      <t>Algorithms in this document are written in Python 3. Type hints are used to
define input and output types. A fatal error in a program (e.g., failure to
parse one of the function parameters) is usually handled by raising an
exception.</t>
      <t>A variable with type <tt>Bytes</tt> is a byte string. This document defines several
byte-string constants. When comprised of printable ASCII characters, they are
written as Python 3 byte-string literals (e.g., <tt>b'some constant string'</tt>).</t>
      <t>A global constant <tt>VERSION</tt> is defined, which algorithms are free to use as
desired. Its value <bcp14>SHALL</bcp14> be <tt>b'vdaf-02'</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>xor(left: Bytes, right: Bytes) -&gt; Bytes</tt> returns the bitwise XOR of <tt>left</tt>
and <tt>right</tt>. An exception is raised if the inputs are not the same length.</li>
        <li>
          <tt>I2OSP</tt> and <tt>OS2IP</tt> from <xref target="RFC8017"/>, which are used, respectively, to
convert a non-negative integer to a byte string and convert a byte string to a
non-negative integer.</li>
        <li>
          <tt>next_power_of_2(n: Unsigned) -&gt; Unsigned</tt> returns the smallest integer
greater than or equal to <tt>n</tt> that is also a power of two.</li>
      </ul>
    </section>
    <section anchor="overview">
      <name>Overview</name>
      <figure anchor="overall-flow">
        <name>Overall data flow of a (V)DAF</name>
        <artwork><![CDATA[
                 +--------------+
           +---->| Aggregator 0 |----+
           |     +--------------+    |
           |             ^           |
           |             |           |
           |             V           |
           |     +--------------+    |
           | +-->| Aggregator 1 |--+ |
           | |   +--------------+  | |
+--------+-+ |           ^         | +->+-----------+
| Client |---+           |         +--->| Collector |--> Aggregate
+--------+-+                         +->+-----------+
           |            ...          |
           |                         |
           |             |           |
           |             V           |
           |    +----------------+   |
           +--->| Aggregator N-1 |---+
                +----------------+

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

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

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

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

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

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

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

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

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

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

    out_shares = []
    for (nonce, measurement) in zip(nonces, measurements):
        # Each Client shards its measurement into input shares.
        (public_share, input_shares) = \
            Vdaf.measurement_to_input_shares(measurement)

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

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

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

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

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

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

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

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

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

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

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

    SEED_SIZE: Unsigned = 16

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

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

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

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

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

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

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

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

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

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

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

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

    out_share = Prio3.Flp.truncate(input_share)

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

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

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

    if inbound is None:
        return (prep, prep_msg)

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

    return out_share

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

        verifier = vec_add(verifier, verifier_share)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    raise ERR_INPUT # unexpected input

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-ppm-dap-01"/>
        </reference>
      </references>
    </references>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>Thanks to David Cook, Henry Corrigan-Gibbs, Armando Faz-Hernandez, Simon
Friedberger, Tim Geoghegan, Mariana Raykova, Jacob Rothstein, and Christopher
Wood for useful feedback on and contributions to the spec.</t>
    </section>
    <section numbered="false" anchor="test-vectors">
      <name>Test Vectors</name>
      <ul empty="true">
        <li>
          <t>NOTE Machine-readable test vectors can be found at
https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec.</t>
        </li>
      </ul>
      <t>Test vectors cover the generation of input shares and the conversion of input
shares into output shares. Vectors specify the verification key, measurements,
aggregation parameter, and any parameters needed to construct the VDAF. (For
example, for <tt>Prio3AesSum</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="prio3aes128count-1">
        <name>Prio3Aes128Count</name>
        <artwork><![CDATA[
verify_key: "01010101010101010101010101010101"
upload_0:
  measurement: 1
  nonce: "01010101010101010101010101010101"
  public_share: >-
  input_share_0: >-
    a46091d07a930ace79bb11d1d03596bf4f921f7e70b853cf6b8d4969287dfb504a1d
    ea6b0eb01a5f50ad24225186c104
  input_share_1: >-
    0101010101010101010101010101010101010101010101010101010101010101
  round_0:
    prep_share_0: >-
      cdbbf14ef0c19728578ce1e50411e1e26eb49eea4dadfada9ed3d13c71d846b8
    prep_share_1: >-
      32440eb00f3e68d95b9f6e2e856cf534948881bf63c24d315e4954159611ebb5
    prep_message: >-
  out_share_0:
    - 11844627344580086478
  out_share_1:
    - 6602116724834497844
agg_share_0: >-
  a46091d07a930ace
agg_share_1: >-
  5b9f6e2e856cf534
agg_result: 1
]]></artwork>
      </section>
      <section numbered="false" anchor="prio3aes128sum">
        <name>Prio3Aes128Sum</name>
        <artwork><![CDATA[
bits: 8
verify_key: "01010101010101010101010101010101"
upload_0:
  measurement: 100
  nonce: "01010101010101010101010101010101"
  public_share: >-
  input_share_0: >-
    a46091d17a930aaf4d02cff822f817a3d10d4d74d526daf00112da46b9b33deaa222
    0ff24fe104b34007f47c4531dc7471b6832358f5d6859fb3b2112e79ec6eb940251d
    14855b16689ab3cfd9100b568729aadfb5558a3bd0277d3ae7c5d967e3525839f26f
    5cb210e4fb0b0aeb0394ce0791de9c4c07f8840dcdd1ce09bb2179bb11d1d03596be
    4f921f7f70b853ce99c2bd80daf08029b7bb7820b7a7632e3b9200ff98adde77a833
    6469ba7fa61ebf135e7f303568ddf63e39978954c40a3fcfa08412f5f03f61699643
    85f167c68c3ae5205e1c3dd075fc76224bf9407ef3fd54334bec36d453460381ee54
    4027bb520f55394873f5dff846794007cc7d77e903b1474095c61140d1e488a98e00
    f433c22491825191261e982affc44e20756db024e0dcdda9746aba73d2ec9a083953
    4a1d0178802fc0ee9393160b34dca94999c91fa788b8308b15880ea3146aabf38e2f
    a4d715c0be7e183fe7f158f47438eaa5a55406da5be56d724afd86e579bc076c669c
    334c93fb724891e0b72c8737a9f65c2d3d56bae20dce052f43293712a603f8a8b9e8
    bcdafad8420ae14201f9a8b4891e9b60dd418d0f71ee2395b9026cb4978f901765e0
    155b127a4fa95a0e0751b95d9ada245c78df820e4bc7f0c9329a5bbad2ee85688cea
    47336da7a798705b6c465678363574e844d1974f6f369e9ef13e920d383f580aa382
    8b7641a77f352b73134886c58e822040747311a9b094137c5f46d6e9ed05bb17d9c7
    0f01b5491805ac83c447035560b00b8e7049c334fcfa003941fa0e307cf52884e461
    8f794848936bfcd8d7f895781d27b006673a6349bdfa04c8c3506b2b64efff5335f7
    6723bce0f1092571cae3d125dcabbb6da4867963ffd29172ef699ecf010101010101
    0101010101010101010132dd9fa5604fadc81ff1636918a6db69
  input_share_1: >-
    01010101010101010101010101010101010101010101010101010101010101010101
    0101010101010101010101010101646430cb3212da0c23bff5618647609c
  round_0:
    prep_share_0: >-
      ede97ab0d3d2dc256a1f82261078cc06b5a423c5f221e9fa029ba023bc71e70fd1
      9e2db541507b4171409bc06c3ac292646430cb3212da0c23bff5618647609c
    prep_share_1: >-
      1216854f2c2d23be95e07dd9ef8733fb779dce023a0e4f7147b74c75c5fd1723a1
      1b7a116c0a89c6b97471597eb2a83c32dd9fa5604fadc81ff1636918a6db69
    prep_message: >-
      56b9af6e525d77c43c4e96089ee1bbf5
  out_share_0:
    - 231691668211413349799981210015670190003
  out_share_1:
    - 108590698709525113146884563352230576306
agg_share_0: >-
  ae4e3131e0f5bea01ba67704684fbfb3
agg_share_1: >-
  51b1cece1f0a4143e45988fb97b040b2
agg_result: 100
]]></artwork>
      </section>
      <section numbered="false" anchor="prio3aes128histogram-1">
        <name>Prio3Aes128Histogram</name>
        <artwork><![CDATA[
buckets: [1, 10, 100]
verify_key: "01010101010101010101010101010101"
upload_0:
  measurement: 50
  nonce: "01010101010101010101010101010101"
  public_share: >-
  input_share_0: >-
    a46091d17a930aaf4d02cff822f817a3d10d4d74d526daf00112da46b9b33deaa222
    0ff24fe104b34007f47c4531dc7471b6832358f5d6859fb3b2112e79ec6e79bb11d1
    d03596be4f921f7f70b853cec138b5a4f1a798810bde46a7265fd6bed9bb8cc8d058
    bb224cc75b17f2ebc7f7b6c7a708b11022329fab97ed7d23309116a6fb53d1d9ff45
    9a67eafcddbd190e69069ef82f361a6d4c9616ec3396776834a7d3d5848409cdd89f
    ec7920a858074db9c2e7adfc4b3397339532f80e327f25f31975e3f5d149ba8c8d5b
    f101488f4882ab2b38ddedc84f814435c2b227ffeee7affc5076d78819d7ce68f247
    355af67c52fc7ef9bbcbf8bc910af7c047a28dfeb4f92158934ce93dac747c1b55a8
    f5efb18e944e0579602c918e670f8d543b530d8ba3730d0a43e8bcd2d54f736c4db1
    ac64c9c49dc5ab20c0ac0cf6530b01010101010101010101010101010101d451ca17
    ca18344ac4925510c71e5ac8
  input_share_1: >-
    01010101010101010101010101010101010101010101010101010101010101010101
    0101010101010101010101010101ef377f05b86ffa85ed011213230bb1d5
  round_0:
    prep_share_0: >-
      a1a7093768a9f8a3c01e31f7e9c6dc7925407d03831c510799fcf30a03c61bcd35
      78329d502e06cd01e994c227d3d1afef377f05b86ffa85ed011213230bb1d5
    prep_share_1: >-
      5e58f6c8975607403fe1ce081639238809c0227ef8c371e897e7950d763d8a37f7
      ee6acb826a97f3ef37fd59e6a95511d451ca17ca18344ac4925510c71e5ac8
    prep_message: >-
      3b66b5127277cecf29934703e415eb1d
  out_share_0:
    - 218494809353158975333103031759951894435
    - 277877721980181983205633439801202130410
    - 215511796844427285058159435311010143348
    - 151150421348124479376036084370309246062
  out_share_1:
    - 121787557567779487613762741607948871774
    - 62404644940756479741232333566698635799
    - 124770570076511177888706338056890622862
    - 189131945572813983570829688997591520147
agg_share_0: >-
  a46091d17a930aaf4d02cff822f817a3d10d4d74d526daf00112da46b9b33deaa2220f
  f24fe104b34007f47c4531dc7471b6832358f5d6859fb3b2112e79ec6e
agg_share_1: >-
  5b9f6e2e856cf534b2fd3007dd07e85e2ef2b28b2ad924f3feed25b9464cc2175dddf0
  0db01efb30bff80b83bace238e8e497cdca70a295e604c4deed1861393
agg_result: [0, 0, 1, 0]
]]></artwork>
      </section>
      <section numbered="false" anchor="poplar1aes128">
        <name>Poplar1Aes128</name>
        <section numbered="false" anchor="sharding-1">
          <name>Sharding</name>
          <artwork><![CDATA[
bits: 4
upload_0:
  measurement: 13
  nonce: "01010101010101010101010101010101"
  public_share: >-
    9a00000000000000000000000000000000ffffffff00000000bd5fef66a8181fb000
    000000000000000000000000000000ffffffff00000000dbf324f2b4351711000000
    00000000000000000000000000ffffffff00000000984542b43f4008f40000000000
    00000000000000000000000000000000000000000000000000000000000000000000
    00000000000000000113aec130616497e38eaafb95841bad26f773979c71d5422d1c
    875c6c007575ce
  input_share_0: >-
    01010101010101010101010101010101010101010101010101010101010101011926
    0bd7b833c3b313d7ba6d15a9f16fec202c82ddf2848909acc634a461a6b8b7758b10
    e0adb885083645e2bbe0c575137f41a015e6cc2ce8fed760ca08589f957eef3d1667
    07d9044d22411142e73568bba4e2f7150dab3316e30966a1d73f660ec47316af0198
    e8682372a232bcef
  input_share_1: >-
    01010101010101010101010101010101010101010101010101010101010101013422
    59973b9807dbbb662f6a81067220a977e09ad54ba5048edb2118c95bb8f3ce11a0dd
    6f0bda66dc2dc274f26ec69e091747a0b26b57ad629d905fae98204c5171179db567
    12e5dd66f792eddc6da955476f1471eb5c12aac55b35c1d80a2022d30da1ac00dfc5
    8c581e8304ab59f1
]]></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: >-
      48c3581799a109398b1943c10957b8c2536f292900de6436
    prep_share_1: >-
      8377f3fcd4d2d1f33233948d19fe2c385f97c52d8e007f76
    prep_message: >-
      cc3b4c146e73db2cbd4cd84e2355e4fab306ee568edee3ac
  round_1:
    prep_share_0: >-
      64ce1f88d77b2a65
    prep_share_1: >-
      9b31e0762884d59c
    prep_message: >-
  out_share_0:
    - 18352387916526274078
    - 14559030685141423577
  out_share_1:
    - 94356152888310243
    - 3887713384273160745
agg_share_0: >-
  feb0c79330b8461eca0c114565ddd5d9
agg_share_1: >-
  014f386bcf47b9e335f3eeb99a222a29
agg_result: [0, 1]
]]></artwork>
          <artwork><![CDATA[
verify_key: "01010101010101010101010101010101"
agg_param: (1, [0, 1, 2, 3])
upload_0:
  round_0:
    prep_share_0: >-
      37c72ca578a032eaeffbd9e63d29e6eaa205d9d67628d055
    prep_share_1: >-
      ab956611d15cfcef0773a4e435fdcb83909785aa50c17513
    prep_message: >-
      e35c92b749fd2fd9f76f7eca7327b26d329d5f81c6ea4567
  round_1:
    prep_share_0: >-
      ee63dfb515814411
    prep_share_1: >-
      119c2049ea7ebbf0
    prep_message: >-
  out_share_0:
    - 7623875273889432259
    - 4753532626118505607
    - 9999595461072379379
    - 1320535832873937471
  out_share_1:
    - 10822868795525152062
    - 13693211443296078714
    - 8447148608342204942
    - 17126208236540646851
agg_share_0: >-
  69cd722b281042c341f7f0bcf805f4878ac5b3177ad3ddf312537c57efa02a3f
agg_share_1: >-
  96328dd3d7efbd3ebe080f4207fa0b7a753a4ce7852c220eedac83a7105fd5c3
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: >-
      7eb8dbda5ea6807e53f22d3f74a43f59ed83ef578b070654
    prep_share_1: >-
      567632dc63ec2294c6f030077726f87ec11e2fc53a38f640
    prep_message: >-
      d52f0eb6c292a3121ae25d47ebcb37d6aea21f1dc53ffc93
  round_1:
    prep_share_0: >-
      9e92c793980229fd
    prep_share_1: >-
      616d386b67fdd604
    prep_message: >-
  out_share_0:
    - 1646250657834468215
    - 16923505979406688621
    - 18330814903122515861
    - 12155602082232726549
  out_share_1:
    - 16800493411580116106
    - 1523238090007895700
    - 115929166292068460
    - 6291141987181857773
agg_share_0: >-
  16d8a840477a0377eadc5f0610bc216dfe642308980dd795a8b15fb0ce7af415
agg_share_1: >-
  e92757beb885fc8a1523a0f8ef43de94019bdcf667f2286c574ea04e31850bed
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: >-
      246777985de3e9fd0ea9e8ea429ae3c7255c0b2aa84cff6bd5c0079a122be38b53
      4e75cbfe8abb2c54b5b277089bb2708b274a17ce26df0ea9881487ac852eee30c1
      8ba6dc40beb7f33e5003fdf065eec844e320d0b9ff49b0b29f5bbbcbcc8d
    prep_share_1: >-
      3dea0b9e72389ea0d62521e91214c654ebf9b2a3d855a32219755216f4cb8eca0d
      864838efc99f1a5d2adecf87e4ff0b839fb7191d4c58c5fd6753c0c6a2fb155071
      efff9719f0e9645d70b398ca24ecb2fa8fbb56a6a90ce6d95b675e1e28f2
    prep_message: >-
      62518336d01c889de4cf0ad354afaa1c1155bdce80a2a28def3559b106f7725560
      d4be04ee545a46b1e091469080b17c0ec70130eb7337d4a6ef684873282a030133
      7ba6735aafa1579bc0b796ba8adb7b3f72dc2760a856978bfac319e9f592
  round_1:
    prep_share_0: >-
      40521213baba54c83b4ddc0cb1e3e4c16897bb8831cc12ea91a82927dd30ae58
    prep_share_1: >-
      3fadedec4545ab37c4b223f34e1c1b3e97684477ce33ed156e57d6d822cf5195
    prep_message: >-
  out_share_0:
    - 27022242238524926041754024638978288940369802983157338113702795433392718442891
    - 8433446103891669428510589487794410319530091467635619512122120272876905203470
    - 31927171851194534364500488903327032909992419490289770138187660233081601268509
    - 13674389066590417186009193737398514883303633790292716630453797389670854762435
    - 49245655988555337792760994399532100867010365510706353464574012401106060986059
    - 38418164104898327452350816690091778787588836972103923142413897241001677348897
    - 17473652484574293745985786122460988541722879368489070298827855759184581179349
  out_share_1:
    - 30873802380133171670031467865365664986265189349662943906025996570563846377058
    - 49462598514766428283274903016549543607104900865184662507606671731079659616479
    - 25968872767463563347285003601016921016642572842530511881541131770874963551440
    - 44221655552067680525776298766945439043331358542527565389274994614285710057514
    - 8650388630102759919024498104811853059624626822113928555154779602850503833890
    - 19477880513759770259434675814252175139046155360716358877314894762954887471053
    - 40422392134083803965799706381882965384912112964331211720900936244771983640600
agg_share_0: >-
  3bbe0c0f2a3ecf406419e5a8636f13c1102df2df86b4dec82daa4669b24f718b12a529
  4d99b7a604a6944dbe1b81cfcc98e4a5a1fa0d08ac727f620ee0b4870e4696238e0b88
  71bb6d93ab6c8fc1680da244dfc59bd0b6f70b8dae1f4c1a1b1d1e3b6e1053afb851cc
  ae5d9ddabb8bff59afea5f6f905e0b2dd1b8a9cc911fc36ce00db4dfb57d404c6bddc9
  0a93a35fa5a476634aab5c2c46b467e2a6ce46cb54efe909f5c78891ac58d782afb5a4
  4dbc5b2f0c190d4ebe8ca7eb1e4af8e02126a1bca0b523a4c67c7176bebb04afed7b50
  6fc5c343e3e7727d3027d68937d5
agg_share_1: >-
  4441f3f0d5c130bf9be61a579c90ec3eefd20d20794b2137d255b9964db08e626d5ad6
  b2664859fb596bb241e47e3033671b5a5e05f2f7538d809df11f4b78df3969dc71f477
  8e44926c5493703e97f25dbb203a642f4908f47251e0b3e5e4d061c491efac5047ae33
  51a26225447400a65015a0906fa1f4d22e4756336ee02a131ff24b204a82bfb3942236
  f56c5ca05a5b899cb554a3d3b94b981d5931b9222b1016f60a38776e53a7287d504a5b
  b243a4d0f3e6f2b141735814e1b5071fcd595e435f4adc5b39838e894144fb501284af
  903a3cbc1c188d82cfd82976c818
agg_result: [0, 0, 0, 0, 0, 1, 0]
]]></artwork>
        </section>
      </section>
    </section>
  </back>
  <!-- ##markdown-source:
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
b+TrhLRT+daQdZYArIrnL4wTwzZcGXbOBXowF9rZoAaSHBONZSNcCNLJynR0
3gDX45JRQaKsigzG/6XRcQ2x1d+SwjEBZAp4OehTt/Wa+If3iPXrRfjYAwyC
i+Fe34t91GLzglgc9BdEzOQsFGj2pQGopsnFG9Riy1lrhPnWlBm/f2b+tX2u
f/fM8u7C8yjkUubzDn0On/FM6vRR4/Wd2us7217faby+W3t9d9vruz5WIggD
aflsvm/M+V1tzu+2zfldO2NujTbZwJm3sOYg5qXlc+MZkZJgqbuAn7KO+mcE
RvDdb5jrH7VzdwkF4fxnh/rmOyMnObHEUYtANLFUsG7hG4LWOdJ8WyHDPo+k
ptkY/zdKJGh0Jr8L6sfX5H0izU9DjklpMfYnjKLpYIxGdV6sKBJg0RclMEG1
eiPF5XRScr5MNdrClZcaxj9g1jI5lNBAir5Hl6kIE1aoRgMFOwtnNJEjEgaR
MgNHvxkP3KIPs2OLcvW4/iTFYjAE5teqG1Pkg5l3/+iQ9FMYjzXUx18zfzIm
R8+eJE8JALw/W0nQgfUWs2XCpSIheV1jCQWSPX3mUmgDYQ2I7bWZTWXaYK/l
GAkg6dUmeQ29m0LQa4/wzJ5TOZwlTsV8rJVNRQa/hVGxjtrHfZ1abKzFZRqj
F2VFi4IaykMm9TcIUmnNyBId1gD+fqDCmxBhv+ZRi9YYx6P64h133ZBnxm4f
LMnpVGJlqw1Lnl9TeNmqkHX/l+CxX0zg/pFU946qsuM3bVjdMkmwri+bq25G
wJl5Pgarw/DwhDxbEIoSMIUXjfKE8YxqimzIT/SFhxnhkAE8j//1x4MTTP0B
Gnw9Tht6iknQkCTqcc3I5JPxn5tUTUvuuuIKcbvkyJDpVEp5UoKlrdT73JUA
5iRS1h3aU3hh5zdUAhv2kAuUfGMz0gsGxWxQTYqld8pr2Ml/FyqvRfHPYO/r
MVXDp1GvznDghzh4kLX7kNhC9XDnW+YLLS5WipUYuNx8gD7VmsMwGvmSUi45
0Ed8juliPU9WTZ2bGN6UKzf9+Q+DQXSSYf7GqzJLp0CPQGXbiw9xZ/kF7+9K
zw6oVMYElIosUWOtuCtx7ONsFWGByhSOiPMESqqWW9OvOESO1U2qog6IQCEX
6AGbYCSKCZWM0H1OTtcFWonRKcC5++S6BhKP8R34WX2woE0MBs8p3he4MTKC
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
JcZgzlpYYIu37Fvg5NWa4mhjJpnr7evZ2/Mjol3a8XRj8ieupcv9u5TUs0Zi
3sC3dNfhdrfnyeCk8i7AlHNkz973GbNP1jFr/ttXrAk2vnIRJ301ow8uZQKe
NXHzCuPnW9KetC5VDFt1y+GN2ZS4kC47zFpJuSqv9pf+bH4zb/byM++Aqs/E
+dnxOvilBkXGcn47nRmHBzVfB9oxdcnxdW7nPMvBgpk+Onvxz+Y0VZByqT8U
w5yweZfvU1Pc/y5nc9fIW6wYpZlZDug2l5vXmysXy7/hO9xmPnwawqV5R8mQ
qaSVclfefRZFl9334sj708GCPh4+vc9X846zpDCR9AYuuES1w0lrunDL44vp
mmQtU9HbGTSKr2VP7UHPuep4PmFgugaW/35CnJ/kxl4I6/tMI1PQk0O2AQu+
n54Ep+DT1TQYm3PF5zIzk+e8xZkozqpTr+gS9V6yMyfsU4vzktZUT86XfMe/
Vh8llyYzzV5KtTjA/RsHq4/wOiO8L4OPM7q4OMUIZfVkdZKA2xYw7vXmHw4g
fkSOz+F2t3N5aul742LQl2NV5flZKAVC7M4tEMVT1JeP5eHhxiCnJ18/84QV
8tc4f6pV7npRAGmObnKk5uLFmJD4n0vUNKOleDxANBMigZdxvg/3z172j2Nj
ls31OJ547BWHdcA42TmLkM1btkODaZs9IdITYumJG29VOns+mITFefaAsyCd
DR8eCDcUOWLeq+Ibqn3oXjziz93izrl4ZuXu+K0456zBxTm/zyy7936tJ9ZQ
1nNsiwaxaA0RZUzMoczg+ACraDn64k4jIjMh3PZPjjNMPDVfuCFG7fprYv7l
PJ3E1Ld2FO/S+NC9ifMu3Hl4iPPuoc/6jATo57tn8un3R/G9UH/2JvPbaa5L
G313+B3IS7hqtZOKoI5v3AleIKB8xQIxPXjhfCMPX7lIV9n948Nrwa+EWKac
+A9FMr09cK15yUlykODfTg+zJ/ZRvlp7/oTHdxwiuzPVwOTZGbBf86MXmex7
cZz7zyZHwwc6nXfxz88zKTSrzkcnx/7m1PF9L4s7Xv5U7B05y0/mft0HHTV7
8XJ5vL8sUTG8CK6fX7AyH0JCs2H6/pe+2gtf3BOjkyPzJXM7J6f9OJ8PW1S/
iA+MLpnSoxMyeUMpt8Zv4P7/0PXPHOdepuXDZWG3B1hDN5B/+cNJEi7T+hfk
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
P2X7P0hTwX7VNgIA

-->

</rfc>
