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

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

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

    out_share_0_0   out_share_1_0       out_share_[SHARES-1]_0
    out_share_0_1   out_share_1_1       out_share_[SHARES-1]_1
    out_share_0_2   out_share_1_2       out_share_[SHARES-1]_2
         ...             ...                     ...
    out_share_0_B   out_share_1_B       out_share_[SHARES-1]_B
      |               |                   |
      V               V                   V
    +-----------+   +-----------+       +-----------+
    | out2agg   |   | out2agg   |   ... | out2agg   |
    +-----------+   +-----------+       +-----------+
      |               |                   |
      V               V                   V
    agg_share_0     agg_share_1         agg_share_[SHARES-1]
]]></artwork>
        </figure>
        <t>For simplicity, we have written this algorithm in a "one-shot" form, where all
output shares for a batch are provided at the same time. Many DAFs may also
support a "streaming" form, where shares are processed one at a time.</t>
        <t>Implementation note: For most natural DAFs (and VDAFs) it is not necessary for
an Aggregator to store all output shares individually before aggregating.
Typically it is possible to merge output shares into aggregate shares as they
arrive, merge these into other aggregate shares, and so on. In particular, this
is the case when the output shares are vectors over some finite field and
aggregating them involves merely adding up the vectors element-wise. Such is the
case for Prio3 <xref target="prio3"/> and Poplar1 <xref target="poplar1"/>.</t>
      </section>
      <section anchor="sec-daf-unshard">
        <name>Unsharding</name>
        <t>After the Aggregators have aggregated a sufficient number of output shares, each
sends its aggregate share to the Collector, who runs the following algorithm to
recover the following output:</t>
        <ul spacing="normal">
          <li>
            <tt>Daf.agg_shares_to_result(agg_param: AggParam,
agg_shares: Vec[Bytes], num_measurements: Unsigned) -&gt; AggResult</tt> is
run by the Collector in order to compute the aggregate result from
the Aggregators' shares. The length of <tt>agg_shares</tt> <bcp14>MUST</bcp14> be <tt>SHARES</tt>.
<tt>num_measurements</tt> is the number of measurements that contributed to
each of the aggregate shares. This algorithm is deterministic.</li>
        </ul>
        <figure anchor="unshard-flow">
          <name>Computation of the final aggregate result from aggregate shares.</name>
          <artwork><![CDATA[
    Aggregator 0    Aggregator 1        Aggregator SHARES-1
    ============    ============        ===================

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        # Function `cSHAKE128(x, l, n, s)` is as defined in
        # [SP800-185, Section 3.3].
        #
        # Implementation note: Rather than re-generate the output
        # stream each time `next()` is invoked, most implementations
        # of SHA-3 will expose an "absorb-then-squeeze" API that
        # allows stateful handling of the stream.
        stream = cSHAKE128(self.x, self.l, b'', self.s)
        return stream[-length:]
]]></artwork>
          </figure>
        </section>
        <section anchor="prg-fixed-key-aes128">
          <name>PrgFixedKeyAes128</name>
          <t>While PrgSha3 as described above can be securely used in all cases where a Prg
is needed in the VDAFs described in this document, there are some cases where
a more efficient instantiation based on fixed-key AES is possible. For now, this
is limited to the Prg used inside the Idpf <xref target="idpf"/> implementation in Poplar1
<xref target="idpf-poplar"/>. It is <bcp14>NOT RECOMMENDED</bcp14> to use this Prg anywhere else.
See Security Considerations <xref target="security"/> for a more detailed discussion.</t>
          <artwork><![CDATA[
class PrgFixedKeyAes128(Prg):
    # Associated parameters
    SEED_SIZE = 16

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

        # Use SHA-3 to derive a key from the binder and customization
        # strings. Note that the AES key does not need to be kept
        # secret from any party. However, when used with IdpfPoplar,
        # we require the binder to be a random nonce.
        #
        # Implementation note: This step can be cached across PRG
        # evaluations with many different seeds.
        self.fixed_key = cSHAKE128(binder, 16, b'', custom)
        self.seed = seed

    def next(self, length: Unsigned) -> Bytes:
        offset = self.length_consumed % 16
        new_length = self.length_consumed + length
        block_range = range(
            int(self.length_consumed / 16),
            int(new_length / 16) + 1)
        self.length_consumed = new_length

        hashed_blocks = [
            self.hash_block(xor(self.seed, to_le_bytes(i, 16))) \
                         for i in block_range
        ]
        return concat(hashed_blocks)[offset:offset+length]

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

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

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

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

    # Split the coins into the various seeds we'll need.
    if len(rand) != Prio3.RAND_SIZE:
        raise ERR_INPUT # unexpected length for random coins
    seeds = [rand[i:i+l] for i in range(0,Prio3.RAND_SIZE,l)]
    if use_joint_rand:
        k_helper_seeds, seeds = front((Prio3.SHARES-1) * 3, seeds)
        k_helper_meas_shares = [
            k_helper_seeds[i]
            for i in range(0, (Prio3.SHARES-1) * 3, 3)
        ]
        k_helper_proof_shares = [
            k_helper_seeds[i]
            for i in range(1, (Prio3.SHARES-1) * 3, 3)
        ]
        k_helper_blinds = [
            k_helper_seeds[i]
            for i in range(2, (Prio3.SHARES-1) * 3, 3)
        ]
        (k_leader_blind,), seeds = front(1, seeds)
    else:
        k_helper_seeds, seeds = front((Prio3.SHARES-1) * 2, seeds)
        k_helper_meas_shares = [
            k_helper_seeds[i]
            for i in range(0, (Prio3.SHARES-1) * 2, 2)
        ]
        k_helper_proof_shares = [
            k_helper_seeds[i]
            for i in range(1, (Prio3.SHARES-1) * 2, 2)
        ]
        k_helper_blinds = [None] * (Prio3.SHARES-1)
        k_leader_blind = None
    (k_prove,), seeds = front(1, seeds)

    # Finish measurement shares and joint randomness parts.
    inp = Prio3.Flp.encode(measurement)
    leader_meas_share = inp
    k_joint_rand_parts = []
    for j in range(Prio3.SHARES-1):
        helper_meas_share = Prio3.Prg.expand_into_vec(
            Prio3.Flp.Field,
            k_helper_meas_shares[j],
            Prio3.custom(DST_MEASUREMENT_SHARE),
            byte(j+1),
            Prio3.Flp.INPUT_LEN
        )
        leader_meas_share = vec_sub(leader_meas_share,
                                    helper_meas_share)
        if use_joint_rand:
            encoded = Prio3.Flp.Field.encode_vec(helper_meas_share)
            k_joint_rand_part = Prio3.Prg.derive_seed(
                k_helper_blinds[j],
                Prio3.custom(DST_JOINT_RAND_PART),
                byte(j+1) + nonce + encoded,
            )
            k_joint_rand_parts.append(k_joint_rand_part)

    # Finish joint randomness.
    if use_joint_rand:
        encoded = Prio3.Flp.Field.encode_vec(leader_meas_share)
        k_joint_rand_part = Prio3.Prg.derive_seed(
            k_leader_blind,
            Prio3.custom(DST_JOINT_RAND_PART),
            byte(0) + nonce + encoded,
        )
        k_joint_rand_parts.insert(0, k_joint_rand_part)
        joint_rand = Prio3.Prg.expand_into_vec(
            Prio3.Flp.Field,
            Prio3.joint_rand(k_joint_rand_parts),
            Prio3.custom(DST_JOINT_RANDOMNESS),
            b'',
            Prio3.Flp.JOINT_RAND_LEN,
        )
    else:
        joint_rand = []

    # Finish the proof shares.
    prove_rand = Prio3.Prg.expand_into_vec(
        Prio3.Flp.Field,
        k_prove,
        Prio3.custom(DST_PROVE_RANDOMNESS),
        b'',
        Prio3.Flp.PROVE_RAND_LEN,
    )
    proof = Prio3.Flp.prove(inp, prove_rand, joint_rand)
    leader_proof_share = proof
    for j in range(Prio3.SHARES-1):
        helper_proof_share = Prio3.Prg.expand_into_vec(
            Prio3.Flp.Field,
            k_helper_proof_shares[j],
            Prio3.custom(DST_PROOF_SHARE),
            byte(j+1),
            Prio3.Flp.PROOF_LEN,
        )
        leader_proof_share = vec_sub(leader_proof_share,
                                     helper_proof_share)

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

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

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

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

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

    if inbound is None:
        return (prep, prep_msg)

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

    return out_share

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

        verifier = vec_add(verifier, verifier_share)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    # Split the coins into coins for IDPF key generation,
    # correlated randomness, and sharding.
    if len(rand) != Poplar1.RAND_SIZE:
        raise ERR_INPUT # unexpected length for random coins
    idpf_rand, rand = front(Poplar1.Idpf.RAND_SIZE, rand)
    seeds = [rand[i:i+l] for i in range(0,3*l,l)]
    corr_seed, seeds = front(2, seeds)
    (k_shard,), seeds = front(1, seeds)

    prg = Poplar1.Prg(k_shard,
                      Poplar1.custom(DST_SHARD_RAND), b'')

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

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

    # Generate correlated randomness used by the Aggregators to
    # compute a sketch over their output shares. PRG seeds are
    # used to encode shares of the `(a, b, c)` triples.
    # (See [BBCGGI21, Appendix C.4].)
    corr_offsets = vec_add(
        Poplar1.Prg.expand_into_vec(
            Poplar1.Idpf.FieldInner,
            corr_seed[0],
            Poplar1.custom(DST_CORR_INNER),
            byte(0) + nonce,
            3 * (Poplar1.Idpf.BITS-1),
        ),
        Poplar1.Prg.expand_into_vec(
            Poplar1.Idpf.FieldInner,
            corr_seed[1],
            Poplar1.custom(DST_CORR_INNER),
            byte(1) + nonce,
            3 * (Poplar1.Idpf.BITS-1),
        ),
    )
    corr_offsets += vec_add(
        Poplar1.Prg.expand_into_vec(
            Poplar1.Idpf.FieldLeaf,
            corr_seed[0],
            Poplar1.custom(DST_CORR_LEAF),
            byte(0) + nonce,
            3,
        ),
        Poplar1.Prg.expand_into_vec(
            Poplar1.Idpf.FieldLeaf,
            corr_seed[1],
            Poplar1.custom(DST_CORR_LEAF),
            byte(1) + nonce,
            3,
        ),
    )

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

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

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

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

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

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

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

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

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

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

    elif step == b'sketch round 2' and opt_sketch != None:
        if len(opt_sketch) == 0:
            return prep_mem # Output shares
        else:
            raise ERR_INPUT # prep message malformed

    raise ERR_INPUT # unexpected input

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

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

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

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

    init_seed = [
        rand[:PrgFixedKeyAes128.SEED_SIZE],
        rand[PrgFixedKeyAes128.SEED_SIZE:],
    ]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

def decode_public_share(IdpfPoplar, encoded):
    l = floor((2*IdpfPoplar.BITS + 7) / 8)
    encoded_ctrl, encoded = encoded[:l], encoded[l:]
    control_bits = unpack_bits(encoded_ctrl, 2 * IdpfPoplar.BITS)
    correction_words = []
    for level in range(IdpfPoplar.BITS):
        Field = IdpfPoplar.current_field(level)
        ctrl_cw = (
            control_bits[level * 2],
            control_bits[level * 2 + 1],
        )
        l = PrgFixedKeyAes128.SEED_SIZE
        seed_cw, encoded = encoded[:l], encoded[l:]
        l = Field.ENCODED_SIZE * IdpfPoplar.VALUE_LEN
        encoded_w_cw, encoded = encoded[:l], encoded[l:]
        w_cw = Field.decode_vec(encoded_w_cw)
        correction_words.append((seed_cw, ctrl_cw, w_cw))
    if len(encoded) != 0:
        raise ERR_DECODE
    return correction_words
]]></artwork>
          </figure>
          <t>Here, <tt>pack_bits()</tt> takes a list of bits, packs each group of eight bits into a
byte, in LSB to MSB order, padding the most significant bits of the last byte
with zeros as necessary, and returns the byte array. <tt>unpack_bits()</tt> performs
the reverse operation: it takes in a byte array and a number of bits, and
returns a list of bits, extracting eight bits from each byte in turn, in LSB to
MSB order, and stopping after the requested number of bits. If the byte array
has an incorrect length, or if unused bits in the last bytes are not zero, it
throws an error.</t>
        </section>
      </section>
      <section anchor="poplar1-inst">
        <name>Instantiation</name>
        <t>By default, Poplar1 is instantiated with IdpfPoplar (<tt>VALUE_LEN == 2</tt>) and
PrgSha3 (<xref target="prg-sha3"/>). This VDAF is suitable for any positive value of <tt>BITS</tt>.
Test vectors can be found in <xref target="test-vectors"/>.</t>
      </section>
    </section>
    <section anchor="security">
      <name>Security Considerations</name>
      <t>VDAFs have two essential security goals:</t>
      <ol spacing="normal" type="1"><li>Privacy: An attacker that controls the network, the Collector, and a subset
of Clients and Aggregators learns nothing about the measurements of honest
Clients beyond what it can deduce from the aggregate result.</li>
        <li>Robustness: An attacker that controls the network and a subset of Clients
cannot cause the Collector to compute anything other than the aggregate of
the measurements of honest Clients.</li>
      </ol>
      <t>Formal definitions of privacy and robustness can be found in <xref target="DPRS23"/>. A VDAF
is the core cryptographic primitive of a protocol that achieves the above
privacy and robustness goals. It is not sufficient on its own, however. The
application will need to assure a few security properties, for example:</t>
      <ul spacing="normal">
        <li>Securely distributing the long-lived parameters, in particular the
verification key.</li>
        <li>
          <t>Establishing secure channels:  </t>
          <ul spacing="normal">
            <li>Confidential and authentic channels among Aggregators, and between the
Aggregators and the Collector; and</li>
            <li>Confidential and Aggregator-authenticated channels between Clients and
Aggregators.</li>
          </ul>
        </li>
        <li>Enforcing the non-collusion properties required of the specific VDAF in use.</li>
      </ul>
      <t>In such an environment, a VDAF provides the high-level privacy property
described above: The Collector learns only the aggregate measurement, and
nothing about individual measurements aside from what can be inferred from the
aggregate result.  The Aggregators learn neither individual measurements nor the
aggregate result.  The Collector is assured that the aggregate statistic
accurately reflects the inputs as long as the Aggregators correctly executed
their role in the VDAF.</t>
      <t>On their own, VDAFs do not mitigate Sybil attacks <xref target="Dou02"/>. In this attack, the
adversary observes a subset of input shares transmitted by a Client it is
interested in. It allows the input shares to be processed, but corrupts and
picks bogus measurements for the remaining Clients.  Applications can guard
against these risks by adding additional controls on report submission,
such as client authentication and rate limits.</t>
      <t>VDAFs do not inherently provide differential privacy <xref target="Dwo06"/>.  The VDAF approach
to private measurement can be viewed as complementary to differential privacy,
relying on non-collusion instead of statistical noise to protect the privacy of
the inputs.  It is possible that a future VDAF could incorporate differential
privacy features, e.g., by injecting noise before the sharding stage and
removing it after unsharding.</t>
      <section anchor="requirements-for-the-verification-key">
        <name>Requirements for the Verification Key</name>
        <t>The Aggregators are responsible for exchanging the verification key in advance
of executing the VDAF. Any procedure is acceptable as long as the following
conditions are met:</t>
        <ol spacing="normal" type="1"><li>To ensure robustness of the computation, the Aggregators <bcp14>MUST NOT</bcp14> reveal the
verification key to the Clients. Otherwise, a malicious Client might be able
to exploit knowledge of this key to craft an invalid report that would be
accepted by the Aggregators.</li>
          <li>To ensure privacy of the measurements, the Aggregators <bcp14>MUST</bcp14> commit to the
verification key prior to processing reports generated by Clients. Otherwise,
a malicious Aggregator may be able to craft a verification key that, for a
given report, causes an honest Aggregator to leak information about the
measurement during preparation.</li>
        </ol>
        <t>Meeting these conditions is required in order to leverage security analysis in
the framework of <xref target="DPRS23"/>. Their definition of robustness allows the attacker,
playing the role of a cohort of malicious Clients, to submit arbitrary reports
to the Aggregators and eavesdrop on their communications as they process them.
Security in this model is achievable as long as the verification key is kept
secret from the attacker.</t>
        <t>The privacy definition of <xref target="DPRS23"/> considers an active attacker that controls
the network and a subset of Aggregators; in addition, the attacker is allowed to
choose the verification key used by each honest Aggregator over the course of
the experiment. Security is achievable in this model as long as the key is
picked at the start of the experiment, prior to any reports being generated.
(The model also requires nonces to be generated at random; see
<xref target="nonce-requirements"/> below.)</t>
        <t>Meeting these requirements is relatively straightforward. For example, the
Aggregators may designate one of their peers to generate the verification key
and distribute it to the others. To assure Clients of key commitment, the
Clients and (honest) Aggregators could bind reports to a shared context string
derived from the key. For instance, the "task ID" of DAP <xref target="DAP"/> could be set to
the hash of the verification key; then as long as honest Aggregators only
consume reports for the task indicated by the Client, forging a new key after
the fact would reduce to finding collisions in the underlying hash function.
(Keeping the key secret from the Clients would require the hash function to be
one-way.) However, since rotating the key implies rotating the task ID, this
scheme would not allow key rotation over the lifetime of a task.</t>
      </section>
      <section anchor="nonce-requirements">
        <name>Requirements for the Nonce</name>
        <t>The sharding and preparation steps of VDAF execution depend on a nonce
associated with the Client's report. To ensure privacy of the underlying
measurement, the Client <bcp14>MUST</bcp14> generate this nonce using a CSPRNG. This is
required in order to leverage security analysis for the privacy definition of
<xref target="DPRS23"/>, which assumes the nonce is chosen at random prior to generating the
report.</t>
        <t>Other security considerations may require the nonce to be non-repeating. For
example, to achieve differential privacy it is necessary to avoid "over
exposing" a measurement by including it too many times in a single batch or
across multiple batches. It is <bcp14>RECOMMENDED</bcp14> that the nonce generated by the
Client be used by the Aggregators for replay protection.</t>
      </section>
      <section anchor="requirements-for-the-aggregation-parameters">
        <name>Requirements for the Aggregation Parameters</name>
        <t>As described in <xref target="sec-daf-validity-scopes"/> and <xref target="sec-vdaf-validity-scopes"/>
respectively, DAFs and VDAFs may impose restrictions on the re-use of input
shares. This is to ensure that correlated randomness provided by the Client
through the input share is not used more than once, which might compromise
confidentiality of the Client's measurements.</t>
        <t>Protocols that make use of VDAFs therefore <bcp14>MUST</bcp14> call <tt>Vdaf.is_valid</tt>
on the set of all aggregation parameters used for a Client's input share, and
only proceed with the preparation and aggregation phases if that function call
returns <tt>True</tt>.</t>
      </section>
      <section anchor="agg-param-privacy">
        <name>Additional Privacy Considerations for Aggregation Parameters</name>
        <t>Aggregating a batch of reports multiple times, each time with a different
aggregation parameter, could result in information leakage beyond what is used
by the application.</t>
        <t>For example, when Poplar1 is used for heavy hitters, the Aggregators learn not
only the heavy hitters themselves, but also the prefix tree (as defined in
<xref target="poplar1"/>) computed along the way. Indeed, this leakage is inherent to any
construction that uses an IDPF (<xref target="idpf"/>) in the same way. Depending on the
distribution of the measurements, the prefix tree can leak a significant amount
of information about unpopular inputs. For instance, it is possible (though
perhaps unlikely) for a large set of non-heavy-hitter values to share a common
prefix, which would be leaked by a prefix tree with a sufficiently small
threshold.</t>
        <t>The only known, general-purpose approach to mitigating this leakage is via
differential privacy.</t>
        <ul empty="true">
          <li>
            <t>TODO(issue #94) Describe (or point to some description of) the central DP
mechanism for Poplar described in <xref target="BBCGGI21"/>.</t>
          </li>
        </ul>
      </section>
      <section anchor="prg-vs-ro">
        <name>Pseudorandom Generators and random oracles</name>
        <t>The objects we describe in <xref target="prg"/> share a common interface, which we have
called Prg. However, these are not necessarily all modeled as cryptographic
Pseudorandom Generators in the security analyses of our protocols. Instead, most
of them are modeled as random oracles. For these use cases, we want to be
conservative in our assumptions, and hence prescribe PrgSha3 as the only
<bcp14>RECOMMENDED</bcp14> Prg instantiation.</t>
        <t>The one exception is the PRG used in the Idpf implementation IdpfPoplar
<xref target="idpf-poplar"/>. Here, a random oracle is not needed to prove security, and
hence a construction based on fixed-key AES <xref target="prg-fixed-key-aes128"/> can be
used. However, as PrgFixedKeyAes128 has been shown to be differentiable from
a random oracle <xref target="GKWWY20"/>, it is <bcp14>NOT RECOMMENDED</bcp14> to use it anywhere else.</t>
        <ul empty="true">
          <li>
            <t>OPEN ISSUE: We may want to drop the common interface for PRGs and random
oracles. See issue #159.</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>A codepoint for each (V)DAF in this document is defined in the table below. Note
that <tt>0xFFFF0000</tt> through <tt>0xFFFFFFFF</tt> are reserved for private use.</t>
      <table anchor="codepoints">
        <name>Unique identifiers for (V)DAFs.</name>
        <thead>
          <tr>
            <th align="left">Value</th>
            <th align="left">Scheme</th>
            <th align="left">Type</th>
            <th align="left">Reference</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>0x00000000</tt></td>
            <td align="left">Prio3Count</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3count"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000001</tt></td>
            <td align="left">Prio3Sum</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3sum"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000002</tt></td>
            <td align="left">Prio3Histogram</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3histogram"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000003</tt> to <tt>0x00000FFF</tt></td>
            <td align="left">reserved for Prio3</td>
            <td align="left">VDAF</td>
            <td align="left">n/a</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00001000</tt></td>
            <td align="left">Poplar1</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="poplar1-inst"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0xFFFF0000</tt> to <tt>0xFFFFFFFF</tt></td>
            <td align="left">reserved</td>
            <td align="left">n/a</td>
            <td align="left">n/a</td>
          </tr>
        </tbody>
      </table>
      <ul empty="true">
        <li>
          <t>TODO Add IANA considerations for the codepoints summarized in <xref target="codepoints"/>.</t>
        </li>
      </ul>
    </section>
  </middle>
  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        <reference anchor="SP800-185">
          <front>
            <title>SHA-3 Derived Functions: cSHAKE, KMAC, TupleHash and ParallelHash</title>
            <author>
              <organization/>
            </author>
            <date year="2016" month="December"/>
          </front>
          <seriesInfo name="NIST Special Publication 800-185" value=""/>
        </reference>
        <reference anchor="FIPS202">
          <front>
            <title>SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions</title>
            <author>
              <organization/>
            </author>
            <date year="2015" month="August"/>
          </front>
          <seriesInfo name="NIST FIPS PUB 202" value=""/>
        </reference>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner">
              <organization/>
            </author>
            <date month="March" year="1997"/>
            <abstract>
              <t>In many standards track documents several words are used to signify the requirements in the specification.  These words are often capitalized. This document defines these words as they should be interpreted in IETF documents.  This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        <reference anchor="RFC8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba">
              <organization/>
            </author>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol  specifications.  This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the  defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
      </references>
      <references>
        <name>Informative References</name>
        <reference anchor="AGJOP21" target="https://ia.cr/2021/576">
          <front>
            <title>Prio+: Privacy Preserving Aggregate Statistics via Boolean Shares</title>
            <author initials="S." surname="Addanki">
              <organization/>
            </author>
            <author initials="K." surname="Garbe">
              <organization/>
            </author>
            <author initials="E." surname="Jaffe">
              <organization/>
            </author>
            <author initials="R." surname="Ostrovsky">
              <organization/>
            </author>
            <author initials="A." surname="Polychroniadou">
              <organization/>
            </author>
            <date year="2021"/>
          </front>
        </reference>
        <reference anchor="BBCGGI19" target="https://ia.cr/2019/188">
          <front>
            <title>Zero-Knowledge Proofs on Secret-Shared Data via Fully Linear PCPs</title>
            <author initials="D." surname="Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2019"/>
          </front>
          <seriesInfo name="CRYPTO 2019" value=""/>
        </reference>
        <reference anchor="BBCGGI21" target="https://ia.cr/2021/017">
          <front>
            <title>Lightweight Techniques for Private Heavy Hitters</title>
            <author initials="D." surname="Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2021"/>
          </front>
          <seriesInfo name="IEEE S&amp;P 2021" value=""/>
        </reference>
        <reference anchor="CGB17" target="https://dl.acm.org/doi/10.5555/3154630.3154652">
          <front>
            <title>Prio: Private, Robust, and Scalable Computation of Aggregate Statistics</title>
            <author initials="H." surname="Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="D." surname="Boneh">
              <organization/>
            </author>
            <date year="2017"/>
          </front>
          <seriesInfo name="NSDI 2017" value=""/>
        </reference>
        <reference anchor="Dou02" target="https://doi.org/10.1007/3-540-45748-8_24">
          <front>
            <title>The Sybil Attack</title>
            <author initials="J." surname="Douceur">
              <organization/>
            </author>
            <date year="2002"/>
          </front>
          <seriesInfo name="IPTPS 2002" value=""/>
        </reference>
        <reference anchor="DPRS23" target="https://ia.cr/2023/130">
          <front>
            <title>Verifiable Distributed Aggregation Functions</title>
            <author initials="H." surname="Davis">
              <organization/>
            </author>
            <author initials="C." surname="Patton">
              <organization/>
            </author>
            <author initials="M." surname="Rosulek">
              <organization/>
            </author>
            <author initials="P." surname="Schoppmann">
              <organization/>
            </author>
            <date>n.d.</date>
          </front>
        </reference>
        <reference anchor="Dwo06" target="https://link.springer.com/chapter/10.1007/11787006_1">
          <front>
            <title>Differential Privacy</title>
            <author initials="C." surname="Dwork">
              <organization/>
            </author>
            <date year="2006"/>
          </front>
          <seriesInfo name="ICALP 2006" value=""/>
        </reference>
        <reference anchor="EPK14" target="https://dl.acm.org/doi/10.1145/2660267.2660348">
          <front>
            <title>RAPPOR: Randomized Aggregatable Privacy-Preserving Ordinal Response</title>
            <author initials="Ú." surname="Erlingsson">
              <organization/>
            </author>
            <author initials="V." surname="Pihur">
              <organization/>
            </author>
            <author initials="A." surname="Korolova">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <seriesInfo name="CCS 2014" value=""/>
        </reference>
        <reference anchor="ENPA" target="https://covid19-static.cdn-apple.com/applications/covid19/current/static/contact-tracing/pdf/ENPA_White_Paper.pdf">
          <front>
            <title>Exposure Notification Privacy-preserving Analytics (ENPA) White Paper</title>
            <author>
              <organization/>
            </author>
            <date year="2021"/>
          </front>
        </reference>
        <reference anchor="GI14" target="https://link.springer.com/chapter/10.1007/978-3-642-55220-5_35">
          <front>
            <title>Distributed Point Functions and Their Applications</title>
            <author initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <seriesInfo name="EUROCRYPT 2014" value=""/>
        </reference>
        <reference anchor="GKWWY20" target="https://link.springer.com/chapter/10.1007/978-3-030-56880-1_28">
          <front>
            <title>Better concrete security for half-gates garbling (in the multi-instance setting)</title>
            <author>
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <seriesInfo name="CRYPTO 2020" value=""/>
        </reference>
        <reference anchor="OriginTelemetry" target="https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/collection/origin.html">
          <front>
            <title>Origin Telemetry</title>
            <author>
              <organization/>
            </author>
            <date year="2020"/>
          </front>
        </reference>
        <reference anchor="DAP">
          <front>
            <title>Distributed Aggregation Protocol for Privacy Preserving Measurement</title>
            <author fullname="Tim Geoghegan" initials="T." surname="Geoghegan">
              <organization>ISRG</organization>
            </author>
            <author fullname="Christopher Patton" initials="C." surname="Patton">
              <organization>Cloudflare</organization>
            </author>
            <author fullname="Eric Rescorla" initials="E." surname="Rescorla">
              <organization>Mozilla</organization>
            </author>
            <author fullname="Christopher A. Wood" initials="C. A." surname="Wood">
              <organization>Cloudflare</organization>
            </author>
            <date day="9" month="December" year="2022"/>
            <abstract>
              <t>   There are many situations in which it is desirable to take
   measurements of data which people consider sensitive.  In these
   cases, the entity taking the measurement is usually not interested in
   people's individual responses but rather in aggregated data.
   Conventional methods require collecting individual responses and then
   aggregating them, thus representing a threat to user privacy and
   rendering many such measurements difficult and impractical.  This
   document describes a multi-party distributed aggregation protocol
   (DAP) for privacy preserving measurement (PPM) which can be used to
   collect aggregate data without revealing any individual user's data.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-ppm-dap-03"/>
        </reference>
      </references>
    </references>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The security considerations in <xref target="security"/> are based largely on the security
analysis of <xref target="DPRS23"/>. Thanks to Hannah Davis and Mike Rosulek, who lent their
time to developing definitions and security proofs.</t>
      <t>Thanks to Henry Corrigan-Gibbs, Armando Faz-Hernández, Simon Friedberger, Tim
Geoghegan, Mariana Raykova, Jacob Rothstein, Xiao Wang, and Christopher Wood for
useful feedback on and contributions to the spec.</t>
    </section>
    <section numbered="false" anchor="test-vectors">
      <name>Test Vectors</name>
      <ul empty="true">
        <li>
          <t>NOTE Machine-readable test vectors can be found at
https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec.</t>
        </li>
      </ul>
      <t>Test vectors cover the generation of input shares and the conversion of input
shares into output shares. Vectors specify the verification key, measurements,
aggregation parameter, and any parameters needed to construct the VDAF. (For
example, for <tt>Prio3Sum</tt>, the user specifies the number of bits for representing
each summand.)</t>
      <t>Byte strings are encoded in hexadecimal. To make the tests deterministic, the
random inputs of randomized algorithms were fixed to the byte sequence starting
with <tt>0</tt>, incrementing by <tt>1</tt>, and wrapping at <tt>256</tt>:</t>
      <artwork><![CDATA[
0, 1, 2, ..., 255, 0, 1, 2, ...
]]></artwork>
      <section numbered="false" anchor="testvec-prio3count">
        <name>Prio3Count</name>
        <artwork><![CDATA[
verify_key: "000102030405060708090a0b0c0d0e0f"
upload_0:
  measurement: 1
  nonce: "000102030405060708090a0b0c0d0e0f"
  public_share: >-
  input_share_0: >-
    e7a225b76420dd6dd0682380363bd782c8ca9ace6e7abc559dd873bafb503e3cc8b7
    9f3b2b8b0a14676172e46be2ce2f
  input_share_1: >-
    000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
  round_0:
    prep_share_0: >-
      56df20acd68725eab85e44c706629df555d635a5b899df767fe28effd0c45f60
    prep_share_1: >-
      ab20df532878da1518b04178e08a39d0d40fdbfe1876e479dc5e94b43afc68d5
    prep_message: >-
  out_share_0:
    - e7a225b76420dd6d
  out_share_1:
    - 1b5dda489adf2292
agg_share_0: >-
  e7a225b76420dd6d
agg_share_1: >-
  1b5dda489adf2292
agg_result: 1
]]></artwork>
      </section>
      <section numbered="false" anchor="testvec-prio3sum">
        <name>Prio3Sum</name>
        <artwork><![CDATA[
bits: 8
verify_key: "000102030405060708090a0b0c0d0e0f"
upload_0:
  measurement: 100
  nonce: "000102030405060708090a0b0c0d0e0f"
  public_share: >-
    da6f5f000d95651e628464f5d086fde6a544464ac776c3812e2299cce1d29095
  input_share_0: >-
    2d97ed6ebc5f6748db3017211c7a31ceeba9500b8317a7f61578b85c08a7f7d95c63
    7bb14b95c062c74bd5b08625bdafbfd91fd01d22291b22b76e54a9be1f7e7015a396
    ae0d6d034b3d22795b3d98db2a9aa51b4ea56c247496d380367deb786a9b34d5cb88
    f0f43e5cb4ab71910c8fa20b0b518f7dd9ce11ec9bf4ce460c81d3e9db05c34e0f05
    14d53f5eadea231dbc1fc575ad52e01622671eaf49a66533a6511710eeea024df0da
    7e7d21451ff5fd9d38e36eee8b78bf7c0767b91e747c6b80d6ca6b726286edebeae4
    ff377040d87f84288f4d0e5960e27b79387caef816c27481be166b71d38d1695e5e5
    061c26f0f667f8fff3133c2ae3ac1853ac542a9af0b5e422764609abd882dedf6aa8
    c835228bbc0cb99a695e81c45a2876a961af0c680662de4400ec96004c45bdc32726
    68b01d7f861f2e03fc18adcc352bdeb7b06b39c2de749da45e9b48f46c45a390cb59
    455dbf3e8be5938203def1c45af5eb5bf2037be005768d74faf11efd255b699f5ae9
    bce8b3bf4688907d11ca89e7609b77c04abde845f63091b934017cf9a83f80eb86fd
    aa063630f86ee982d812062db0d1d760d84cfebbf99927cad516dd028bf2f9e9b7d2
    4aa0bd9c0cb16a46c469eacfe1c48b8d7bf626e5d3eedb3f3cc4972f14a4ba605565
    ec795dd9e68af4ac6185f370f1f77610c64b04d295007b34ed59ed7bceace7b9dea8
    8346a2ee47dfec257ede5cd6985c34abaf5983d067786a695ae1039b631555bbe876
    7baeedfe4f30df6b47479543c58a87e0aaf371234fc9094c4b2b79d025229634a3fd
    f68a36be0e8661a4f043504b7025f03f02e57704b4e410c60e69e88050d0c33ea71b
    c37f306c225f457fbab4929c65ba9401dc57a2dc31bd6d3f53099a00303132333435
    363738393a3b3c3d3e3f
  input_share_1: >-
    000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021
    22232425262728292a2b2c2d2e2f
  round_0:
    prep_share_0: >-
      7ae72bff1c063181bfea222dd77bcd40c5d15f62174d4af984d728effb82edd302
      74c927a9ffa51b90c167c60b40c3cdda6f5f000d95651e628464f5d086fde6
    prep_share_1: >-
      8718d400e3f9ce7e2415ddd2288432bf85623812cb8a7cdfed57f5a417c422e25e
      84a67ab22c0b8ef7b0500c366feb95a544464ac776c3812e2299cce1d29095
    prep_message: >-
      4f351791f4d706a31c54ce699ef1af97
  out_share_0:
    - a18d0c7e2a74470727d4f628ff934e52
  out_share_1:
    - c472f381d58bb8f8bc2b09d7006cb1ad
agg_share_0: >-
  a18d0c7e2a74470727d4f628ff934e52
agg_share_1: >-
  c472f381d58bb8f8bc2b09d7006cb1ad
agg_result: 100
]]></artwork>
      </section>
      <section numbered="false" anchor="testvec-prio3histogram">
        <name>Prio3Histogram</name>
        <artwork><![CDATA[
buckets: [1, 10, 100]
verify_key: "000102030405060708090a0b0c0d0e0f"
upload_0:
  measurement: 50
  nonce: "000102030405060708090a0b0c0d0e0f"
  public_share: >-
    5e015517900cfc204138c24f808ddf4ee85eca87ba246cd715d116195172e500
  input_share_0: >-
    c269f2189db431ca2ebe7230bacd692ac02a7790818681b6ee5ecbd509587b2976c7
    897326840bb70083ee4df8ffe3dc65dbd71f56735a7dcc3a150da8e77171e6d380f2
    f6886845e310dabec4382a037ffc3520737af8874f5b2aec2fae1405cce12c257ef2
    9d22b3e511c30e8f9545251286b3ef3e3728256fc0cc21f5a8ea1d095187cc29132e
    52d24ad778920c740af125833e9a8d2f6b0255740e8d2a4e7b718446610a0650ba40
    61e6a3ee805c1dcffec90d00a3ea5817c9956459538c99efbb56b38eaa6aed93f5a0
    0f11ab0210af030b91c56e6b2b47bb30fcdc5f44a28b5d733e4661cbd736ae071e78
    4f99ba86ff2688f6751d2d16e80ddd99c9aceeb39ca660215f0fc1178f828e295840
    f941fa9a3217afd52b32ec6c8ee3ec58291f2c88e8150374ccfd503f07bc0021d6a9
    f1c81050df96ec5ce5c7d4f41255303132333435363738393a3b3c3d3e3f
  input_share_1: >-
    000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021
    22232425262728292a2b2c2d2e2f
  round_0:
    prep_share_0: >-
      ac872edaaaa532de61bcd63b168e522230b35064b09b6b35c1352bc354560fdeac
      684da645d3e509c6db8ba31f58dabb5e015517900cfc204138c24f808ddf4e
    prep_share_1: >-
      5578d125555acd21824329c4e971adddc07187f0f25a30ceba8407513f60f8e3d1
      5c17270c5631a718b3b4f5702aff54e85eca87ba246cd715d116195172e500
    prep_message: >-
      890bfbdf0c619d5c853a92e28bce41b3
  out_share_0:
    - c269f2189db431ca2ebe7230bacd692a
    - c02a7790818681b6ee5ecbd509587b29
    - 76c7897326840bb70083ee4df8ffe3dc
    - 65dbd71f56735a7dcc3a150da8e77171
  out_share_1:
    - 3f960de7624bce35b5418dcf453296d5
    - 41d5886f7e797e49f5a0342af6a784d6
    - 8c38768cd97bf448e37c11b207001c23
    - 9c2428e0a98ca58217c5eaf257188e8e
agg_share_0: >-
  c269f2189db431ca2ebe7230bacd692ac02a7790818681b6ee5ecbd509587b2976c789
  7326840bb70083ee4df8ffe3dc65dbd71f56735a7dcc3a150da8e77171
agg_share_1: >-
  3f960de7624bce35b5418dcf453296d541d5886f7e797e49f5a0342af6a784d68c3876
  8cd97bf448e37c11b207001c239c2428e0a98ca58217c5eaf257188e8e
agg_result: [0, 0, 1, 0]
]]></artwork>
      </section>
      <section numbered="false" anchor="testvec-poplar1">
        <name>Poplar1</name>
        <section numbered="false" anchor="sharding-1">
          <name>Sharding</name>
          <artwork><![CDATA[
bits: 4
upload_0:
  measurement: 13
  nonce: "000102030405060708090a0b0c0d0e0f"
  public_share: >-
    8b332c8b09b84f5801ad1cfd30b0df3fba69d11ddf6065a9cdb87cb31579ba0443a4
    82f4ed21ac079b96f5944d1669a1159406148c00878ac9953bcfbadc0273042653fd
    0fae8c43ce746fd31f248d1cbf5d1bc01fe02a883571cf38a1a4c10f54d41979b6fc
    35ef1fb051f968ba4397b8e61a81d835fa7ee54b949a35abf76c13e0a9daf90f1528
    c40db5904b6e24d70116538b28c16d9dbfee45000fe14db45cafbb76768b28250e74
    6af691f4bb1619
  input_share_0: >-
    000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f0734
    d55dcb0dec9599b96f38ca694d46056dbe5bb24ab41ca10faaa8249839632c6503c9
    795300a160e8c378762f3b329e9ebe6a081eaed2d72aaff0aeb52415211c314f609a
    0377e66b7be10a3d8d4e75890da4c93f62172bc07e54be31c060c5970b52af8e8633
    d63560f59fa0bb36
  input_share_1: >-
    101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3f9558
    af2229b50110d88e17b5b3a81902194a5eab5f8ad69f5c061f16ac1e92deadc3c6ed
    32714a3756fa68e580d523d6c0e4b92ba2277033a7adb060e7a2ee3b2e44591d7c99
    b1cbcbfc58e4ae9ef7613a1ff24e53201e7264940bed2cd318e8e80ab7aae630f342
    911d75c85980691d
]]></artwork>
        </section>
        <section numbered="false" anchor="preparation-aggregation-and-unsharding">
          <name>Preparation, Aggregation, and Unsharding</name>
          <artwork><![CDATA[
verify_key: "000102030405060708090a0b0c0d0e0f"
agg_param: (0, [0, 1])
upload_0:
  round_0:
    prep_share_0: >-
      a2d369b7ee44e5f8b903e889b37ea7ef4d29ee36d1abdb13
    prep_share_1: >-
      31182ff6e075b925a06c802eac3b14c1ad66ce991ca2ffc2
    prep_message: >-
      d2eb98add0ba9e1e587068b860babbb0fa8fbcd0ed4ddbd6
  round_1:
    prep_share_0: >-
      f4445265dc801ab5
    prep_share_1: >-
      0dbbad9a227fe54a
    prep_message: >-
  out_share_0:
    - d47170d4f804449e
    - e16add75c1d3f0c4
  out_share_1:
    - 2d8e8f2b06fbbb61
    - 2195228a3d2c0f3b
agg_share_0: >-
  d47170d4f804449ee16add75c1d3f0c4
agg_share_1: >-
  2d8e8f2b06fbbb612195228a3d2c0f3b
agg_result: [0, 1]
]]></artwork>
          <artwork><![CDATA[
verify_key: "000102030405060708090a0b0c0d0e0f"
agg_param: (1, [0, 1, 2, 3])
upload_0:
  round_0:
    prep_share_0: >-
      94352b588fbd978be7ef2cacb83b1b64c1d11af699253242
    prep_share_1: >-
      4a3529a2b34159be1666064ba0a3a9cc4e72223ef6d0ac79
    prep_message: >-
      dd6a54fa43fff049fc5533f759dfc4300f443d3490f6debb
  round_1:
    prep_share_0: >-
      3dc2833b1f9010ee
    prep_share_1: >-
      c43d7cc4df6fef11
    prep_message: >-
  out_share_0:
    - c03ede9261e7f441
    - 8ef9fde3f50eb967
    - de3bb4acf0b9dff8
    - 24687334644cc809
  out_share_1:
    - 41c1216d9d180bbe
    - 7306021c09f14698
    - 23c44b530e462007
    - de978ccb9ab337f6
agg_share_0: >-
  c03ede9261e7f4418ef9fde3f50eb967de3bb4acf0b9dff824687334644cc809
agg_share_1: >-
  41c1216d9d180bbe7306021c09f1469823c44b530e462007de978ccb9ab337f6
agg_result: [0, 0, 0, 1]
]]></artwork>
          <artwork><![CDATA[
verify_key: "000102030405060708090a0b0c0d0e0f"
agg_param: (2, [0, 2, 4, 6])
upload_0:
  round_0:
    prep_share_0: >-
      b640798e11bc37ac1f4981c99f0de15569b2bcc187d2f0f2
    prep_share_1: >-
      37a720e1739caca1b39b8fe97ce96e09277eee9cc694c2cf
    prep_message: >-
      ece7996f8658e44dd2e410b31cf74f5f8f30ab5e4f67b3c2
  round_1:
    prep_share_0: >-
      52a1848f964385f8
    prep_share_1: >-
      af5e7b7068bc7a07
    prep_message: >-
  out_share_0:
    - 352395a6c5e5804e
    - f9b61274892e76dd
    - b27e3eb4accbaa0a
    - 3b1c4a7f78d59935
  out_share_1:
    - ccdc6a59391a7fb1
    - 0849ed8b75d18922
    - 4f81c14b523455f5
    - c7e3b580862a66ca
agg_share_0: >-
  352395a6c5e5804ef9b61274892e76ddb27e3eb4accbaa0a3b1c4a7f78d59935
agg_share_1: >-
  ccdc6a59391a7fb10849ed8b75d189224f81c14b523455f5c7e3b580862a66ca
agg_result: [0, 0, 0, 1]
]]></artwork>
          <artwork><![CDATA[
verify_key: "000102030405060708090a0b0c0d0e0f"
agg_param: (3, [1, 3, 5, 7, 9, 13, 15])
upload_0:
  round_0:
    prep_share_0: >-
      08efd12285f6e61599b2f9d941577fd843597d3b15f747d15b0b02daf6147752c6
      a7a72723fa0cad98c7c38a0716ff8833dd7f97d40ed374f963dd2bced921614ccd
      4dca993e6c4f5d1ab0ce9bf37df76b41e2c111868322dfc39b3145dfc832
    prep_share_1: >-
      04eb21e562d79e4255b2c5001ed5949fc01841f40d921fdf5c1100b5c993f34e9d
      a143558cc507fb9c3e3832d85b751575b8f5a102257b141b94027bc0a849013f46
      00d8257361b9d17e43f8cddc106b512f69c78b63bcde177e2d3c0cfb353d
    prep_message: >-
      1fdaf307e8cd8558ee64bfda5f2c14780472be2f238967b0b81c028fc0a86a2163
      49eb7cafbf14a83506fcbcdf71749ea8957539d7334e8914f8dfa68e826b628b13
      4ea2bfb1cd082f99f3c669d08e62bd704b899de93f01f741c96d51dafe6f
  round_1:
    prep_share_0: >-
      3e1ded312b78a4a2003d9365472d481c0adb6411d7049869693fb0b331750301
    prep_share_1: >-
      afe212ced4875b5dffc26c9ab8d2b7e3f5249bee28fb679696c04f4cce8afc7e
    prep_message: >-
  out_share_0:
    - 034a3226150cf3aa5e7f6e76b0c6a6b2aa9b750cdafdc6aae0ff2f4076894e2a
    - 1413b483f800a4faa67b1e1c6bb1be2a1c9cc590761edb85f77692b67f9c696a
    - 85591b91ee55008c7e7a58176d5bce3ca9974482b0c1aa2b7c69e0ab2e2e212c
    - 03d9e6cde627cc30ceac7a6b5e3192a382d641e761c05c01eea4bc543c7fc41d
    - cd8891db6ac77a7fbba2c401c1488b8d31ee2cbc65cb26d02cb037cc99d32543
    - 732e3e133c6d8c9a0f6647fc24be3c5d8a960b63c3163979fd4d42fd554a7812
    - 8a2964a89cd70d7ba65bb52f0f15fb2db7dc1c534d743e37f223f74b8489c85d
  out_share_1:
    - eab5cdd9eaf30c55a18091894f39594d55648af3250239551f00d0bf8976b155
    - d9ec4b7c07ff5b055984e1e3944e41d5e3633a6f89e1247a08896d4980639615
    - 68a6e46e11aaff738185a7e892a431c35668bb7d4f3e55d483961f54d1d1de53
    - ea26193219d833cf31538594a1ce6d5c7d29be189e3fa3fe115b43abc3803b62
    - 20776e2495388580445d3bfe3eb77472ce11d3439a34d92fd34fc833662cda3c
    - 7bd1c1ecc3927365f099b803db41c3a27569f49c3ce9c68602b2bd02aab5876d
    - 63d69b576328f28459a44ad0f0ea04d24823e3acb28bc1c80ddc08b47b763722
agg_share_0: >-
  034a3226150cf3aa5e7f6e76b0c6a6b2aa9b750cdafdc6aae0ff2f4076894e2a1413b4
  83f800a4faa67b1e1c6bb1be2a1c9cc590761edb85f77692b67f9c696a85591b91ee55
  008c7e7a58176d5bce3ca9974482b0c1aa2b7c69e0ab2e2e212c03d9e6cde627cc30ce
  ac7a6b5e3192a382d641e761c05c01eea4bc543c7fc41dcd8891db6ac77a7fbba2c401
  c1488b8d31ee2cbc65cb26d02cb037cc99d32543732e3e133c6d8c9a0f6647fc24be3c
  5d8a960b63c3163979fd4d42fd554a78128a2964a89cd70d7ba65bb52f0f15fb2db7dc
  1c534d743e37f223f74b8489c85d
agg_share_1: >-
  eab5cdd9eaf30c55a18091894f39594d55648af3250239551f00d0bf8976b155d9ec4b
  7c07ff5b055984e1e3944e41d5e3633a6f89e1247a08896d498063961568a6e46e11aa
  ff738185a7e892a431c35668bb7d4f3e55d483961f54d1d1de53ea26193219d833cf31
  538594a1ce6d5c7d29be189e3fa3fe115b43abc3803b6220776e2495388580445d3bfe
  3eb77472ce11d3439a34d92fd34fc833662cda3c7bd1c1ecc3927365f099b803db41c3
  a27569f49c3ce9c68602b2bd02aab5876d63d69b576328f28459a44ad0f0ea04d24823
  e3acb28bc1c80ddc08b47b763722
agg_result: [0, 0, 0, 0, 0, 1, 0]
]]></artwork>
        </section>
      </section>
    </section>
  </back>
  <!-- ##markdown-source:
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
m3fdhKnzR0t9A+UHyf6Zlf1HzQKS/WCrp2+3h5Hw1ucku5yxQ0ny4Qa2HoNn
D4FEvht52vhZCWL/67oTqMwut/hwu5ErU0pLpNpwkoEqqtt8rBOYzd+pGXDb
rYqbCX+pz4Wcc883DIzb10Nh73BXRs5zK/LpltCON59Plp4dPuTVenSB8+9f
Oot7tX7tl33UZRjXr12OH829h+7UGhz4jGWNL8jwvSfQnVdHIagiqT4i5V8J
pM+ZjHxJz/Byv5bMVJrl9R2SVNBb50OdOMmkUBodFBf71Vy5PT/MlP7ADX0E
o6Xx8YaLEJI3fj+4gNaIZsAwJay9gwiOi+5Rb1UATrWOsZG7ArxPlOfUNsYW
OOn0ceV5kaaLjG2m09Y/oxO4Iz1ENxiv2XIFtr/IwxrJavGXWeupg87ko9d/
WcjMz9ab9ydWpa1Ha7bjYcX1zNGOnDVy7tln/v68PDTvWShzn9lxJzWfQRKV
KYjWXXHmtroTtgLD5EB7HNIUwONuTCanfb3XEf2tdk1zmdNbVdX1gYrXA/Wu
B6pdx7Uuw2Jd18lRpcs+vRqOPqFz3fX4hMoVDxbtPj6hcSnBMXzpmJpFVK4J
eLjV+2tZD1CyDDsSVSv4eXt1Ue0ictrLb8f99OpR8Dn2Q0+kZB+q/TulOKki
HFyKjjSbg45Q0CkVXz8nHNG6k1tqg96x7cVg35+SdS8j7E3kwQXJPh5kXJFL
wlCkV1zlZeI/ajDjuoVoo4ITpGhJdEjnt0jn4pHrvVTouOZ93ASXVEZMXXeT
c1INQHcIxuUvY6uvtOqmK/xINTxlOjZUxoOrlm0cH4fAmGj4sG22FyaBNY6o
bIOQ/03l1ZHzasS97ar3t9BiD4IA7zlCXO1dlVQQOJ4FTw44F8qMDihC6MLE
AsrEVARu71YWkngB52j3VxckK/l/zsjCqLzyDXJrJsytM+USTbyAhfzZLB4d
BtRqTqNSVUTWB64oJzsaApx6tu2rW3ZrqkLxMJnOZsl4VO+2j9GZqmfQcnxo
2R0Y9V6HDqrKjTYryfR/f+v1bXSi9dcuMnJQwmgHZ7N0vFqCHr253o3a7Wl0
Nw33yI+21bUn92qxl26pSUG/axWYcwR1MxXV8P0oKH3bm8WKHNs2zfWO4GBK
Kq7A4jgX9EzVh6VlmJfI3uFaSh4vUNekNKEHJhrslPH6VOE1awM/6btQv0ai
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
AA==

-->

</rfc>
