<?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.10 (Ruby 3.0.4) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-irtf-cfrg-vdaf-01" category="info" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.12.7 -->
  <front>
    <title abbrev="VDAF">Verifiable Distributed Aggregation Functions</title>
    <seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-vdaf-01"/>
    <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="May" day="26"/>
    <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 compatibility with the previous draft.</t>
        <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-01'</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; Vec[Bytes]</tt> is the
randomized input-distribution algorithm run by each Client. It consumes the
measurement and produces a sequence of input shares, one for each Aggregator.
The length of the output vector <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 an input share form a Client, 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, input_share: Bytes) -&gt;
OutShare</tt> is the deterministic preparation algorithm. It takes as input an
input share generated by a Client, the Aggregator's unique identifier, and the
aggregation parameter selected by the Collector and returns an output share.</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]) -&gt;
AggResult</tt> is run by the Collector in order to compute the aggregate result
from the Aggregators' shares. The length of <tt>agg_shares</tt> <bcp14>MUST</bcp14> be <tt>SHARES</tt>.
This algorithm is deterministic.</li>
        </ul>
        <figure anchor="unshard-flow">
          <name>Computation of the final aggregate result from aggregate shares.</name>
          <artwork><![CDATA[
    Aggregator 0    Aggregator 1        Aggregator SHARES-1
    ============    ============        ===================

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

    Collector
    =========
]]></artwork>
        </figure>
        <ul empty="true">
          <li>
            <t>QUESTION Maybe the aggregation algorithms should be randomized in order to
allow the Aggregators (or the Collector) to add noise for differential
privacy. (See the security considerations of <xref target="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.
        input_shares = Daf.measurement_to_input_shares(measurement)

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

    # Each Aggregator aggregates its output shares into an aggregate
    # share and 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.
    agg_result = Daf.agg_shares_to_result(agg_param, agg_shares)
    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; Vec[Bytes]</tt> is
the randomized input-distribution algorithm run by each Client. It consumes
the measurement and produces a sequence of input shares, one for each
Aggregator. Depending on the VDAF, the input shares may encode additional
information used to verify the recovered output shares (e.g., the "proof
shares" in Prio3 <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, 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 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.</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]) -&gt;
AggResult</tt> is run by the Collector in order to compute the aggregate result
from the Aggregators' shares. The length of <tt>agg_shares</tt> <bcp14>MUST</bcp14> be <tt>SHARES</tt>.
This algorithm is deterministic.</li>
        </ul>
        <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.
        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,
                                   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.
    agg_result = Vdaf.agg_shares_to_result(agg_param, agg_shares)
    return agg_result
]]></artwork>
        </figure>
        <t>The inputs to this algorithm are the aggregation parameter, 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.
If <tt>integer &gt;= Field.MODULUS</tt>, then <tt>integer</tt> is first reduced modulo
<tt>Field.MODULUS</tt>.</li>
        </ul>
        <t>Finally, each concrete <tt>Field</tt> has two derived class methods, one for encoding
a vector of field elements as a byte string and another for decoding a vector of
field elements.</t>
        <figure anchor="field-derived-methods">
          <name>Derived class methods for finite fields.</name>
          <artwork><![CDATA[
def encode_vec(Field, data: Vec[Field]) -> Bytes:
    encoded = Bytes()
    for x in data:
        encoded += I2OSP(x.as_unsigned(), Field.ENCODED_SIZE)
    return encoded

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

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

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

# Add the right operand to the left and return the result.
def vec_add(left: Vec[Field], right: Vec[Field]):
    return list(map(lambda x: x[0] + x[1], zip(left, right)))
]]></artwork>
          </figure>
        </section>
        <section anchor="field-fft-friendly">
          <name>FFT-Friendly Fields</name>
          <t>Some VDAFs require fields that are suitable for efficient computation of the
discrete Fourier transform. (One example is Prio3 (<xref target="prio3"/>) when instantiated
with the generic FLP of <xref target="flp-generic-construction"/>.) Specifically, a field is
said to be "FFT-friendly" if, in addition to satisfying the interface described
in <xref target="field"/>, it implements the following method:</t>
          <ul spacing="normal">
            <li>
              <tt>Field.gen() -&gt; Field</tt> returns the generator of a large subgroup of the
multiplicative group.</li>
          </ul>
          <t>FFT-friendly fields also define the following parameter:</t>
          <ul spacing="normal">
            <li>
              <tt>GEN_ORDER: Unsigned</tt> is the order of a multiplicative subgroup generated by
<tt>Field.gen()</tt>. This value <bcp14>MUST</bcp14> be a power of 2.</li>
          </ul>
        </section>
        <section anchor="parameters">
          <name>Parameters</name>
          <t>The tables below define finite fields used in the remainder of this document.</t>
          <table anchor="field64">
            <name>Field64, an FFT-friendly field.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">MODULUS</td>
                <td align="left">2^32 * 4294967295 + 1</td>
              </tr>
              <tr>
                <td align="left">ENCODED_SIZE</td>
                <td align="left">8</td>
              </tr>
              <tr>
                <td align="left">Generator</td>
                <td align="left">7^4294967295</td>
              </tr>
              <tr>
                <td align="left">GEN_ORDER</td>
                <td align="left">2^32</td>
              </tr>
            </tbody>
          </table>
          <table anchor="field128">
            <name>Field128, an FFT-friendly field.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">MODULUS</td>
                <td align="left">2^66 * 4611686018427387897 + 1</td>
              </tr>
              <tr>
                <td align="left">ENCODED_SIZE</td>
                <td align="left">16</td>
              </tr>
              <tr>
                <td align="left">Generator</td>
                <td align="left">7^4611686018427387897</td>
              </tr>
              <tr>
                <td align="left">GEN_ORDER</td>
                <td align="left">2^66</td>
              </tr>
            </tbody>
          </table>
        </section>
      </section>
      <section anchor="prg">
        <name>Pseudorandom Generators</name>
        <t>A pseudorandom generator (PRG) is used to expand a short, (pseudo)random seed
into a long string of pseudorandom bits. A PRG suitable for this document
implements the interface specified in this section. Concrete constructions are
described in 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)

# Expand a seed into a vector of Field elements.
def expand_into_vec(Prg,
                    Field,
                    seed: Bytes,
                    info: Bytes,
                    length: Unsigned):
    m = next_power_of_2(Field.MODULUS) - 1
    prg = Prg(seed, info)
    vec = []
    while len(vec) < length:
        x = OS2IP(prg.next(Field.ENCODED_SIZE))
        x &= m
        if x < Field.MODULUS:
            vec.append(Field(x))
    return vec
]]></artwork>
        </figure>
        <section anchor="prg-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 "invalid".</li>
        <li>The aggregate result is obtained by summing up the encoded input vectors and
computing some function of the sum.</li>
      </ul>
      <t>At a high level, Prio3 distributes this computation as follows. Each Client
first shards its measurement by first encoding it, then splitting the vector into
secret shares and sending a share to each Aggregator. Next, in the preparation
phase, the Aggregators carry out a multi-party computation to determine if their
shares correspond to a valid input (as determined by the arithmetic circuit).
This computation involves a "proof" of validity generated by the Client. Next,
each Aggregator sums up its input shares locally. Finally, the Collector sums up
the aggregate shares and computes the aggregate result.</t>
      <t>This VDAF does not have an aggregation parameter. Instead, the output share is
derived from the input share by applying a fixed map. See <xref target="poplar1"/> for an
example of a VDAF that makes meaningful use of the aggregation parameter.</t>
      <t>As the name implies, Prio3 is a descendant of the original Prio construction.
A second iteration was deployed in the <xref target="ENPA"/> system, and like the VDAF
described here, the ENPA system was built from techniques introduced in
<xref target="BBCGGI19"/> that significantly improve communication cost. That system was
specialized for a particular aggregation function; the goal of Prio3 is to
provide the same level of generality as the original construction.</t>
      <t>The core component of Prio3 is a "Fully Linear Proof (FLP)" system. Introduced
by <xref target="BBCGGI19"/>, the FLP encapsulates the functionality required for encoding
and validating inputs. Prio3 can be thought of as a transformation of a
particular class of FLPs into a VDAF.</t>
      <t>The remainder of this section is structured as follows. The syntax for FLPs is
described in <xref target="flp"/>. The generic transformation of an FLP into Prio3 is
specified in <xref target="prio3-construction"/>. Next, a concrete FLP suitable for any
validity circuit is specified in <xref target="flp-generic"/>. Finally, instantiations of
Prio3 for various types of measurements are specified in
<xref target="prio3-instantiations"/>. Test vectors can be found in <xref target="test-vectors"/>.</t>
      <section anchor="flp">
        <name>Fully Linear Proof (FLP) Systems</name>
        <t>Conceptually, an FLP is a two-party protocol executed by a prover and a
verifier. In actual use, however, the prover's computation is carried out by the
Client, and the verifier's computation is distributed among the Aggregators. The
Client generates a "proof" of its input's validity and distributes shares of the
proof to the Aggregators. Each Aggregator then performs some a computation on
its input share and proof share locally and sends the result to the other
Aggregators. Combining the exchanged messages allows each Aggregator to decide
if it holds a share of a valid input. (See <xref target="prio3-construction"/> for details.)</t>
        <t>As usual, we will describe the interface implemented by a concrete FLP in terms
of an abstract base class <tt>Flp</tt> that specifies the set of methods and parameters
a concrete FLP must provide.</t>
        <t>The parameters provided by a concrete FLP are listed in <xref target="flp-param"/>.</t>
        <table anchor="flp-param">
          <name>Constants and types defined by a concrete FLP.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>PROVE_RAND_LEN</tt></td>
              <td align="left">Length of the prover randomness, the number of random field elements consumed by the prover when generating a proof</td>
            </tr>
            <tr>
              <td align="left">
                <tt>QUERY_RAND_LEN</tt></td>
              <td align="left">Length of the query randomness, the number of random field elements consumed by the verifier</td>
            </tr>
            <tr>
              <td align="left">
                <tt>JOINT_RAND_LEN</tt></td>
              <td align="left">Length of the joint randomness, the number of random field elements consumed by both the prover and verifier</td>
            </tr>
            <tr>
              <td align="left">
                <tt>INPUT_LEN</tt></td>
              <td align="left">Length of the encoded measurement (<xref target="flp-encode"/>)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>OUTPUT_LEN</tt></td>
              <td align="left">Length of the aggregatable output (<xref target="flp-encode"/>)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>PROOF_LEN</tt></td>
              <td align="left">Length of the proof</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VERIFIER_LEN</tt></td>
              <td align="left">Length of the verifier message generated by querying the input and proof</td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">Type of the measurement</td>
            </tr>
            <tr>
              <td align="left">
                <tt>Field</tt></td>
              <td align="left">As defined in (<xref target="field"/>)</td>
            </tr>
          </tbody>
        </table>
        <t>An FLP specifies the following algorithms for generating and verifying proofs of
validity (encoding is described below in <xref target="flp-encode"/>):</t>
        <ul spacing="normal">
          <li>
            <tt>Flp.prove(input: Vec[Field], prove_rand: Vec[Field], joint_rand: Vec[Field])
-&gt; Vec[Field]</tt> is the deterministic proof-generation algorithm run by the
prover. Its inputs are the encoded input, the "prover randomness"
<tt>prove_rand</tt>, and the "joint randomness" <tt>joint_rand</tt>. The proof randomness is
used only by the prover, but the joint randomness is shared by both the prover
and verifier.</li>
          <li>
            <tt>Flp.query(input: Vec[Field], proof: Vec[Field], query_rand: Vec[Field],
joint_rand: Vec[Field], 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. The
semantics of <tt>num_shares</tt> is discussed below.</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-instantiations"/>). After consuming this vector,
all that is needed is the integer it represents. Thus the FLP defines an
algorithm for truncating the input to the length of the aggregated output:</t>
          <ul spacing="normal">
            <li>
              <tt>Flp.truncate(input: Vec[Field]) -&gt; Vec[Field]</tt> maps an encoded input to an
aggregatable output. The length of the input <bcp14>MUST</bcp14> be <tt>INPUT_LEN</tt> and the length
of the output <bcp14>MUST</bcp14> be <tt>OUTPUT_LEN</tt>.</li>
          </ul>
          <t>We remark that, taken together, these two functionalities correspond roughly to
the notion of "Affine-aggregatable encodings (AFEs)" from <xref target="CGB17"/>.</t>
        </section>
      </section>
      <section anchor="prio3-construction">
        <name>Construction</name>
        <t>This section specifies <tt>Prio3</tt>, an implementation of the <tt>Vdaf</tt> interface
(<xref target="vdaf"/>). It has two generic parameters: an <tt>Flp</tt> (<xref target="flp"/>) and a <tt>Prg</tt>
(<xref target="prg"/>). The associated constants and types required by the <tt>Vdaf</tt> interface
are defined in <xref target="prio3-param"/>. The methods required for sharding, preparation,
aggregation, and unsharding are described in the remaining subsections.</t>
        <table anchor="prio3-param">
          <name>Associated parameters for the Prio3 VDAF.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>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>Vec[Unsigned]</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 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 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, 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):
    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 list(map(lambda x: x.as_unsigned(), agg))
]]></artwork>
          </figure>
        </section>
        <section anchor="prio3-helper-functions">
          <name>Auxiliary Functions</name>
          <figure anchor="prio3-helpers">
            <name>Helper functions required for Prio3.</name>
            <artwork><![CDATA[
def encode_leader_share(Prio3,
                        input_share,
                        proof_share,
                        k_blind,
                        k_hint):
    encoded = Bytes()
    encoded += Prio3.Flp.Field.encode_vec(input_share)
    encoded += Prio3.Flp.Field.encode_vec(proof_share)
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        encoded += k_blind
        encoded += k_hint
    return encoded

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

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

def decode_helper_share(Prio3, dst, 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>Field</tt></td>
                <td align="left">An FFT-friendly finite field as defined in <xref target="field-fft-friendly"/></td>
              </tr>
            </tbody>
          </table>
          <t>Each gadget <tt>G</tt> in <tt>GADGETS</tt> defines a constant <tt>DEGREE</tt> that specifies the
circuit's "arithmetic degree". This is defined to be the degree of the
polynomial that computes it. For example, the <tt>Mul</tt> circuit in
<xref target="flp-generic-overview"/> is defined by the polynomial <tt>Mul(x) = x * x</tt>, which
has degree <tt>2</tt>. Hence, the arithmetic degree of this gadget is <tt>2</tt>.</t>
          <t>Each gadget also defines a parameter <tt>ARITY</tt> that specifies the circuit's arity
(i.e., the number of input wires).</t>
          <t>A concrete <tt>Valid</tt> provides the following methods for encoding a measurement as
an input vector and truncating an input vector to the length of an aggregatable
output:</t>
          <ul spacing="normal">
            <li>
              <tt>Valid.encode(measurement: Measurement) -&gt; Vec[Field]</tt> returns a vector of
length <tt>INPUT_LEN</tt> representing a measurement.</li>
            <li>
              <tt>Valid.truncate(input: Vec[Field]) -&gt; Vec[Field]</tt> returns a vector of length
<tt>OUTPUT_LEN</tt> representing an aggregatable output.</li>
          </ul>
          <t>Finally, the following class methods are derived for each concrete <tt>Valid</tt>:</t>
          <figure>
            <name>Derived methods for validity circuits.</name>
            <artwork><![CDATA[
# Length of the prover randomness.
def prove_rand_len(Valid):
    return sum(map(lambda g: g.ARITY, Valid.GADGETS))

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

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

# Length of the verifier message.
def verifier_len(Valid):
    length = 1
    for g in Valid.GADGETS:
        length += g.ARITY + 1
    return length
]]></artwork>
          </figure>
        </section>
        <section anchor="flp-generic-construction">
          <name>Construction</name>
          <t>This section specifies <tt>FlpGeneric</tt>, an implementation of the <tt>Flp</tt> interface
(<xref target="flp"/>). It has as a generic parameter a validity circuit <tt>Valid</tt> implementing
the interface defined in <xref target="flp-generic-valid"/>.</t>
          <ul empty="true">
            <li>
              <t>NOTE A reference implementation can be found in
https://github.com/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>
          <t><br/></t>
          <table anchor="flp-generic-param">
            <name>FLP Parameters of FlpGeneric.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>PROVE_RAND_LEN</tt></td>
                <td align="left">
                  <tt>Valid.prove_rand_len()</tt> (see <xref target="flp-generic-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>QUERY_RAND_LEN</tt></td>
                <td align="left">
                  <tt>Valid.query_rand_len()</tt> (see <xref target="flp-generic-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>Valid.JOINT_RAND_LEN</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>INPUT_LEN</tt></td>
                <td align="left">
                  <tt>Valid.INPUT_LEN</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>Valid.OUTPUT_LEN</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOF_LEN</tt></td>
                <td align="left">
                  <tt>Valid.proof_len()</tt> (see <xref target="flp-generic-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>VERIFIER_LEN</tt></td>
                <td align="left">
                  <tt>Valid.verifier_len()</tt> (see <xref target="flp-generic-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>Valid.Measurement</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Valid.Field</tt></td>
              </tr>
            </tbody>
          </table>
          <section anchor="flp-generic-construction-prove">
            <name>Proof Generation</name>
            <t>On input <tt>inp</tt>, <tt>prove_rand</tt>, and <tt>joint_rand</tt>, the proof is computed as
follows:</t>
            <ol spacing="normal" type="1"><li>For each <tt>i</tt> in <tt>[H]</tt> create an empty table <tt>wire_i</tt>.</li>
              <li>Partition the prover randomness <tt>prove_rand</tt> into subvectors <tt>seed_1, ...,
seed_H</tt> where <tt>len(seed_i) == L_i</tt> for all <tt>i</tt> in <tt>[H]</tt>. Let us call these
the "wire seeds" of each gadget.</li>
              <li>Evaluate <tt>Valid</tt> on input of <tt>inp</tt> and <tt>joint_rand</tt>, recording the inputs of
each gadget in the corresponding table. Specifically, for every <tt>i</tt> in <tt>[H]</tt>,
set <tt>wire_i[j-1,k-1]</tt> to the value on the <tt>j</tt>th wire into the <tt>k</tt>th call to
gadget <tt>G_i</tt>.</li>
              <li>
                <t>Compute the "wire polynomials". That is, for every <tt>i</tt> in <tt>[H]</tt> and <tt>j</tt> in
<tt>[L_i]</tt>, construct <tt>poly_wire_i[j-1]</tt>, the <tt>j</tt>th wire polynomial for the
<tt>i</tt>th gadget, as follows:  </t>
                <ul spacing="normal">
                  <li>Let <tt>w = [seed_i[j-1], wire_i[j-1,0], ..., wire_i[j-1,M_i-1]]</tt>.</li>
                  <li>Let <tt>padded_w = w + Field.zeros(P_i - len(w))</tt>.</li>
                </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> and
<tt>Valid.truncate</tt> in the natural way.</t>
          </section>
        </section>
      </section>
      <section anchor="prio3-instantiations">
        <name>Instantiations</name>
        <t>This section specifies instantiations of Prio3 for various measurement types.
Each uses <tt>FlpGeneric</tt> as the FLP (<xref target="flp-generic"/>) and is determined by a
validity circuit (<xref target="flp-generic-valid"/>) and a PRG (<xref target="prg"/>). Test vectors for
each can be found in <xref target="test-vectors"/>.</t>
        <ul empty="true">
          <li>
            <t>NOTE Reference implementations of each of these VDAFs can be found in
https://github.com/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 as a singleton vector in the natural way. The
parameters for this circuit are summarized below.</t>
          <t><br/></t>
          <table>
            <name>Parameters of validity circuit Count.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">
                  <tt>[Mul]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[1]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>INPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>0</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>Unsigned</tt>, in range <tt>[0,2)</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field64</tt> (<xref target="field64"/>)</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section anchor="prio3-sum">
          <name>Prio3Aes128Sum</name>
          <t>The next instance of Prio3 supports summing of integers in a pre-determined
range. Each measurement is an integer in range <tt>[0, 2^bits)</tt>, where <tt>bits</tt> is an
associated parameter.</t>
          <t>This instance of Prio3 uses <tt>PrgAes128</tt> (<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]
]]></artwork>
          <t>The validity circuit checks that the input comprised of ones and zeros. Its
gadget, denoted <tt>Range2</tt>, is the degree-2, arity-1 gadget defined as</t>
          <artwork><![CDATA[
def Range2(x):
    return x^2 - x
]]></artwork>
          <t>The validity circuit is defined as</t>
          <artwork><![CDATA[
def Sum(inp: Vec[Field128], joint_rand: Vec[Field128]):
    out = Field128(0)
    r = joint_rand[0]
    for x in inp:
        out += r * Range2(x)
        r *= joint_rand[0]
    return out
]]></artwork>
          <t><br/></t>
          <table>
            <name>Parameters of validity circuit Sum.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">
                  <tt>[Range2]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[bits]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>INPUT_LEN</tt></td>
                <td align="left">
                  <tt>bits</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>Unsigned</tt>, in range <tt>[0, 2^bits)</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="field128"/>)</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section anchor="prio3aes128histogram">
          <name>Prio3Aes128Histogram</name>
          <t>This instance of Prio3 allows for estimating the distribution of the
measurements by computing a simple histogram. Each measurement is an arbitrary
integer and the aggregate result counts the number of measurements that fall in
a set of fixed buckets.</t>
          <t>This instance of Prio3 uses <tt>PrgAes128</tt> (<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
]]></artwork>
          <t>The validity circuit uses <tt>Range2</tt> (see <xref target="prio3-sum"/>) as its single gadget. It
checks for one-hotness in two steps, as follows:</t>
          <artwork><![CDATA[
def Histogram(inp: Vec[Field128],
              joint_rand: Vec[Field128],
              num_shares: Unsigned):
    # Check that each bucket is one or zero.
    range_check = Field128(0)
    r = joint_rand[0]
    for x in inp:
        range_check += r * Range2(x)
        r *= joint_rand[0]

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

    out = joint_rand[1]   * range_check + \
          joint_rand[1]^2 * sum_check
    return out
]]></artwork>
          <t>Note that this circuit depends on the number of shares into which the input is
sharded. This is provided to the FLP by Prio3.</t>
          <t><br/></t>
          <table>
            <name>Parameters of validity circuit Histogram.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">
                  <tt>[Range2]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[buckets + 1]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>INPUT_LEN</tt></td>
                <td align="left">
                  <tt>buckets + 1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>buckets + 1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>2</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>Integer</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="field128"/>)</td>
              </tr>
            </tbody>
          </table>
        </section>
      </section>
    </section>
    <section anchor="poplar1">
      <name>Poplar1</name>
      <ul empty="true">
        <li>
          <t>TODO Update this section in light of removing the public parameter and
replacing the verification parameter.</t>
        </li>
      </ul>
      <ul empty="true">
        <li>
          <t>NOTE The spec for Poplar1 is still a work-in-progress. A partial
implementation can be found at
https://github.com/divviup/libprio-rs/blob/main/src/vdaf/poplar1.rs. The
verification logic is nearly complete, however as of this draft the code is
missing the IDPF. An implementation of the IDPF can be found at
https://github.com/google/distributed_point_functions/.</t>
        </li>
      </ul>
      <t>This section specifies Poplar1, a VDAF for the following task. Each Client holds
a <tt>BITS</tt>-bit string and the Aggregators hold a set of <tt>l</tt>-bit strings, where <tt>l
&lt;= BITS</tt>. We will refer to the latter as the set of "candidate prefixes". The
Aggregators' goal is to count how many inputs are prefixed by each candidate
prefix.</t>
      <t>This functionality is the core component of Poplar <xref target="BBCGGI21"/>. At a high level,
the protocol works as follows.</t>
      <ol spacing="normal" type="1"><li>Each Clients runs the input-distribution algorithm on its <tt>n</tt>-bit string and
sends an input share to each Aggregator.</li>
        <li>The Aggregators agree on an initial set of candidate prefixes, say <tt>0</tt> and
<tt>1</tt>.</li>
        <li>The Aggregators evaluate the VDAF on each set of input shares and aggregate
the recovered output shares. The aggregation parameter is the set of
candidate prefixes.</li>
        <li>The Aggregators send their aggregate shares to the Collector, who combines
them to recover the counts of each candidate prefix.</li>
        <li>Let <tt>H</tt> denote the set of prefixes that occurred at least <tt>t</tt> times. If the
prefixes all have length <tt>BITS</tt>, then <tt>H</tt> is the set of <tt>t</tt>-heavy-hitters.
Otherwise compute the next set of candidate prefixes as follows. For each <tt>p</tt>
in <tt>H</tt>, add add <tt>p || 0</tt> and <tt>p || 1</tt> to the set. Repeat step 3 with the new
set of candidate prefixes.</li>
      </ol>
      <t>Poplar1 is constructed from an "Incremental Distributed Point Function (IDPF)", a
primitive described by <xref target="BBCGGI21"/> that generalizes the notion of a Distributed
Point Function (DPF) <xref target="GI14"/>. Briefly, a DPF is used to distribute the
computation of a "point function", a function that evaluates to zero on every
input except at a programmable "point". The computation is distributed in such a
way that no one party knows either the point or what it evaluates to.</t>
      <t>An IDPF generalizes this "point" to a path on a full binary tree from the root
to one of the leaves. It is evaluated on an "index" representing a unique node
of the tree. If the node is on the path, then function evaluates to to a
non-zero value; otherwise it evaluates to zero. This structure allows an IDPF to
provide the functionality required for the above protocol, while at the same
time ensuring the same degree of privacy as a DPF.</t>
      <t>Our VDAF composes an IDPF with the "secure sketching" protocol of <xref target="BBCGGI21"/>.
This protocol ensures that evaluating a set of input shares on a unique set of
candidate prefixes results in shares of a "one-hot" vector, i.e., a vector that
is zero everywhere except for one element, which is equal to one.</t>
      <section anchor="incremental-distributed-point-functions-idpfs">
        <name>Incremental Distributed Point Functions (IDPFs)</name>
        <t>An IDPF is defined over a domain of size <tt>2^BITS</tt>, where <tt>BITS</tt> is constant
defined by the IDPF. The Client specifies an index <tt>alpha</tt> and a pair of values
<tt>beta</tt>, one for each "level" <tt>1 &lt;= l &lt;= BITS</tt>. The key generation generates two
IDPF keys, one for each Aggregator. When evaluated at index <tt>0 &lt;= x &lt; 2^l</tt>, each
IDPF share returns an additive share of <tt>beta[l]</tt> if <tt>x</tt> is the <tt>l</tt>-bit prefix
of <tt>alpha</tt> and shares of zero otherwise.</t>
        <ul empty="true">
          <li>
            <t>CP What does it mean for <tt>x</tt> to be the <tt>l</tt>-bit prefix of <tt>alpha</tt>? We need to
be a bit more precise here.</t>
          </li>
        </ul>
        <ul empty="true">
          <li>
            <t>CP Why isn't the domain size actually <tt>2^(BITS+1)</tt>, i.e., the number of nodes
in a binary tree of height <tt>BITS</tt> (excluding the root)?</t>
          </li>
        </ul>
        <t>Each <tt>beta[l]</tt> is a pair of elements of a finite field. Each level <bcp14>MAY</bcp14> have
different field parameters. Thus a concrete IDPF specifies associated types
<tt>Field[1]</tt>, <tt>Field[2]</tt>, ..., and <tt>Field[BITS]</tt> defining, respectively, the field
parameters at level 1, level 2, ..., and level <tt>BITS</tt>.</t>
        <t>An IDPF is comprised of the following algorithms (let type <tt>Value[l]</tt> denote
<tt>(Field[l], Field[l])</tt> for each level <tt>l</tt>):</t>
        <ul spacing="normal">
          <li>
            <tt>idpf_gen(alpha: Unsigned, beta: (Value[1], ..., Value[BITS])) -&gt; key:
(IDPFKey, IDPFKey)</tt> is the randomized key-generation algorithm run by the
client. Its inputs are the index <tt>alpha</tt> and the values <tt>beta</tt>. The value of
<tt>alpha</tt> <bcp14>MUST</bcp14> be in range <tt>[0, 2^BITS)</tt>.</li>
          <li>
            <tt>IDPFKey.eval(l: Unsigned, x: Unsigned) -&gt; value: Value[l])</tt> is deterministic,
stateless key-evaluation algorithm run by each Aggregator. It returns the
value corresponding to index <tt>x</tt>. The value of <tt>l</tt> <bcp14>MUST</bcp14> be in <tt>[1, BITS]</tt> and
the value of <tt>x</tt> <bcp14>MUST</bcp14> be in range <tt>[2^(l-1), 2^l)</tt>.</li>
        </ul>
        <t>A concrete IDPF specifies a single associated constant:</t>
        <ul spacing="normal">
          <li>
            <tt>BITS: Unsigned</tt> is the length of each Client input.</li>
        </ul>
        <t>A concrete IDPF also specifies the following associated types:</t>
        <ul spacing="normal">
          <li>
            <tt>Field[l]</tt> for each level <tt>1 &lt;= l &lt;= BITS</tt>. Each defines the same methods and
associated constants as <tt>Field</tt> in <xref target="prio3"/>.</li>
        </ul>
        <t>Note that IDPF construction of <xref target="BBCGGI21"/> uses one field for the inner nodes of
the tree and a different, larger field for the leaf nodes. See <xref target="BBCGGI21"/>,
Section 4.3.</t>
        <t>Finally, an implementation note. The interface for IDPFs specified here is
stateless, in the sense that there is no state carried between IDPF evaluations.
This is to align the IDPF syntax with the VDAF abstraction boundary, which does
not include shared state across across VDAF evaluations. In practice, of course,
it will often be beneficial to expose a stateful API for IDPFs and carry the
state across evaluations.</t>
      </section>
      <section anchor="poplar1-construction">
        <name>Construction</name>
        <t>The VDAF involves two rounds of communication (<tt>ROUNDS == 2</tt>) and is defined for
two Aggregators (<tt>SHARES == 2</tt>).</t>
        <section anchor="setup">
          <name>Setup</name>
          <t>The verification parameter is a symmetric key shared by both Aggregators. This
VDAF has no public parameter.</t>
          <figure anchor="poplar1-eval-setup">
            <name>The setup algorithm for poplar1.</name>
            <artwork><![CDATA[
def vdaf_setup():
  k_verify_init = gen_rand(SEED_SIZE)
  return (None, [(0, k_verify_init), (1, k_verify_init)])
]]></artwork>
          </figure>
          <section anchor="client">
            <name>Client</name>
            <t>The client's input is an IDPF index, denoted <tt>alpha</tt>. The values are pairs of
field elements <tt>(1, k)</tt> where each <tt>k</tt> is chosen at random. This random value is
used as part of the secure sketching protocol of <xref target="BBCGGI21"/>. After evaluating
their IDPF key shares on the set of candidate prefixes, the sketching protocol
is used by the Aggregators to verify that they hold shares of a one-hot vector.
In addition, for each level of the tree, the prover generates random elements
<tt>a</tt>, <tt>b</tt>, and <tt>c</tt> and computes</t>
            <artwork><![CDATA[
    A = -2*a + k
    B = a*a + b - k*a + c
]]></artwork>
            <t>and sends additive shares of <tt>a</tt>, <tt>b</tt>, <tt>c</tt>, <tt>A</tt> and <tt>B</tt> to the Aggregators.
Putting everything together, the input-distribution algorithm is defined as
follows. Function <tt>encode_input_share</tt> is defined in <xref target="poplar1-helper-functions"/>.</t>
            <figure anchor="poplar1-mes2inp">
              <name>The input-distribution algorithm for poplar1.</name>
              <artwork><![CDATA[
def measurement_to_input_shares(_, alpha):
  if alpha < 2**BITS: raise ERR_INVALID_INPUT

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

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

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

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

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

  return input_shares
]]></artwork>
            </figure>
            <ul empty="true">
              <li>
                <t>TODO It would be more efficient to represent the shares of <tt>a</tt>, <tt>b</tt>, and <tt>c</tt>
using PRG seeds as suggested in <xref target="BBCGGI21"/>.</t>
              </li>
            </ul>
          </section>
        </section>
        <section anchor="preparation-1">
          <name>Preparation</name>
          <t>The aggregation parameter encodes a sequence of candidate prefixes. When an
Aggregator receives an input share from the Client, it begins by evaluating its
IDPF share on each candidate prefix, recovering a pair of vectors of field
elements <tt>data_share</tt> and <tt>auth_share</tt>, The Aggregators use <tt>auth_share</tt> and the
correlation shares provided by the Client to verify that their <tt>data_share</tt>
vectors are additive shares of a one-hot vector.</t>
          <ul empty="true">
            <li>
              <t>CP Consider adding aggregation parameter as input to <tt>k_verify_rand</tt>
derivation.</t>
            </li>
          </ul>
          <figure anchor="poplar1-prep-state">
            <name>Preparation state for poplar1.</name>
            <artwork><![CDATA[
class PrepState:
  def __init__(verify_param, agg_param, nonce, input_share):
    (self.l, self.candidate_prefixes) = decode_indexes(agg_param)
    (self.idpf_key,
     self.correlation_shares) = decode_input_share(input_share)
    (self.party_id, k_verify_init) = verify_param
    self.k_verify_rand = get_key(k_verify_init, nonce)
    self.step = 'ready'

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

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

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

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

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

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

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

    else: raise ERR_INVALID_STATE

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

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

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

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

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

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

  return Field[l].encode_vec(agg)
]]></artwork>
          </figure>
        </section>
        <section anchor="poplar1-helper-functions">
          <name>Helper Functions</name>
          <ul empty="true">
            <li>
              <t>TODO Specify the following functionalities:</t>
            </li>
          </ul>
          <ul spacing="normal">
            <li>
              <tt>encode_input_share</tt> is used to encode an input share, consisting of an IDPF
key share and correlation shares.</li>
            <li>
              <tt>decode_input_share</tt> is used to decode an input share.</li>
            <li>
              <tt>decode_indexes(encoded: Bytes) -&gt; (l: Unsigned, indexes: Vec[Unsigned])</tt>
decodes a sequence of indexes, i.e., candidate indexes for IDPF evaluation.
The value of <tt>l</tt> <bcp14>MUST</bcp14> be in range <tt>[1, BITS]</tt> and <tt>indexes[i]</tt> <bcp14>MUST</bcp14> be in range
<tt>[2^(l-1), 2^l)</tt> for all <tt>i</tt>. An error is raised if <tt>encoded</tt> cannot be
decoded.</li>
          </ul>
        </section>
      </section>
    </section>
    <section anchor="security">
      <name>Security Considerations</name>
      <ul empty="true">
        <li>
          <t>NOTE: This is a brief outline of the security considerations.  This section
will be filled out more as the draft matures and security analyses are
completed.</t>
        </li>
      </ul>
      <t>VDAFs have two essential security goals:</t>
      <ol spacing="normal" type="1"><li>Privacy: An attacker that controls the network, the Collector, and a subset
of Clients and Aggregators learns nothing about the measurements of honest
Clients beyond what it can deduce from the aggregate result.</li>
        <li>Robustness: An attacker that controls the network and a subset of Clients
cannot cause the Collector to compute anything other than the aggregate of
the measurements of honest Clients.</li>
      </ol>
      <t>Note that, to achieve robustness, it is important to ensure that the
verification key distributed to the Aggregators (<tt>verify_key</tt>, see <xref target="setup"/>) is
never revealed to the Clients.</t>
      <t>It is also possible to consider a stronger form of robustness, where the
attacker also controls a subset of Aggregators (see <xref target="BBCGGI19"/>, Section 6.3).
To satisfy this stronger notion of robustness, it is necessary to prevent the
attacker from sharing the verification 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="4" month="May" 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-00"/>
        </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"
  input_share_0: >-
    ae5483343eb35a52fcb36a62271a7ddb47f09d0ea2c6613807f84ac2e16814c82bca
    bdc9db5080fdf4f4f778734644fc
  input_share_1: >-
    0101010101010101010101010101010101010101010101010101010101010101
  round_0:
    prep_share_0: >-
      22ce013d3aaa7e7574ed01fe1d074cd845dfbbbc5901cabd487d4e2e228274cc
    prep_share_1: >-
      dd31fec1c555818c51ab7ccac14ca5b00aae1c33d835c76dfa9406011a92a8e9
    prep_message: >-
  out_share_0:
    - 12561809521056635474
  out_share_1:
    - 5884934548357948848
agg_share_0: >-
  ae5483343eb35a52
agg_share_1: >-
  51ab7ccac14ca5b0
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"
  input_share_0: >-
    ae5483353eb35a3371beec8f796e9afd086cb72d05a83a3dbefbe273acb0410787b1
    afba2065df5389011fd8963091e3004fa07fc91018af378da47c89abf1bd85047e40
    874e2cdc5f3bc48f363b89f746770a402a777bed31b5a10c7319b3908d72de0c6512
    15ba78d3cf681e07c564c0b4a9a4508df645bad8fef61e3ddf37fcb36a63271a7dbe
    47f09d0ea2c661396ad006d8915d149ad88f9b1cdb86e1d13d683c359b7ac899a245
    4316051e4e235dfd566f3459c336826555ed7f1baabf241e9a697d458912f3bd3778
    225e832b78cd4f17e57c9b9678cf6043894aff0d0f2e06828982ac3493ae5ded0c98
    86ea13d52bc0f209dc2f4e676c42b95b548a413f67b03ff18e9e6b699338400e9dff
    a800563abb495364acffc17126bf0bf8ff3c5caba82333e91352e03c637d44dc4db1
    59a1b19d8db4d5a3fce356f6f2fca4adc9bcf65bec8d4d962b2b40f7ea413aead099
    79d4958707bf4098bb28829b79e381aaad8f69b7f2e6c159bbcb342ef7df2d9c56a9
    06b171ab61b025b7c19aad8de495a8a97af2baab6d1240d30df417d1cc0fe7a90ada
    ad8115924c0987fe1d16abe0c8a3c297d58a3112b818df72a10a41b34aa6b4ae370b
    1340a6085c8dcd597eead5d2584fdb160f0a086a56ea6a7736666ae34d3012fdb2c2
    4af3d4b2a6ae735edfe837eaab1309eaa2d8273e7dbfe0fd4166d545ce8354e1237b
    48456715d12e38d02cd64c96b9daa01a2281d8a930817088c648b7c115e1550ada14
    b6072ada49be3c7e3f184db2461160d29937caa97db6020a5598063f1dc05653d1d3
    80b34e923bd7170eeeb811bfc3ce12c1df55cf552e986a823743fac4723a48bda6c1
    8ffec653c1f182890197e9fc74631dcbd0283c4258933c03aee9404f010101010101
    01010101010101010101fb0c701f7c07b9407a4a7b77d1ea017e
  input_share_1: >-
    01010101010101010101010101010101010101010101010101010101010101010101
    01010101010101010101010101012d7667bffd0f81b078896503385f6f13
  round_0:
    prep_share_0: >-
      9f7aca77f790b930b46e8cd786ff1a239aa00e7aaaa734cc2bbcb121eb7c5bc00a
      ef22fd95a24cd1a0054bde0dba06062d7667bffd0f81b078896503385f6f13
    prep_share_1: >-
      60853588086f46b34b9173287900e5de2becb1bdb8a8009d2cdc258674f08e8157
      e3a202a38282c20e220e733ab61e4cfb0c701f7c07b9407a4a7b77d1ea017e
    prep_message: >-
      d67a17a0810838f002c31e74e9b56e6d
  out_share_0:
    - 242787699414660215404830418280405596120
  out_share_1:
    - 97494667506278247542035355087495170189
agg_share_0: >-
  b6a735c5636efee29c0c1455e0c0f7d8
agg_share_1: >-
  4958ca3a9c91010163f3ebaa1f3f088d
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"
  input_share_0: >-
    ae5483353eb35a3371beec8f796e9afd086cb72d05a83a3dbefbe273acb0410787b1
    afba2065df5389011fd8963091e3004fa07fc91018af378da47c89abf1bdfcb36a63
    271a7dbe47f09d0ea2c6613956dfe44e1302160dd2ade0205aa0409225caf0f966df
    97691568169000ef0af27c0985636e34889bc3fef4df192d7ead56e0dd51187bdc66
    62505cbd2962843cf2a1929642367f32058c531a6c611d76441e4ba82d136ba4aab1
    6f2a612df63678d42d527e59d8a0b4cb2f07ed8aaf04199819a25fad1b8cad62fb2e
    c5a9bd78b2e013a50250c8bd44a15ad7d5edac35a58bed81a4088c72430afbd6fe34
    635a737cb7c4d29ffc9947b6b0fb8f3fdede9d8bd495b4d47e8400bded8aa53e4a5a
    2d063c6091c29613e044082b0555ce74c45b823aa8c5804aacdd3dc92a6ac0058755
    7770972dcdc37eefb42eef43a1b401010101010101010101010101010101d5bf864d
    e68bac19204e29697bf9504d
  input_share_1: >-
    01010101010101010101010101010101010101010101010101010101010101010101
    01010101010101010101010101018e2e553b5e45c62e0ced57ec947c8627
  round_0:
    prep_share_0: >-
      93b9dd4a3b46d8941fe7524a5cf1cd47ff8ee9c0c2e9b8230b1b940b665263b7b1
      c4b370652a333ee774ec9cd379b6e78e2e553b5e45c62e0ced57ec947c8627
    prep_share_1: >-
      6c4622b5c4b9274fe018adb5a30e32baa310ddd3e5ed87892dca520d1bed7d0299
      8e38190652ba60a225e19211d77e22d5bf864de68bac19204e29697bf9504d
    prep_message: >-
      5b91d376b8ce6a372ca37e85ef85d66a
  out_share_0:
    - 231724485416847873323492487111470127869
    - 11198307274976669387765744195748249863
    - 180368380143069850478496598824148046307
    - 413446761563421317675646300023681469
  out_share_1:
    - 108557881504090589623373286256430638340
    - 329084059645961793559100029172152516346
    - 159913986777868612468369174543752719903
    - 339868920159375041629190127067877084740
agg_share_0: >-
  ae5483353eb35a3371beec8f796e9afd086cb72d05a83a3dbefbe273acb0410787b1af
  ba2065df5389011fd8963091e3004fa07fc91018af378da47c89abf1bd
agg_share_1: >-
  51ab7ccac14ca5b08e41137086916504f79348d2fa57c5a641041d8c534fbefa784e50
  45df9a209076fee02769cf6e1fffb05f8036efe734c8725b8376540e44
agg_result: [0, 0, 1, 0]
]]></artwork>
      </section>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA+y963bbZpYg+h9PgaLXtMkySUuKYyeqsrsVWXbU5VhqyUlN
jccRQRKUEJEAGwAlqxz3g8yv8yznvNjZ1+8GkJKc1HTPWuO1qiKSwHfZ3/72
/TIYDKI6q+fpbtz5KS2zWZaM52n8MqvqMhuv6nQa752fl+l5UmdFHr9a5RP8
o+pEyXhcplf42su9V51oWkzyZAHDTMtkVg+ysp4NJrPyfHA1TWaDre1oktTp
eVHe7MZZPiuiKFuWu3Fdrqp6Z2vr262dKCnTZDc+PHn3Krouysvzslgtd+P9
Vyevo8v0Br6awq95nZZ5Wg9e4ixRVNVJPj1L5kUOM9+kVVQtkrI++/dVUafV
bpwX0TLbjd/XxaQfV0VZl+msgr9uFvjHhyhKVvVFUe5G8SCK4R/v4CSbXCTl
NH4zjL9LYLaKfivK8yTP/k5wgGVl1aSg79NFks1343I+/pdseTWsPvqD7V+U
AMtieZGW8XFS10XeNtq8WE1nc4CAO+QEX13SO4+ytJ79yzl+P5wUC3+K44ts
Ps+Wy/h0clEsl4skb5vjdVGcz73xK/P4v5zTjzR0lBflAt65SnfhkOCo7Kc4
3nv9r0fHO9u7NIzizXGZFY9gGWV2lUxu4L9plZZXWX5uUCeNT2sYpKqzSRVf
ZUn8XVHM0ySPTwHQKSATDmfOgv4NAE3gBE+H8d50muSXmf/9X4bx66Qcp/63
B8P4X5PZLPj2ZBgfAToXV9Xljf/L3jA+LuY3AOgiz5JpsaKfp7Dg3Xhna2eb
t5mU52m9G1/U9bLaffw4S4aT8jH+/PjrZ08RKt99t//69eH2tz5Y/kdaFoO/
5MX1PJ2epwCWophVMVyi03RSAgrT3qfxy6ROCCavVvP5Tfwmy9MEUGX/eBNY
XgJqAs5fNLb/XXEzD7b//TDeL8oyA2QYvM7G48r/+S1AMpuPi8T/+m/D+LC6
SDIPItvf0kc43iytEDcAdU/+dvzuyP62Dlrb3z7e/uYbC60Qid5k5xf1dYr/
H79LJxd59u+rtIoB/RixAIe+T5Orm/j7rAYa8F8QOIIuLnAODw4O4tN/Or4T
Mm1tP0Pw7L/+bvtZ84LtKhj68UkxBqrZj4H0wZVP5kSx94vFclUzlS5mrTdv
A8huAYMHUYMMzxr7fXv68tD+Eu51Oh8mk8UQyNLjaZE93t4afg3/Hn+1/fWT
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
b1ADzn4x5x9IgppDV45OJPPDM7uDaSZxauEB/TfF4j3BKnOsW8bihSiVM8p2
1cW2idGbO66WLb1Kt+SmZ+YBLZ+hlPvTZCsuytcqM/Be+nZTqsT8Si6T/voF
fF4y1RTwluz11O28Q3nMWhcpHc08+PM62ik3Vvo4I6w5eq88DQSRdkte5Uoq
92ct+e/Om/BL/5wXKF6wfWl44qWZjm0vP1QaplnmgIZp+ed+2oequBQqJ299
yz+thM1Wek2Jcqvn9oiVV60sePofljw9tclbqNUUty/vPbEaYrEaZ3NrlEb+
s+3y9ybo8rL9ij/9lfiBgkMXmqt59vMq9h/o6vOqEU4uzkm6ixXdJ7IUlEVk
WdPh/HmLIZ63GOJ5i3ET21dSGfhjV+fjczli02kyh3DKd/r2u6vvvtqUrLDh
fYWVkHb69awxkZOSp2DoRr+XCvZ1OjR0UeLAn/bUSM+9+pjtbPJSfICApULC
soDBB18omvEZHHG8P0RUucxbezX0cwakZfvxxO7QBMsSbK1+8H4C6kRwmnu2
9w3V26U8HNGeyPhfxyRlxRZNp3WjT08099HVnEberlTOTvZEk+fFpV4o1FQD
qZ1u6ndu/PPTfHDE7R9Y2Kmx45VFMwJf12VtFuzDG390FkJh3ykVRl3ZqZ+0
sjlAoV3W+fuTa/pR0ShLODfzTLmjCZ6m4tzUkUB95HH+w++eQfZjguPDyxIh
WGj+xTIu6uRdqlMr8Nu02dSEWcwb6kf7UJMPm3McPq4On9qAm5t69vTExleN
7spfr5zFUskqVcAtydwJaNKGdt0nLbuHa1csH2IeuwGLPvPXqz5Xb2a+Kfd4
Xm4Tj6Vjz+WhaHkwM2L9+IeU3zY3tfaiyws11GDGzeWL6UhkkW9q+8GTzXpW
uTjfpDRgqUVK8nT0NJ0Kr8422wScKZw7Vx1Lu+DpRJ7iQApBrmngdITkwzRT
yjJIxx/Dw10qlVJ81CnbzKF887caPP9yuunhtp7C/0iD3d7McWr1jamuWT2D
2rYx4Git1leKN6mmB119STsrJcY6B7C/o5wWJe52atmBWR8P+dwADdU4eJpL
TuKSYkrp5IfKAO9KoHB5maKxa6alHAn2kujm7u/d8DaX3MmVve/2tyU0MtzP
dayb6Np8kpmyTqckRSBAjZSmr9p9idvg6EQcxE971M7TbFfX/NLmwRu6ip1a
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
uIOgB/7OOOY/AZLCeyL2ywEA

-->

</rfc>
