<?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.7.17 (Ruby 3.3.3) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-irtf-cfrg-vdaf-10" category="info" submissionType="IRTF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.22.0 -->
  <front>
    <title abbrev="VDAF">Verifiable Distributed Aggregation Functions</title>
    <seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-vdaf-10"/>
    <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="2024" month="July" day="08"/>
    <area>IRTF</area>
    <workgroup>CFRG</workgroup>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <?line 212?>

<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
measurement that would result in an invalid 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>
    <?line 222?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>(TO BE REMOVED BY RFC EDITOR: The source for this draft and and the reference
implementation can be found at https://github.com/cfrg/draft-irtf-cfrg-vdaf.)</t>
      <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>This problem is often formulated in terms 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 measurement before submitting to the
aggregation server. The aggregation server then adds up the noisy measurements,
and because it knows the distribution from which the noise was sampled, it can
estimate the true sum with reasonable accuracy.</t>
      <t>However, even when noise is added to the measurements, collecting them in the
clear still reveals a significant amount of information to the collector. On
the one hand, depending on the "amount" of noise a client adds to its
measurement, it may be possible for a curious collector to make a reasonable
guess of the measurement's true value. On the other hand, the more noise the
clients add, the less reliable will be the server's estimate of the output.
Thus systems relying solely on a DP mechanism 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 measurement beyond what it can deduce from the
differentially private aggregate <xref target="MPRV09"/>. In this document, we describe
Verifiable Distributed Aggregation Functions (VDAFs) as a general class of
delegated MPC protocols that can be used to 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
measurement is ever accessible to any party besides the client that submitted
it. VDAFs can also be composed with various DP mechanisms, thereby ensuring the
aggregate result does not leak too much information about any one measurmment.
At the same time, VDAFs are "verifiable" in the sense that malformed
measurements that would otherwise garble the result of the computation can be
detected and removed from the set of measurements. We refer to this property as
"robustness".</t>
      <t>The cost of achieving these security properties is the need for multiple servers
to participate in the protocol, and the need to ensure they do not collude to
undermine the VDAF's privacy guarantees.  Recent implementation experience has
shown that practical challenges of coordinating multiple servers can be
overcome.  The Prio system <xref target="CGB17"/> (essentially a VDAF) has been deployed in
systems supporting hundreds of millions of users: The Mozilla Origin Telemetry
project <xref target="OriginTelemetry"/> and the Exposure Notification Private Analytics
collaboration among the Internet Security Research Group (ISRG), Google, Apple,
and others <xref target="ENPA"/>.</t>
      <t>The VDAF abstraction laid out in <xref target="vdaf"/> represents a class of multi-party
protocols for privacy-preserving measurement proposed in the literature. These
protocols vary in their operational and security requirements, 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, documenting relevant operational and security requirements, and
specifying constraints for safe usage:  </t>
          <ol spacing="normal" type="1"><li>
              <t>General patterns of communications among the various actors involved in
the system (clients, aggregation servers, and the collector of the
aggregate result);</t>
            </li>
            <li>
              <t>Capabilities of a malicious coalition of servers attempting to divulge
information about client measurements; and</t>
            </li>
            <li>
              <t>Conditions that are necessary to ensure that malicious clients cannot
corrupt the computation.</t>
            </li>
          </ol>
        </li>
        <li>
          <t>Providing cryptographers with design criteria that provide a clear
deployment roadmap for new constructions.</t>
        </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>
              <t>Each client shards its measurement into a sequence of additive shares and
distributes the shares among the aggregation servers.</t>
            </li>
            <li>
              <t>Next, each server adds up its shares locally, resulting in an additive
share of the aggregate.</t>
            </li>
            <li>
              <t>Finally, the aggregation servers send their aggregate shares to the data
collector, who combines them to obtain the aggregate result.</t>
            </li>
          </ol>
          <t>
The difficult part of this system is ensuring that the servers hold shares of
a valid, aggregatable value, e.g., the measurement 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 strings 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 string. 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 string.  </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>10:</t>
        <ul spacing="normal">
          <li>
            <t>Define Prio3MultihotCountVec, a variant of Prio3 for aggregating bit vectors
with bounded weight.</t>
          </li>
          <li>
            <t>FLP: Allow the output of the circuit to be a vector. This makes it possible
to skip joint randomness derivation in more cases.</t>
          </li>
          <li>
            <t>Poplar1: On the first round of preparation, handle <tt>None</tt> as an error.
Previously this message was interpreted as a length-3 vector of zeros.</t>
          </li>
          <li>
            <t>Prio3: Move specification of the field from the FLP validity circuit to the
VDAF itself.</t>
          </li>
          <li>
            <t>Clarify the extent to which the attacker controls the network in our threat
models for privacy and robustness.</t>
          </li>
          <li>
            <t>Clean up various aspects of the code, including: follow existing
object-oriented programming patterns for Python more closely; make the type
hints enforceable; and avoid shadowing variables.</t>
          </li>
          <li>
            <t>Poplar1: Align terminology with <xref target="BBCGGI23"/>.</t>
          </li>
          <li>
            <t>IDPF: Add guidance for encoding byte strings as indices.</t>
          </li>
        </ul>
        <t>09:</t>
        <ul spacing="normal">
          <li>
            <t>Poplar1: Make prefix tree traversal stricter by requiring each node to be a
child of a node that was already visited. This change is intended to make it
harder for a malicious Aggregator to steer traversal towards
non-heavy-hitting measurements.</t>
          </li>
          <li>
            <t>Prio3: Add more explicit guidance for choosing the field size.</t>
          </li>
          <li>
            <t>IDPF: Define extractability and clarify (un)safe usage of intermediate prefix
counts. Accordingly, add text ensuring public share consistency to security
considerations.</t>
          </li>
        </ul>
        <t>08:</t>
        <ul spacing="normal">
          <li>
            <t>Poplar1: Bind the report nonce to the authenticator vector programmed into
the IDPF. (*)</t>
          </li>
          <li>
            <t>IdpfPoplar: Modify <tt>extend()</tt> by stealing each control bit from its
corresponding seed. This improves performance by reducing the number of AES
calls per level from 3 to 2. The cost is a slight reduction in the concrete
privacy bound. (*)</t>
          </li>
          <li>
            <t>Prio3: Add support for generating and verifying mutliple proofs per
measurement. This enables a trade-off between communication cost and runtime:
if more proofs are used, then a smaller field can be used without impacting
robustness. (*)</t>
          </li>
          <li>
            <t>Replace SHAKE128 with TurboSHAKE128. (*)</t>
          </li>
        </ul>
        <t>07:</t>
        <ul spacing="normal">
          <li>
            <t>Rename PRG to XOF ("eXtendable Output Function"). Accordingly, rename PrgSha3
to XofShake128 and PrgFixedKeyAes128 to XofFixedKeyAes128. "PRG" is a misnomer
since we don't actually treat this object as a pseudorandom generator in
existing security analysis.</t>
          </li>
          <li>
            <t>Replace cSHAKE128 with SHAKE128, re-implementing domain separation for the
customization string using a simpler scheme. This change addresses the
reality that implementations of cSHAKE128 are less common. (*)</t>
          </li>
          <li>
            <t>Define a new VDAF, called Prio3SumVec, that generalizes Prio3Sum to a vector
of summands.</t>
          </li>
          <li>
            <t>Prio3Histogram: Update the codepoint and use the parallel sum optimization
introduced by Prio3SumVec to reduce the proof size. (*)</t>
          </li>
          <li>
            <t>Daf, Vdaf: Rename interface methods to match verbiage in the draft.</t>
          </li>
          <li>
            <t>Daf: Align with Vdaf by adding a nonce to <tt>shard()</tt> and <tt>prep()</tt>.</t>
          </li>
          <li>
            <t>Vdaf: Have <tt>prep_init()</tt> compute the first prep share. This change is
intended to simplify the interface by making the input to <tt>prep_next()</tt> not
optional.</t>
          </li>
          <li>
            <t>Prio3: Split sharding into two auxiliary functions, one for sharding with
joint randomness and another without. This change is intended to improve
readability.</t>
          </li>
          <li>
            <t>Fix bugs in the ping-pong interface discovered after implementing it.</t>
          </li>
        </ul>
        <t>06:</t>
        <ul spacing="normal">
          <li>
            <t>Vdaf: Define a wrapper interface for preparation that is suitable for the
"ping-pong" topology in which two Aggregators exchange messages over a
request/response protocol, like HTTP, and take turns executing the
computation until input from the peer is required.</t>
          </li>
          <li>
            <t>Prio3Histogram: Generalize the measurement type so that the histogram can be
used more easily with discrete domains. (*)</t>
          </li>
          <li>
            <t>Daf, Vdaf: Change the aggregation parameter validation algorithm to take the
set of previous parameters rather than a list. (The order of the parameters
is irrelevant.)</t>
          </li>
          <li>
            <t>Daf, Vdaf, Idpf: Add parameter <tt>RAND_SIZE</tt> that specifies the number of
random bytes consumed by the randomized algorithm (<tt>shard()</tt> for Daf and Vdaf
and <tt>gen()</tt> for Idpf).</t>
          </li>
        </ul>
        <t>05:</t>
        <ul spacing="normal">
          <li>
            <t>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. (*)</t>
          </li>
          <li>
            <t>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.</t>
          </li>
          <li>
            <t>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.</t>
          </li>
          <li>
            <t>Use little-endian byte-order for field element encoding. (*)</t>
          </li>
          <li>
            <t>Poplar1: Move the last step of sketch evaluation from <tt>prep_next()</tt> to
<tt>prep_shares_to_prep()</tt>.</t>
          </li>
        </ul>
        <t>04:</t>
        <ul spacing="normal">
          <li>
            <t>Align security considerations with the security analysis of <xref target="DPRS23"/>.</t>
          </li>
          <li>
            <t>Vdaf: Pass the nonce to the sharding algorithm.</t>
          </li>
          <li>
            <t>Vdaf: Rather than allow the application to choose the nonce length, have each
implementation of the Vdaf interface specify the expected nonce length. (*)</t>
          </li>
          <li>
            <t>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.</t>
          </li>
          <li>
            <t>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"/>. (*)</t>
          </li>
          <li>
            <t>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. (*)</t>
          </li>
          <li>
            <t>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. (*)</t>
          </li>
          <li>
            <t>Prio3: Bind nonce to joint randomness parts. This is intended to address
birthday attacks on robustness pointed out by <xref target="DPRS23"/>. (*)</t>
          </li>
          <li>
            <t>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. (*)</t>
          </li>
          <li>
            <t>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. (*)</t>
          </li>
          <li>
            <t>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. (*)</t>
          </li>
          <li>
            <t>Poplar1: Increase the maximum candidate prefix count in the encoding of the
aggregation parameter. (*)</t>
          </li>
          <li>
            <t>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. (*)</t>
          </li>
          <li>
            <t>Poplar1: Clarify that the aggregation parameter encoding is <bcp14>OPTIONAL</bcp14>.
Accordingly, update implementation considerations around cross-aggregation
state.</t>
          </li>
          <li>
            <t>IdpfPoplar: Add implementation considerations around branching on the values
of control bits.</t>
          </li>
          <li>
            <t>IdpfPoplar: When decoding the the control bits in the public share, assert
that the trailing bits of the final byte are all zero. (*)</t>
          </li>
        </ul>
        <t>03:</t>
        <ul spacing="normal">
          <li>
            <t>Define codepoints for (V)DAFs and use them for domain separation in Prio3 and
Poplar1. (*)</t>
          </li>
          <li>
            <t>Prio3: Align joint randomness computation with revised paper <xref target="BBCGGI19"/>.
This change mitigates an attack on robustness. (*)</t>
          </li>
          <li>
            <t>Prio3: Remove an intermediate PRG evaluation from query randomness generation.
(*)</t>
          </li>
          <li>
            <t>Add additional guidance for choosing FFT-friendly fields.</t>
          </li>
        </ul>
        <t>02:</t>
        <ul spacing="normal">
          <li>
            <t>Complete the initial specification of Poplar1.</t>
          </li>
          <li>
            <t>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.)</t>
          </li>
          <li>
            <t>Extend (V)DAF syntax to allow the unsharding step to take into account the
number of measurements aggregated.</t>
          </li>
          <li>
            <t>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.</t>
          </li>
          <li>
            <t>Prio3: Align aggregate result computation with updated FLP syntax.</t>
          </li>
          <li>
            <t>Prg: Add a method for statefully generating a vector of field elements.</t>
          </li>
          <li>
            <t>Field: Require that field elements are fully reduced before decoding. (*)</t>
          </li>
          <li>
            <t>Define new field Field255.</t>
          </li>
        </ul>
        <t>01:</t>
        <ul spacing="normal">
          <li>
            <t>Require that VDAFs specify serialization of aggregate shares.</t>
          </li>
          <li>
            <t>Define Distributed Aggregation Functions (DAFs).</t>
          </li>
          <li>
            <t>Prio3: Move proof verifier check from <tt>prep_next()</tt> to
<tt>prep_shares_to_prep()</tt>. (*)</t>
          </li>
          <li>
            <t>Remove public parameter and replace verification parameter with a
"verification key" and "Aggregator ID".</t>
          </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>
      <?line -18?>

<t>Algorithms in this document are written in Python 3. Type hints are used to
define input and output types. The type variable <tt>F</tt> is used in signatures to
signify any type that is a subclass of <tt>Field</tt>. 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>int</tt> is defined, which algorithms are
free to use as desired. Its value <bcp14>SHALL</bcp14> be <tt>8</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>
          <t><tt>zeros(len: int) -&gt; bytes</tt> returns an array of zero bytes. The length of
<tt>output</tt> <bcp14>MUST</bcp14> be <tt>len</tt>.</t>
        </li>
        <li>
          <t><tt>gen_rand(len: int) -&gt; bytes</tt> returns an array of random bytes generated by a
cryptographically secure pseudorandom number generator (CSPRNG). The length
of <tt>output</tt> <bcp14>MUST</bcp14> be <tt>len</tt>.</t>
        </li>
        <li>
          <t><tt>byte(int: int) -&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>.</t>
        </li>
        <li>
          <t><tt>concat(parts: list[bytes]) -&gt; bytes</tt> returns the concatenation of the input
byte strings, i.e., <tt>parts[0] || ... || parts[len(parts)-1]</tt>.</t>
        </li>
        <li>
          <t><tt>front(length: int, vec: list[Any]) -&gt; (list[Any], list[Any])</tt> splits <tt>vec</tt>
into two vectors, where the first vector is made up of the first <tt>length</tt>
elements of the input. I.e., <tt>(vec[:length], vec[length:])</tt>.</t>
        </li>
        <li>
          <t><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.</t>
        </li>
        <li>
          <t><tt>to_be_bytes(val: int, length: int) -&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; int</tt> computes the inverse.</t>
        </li>
        <li>
          <t><tt>to_le_bytes(val: int, length: int) -&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; int</tt> computes the inverse.</t>
        </li>
        <li>
          <t><tt>next_power_of_2(n: int) -&gt; int</tt> returns the smallest integer
greater than or equal to <tt>n</tt> that is also a power of two.</t>
        </li>
        <li>
          <t><tt>additive_secret_share(vec: list[Field], num_shares: int, field: type)
-&gt; list[list[Field]]</tt> takes a vector of field elements and returns multiple
vectors of the same length, such that they all add up to the input vector,
and each proper subset of the vectors are indistinguishable from random.</t>
        </li>
        <li>
          <t><tt>cast(typ: type, val: object) -&gt; object</tt> returns the input value unchanged.
This is only present to assist with static analysis of the Python code.
Type checkers will ignore the inferred type of the input value, and assume
the output value has the given type.</t>
        </li>
        <li>
          <t><tt>range(stop)</tt> or <tt>range(start, stop[, step])</tt> is the range function from the
Python standard library. The one-argument form returns the integers from zero
(inclusive) to <tt>stop</tt>, exclusive. The two- and three-argument forms allow
overriding the start of the range and overriding the step between successive
output values.</t>
        </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>
          <t>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".</t>
        </li>
        <li>
          <t>The Aggregators refine their input shares into "output shares".
          </t>
          <ul spacing="normal">
            <li>
              <t>Output shares are in one-to-one correspondence with the input shares.</t>
            </li>
            <li>
              <t>Just as each Aggregator receives one input share of each measurement, if
this process succeeds, then each aggregator holds one output share.</t>
            </li>
            <li>
              <t>In VDAFs, Aggregators will need to exchange information among themselves
as part of the validation process.</t>
            </li>
          </ul>
        </li>
        <li>
          <t>Each Aggregator combines the output shares in the batch to compute the
"aggregate share" for that batch, i.e., its share of the desired aggregate
result.</t>
        </li>
        <li>
          <t>The Aggregators submit their aggregate shares to the Collector, who combines
them to obtain the aggregate result over the batch.</t>
        </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>
          <t>Sharding - Each Client generates input shares from its measurement and
distributes them among the Aggregators.</t>
        </li>
        <li>
          <t>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.</t>
        </li>
        <li>
          <t>Aggregation - Each Aggregator combines a sequence of output shares into its
aggregate share and sends the aggregate share to the Collector.</t>
        </li>
        <li>
          <t>Unsharding - The Collector combines the aggregate shares into the aggregate
result.</t>
        </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: int</tt></td>
            <td align="left">Algorithm identifier for this DAF, in <tt>range(2**32)</tt>.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>SHARES: int</tt></td>
            <td align="left">Number of input shares into which each measurement is sharded.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>NONCE_SIZE: int</tt></td>
            <td align="left">Size of the nonce passed by the application.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>RAND_SIZE: int</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>PublicShare</tt></td>
            <td align="left">Type of each public share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>InputShare</tt></td>
            <td align="left">Type of each input share.</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>AggShare</tt></td>
            <td align="left">Type of the aggregate 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 the inputs and outputs of DAF methods at various stages of
the computation. Some of these values need to be written to the network in
order to carry out the computation. In particular, it is <bcp14>RECOMMENDED</bcp14> that
concrete instantiations of the <tt>Daf</tt> interface specify a method of encoding the
<tt>PublicShare</tt>, <tt>InputShare</tt>, and <tt>AggShare</tt>.</t>
      <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>shard</tt> method is used for
this purpose.</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.shard(measurement: Measurement, nonce: bytes, rand: bytes) -&gt;
tuple[PublicShare, list[InputShare]]</tt> is the randomized sharding algorithm
run by each Client that consumes a measurement and nonce and produces a
"public share" distributed to each of the Aggregate and a corresponding
sequence of input shares, one for each Aggregator.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>nonce</tt> <bcp14>MUST</bcp14> have length equal to <tt>NONCE_SIZE</tt> and <bcp14>MUST</bcp14> be generated using
a CSPRNG.</t>
              </li>
              <li>
                <t><tt>rand</tt> consists of the random bytes consumed by the algorithm. It <bcp14>MUST</bcp14> have
length equal to <tt>RAND_SIZE</tt> and <bcp14>MUST</bcp14> be generated using a CSPRNG.</t>
              </li>
            </ul>
            <t>
Post-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t>The number of input shares <bcp14>MUST</bcp14> equal <tt>SHARES</tt>.</t>
              </li>
            </ul>
          </li>
        </ul>
        <figure anchor="shard-flow">
          <name>The Client divides its measurement into input shares and distributes them to the Aggregators. The public share is broadcast to all Aggregators.</name>
          <artwork><![CDATA[
    Client
    ======

    measurement
      |
      V
    +----------------------------------------------+
    | shard                                        |
    +----------------------------------------------+
      |              |              |     |
      |              |         ...  |    public_share
      |              |              |     |
      |    +---------|-----+--------|-----+
      |    |         |     |        |     |
      V    |         V     |        V     |
     input_share_0  input_share_1  input_share_[SHARES-1]
      |    |         |     |   ...  |     |
      V    V         V     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>
            <t><tt>daf.prep(agg_id: int, agg_param: AggParam, nonce: bytes, public_share:
PublicShare, input_share: InputShare) -&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, the
aggregation parameter selected by the Collector, and a nonce and returns an
output share.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>agg_id</tt> <bcp14>MUST</bcp14> be in range <tt>range(SHARES)</tt> and match the index of
<tt>input_share</tt> in the sequence of input shares produced by the Client.</t>
              </li>
              <li>
                <t><tt>nonce</tt> <bcp14>MUST</bcp14> have length <tt>NONCE_SIZE</tt>.</t>
              </li>
            </ul>
          </li>
        </ul>
      </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>
            <t><tt>daf.is_valid(agg_param: AggParam, previous_agg_params: set[AggParam]) -&gt;
bool</tt>: Checks if the <tt>agg_param</tt> is compatible with all elements of
<tt>previous_agg_params</tt>.</t>
          </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>
            <t><tt>daf.aggregate(agg_param: AggParam, out_shares: list[OutShare]) -&gt; AggShare</tt>
is the deterministic aggregation algorithm. It is run by each Aggregator a
set of recovered output shares.</t>
          </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
    +-----------+   +-----------+       +-----------+
    | aggregate |   | aggregate |   ... | aggregate |
    +-----------+   +-----------+       +-----------+
      |               |                   |
      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>
            <t><tt>daf.unshard(agg_param: AggParam, agg_shares: list[AggShare],
num_measurements: int) -&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.</t>
          </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
    +-----------------------------------------------+
    | unshard                                       |
    +-----------------------------------------------+
      |
      V
    agg_result

    Collector
    =========
]]></artwork>
        </figure>
      </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>
          <sourcecode type="python"><![CDATA[
def run_daf(
        daf: Daf[
            Measurement,
            AggParam,
            PublicShare,
            InputShare,
            OutShare,
            AggShare,
            AggResult,
        ],
        agg_param: AggParam,
        measurements: list[Measurement],
        nonces: list[bytes]) -> AggResult:
    """
    Run a DAF on a list of measurements.

    Pre-conditions:

        - `type(agg_param) == daf.AggParam`
        - `type(measurement) == daf.Measurement` for each
          `measurement` in `measurements`
        - `len(nonce) == daf.NONCE_SIZE` for each `nonce` in `nonces`
        - `len(nonces) == len(measurements)`
    """
    if any(len(nonce) != daf.NONCE_SIZE for nonce in nonces):
        raise ValueError("incorrect nonce size")
    if len(nonces) != len(measurements):
        raise ValueError(
            "measurements and nonces lists have different lengths"
        )

    out_shares: list[list[OutShare]]
    out_shares = [[] for j in range(daf.SHARES)]
    for (measurement, nonce) in zip(measurements, nonces):
        # 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.shard(measurement, nonce, rand)

        # Each Aggregator prepares its input share for aggregation.
        for j in range(daf.SHARES):
            out_shares[j].append(
                daf.prep(j, agg_param, nonce,
                         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.aggregate(agg_param,
                                    out_shares[j])
        agg_shares.append(agg_share_j)

    # Collector unshards the aggregate result.
    num_measurements = len(measurements)
    agg_result = daf.unshard(agg_param, agg_shares,
                             num_measurements)
    return agg_result
]]></sourcecode>
        </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>
          <t>Sharding - Computing input shares from an individual measurement</t>
        </li>
        <li>
          <t>Preparation - Conversion and verification of input shares to output shares
compatible with the aggregation function being computed</t>
        </li>
        <li>
          <t>Aggregation - Combining a sequence of output shares into an aggregate share</t>
        </li>
        <li>
          <t>Unsharding - Combining a sequence of aggregate shares into an aggregate
result</t>
        </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>
      <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>PublicShare</tt></td>
            <td align="left">Type of each public share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>InputShare</tt></td>
            <td align="left">Type of each input share.</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>AggShare</tt></td>
            <td align="left">Type of the aggregate share.</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>PrepState</tt></td>
            <td align="left">Aggregator's state during preparation.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PrepShare</tt></td>
            <td align="left">Type of each prep share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PrepMessage</tt></td>
            <td align="left">Type of each prep message.</td>
          </tr>
        </tbody>
      </table>
      <t>Some of these values need to be written to the network in order to carry out
the computation. In particular, it is <bcp14>RECOMMENDED</bcp14> that concrete instantiations
of the <tt>Vdaf</tt> interface specify a method of encoding the <tt>PublicShare</tt>,
<tt>InputShare</tt>, <tt>AggShare</tt>, <tt>PrepShare</tt>, and <tt>PrepMessage</tt>.</t>
      <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>
      <sourcecode type="python"><![CDATA[
def domain_separation_tag(self, usage: int) -> bytes:
    """
    Format domain separation tag for this VDAF with the given usage.

    Pre-conditions:

        - `usage` in `range(2**16)`
    """
    return format_dst(0, self.ID, usage)
]]></sourcecode>
      <t>It is used to construct a domain separation tag for an instance of <tt>Xof</tt> used by
the VDAF. (See <xref target="xof"/>.)</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>
            <t><tt>vdaf.shard(measurement: Measurement, nonce: bytes, rand: bytes) -&gt;
tuple[PublicShare, list[InputShare]]</tt> is the randomized sharding algorithm
run by each Client that consumes a measurement and nonce and produces a
public share distributed to each of the Aggregate and a 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"/>)  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>nonce</tt> <bcp14>MUST</bcp14> have length equal to <tt>NONCE_SIZE</tt> and <bcp14>MUST</bcp14> be generated using
a CSPRNG. (See <xref target="security"/> for details.)</t>
              </li>
              <li>
                <t><tt>rand</tt> consists of the random bytes consumed by the algorithm. It <bcp14>MUST</bcp14> have
length equal to <tt>RAND_SIZE</tt> and <bcp14>MUST</bcp14> be generated using a CSPRNG.</t>
              </li>
            </ul>
            <t>
Post-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t>The number of input shares <bcp14>MUST</bcp14> equal <tt>SHARES</tt>.</t>
              </li>
            </ul>
          </li>
        </ul>
      </section>
      <section anchor="sec-vdaf-prepare">
        <name>Preparation</name>
        <t>To recover and verify output shares, the Aggregators interact with one another
over <tt>ROUNDS</tt> rounds. Prior to each round, each Aggregator constructs an
outbound message. Next, the sequence of outbound messages is combined into a
single message, called a "preparation message", or "prep message" for short.
(Each of the outbound messages are called "preparation-message shares", or
"prep shares" for short.) 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 prep message. Its output in the last round
is its output share and its output in each of the preceding rounds is a prep
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 the measurement shares 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_shares_to_prep                          |   |
    +----------------------------------------------+   |
      |              |              ...  |             |
      V              V                   V             | x ROUNDS
    +-----------+  +-----------+       +-----------+   |
    | prep_next |  | prep_next |       | prep_next |   |
    +-----------+  +-----------+       +-----------+   |
      |              |              ...  |             |
      V              V                   V             /
     ...            ...                 ...
      |              |              ...  |
      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
methods:</t>
        <ul spacing="normal">
          <li>
            <t><tt>vdaf.prep_init(verify_key: bytes, agg_id: int, agg_param: AggParam, nonce:
bytes, public_share: PublicShare, input_share: InputShare) -&gt;
tuple[PrepState, PrepShare]</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 and initial prep share.  </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 <bcp14>MUST</bcp14> ensure that public share consumed by each of the Aggregators is
identical. This is security critical for VDAFs such as Poplar1.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>verify_key</tt> <bcp14>MUST</bcp14> have length <tt>vdaf.VERIFY_KEY_SIZE</tt>.</t>
              </li>
              <li>
                <t><tt>agg_id</tt> <bcp14>MUST</bcp14> be the integer in <tt>range(0, vdaf.SHARES)</tt> that matches the
index of <tt>input_share</tt> in the sequence of input shares output by the
Client.</t>
              </li>
              <li>
                <t><tt>nonce</tt> <bcp14>MUST</bcp14> have length <tt>vdaf.NONCE_SIZE</tt>.</t>
              </li>
            </ul>
          </li>
          <li>
            <t><tt>vdaf.prep_next(prep_state: PrepState, prep_msg: PrepMessage) -&gt;
Union[tuple[PrepState, PrepShare], OutShare]</tt> is the deterministic
preparation-state update algorithm run by each Aggregator. It updates the
Aggregator's preparation state (<tt>prep_state</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.</t>
          </li>
          <li>
            <t><tt>vdaf.prep_shares_to_prep(agg_param: AggParam, prep_shares: list[PrepShare])
-&gt; PrepMessage</tt> is the deterministic preparation-message pre-processing
algorithm. It combines the prep shares generated by the Aggregators in the
previous round into the prep message consumed by each in the next round.</t>
          </li>
        </ul>
        <t>In effect, each Aggregator moves through a linear state machine with <tt>ROUNDS</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>
        <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>
      </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>
            <t><tt>vdaf.is_valid(agg_param: AggParam, previous_agg_params: list[AggParam]) -&gt;
bool</tt>: Checks if the <tt>agg_param</tt> is compatible with all elements of
<tt>previous_agg_params</tt>.</t>
          </li>
        </ul>
      </section>
      <section anchor="sec-vdaf-aggregate">
        <name>Aggregation</name>
        <t>VDAF Aggregation is identical to DAF Aggregation (cf. <xref target="sec-daf-aggregate"/>):</t>
        <ul spacing="normal">
          <li>
            <t><tt>vdaf.aggregate(agg_param: AggParam, out_shares: list[OutShare]) -&gt; AggShare</tt>
is the deterministic aggregation algorithm. It is run by each Aggregator over
the output shares it has computed for a batch of measurements.</t>
          </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>
            <t><tt>vdaf.unshard(agg_param: AggParam, agg_shares: list[AggShare],
num_measurements: int) -&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.</t>
          </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>
          <sourcecode type="python"><![CDATA[
def run_vdaf(
        vdaf: Vdaf[
            Measurement,
            AggParam,
            PublicShare,
            InputShare,
            list[F],  # OutShare
            AggShare,
            AggResult,
            PrepState,
            PrepShare,
            PrepMessage,
        ],
        verify_key: bytes,
        agg_param: AggParam,
        nonces: list[bytes],
        measurements: list[Measurement]) -> AggResult:
    """
    Run the VDAF on a list of measurements.

    Pre-conditions:

        - `len(verify_key) == vdaf.VERIFY_KEY_SIZE`
        - `len(nonces) == len(measurements)`
        - `all(len(nonce) == vdaf.NONCE_SIZE for nonce in nonces)`
    """

    if len(verify_key) != vdaf.VERIFY_KEY_SIZE:
        raise ValueError("incorrect verify_key size")
    if any(len(nonce) != vdaf.NONCE_SIZE for nonce in nonces):
        raise ValueError("incorrect nonce size")
    if len(nonces) != len(measurements):
        raise ValueError(
            "measurements and nonces lists have different lengths"
        )

    out_shares = []
    for (nonce, measurement) in zip(nonces, measurements):
        assert len(nonce) == vdaf.NONCE_SIZE

        # Each Client shards its measurement into input shares.
        rand = gen_rand(vdaf.RAND_SIZE)
        (public_share, input_shares) = \
            vdaf.shard(measurement, nonce, rand)

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

        # Aggregators recover their output shares.
        for i in range(vdaf.ROUNDS - 1):
            prep_msg = vdaf.prep_shares_to_prep(agg_param,
                                                outbound_prep_shares)
            outbound_prep_shares = []
            for j in range(vdaf.SHARES):
                out = vdaf.prep_next(prep_states[j], prep_msg)
                assert isinstance(out, tuple)
                (prep_states[j], prep_share) = out
                outbound_prep_shares.append(prep_share)

        # The final outputs of the prepare phase are the output
        # shares.
        prep_msg = vdaf.prep_shares_to_prep(agg_param,
                                            outbound_prep_shares)

        outbound_out_shares = []
        for j in range(vdaf.SHARES):
            out_share = vdaf.prep_next(prep_states[j], prep_msg)
            assert not isinstance(out_share, tuple)
            outbound_out_shares.append(out_share)
        out_shares.append(outbound_out_shares)

    # 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.aggregate(agg_param, out_shares_j)
        agg_shares.append(agg_share_j)

    # Collector unshards the aggregate.
    num_measurements = len(measurements)
    agg_result = vdaf.unshard(agg_param, agg_shares,
                              num_measurements)
    return agg_result
]]></sourcecode>
        </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 anchor="vdaf-prep-comm">
        <name>Communication Patterns for Preparation</name>
        <t>In each round of preparation, each Aggregator writes a prep share to some
broadcast channel, which is then processed into the prep message using the
public <tt>prep_shares_to_prep()</tt> algorithm and broadcast to the Aggregators to
start the next round. In this section we describe some approaches to realizing
this broadcast channel functionality in protocols that use VDAFs.</t>
        <t>The state machine of each Aggregator is shown in <xref target="vdaf-prep-state-machine"/>.</t>
        <figure anchor="vdaf-prep-state-machine">
          <name>State machine for VDAF preparation.</name>
          <artwork><![CDATA[
               +----------------+
               |                |
               v                |
Start ------> Continued(prep_state) --> Finished(out_share)
 |                |
 |                |
 +--> Rejected <--+
]]></artwork>
        </figure>
        <t>State transitions are made when the state is acted upon by the host's local
inputs and/or messages sent by the peers. The initial state is <tt>Start</tt>. The
terminal states are <tt>Rejected</tt>, which indicates that the report cannot be
processed any further, and <tt>Finished(out_share)</tt>, which indicates that the
Aggregator has recovered an output share <tt>out_share</tt>.</t>
        <sourcecode type="pseudocode"><![CDATA[
class State:
    pass

class Start(State):
    pass

class Continued(State):
    def __init__(self, prep_state):
        self.prep_state = prep_state

class Finished(State):
    def __init__(self, output_share):
        self.output_share = output_share

class Rejected(State):
    def __init__(self):
        pass
]]></sourcecode>
        <t>Note that there is no representation of the <tt>Start</tt> state as it is never
instantiated in the ping-pong topology.</t>
        <t>For convenience, the methods described in this section are defined in terms of
opaque byte strings. A compatible <tt>Vdaf</tt> <bcp14>MUST</bcp14> specify methods for encoding
public shares, input shares, prep shares, prep messages, and aggregation
parameters. Minimally:</t>
        <ul spacing="normal">
          <li>
            <t><tt>vdaf.decode_public_share(encoded: bytes) -&gt; PublicShare</tt> decodes a
public share.</t>
          </li>
          <li>
            <t><tt>vdaf.decode_input_share(agg_id: int, encoded: bytes) -&gt; InputShare</tt>
decodes an input share, using the aggregator ID as optional
context.</t>
          </li>
          <li>
            <t><tt>vdaf.encode_prep_share(prep_share: PrepShare) -&gt; bytes</tt> encodes a prep
share.</t>
          </li>
          <li>
            <t><tt>vdaf.decode_prep_share(prep_state: PrepState, encoded: bytes) -&gt;
PrepShare</tt> decodes a prep share, using the prep state as optional
context.</t>
          </li>
          <li>
            <t><tt>vdaf.encode_prep_msg(prep_msg: PrepMessage) -&gt; bytes</tt> encodes a prep
message.</t>
          </li>
          <li>
            <t><tt>vdaf.decode_prep_msg(prep_state: PrepState, encoded: bytes) -&gt;
PrepMessage</tt> decodes a prep message, using the prep state as optional
decoding context.</t>
          </li>
          <li>
            <t><tt>vdaf.decode_agg_param(encoded: bytes) -&gt; AggParam</tt> decodes an
aggregation parameter.</t>
          </li>
          <li>
            <t><tt>vdaf.encode_agg_param(agg_param: AggParam) -&gt; bytes</tt> encodes an
aggregation parameter.</t>
          </li>
        </ul>
        <t>Implementations of Prio3 and Poplar1 <bcp14>MUST</bcp14> use the encoding scheme specified in
<xref target="prio3-encode"/> and <xref target="poplar1-encode"/> respectively.</t>
      </section>
      <section anchor="ping-pong-topology-only-two-aggregators">
        <name>Ping-Pong Topology (Only Two Aggregators)</name>
        <t>For VDAFs with precisely two Aggregators (i.e., <tt>SHARES == 2</tt>), the following
"ping pong" communication pattern can be used. It is compatible with any
request/response transport protocol, such as HTTP.</t>
        <t>Let us call the initiating party the "Leader" and the responding party the
"Helper". The high-level idea is that the Leader and Helper will take turns
running the computation locally until input from their peer is required:</t>
        <ul spacing="normal">
          <li>
            <t>For a 1-round VDAF (e.g., Prio3 (<xref target="prio3"/>)), the Leader sends its prep share
to the Helper, who computes the prep message locally, computes its output
share, then sends the prep message to the Leader. Preparation requires just
one round trip between the Leader and the Helper.</t>
          </li>
          <li>
            <t>For a 2-round VDAF (e.g., Poplar1 (<xref target="poplar1"/>)), the Leader sends its
first-round prep share to the Helper, who replies with the first-round prep
message and its second-round prep share. In the next request, the Leader
computes its second-round prep share locally, computes its output share, and
sends the second-round prep message to the Helper. Finally, the Helper
computes its own output share.</t>
          </li>
          <li>
            <t>In general, each request includes the Leader's prep share for the previous
round and/or the prep message for the current round; correspondingly, each
response consists of the prep message for the current round and the Helper's
prep share for the next round.</t>
          </li>
        </ul>
        <t>The Aggregators proceed in this ping-ponging fashion until a step of the
computation fails (indicating the report is invalid and should be rejected) or
preparation is completed. All told there there are <tt>ceil((ROUNDS+1)/2)</tt>
requests sent.</t>
        <t>Each message in the ping-pong protocol is structured as follows (expressed in
TLS syntax as defined in <xref section="3" sectionFormat="of" target="RFC8446"/>):</t>
        <sourcecode type="tls-presentation"><![CDATA[
enum {
  initialize(0),
  continue(1),
  finish(2),
  (255)
} MessageType;

struct {
  MessageType type;
  select (Message.type) {
    case initialize:
      opaque prep_share<0..2^32-1>;
    case continue:
      opaque prep_msg<0..2^32-1>;
      opaque prep_share<0..2^32-1>;
    case finish:
      opaque prep_msg<0..2^32-1>;
  };
} Message;
]]></sourcecode>
        <t>These messages are used to transition between the states described in
<xref target="vdaf-prep-comm"/>. They are encoded and decoded to or from byte buffers as
described <xref section="3" sectionFormat="of" target="RFC8446"/>) using the following routines:</t>
        <ul spacing="normal">
          <li>
            <t><tt>encode_ping_pong_message(message: Message) -&gt; bytes</tt> encodes a <tt>Message</tt> into
an opaque byte buffer.</t>
          </li>
          <li>
            <t><tt>decode_pong_pong_message(encoded: bytes) -&gt; Message</tt> decodes an opaque byte
buffer into a <tt>Message</tt>, raising an error if the bytes are not a valid
encoding.</t>
          </li>
        </ul>
        <t>The Leader's initial transition is computed with the following procedure:</t>
        <sourcecode type="pseudocode"><![CDATA[
def ping_pong_leader_init(
            vdaf,
            vdaf_verify_key: bytes,
            agg_param: bytes,
            nonce: bytes,
            public_share: bytes,
            input_share: bytes,
        ) -> tuple[State, bytes]:
    try:
        (prep_state, prep_share) = vdaf.prep_init(
            vdaf_verify_key,
            0,
            vdaf.decode_agg_param(agg_param),
            nonce,
            vdaf.decode_public_share(public_share),
            vdaf.decode_input_share(0, input_share),
        )
        outbound = Message.initialize(
            vdaf.encode_prep_share(prep_share))
        return (
            Continued(prep_state),
            encode_ping_pong_message(outbound),
        )
    except:
        return (Rejected(), None)
]]></sourcecode>
        <t>The output is the <tt>State</tt> to which the Leader has transitioned and an encoded
<tt>Message</tt>. If the Leader's state is <tt>Rejected</tt>, then processing halts.
Otherwise, if the state is <tt>Continued</tt>, then processing continues.</t>
        <t>The Leader sends the outbound message to the Helper. The Helper's initial
transition is computed using the following procedure:</t>
        <sourcecode type="pseudocode"><![CDATA[
def ping_pong_helper_init(
            vdaf,
            vdaf_verify_key: bytes,
            agg_param: bytes,
            nonce: bytes,
            public_share: bytes,
            input_share: bytes,
            inbound_encoded: bytes,
        ) -> tuple[State, bytes]:
    try:
        (prep_state, prep_share) = vdaf.prep_init(
            vdaf_verify_key,
            1,
            vdaf.decode_agg_param(agg_param),
            nonce,
            vdaf.decode_public_share(public_share),
            vdaf.decode_input_share(1, input_share),
        )

        inbound = decode_ping_pong_message(inbound_encoded)

        if inbound.type != 0: # initialize
            return (Rejected(), None)

        prep_shares = [
            vdaf.decode_prep_share(prep_state, inbound.prep_share),
            prep_share,
        ]
        return vdaf.ping_pong_transition(
            agg_param,
            prep_shares,
            prep_state,
        )
    except:
        return (Rejected(), None)
]]></sourcecode>
        <t>Procedure <tt>ping_pong_transition()</tt> takes in the prep shares, combines them into
the prep message, and computes the next prep state of the caller:</t>
        <sourcecode type="pseudocode"><![CDATA[
def ping_pong_transition(
            vdaf,
            agg_param: AggParam,
            prep_shares: list[PrepShare],
            prep_state: PrepState,
         ) -> (State, bytes):
    prep_msg = vdaf.prep_shares_to_prep(agg_param,
                                        prep_shares)
    out = vdaf.prep_next(prep_state, prep_msg)
    if type(out) == OutShare:
        outbound = Message.finish(vdaf.encode_prep_msg(prep_msg))
        return (Finished(out), encode_ping_pong_message(outbound))
    (prep_state, prep_share) = out
    outbound = Message.continue(
        vdaf.encode_prep_msg(prep_msg),
        vdaf.encode_prep_share(prep_share),
    )
    return (
        Continued(prep_state),
        encode_ping_pong_message(outbound),
    )
]]></sourcecode>
        <t>The output is the <tt>State</tt> to which the Helper has transitioned and an encoded
<tt>Message</tt>. If the Helper's state is <tt>Finished</tt> or <tt>Rejected</tt>, then processing
halts. Otherwise, if the state is <tt>Continued</tt>, then processing continues.</t>
        <t>Next, the Helper sends the outbound message to the Leader. The Leader computes
its next state transition using the function <tt>ping_pong_leader_continued</tt>:</t>
        <sourcecode type="pseudocode"><![CDATA[
def ping_pong_leader_continued(
            vdaf,
            agg_param: bytes,
            state: State,
            inbound_encoded: bytes,
        ) -> (State, Optional[bytes]):
    return vdaf.ping_pong_continued(
        True,
        agg_param,
        state,
        inbound_encoded,
    )

def ping_pong_continued(
            vdaf,
            is_leader: bool,
            agg_param: bytes,
            state: State,
            inbound_encoded: bytes,
        ) -> (State, Optional[bytes]):
    try:
        inbound = decode_ping_pong_message(inbound_encoded)

        if inbound.type == 0: # initialize
            return (Rejected(), None)

        if !isinstance(state, Continued):
            return (Rejected(), None)

        prep_msg = vdaf.decode_prep_msg(
            state.prep_state,
            inbound.prep_msg,
        )
        out = vdaf.prep_next(state.prep_state, prep_msg)
        if type(out) == tuple[PrepState, PrepShare] \
                and inbound.type == 1:
            # continue
            (prep_state, prep_share) = out
            prep_shares = [
                vdaf.decode_prep_share(
                    prep_state,
                    inbound.prep_share,
                ),
                prep_share,
            ]
            if is_leader:
                prep_shares.reverse()
            return vdaf.ping_pong_transition(
                vdaf.decode_agg_param(agg_param),
                prep_shares,
                prep_state,
            )
        elif type(out) == OutShare and inbound.type == 2:
            # finish
            return (Finished(out), None)
        else:
            return (Rejected(), None)

    except:
        return (Rejected(), None)
]]></sourcecode>
        <t>If the Leader's state is <tt>Finished</tt> or <tt>Rejected</tt>, then processing halts.
Otherwise, the Leader sends the outbound message to the Helper. The Helper
computes its next state transition using the function
<tt>ping_pong_helper_continued</tt>:</t>
        <sourcecode type="pseudocode"><![CDATA[
def ping_pong_helper_continued(
            vdaf,
            agg_param: bytes,
            state: State,
            inbound_encoded: bytes,
        ) -> (State, Optional[bytes]):
    return vdaf.ping_pong_continued(
        False,
        agg_param,
        state,
        inbound_encoded,
    )
]]></sourcecode>
        <t>They continue in this way until processing halts. Note that, depending on the
number of rounds of preparation that are required, there may be one more
message to send before the peer can also finish processing (i.e., <tt>outbound !=
None</tt>).</t>
      </section>
      <section anchor="star-topology-any-number-of-aggregators">
        <name>Star Topology (Any Number of Aggregators)</name>
        <t>The ping-pong topology of the previous section is only suitable for VDAFs
involving exactly two Aggregators. If more Aggregators are required, the star
topology described in this section can be used instead.</t>
        <ul empty="true">
          <li>
            <t>TODO Describe the Leader-emulated broadcast channel architecture that was
originally envisioned for DAP. (As of DAP-05 we are going with the ping pong
architecture described in the previous section.)</t>
          </li>
        </ul>
      </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>
            <t><tt>MODULUS: int</tt> is the prime modulus that defines the field.</t>
          </li>
          <li>
            <t><tt>ENCODED_SIZE: int</tt> is the number of bytes used to encode a field element
as a byte string.</t>
          </li>
        </ul>
        <t>A concrete <tt>Field</tt> also implements the following class methods:</t>
        <ul spacing="normal">
          <li>
            <t><tt>Field.zeros(length: int) -&gt; list[Self]</tt> returns a vector of
zeros.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>length</tt> <bcp14>MUST</bcp14> be greater than or equal <tt>0</tt>.</t>
              </li>
            </ul>
            <t>
Post-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t>The length of the output <bcp14>MUST</bcp14> be <tt>length</tt>.</t>
              </li>
            </ul>
          </li>
          <li>
            <t><tt>Field.rand_vec(length: int) -&gt; list[Self]</tt> returns a vector of
random field elements. Same pre- and post-conditions as for <tt>Field.zeros()</tt>.</t>
          </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>
            <t><tt>elem.as_unsigned() -&gt; int</tt> returns the integer representation of
field element <tt>elem</tt>.</t>
          </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>
            <t><tt>Field(integer: int)</tt> returns <tt>integer</tt> represented as a field element.
The value of <tt>integer</tt> <bcp14>MUST</bcp14> be non-negative and less than <tt>Field.MODULUS</tt>.</t>
          </li>
        </ul>
        <t>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>
          <sourcecode type="python"><![CDATA[
def encode_vec(cls, vec: list[Self]) -> bytes:
    """
    Encode a vector of field elements `vec` as a byte string.
    """
    encoded = bytes()
    for x in vec:
        encoded += to_le_bytes(x.as_unsigned(), cls.ENCODED_SIZE)
    return encoded

def decode_vec(cls, encoded: bytes) -> list[Self]:
    """
    Parse a vector of field elements from `encoded`.
    """
    L = cls.ENCODED_SIZE
    if len(encoded) % L != 0:
        raise ValueError(
            'input length must be a multiple of the size of an '
            'encoded field element')

    vec = []
    for i in range(0, len(encoded), L):
        encoded_x = encoded[i:i+L]
        x = from_le_bytes(encoded_x)
        if x >= cls.MODULUS:
            raise ValueError('modulus overflow')
        vec.append(cls(x))
    return vec
]]></sourcecode>
        </figure>
        <t>Finally, <tt>Field</tt> implements the following methods for representing a value as
a sequence of field elements, each of which represents a bit of the input.</t>
        <figure anchor="field-bit-rep">
          <name>Derived class methods to encode integers into bit vector representation.</name>
          <sourcecode type="python"><![CDATA[
def encode_into_bit_vector(
        cls,
        val: int,
        bits: int) -> list[Self]:
    """
    Encode the bit representation of `val` with at most `bits` number
    of bits, as a vector of field elements.

    Pre-conditions:

        - `val >= 0`
        - `bits >= 0`
    """
    if val >= 2 ** bits:
        # Sanity check we are able to represent `val` with `bits`
        # number of bits.
        raise ValueError("Number of bits is not enough to represent "
                         "the input integer.")
    encoded = []
    for l in range(bits):
        encoded.append(cls((val >> l) & 1))
    return encoded

def decode_from_bit_vector(cls, vec: list[Self]) -> Self:
    """
    Decode the field element from the bit representation, expressed
    as a vector of field elements `vec`.
    """
    bits = len(vec)
    if cls.MODULUS >> bits == 0:
        raise ValueError("Number of bits is too large to be "
                         "represented by field modulus.")
    decoded = cls(0)
    for (l, bit) in enumerate(vec):
        decoded += cls(1 << l) * bit
    return decoded
]]></sourcecode>
        </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>
            <sourcecode type="python"><![CDATA[
def vec_sub(left: list[F], right: list[F]) -> list[F]:
    """
    Subtract the right operand from the left and return the result.
    """
    if len(left) != len(right):
        raise ValueError("mismatched vector sizes")
    return list(map(lambda x: x[0] - x[1], zip(left, right)))

def vec_add(left: list[F], right: list[F]) -> list[F]:
    """Add the right operand to the left and return the result."""
    if len(left) != len(right):
        raise ValueError("mismatched vector sizes")
    return list(map(lambda x: x[0] + x[1], zip(left, right)))

def vec_neg(vec: list[F]) -> list[F]:
    """Negate the input vector."""
    return list(map(lambda x: -x, vec))
]]></sourcecode>
          </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 FLP of
<xref target="flp-bbcggi19-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>
              <t><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>.</t>
            </li>
          </ul>
          <t>FFT-friendly fields also define the following parameter:</t>
          <ul spacing="normal">
            <li>
              <t><tt>GEN_ORDER: int</tt> is the order of a multiplicative subgroup generated by
<tt>Field.gen()</tt>.</t>
            </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>
        </section>
      </section>
      <section anchor="xof">
        <name>Extendable Output Functions</name>
        <t>VDAFs in this specification use extendable output functions (XOFs) to extract
short, fixed-length strings we call "seeds" from long input strings and expand
seeds into long output strings. We specify a single interface that is suitable
for both purposes.</t>
        <t>XOFs are defined by a class <tt>Xof</tt> with the following associated parameter and
methods:</t>
        <ul spacing="normal">
          <li>
            <t><tt>SEED_SIZE: int</tt> is the size (in bytes) of a seed.</t>
          </li>
          <li>
            <t><tt>Xof(seed: bytes, dst: bytes, binder: bytes)</tt> constructs an instance of <tt>Xof</tt>
from the given seed, domain separation tag, and binder string. (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 a CSPRNG or a previous
invocation of the XOF).</t>
          </li>
          <li>
            <t><tt>xof.next(length: int)</tt> returns the next <tt>length</tt> bytes of output of
<tt>xof</tt>.</t>
          </li>
        </ul>
        <t>Each <tt>Xof</tt> has three derived methods. The first is used to derive a fresh seed
from an existing one. The second is used to compute a sequence of field
elements. The third is a convenience method to construct an <tt>Xof</tt> from a seed,
domain separation tag, and binder string, and then use it to compute a sequence
of field elements.</t>
        <figure anchor="xof-derived-methods">
          <name>Derived methods for XOFs.</name>
          <sourcecode type="python"><![CDATA[
def derive_seed(cls,
                seed: bytes,
                dst: bytes,
                binder: bytes) -> bytes:
    """
    Derive a new seed.

    Pre-conditions:

        - `len(seed) == Xof.SEED_SIZE`
    """
    xof = cls(seed, dst, binder)
    return xof.next(cls.SEED_SIZE)

def next_vec(self, field: type[F], length: int) -> list[F]:
    """
    Output the next `length` field elements.

    Pre-conditions:

        - `field` is sub-class of `Field`
        - `length > 0`
    """
    m = next_power_of_2(field.MODULUS) - 1
    vec: list[F] = []
    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

def expand_into_vec(cls,
                    field: type[F],
                    seed: bytes,
                    dst: bytes,
                    binder: bytes,
                    length: int) -> list[F]:
    """
    Expand the input `seed` into vector of `length` field elements.

    Pre-conditions:

        - `field` is sub-class of `Field`
        - `len(seed) == Xof.SEED_SIZE`
        - `length > 0`
    """
    xof = cls(seed, dst, binder)
    return xof.next_vec(field, length)
]]></sourcecode>
        </figure>
        <section anchor="xof-turboshake128">
          <name>XofTurboShake128</name>
          <t>This section describes XofTurboShake128, an XOF based on the
TurboSHAKE128 <xref target="TurboSHAKE"/>. This
XOF is <bcp14>RECOMMENDED</bcp14> for all use cases within VDAFs. The length of the
domain separation string <tt>dst</tt> passed to XofTurboShake128 <bcp14>MUST NOT</bcp14>
exceed 255 bytes.</t>
          <figure>
            <name>Definition of XOF XofTurboShake128.</name>
            <sourcecode type="python"><![CDATA[
class XofTurboShake128(Xof):
    """XOF wrapper for TurboSHAKE128."""

    # Associated parameters
    SEED_SIZE = 16

    def __init__(self, seed: bytes, dst: bytes, binder: bytes):
        self.l = 0
        self.m = to_le_bytes(len(dst), 1) + dst + seed + binder

    def next(self, length: int) -> bytes:
        self.l += length

        # Function `TurboSHAKE128(M, D, L)` is as defined in
        # Section 2.2 of [TurboSHAKE].
        #
        # Implementation note: Rather than re-generate the output
        # stream each time `next()` is invoked, most implementations
        # of TurboSHAKE128 will expose an "absorb-then-squeeze" API
        # that allows stateful handling of the stream.
        stream = TurboSHAKE128(self.m, 1, self.l)
        return stream[-length:]
]]></sourcecode>
          </figure>
        </section>
        <section anchor="xof-fixed-key-aes128">
          <name>XofFixedKeyAes128</name>
          <t>While XofTurboShake128 as described above can be securely used in all cases
where a XOF 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 XOF used inside the Idpf <xref target="idpf"/>
implementation in Poplar1 <xref target="idpf-bbcggi21"/>. It is <bcp14>NOT RECOMMENDED</bcp14> to use this
XOF anywhere else. The length of the domain separation string <tt>dst</tt> passed to
XofFixedKeyAes128 <bcp14>MUST NOT</bcp14> exceed 255 bytes. See Security Considerations
<xref target="security"/> for a more detailed discussion.</t>
          <sourcecode type="python"><![CDATA[
class XofFixedKeyAes128(Xof):
    """
    XOF based on a circular collision-resistant hash function from
    fixed-key AES.
    """

    # Associated parameters
    SEED_SIZE = 16

    def __init__(self, seed: bytes, dst: bytes, binder: bytes):
        if len(seed) != self.SEED_SIZE:
            raise ValueError("incorrect seed size")

        self.length_consumed = 0

        # Use TurboSHAKE128 to derive a key from the binder string
        # and domain separation tag. Note that the AES key does not
        # need to be kept secret from any party. However, when used
        # with an IDPF, we require the binder to be a random nonce.
        #
        # Implementation note: This step can be cached across XOF
        # evaluations with many different seeds.
        dst_length = to_le_bytes(len(dst), 1)
        self.fixed_key = TurboSHAKE128(
            dst_length + dst + binder,
            2,
            16,
        )
        self.seed = seed

    def next(self, length: int) -> bytes:
        offset = self.length_consumed % 16
        new_length = self.length_consumed + length
        block_range = range(
            self.length_consumed // 16,
            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]

    def hash_block(self, block: bytes) -> bytes:
        """
        The multi-instance tweakable circular correlation-robust hash
        function of [GKWWY20] (Section 4.2). The tweak here is the
        key that stays constant for all XOF evaluations of the same
        Client, but differs between Clients.

        Function `AES128(key, block)` is the AES-128 blockcipher.
        """
        lo, hi = block[:8], block[8:]
        sigma_block = concat([hi, xor(hi, lo)])
        return xor(AES128(self.fixed_key, sigma_block), sigma_block)
]]></sourcecode>
        </section>
        <section anchor="the-domain-separation-tag-and-binder-string">
          <name>The Domain Separation Tag and Binder String</name>
          <t>XOFs 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 domain separation tag. The domain separation tag
encodes the following values:</t>
          <ol spacing="normal" type="1"><li>
              <t>The document version (i.e.,<tt>VERSION</tt>);</t>
            </li>
            <li>
              <t>The "class" of the algorithm using the output (e.g., VDAF);</t>
            </li>
            <li>
              <t>A unique identifier for the algorithm; and</t>
            </li>
            <li>
              <t>Some indication of how the output is used (e.g., for deriving the measurement
shares in Prio3 <xref target="prio3"/>).</t>
            </li>
          </ol>
          <t>The following algorithm is used in the remainder of this document in order to
format the domain separation tag:</t>
          <sourcecode type="python"><![CDATA[
def format_dst(algo_class: int,
               algo: int,
               usage: int) -> bytes:
    """
    Format XOF domain separation tag for use within a (V)DAF.

    Pre-conditions:

        - `algo_class` in `range(0, 2 ** 8)`
        - `algo` in `range(0, 2 ** 32)`
        - `usage` in `range(0, 2 ** 16)`
    """
    return concat([
        to_be_bytes(VERSION, 1),
        to_be_bytes(algo_class, 1),
        to_be_bytes(algo, 4),
        to_be_bytes(usage, 2),
    ])
]]></sourcecode>
          <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>
          <t>Each measurement is encoded as a vector over some finite field.</t>
        </li>
        <li>
          <t>Measurement validity is determined by an arithmetic circuit evaluated over
the encoded measurement. (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 measurement is said to be "valid"; otherwise, if
the output is non-zero, then the measurement is said to be "invalid".</t>
        </li>
        <li>
          <t>The aggregate result is obtained by summing up the encoded measurement
vectors and computing some function of the sum.</t>
        </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 measurement (as determined by the arithmetic
circuit). This computation involves a "proof" of validity generated by the
Client. Next, each Aggregator sums up its 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 measurement 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 measurements. 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-bbcggi19"/>. 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 measurement's validity and
distributes shares of the proof to the Aggregators. Each Aggregator then
performs some computation on its measurement 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 measurement.
(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>MEAS_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 measurement 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">Class object for the field (<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>
            <t><tt>flp.prove(meas: list[F], prove_rand: list[F], joint_rand: list[F]) -&gt;
list[F]</tt> is the deterministic proof-generation algorithm run by the prover.
Its inputs are the encoded measurement, 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.</t>
          </li>
          <li>
            <t><tt>flp.query(meas: list[F], proof: list[F], query_rand: list[F], joint_rand:
list[F], num_shares: int) -&gt; list[F]</tt> is the query-generation algorithm run
by the verifier. This is used to "query" the measurement and proof. The
result of the query (i.e., the output of this function) is called the
"verifier message". In addition to the measurement 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 shares were generated.</t>
          </li>
          <li>
            <t><tt>flp.decide(verifier: list[F]) -&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 measurement from which it was generated
is valid.</t>
          </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 measurement and proof, the query-generation algorithm
outputs a share of the verifier message. Furthermore, the privacy property of
the FLP system ensures that the verifier message reveals nothing about the measurement
other than whether it is valid. Therefore, to decide if a measurement 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 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-bbcggi19"/> 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 measurement, 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>
          <sourcecode type="python"><![CDATA[
def run_flp(
        flp: Flp[Measurement, AggResult, F],
        meas: list[F],
        num_shares: int) -> bool:
    """Run the FLP on an encoded measurement."""

    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(meas, prove_rand, joint_rand)

    # Shard the measurement and the proof.
    meas_shares = additive_secret_share(
        meas,
        num_shares,
        flp.field,
    )
    proof_shares = additive_secret_share(
        proof,
        num_shares,
        flp.field,
    )

    # Verifier queries the meas shares and proof shares.
    verifier_shares = [
        flp.query(
            meas_share,
            proof_share,
            query_rand,
            joint_rand,
            num_shares,
        )
        for meas_share, proof_share in zip(meas_shares, proof_shares)
    ]

    # Combine the verifier shares into the verifier.
    verifier = flp.field.zeros(len(verifier_shares[0]))
    for verifier_share in verifier_shares:
        verifier = vec_add(verifier, verifier_share)

    # Verifier decides if the measurement is valid.
    return flp.decide(verifier)
]]></sourcecode>
        </figure>
        <t>The proof system is constructed so that, if <tt>meas</tt> is valid, then <tt>run_flp(flp,
meas, 1)</tt> always returns <tt>True</tt>. On the other hand, if <tt>meas</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 high probability. False positives are possible: there is
a small probability that a verifier accepts an invalid input as valid. An FLP
is said to be "sound" if this probability is sufficiently small. The soundness
of the FLP depends on a variety of parameters, like the length of the
input and the size of the field. See <xref target="flp-bbcggi19"/> for details.</t>
        <t>Note that soundness of an FLP system is not the same as robustness for a VDAF
In particular, soundness of the FLP is necessary, but insufficient for
robusntess of Prio3 (<xref target="prio3"/>). See <xref target="security-multiproof"/> for details.</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>
              <t><tt>flp.encode(measurement: Measurement) -&gt; list[F]</tt> encodes a raw measurement
as a vector of field elements. The return value <bcp14>MUST</bcp14> be of length <tt>MEAS_LEN</tt>.</t>
            </li>
          </ul>
          <t>For some FLPs, the encoded measurement 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, each representing a bit of the integer (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
encoded measurement to the length of the aggregated output:</t>
          <ul spacing="normal">
            <li>
              <t><tt>flp.truncate(meas: list[F]) -&gt; list[F]</tt> maps an encoded measurement (e.g.,
the bit-encoding of the measurement) to an aggregatable output (e.g., the
singleton vector containing the measurement). The length of the input <bcp14>MUST</bcp14> be
<tt>MEAS_LEN</tt> and the length of the output <bcp14>MUST</bcp14> be <tt>OUTPUT_LEN</tt>.</t>
            </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>
              <t><tt>flp.decode(output: list[F], num_measurements: int) -&gt; AggResult</tt> maps a sum
of aggregate shares to an aggregate result.  </t>
              <t>
Pre-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The length of <tt>output</tt> <bcp14>MUST</bcp14> be <tt>OUTPUT_LEN</tt>.</t>
                </li>
                <li>
                  <t><tt>num_measurements</tt> <bcp14>MUST</bcp14> equal the number of measurements that contributed
to the <tt>output</tt>.</t>
                </li>
              </ul>
            </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 anchor="multiproofs">
          <name>Multiple Proofs</name>
          <t>It is sometimes desirable to generate and verify multiple independent proofs
for the same input. First, this improves the soundness of the proof system
without having to change any of its parameters. Second, it allows a smaller
field to be used (e.g., replace Field128 with Field64, see <xref target="flp-bbcggi19"/>)
without sacrificing soundness. Generally, choosing a smaller field can
significantly reduce communication cost. (This is a trade-off, of course, since
generating and verifying more proofs requires more time.) Given these benefits,
this feature is implemented by Prio3 (<xref target="prio3"/>).</t>
          <t>To generate these proofs for a specific measurement, the prover calls
<tt>flp.prove</tt> multiple times, each time using an independently generated prover
and joint randomness string. The verifier checks each proof independently, each
time with an independently generated query randomness string. It accepts the
measurement only if all the decision algorithm accepts on each proof.</t>
          <t>See <xref target="security-multiproof"/> below for discussions on choosing the right number
of proofs.</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 three generic parameters: an <tt>FftField ({{fft-field}}), an
</tt>Flp<tt> ({{flp}}) and a </tt>Xof<tt> ({{xof}}). It also has an associated constant,
</tt>PROOFS<tt>, with a value within the range of </tt>[1, 256)`, denoting the number of
FLPs generated by the Client (<xref target="multiproofs"/>).</t>
        <t>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>Xof.SEED_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>RAND_SIZE</tt></td>
              <td align="left">
                <tt>Xof.SEED_SIZE * (1 + 2 * (SHARES - 1)) if flp.JOINT_RAND_LEN == 0 else Xof.SEED_SIZE * (1 + 2 * (SHARES - 1) + SHARES)</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>PublicShare</tt></td>
              <td align="left">
                <tt>Optional[list[bytes]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>InputShare</tt></td>
              <td align="left">
                <tt>Union[tuple[list[F], list[F], Optional[bytes]], tuple[bytes, bytes, Optional[bytes]]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>OutShare</tt></td>
              <td align="left">
                <tt>list[F]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggShare</tt></td>
              <td align="left">
                <tt>list[F]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">
                <tt>Flp.AggResult</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepState</tt></td>
              <td align="left">
                <tt>tuple[list[F], Optional[bytes]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepShare</tt></td>
              <td align="left">
                <tt>tuple[list[F], Optional[bytes]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepMessage</tt></td>
              <td align="left">
                <tt>Optional[bytes]</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>USAGE_MEAS_SHARE: int</tt></td>
              <td align="left">1</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_PROOF_SHARE: int</tt></td>
              <td align="left">2</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_JOINT_RANDOMNESS: int</tt></td>
              <td align="left">3</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_PROVE_RANDOMNESS: int</tt></td>
              <td align="left">4</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_QUERY_RANDOMNESS: int</tt></td>
              <td align="left">5</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_JOINT_RAND_SEED: int</tt></td>
              <td align="left">6</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_JOINT_RAND_PART: int</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
measurement in a way that allows the Aggregators to reconstruct it from their
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>
              <t>Encode the Client's measurement for the FLP</t>
            </li>
            <li>
              <t>Shard the measurement into a sequence of measurement shares</t>
            </li>
            <li>
              <t>Derive the joint randomness from the measurement shares and nonce</t>
            </li>
            <li>
              <t>Run the FLP proof-generation algorithm using the derived joint randomness</t>
            </li>
            <li>
              <t>Shard the proof into a sequence of proof shares</t>
            </li>
            <li>
              <t>Return the public share, consisting of the joint randomness parts, and the
input shares, each consisting of the measurement share, proof share, and
blind of one of the Aggregators</t>
            </li>
          </ol>
          <t>As described in <xref target="multiproofs"/>, the soundness of the FLP can be amplified
by generating and verifying multiple FLPs. (This in turn improves the
robustness of Prio3.) To support this, in Prio3:</t>
          <ul spacing="normal">
            <li>
              <t>In step 3, derive as much joint randomness as required by <tt>PROOFS</tt> proofs</t>
            </li>
            <li>
              <t>Repeat step 4 <tt>PROOFS</tt> times, each time with a unique joint randomness</t>
            </li>
          </ul>
          <t>Depending on the FLP, joint randomness may not be required. In particular, when
<tt>flp.JOINT_RAND_LEN == 0</tt>, the Client does not derive the joint randomness
(Step 3). The sharding algorithm is specified below.</t>
          <figure anchor="prio3-eval-input">
            <name>Input-distribution algorithm for Prio3.</name>
            <sourcecode type="python"><![CDATA[
def shard(
        self,
        measurement: Measurement,
        nonce: bytes,
        rand: bytes) -> tuple[
            Optional[list[bytes]],
            list[Prio3InputShare]]:
    if len(nonce) != self.NONCE_SIZE:
        raise ValueError("incorrect nonce size")
    if len(rand) != self.RAND_SIZE:
        raise ValueError("incorrect size of random bytes argument")

    l = self.xof.SEED_SIZE
    seeds = [rand[i:i + l] for i in range(0, self.RAND_SIZE, l)]

    meas = self.flp.encode(measurement)
    if self.flp.JOINT_RAND_LEN > 0:
        return self.shard_with_joint_rand(meas, nonce, seeds)
    else:
        return self.shard_without_joint_rand(meas, seeds)
]]></sourcecode>
          </figure>
          <t>It starts by splitting the randomness into seeds. It then encodes the
measurement as prescribed by the FLP and calls one of two methods, depending on
whether joint randomness is required by the FLP. The methods are defined in the
subsections below.</t>
          <section anchor="flps-without-joint-randomness">
            <name>FLPs without joint randomness</name>
            <t>The following method is used for FLPs that do not require joint randomness,
i.e., when <tt>flp.JOINT_RAND_LEN == 0</tt>:</t>
            <figure anchor="prio3-shard-without-joint-rand">
              <name>Sharding an encoded measurement without joint randomness.</name>
              <sourcecode type="python"><![CDATA[
def shard_without_joint_rand(
        self,
        meas: list[F],
        seeds: list[bytes]) -> tuple[
            Optional[list[bytes]],
            list[Prio3InputShare[F]]]:
    k_helper_seeds, seeds = front((self.SHARES - 1) * 2, seeds)
    k_helper_meas_shares = [
        k_helper_seeds[i]
        for i in range(0, (self.SHARES - 1) * 2, 2)
    ]
    k_helper_proofs_shares = [
        k_helper_seeds[i]
        for i in range(1, (self.SHARES - 1) * 2, 2)
    ]
    (k_prove,), seeds = front(1, seeds)

    # Shard the encoded measurement into shares.
    leader_meas_share = meas
    for j in range(self.SHARES - 1):
        leader_meas_share = vec_sub(
            leader_meas_share,
            self.helper_meas_share(j + 1, k_helper_meas_shares[j]),
        )

    # Generate and shard each proof into shares.
    prove_rands = self.prove_rands(k_prove)
    leader_proofs_share = []
    for _ in range(self.PROOFS):
        prove_rand, prove_rands = front(
            self.flp.PROVE_RAND_LEN, prove_rands)
        leader_proofs_share += self.flp.prove(meas, prove_rand, [])
    for j in range(self.SHARES - 1):
        leader_proofs_share = vec_sub(
            leader_proofs_share,
            self.helper_proofs_share(
                j + 1,
                k_helper_proofs_shares[j],
            ),
        )

    # Each Aggregator's input share contains its measurement share
    # and share of proof(s).
    input_shares: list[Prio3InputShare[F]] = []
    input_shares.append((
        leader_meas_share,
        leader_proofs_share,
        None,
    ))
    for j in range(self.SHARES - 1):
        input_shares.append((
            k_helper_meas_shares[j],
            k_helper_proofs_shares[j],
            None,
        ))
    return (None, input_shares)
]]></sourcecode>
            </figure>
            <t>The steps in this method are as follows:</t>
            <ol spacing="normal" type="1"><li>
                <t>Shard the encoded measurement into shares</t>
              </li>
              <li>
                <t>Generate and shard each proof into shares</t>
              </li>
              <li>
                <t>Encode each measurement and shares of each proof into an input share</t>
              </li>
            </ol>
            <t>Notice that only one pair of measurement and proof(s) share (called the
"leader" shares above) are vectors of field elements. The other shares
(called the "helper" shares) are represented instead by XOF seeds, which
are expanded into vectors of field elements.</t>
            <t>The methods on <tt>Prio3</tt> for deriving the prover randomness, measurement shares,
and proof shares and the methods for encoding the input shares are defined in
<xref target="prio3-auxiliary"/>.</t>
          </section>
          <section anchor="flps-with-joint-randomness">
            <name>FLPs with joint randomness</name>
            <t>The following method is used for FLPs that require joint randomness,
i.e., for which <tt>flp.JOINT_RAND_LEN &gt; 0</tt>:</t>
            <figure anchor="prio3-shard-with-joint-rand">
              <name>Sharding an encoded measurement with joint randomness.</name>
              <sourcecode type="python"><![CDATA[
def shard_with_joint_rand(
        self,
        meas: list[F],
        nonce: bytes,
        seeds: list[bytes]) -> tuple[
            Optional[list[bytes]],
            list[Prio3InputShare[F]]]:
    k_helper_seeds, seeds = front((self.SHARES - 1) * 3, seeds)
    k_helper_meas_shares = [
        k_helper_seeds[i]
        for i in range(0, (self.SHARES - 1) * 3, 3)
    ]
    k_helper_proofs_shares = [
        k_helper_seeds[i]
        for i in range(1, (self.SHARES - 1) * 3, 3)
    ]
    k_helper_blinds = [
        k_helper_seeds[i]
        for i in range(2, (self.SHARES - 1) * 3, 3)
    ]
    (k_leader_blind, k_prove), seeds = front(2, seeds)

    # Shard the encoded measurement into shares and compute the
    # joint randomness parts.
    leader_meas_share = meas
    k_joint_rand_parts = []
    for j in range(self.SHARES - 1):
        helper_meas_share = self.helper_meas_share(
            j + 1, k_helper_meas_shares[j])
        leader_meas_share = vec_sub(leader_meas_share,
                                    helper_meas_share)
        k_joint_rand_parts.append(self.joint_rand_part(
            j + 1, k_helper_blinds[j], helper_meas_share, nonce))
    k_joint_rand_parts.insert(0, self.joint_rand_part(
        0, k_leader_blind, leader_meas_share, nonce))

    # Generate the proof and shard it into proof shares.
    prove_rands = self.prove_rands(k_prove)
    joint_rands = self.joint_rands(
        self.joint_rand_seed(k_joint_rand_parts))
    leader_proofs_share = []
    for _ in range(self.PROOFS):
        prove_rand, prove_rands = front(
            self.flp.PROVE_RAND_LEN, prove_rands)
        joint_rand, joint_rands = front(
            self.flp.JOINT_RAND_LEN, joint_rands)
        leader_proofs_share += self.flp.prove(
            meas,
            prove_rand,
            joint_rand,
        )
    for j in range(self.SHARES - 1):
        leader_proofs_share = vec_sub(
            leader_proofs_share,
            self.helper_proofs_share(
                j + 1,
                k_helper_proofs_shares[j],
            ),
        )

    # Each Aggregator's input share contains its measurement share,
    # share of proof(s), and blind. The public share contains the
    # Aggregators' joint randomness parts.
    input_shares: list[Prio3InputShare[F]] = []
    input_shares.append((
        leader_meas_share,
        leader_proofs_share,
        k_leader_blind,
    ))
    for j in range(self.SHARES - 1):
        input_shares.append((
            k_helper_meas_shares[j],
            k_helper_proofs_shares[j],
            k_helper_blinds[j],
        ))
    return (k_joint_rand_parts, input_shares)
]]></sourcecode>
            </figure>
            <t>The difference between this procedure and previous one is that here we compute
joint randomnesses <tt>joint_rands</tt>, split it into multiple <tt>joint_rand</tt>,
and pass each <tt>joint_rand</tt> to the proof generationg algorithm.
(In <xref target="prio3-shard-without-joint-rand"/> the joint randomness is the empty
vector, <tt>[]</tt>.) This requires generating an additional value, called the
"blind", that is incorporated into each input share.</t>
            <t>The joint randomness computation involves the following steps:</t>
            <ol spacing="normal" type="1"><li>
                <t>Compute a "joint randomness part" from each measurement share and blind</t>
              </li>
              <li>
                <t>Compute a "joint randomness seed" from the joint randomness parts</t>
              </li>
              <li>
                <t>Compute the joint randomness for each proof evaluation from the joint randomness seed</t>
              </li>
            </ol>
            <t>This three-step process is designed to ensure that the joint randomness does
not leak the measurement to the Aggregators while preventing a malicious Client
from tampering with the joint randomness in a way that allows it to break
robustness. To bootstrap the required check, the Client encodes the joint
randomness parts in the public share. (See <xref target="prio3-preparation"/> for details.)</t>
            <t>The methods used in this computation are defined in <xref target="prio3-auxiliary"/>.</t>
          </section>
        </section>
        <section anchor="prio3-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
measurement and share of proof(s) locally, then exchanges its share of
verifier(s) with the other Aggregators. The shares of verifier(s) are then
combined into the verifier message(s) used to decide whether to accept.</t>
          <t>In addition, for FLPs that require joint randomness, the Aggregators must
ensure that they have all used the same joint randomness for the
query-generation algorithm. To do so, they collectively re-derive the joint
randomness from their measurement shares just as the Client did during
sharding.</t>
          <t>In order to avoid extra round of communication, the Client sends each
Aggregator a "hint" consisting of the joint randomness parts. 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 shares of
verifier(s).</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>
            <sourcecode type="python"><![CDATA[
def prep_init(
        self,
        verify_key: bytes,
        agg_id: int,
        _agg_param: None,
        nonce: bytes,
        public_share: Optional[list[bytes]],
        input_share: Prio3InputShare[F]) -> tuple[
            Prio3PrepState[F],
            Prio3PrepShare[F]]:
    k_joint_rand_parts = public_share
    (meas_share, proofs_share, k_blind) = \
        self.expand_input_share(agg_id, input_share)
    out_share = self.flp.truncate(meas_share)

    # Compute the joint randomness.
    joint_rand: list[F] = []
    k_corrected_joint_rand, k_joint_rand_part = None, None
    if self.flp.JOINT_RAND_LEN > 0:
        assert k_blind is not None
        assert k_joint_rand_parts is not None
        k_joint_rand_part = self.joint_rand_part(
            agg_id, k_blind, meas_share, nonce)
        k_joint_rand_parts[agg_id] = k_joint_rand_part
        k_corrected_joint_rand = self.joint_rand_seed(
            k_joint_rand_parts)
        joint_rands = self.joint_rands(k_corrected_joint_rand)

    # Query the measurement and proof share.
    query_rands = self.query_rands(verify_key, nonce)
    verifiers_share = []
    for _ in range(self.PROOFS):
        proof_share, proofs_share = front(
            self.flp.PROOF_LEN, proofs_share)
        query_rand, query_rands = front(
            self.flp.QUERY_RAND_LEN, query_rands)
        if self.flp.JOINT_RAND_LEN > 0:
            joint_rand, joint_rands = front(
                self.flp.JOINT_RAND_LEN, joint_rands)
        verifiers_share += self.flp.query(
            meas_share,
            proof_share,
            query_rand,
            joint_rand,
            self.SHARES,
        )

    prep_state = (out_share, k_corrected_joint_rand)
    prep_share = (verifiers_share, k_joint_rand_part)
    return (prep_state, prep_share)

def prep_next(
        self,
        prep_state: Prio3PrepState[F],
        prep_msg: Optional[bytes]) -> Union[
            tuple[Prio3PrepState[F], Prio3PrepShare[F]],
            list[F]]:
    k_joint_rand = prep_msg
    (out_share, k_corrected_joint_rand) = prep_state

    # If joint randomness was used, check that the value computed by
    # the Aggregators matches the value indicated by the Client.
    if k_joint_rand != k_corrected_joint_rand:
        raise ValueError('joint randomness check failed')

    return out_share

def prep_shares_to_prep(
        self,
        _agg_param: None,
        prep_shares: list[Prio3PrepShare[F]]) -> Optional[bytes]:
    # Unshard the verifier shares into the verifier message.
    verifiers = self.flp.field.zeros(
        self.flp.VERIFIER_LEN * self.PROOFS)
    k_joint_rand_parts = []
    for (verifiers_share, k_joint_rand_part) in prep_shares:
        verifiers = vec_add(verifiers, verifiers_share)
        if self.flp.JOINT_RAND_LEN > 0:
            assert k_joint_rand_part is not None
            k_joint_rand_parts.append(k_joint_rand_part)

    # Verify that each proof is well-formed and input is valid
    for _ in range(self.PROOFS):
        verifier, verifiers = front(self.flp.VERIFIER_LEN, verifiers)
        if not self.flp.decide(verifier):
            raise ValueError('proof verifier check failed')

    # Combine the joint randomness parts computed by the
    # Aggregators into the true joint randomness seed. This is
    # used in the last step.
    k_joint_rand = None
    if self.flp.JOINT_RAND_LEN > 0:
        k_joint_rand = self.joint_rand_seed(k_joint_rand_parts)
    return k_joint_rand
]]></sourcecode>
          </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>
            <sourcecode type="python"><![CDATA[
def is_valid(
        self,
        _agg_param: None,
        previous_agg_params: list[None]) -> bool:
    """
    Checks if `previous_agg_params` is empty, as input shares in
    Prio3 may only be used once.
    """
    return len(previous_agg_params) == 0
]]></sourcecode>
          </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>
            <sourcecode type="python"><![CDATA[
def aggregate(
        self,
        _agg_param: None,
        out_shares: list[list[F]]) -> list[F]:
    agg_share = self.flp.field.zeros(self.flp.OUTPUT_LEN)
    for out_share in out_shares:
        agg_share = vec_add(agg_share, out_share)
    return agg_share
]]></sourcecode>
          </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>
            <sourcecode type="python"><![CDATA[
def unshard(
        self,
        _agg_param: None,
        agg_shares: list[list[F]],
        num_measurements: int) -> AggResult:
    agg = self.flp.field.zeros(self.flp.OUTPUT_LEN)
    for agg_share in agg_shares:
        agg = vec_add(agg, agg_share)
    return self.flp.decode(agg, num_measurements)
]]></sourcecode>
          </figure>
        </section>
        <section anchor="prio3-auxiliary">
          <name>Auxiliary Functions</name>
          <t>This section defines a number of auxiliary functions referenced by the main
algorithms for Prio3 in the preceding sections.</t>
          <t>The following methods are called by the sharding and preparation algorithms.</t>
          <sourcecode type="python"><![CDATA[
def helper_meas_share(self, agg_id: int, k_share: bytes) -> list[F]:
    return self.xof.expand_into_vec(
        self.flp.field,
        k_share,
        self.domain_separation_tag(USAGE_MEAS_SHARE),
        byte(agg_id),
        self.flp.MEAS_LEN,
    )

def helper_proofs_share(
        self,
        agg_id: int,
        k_share: bytes) -> list[F]:
    return self.xof.expand_into_vec(
        self.flp.field,
        k_share,
        self.domain_separation_tag(USAGE_PROOF_SHARE),
        byte(self.PROOFS) + byte(agg_id),
        self.flp.PROOF_LEN * self.PROOFS,
    )

def expand_input_share(
        self,
        agg_id: int,
        input_share: Prio3InputShare[F]) -> tuple[
            list[F],
            list[F],
            Optional[bytes]]:
    (meas_share, proofs_share, k_blind) = input_share
    if agg_id > 0:
        assert isinstance(meas_share, bytes)
        assert isinstance(proofs_share, bytes)
        meas_share = self.helper_meas_share(agg_id, meas_share)
        proofs_share = self.helper_proofs_share(agg_id, proofs_share)
    else:
        assert isinstance(meas_share, list)
        assert isinstance(proofs_share, list)
    return (meas_share, proofs_share, k_blind)

def prove_rands(self, k_prove: bytes) -> list[F]:
    return self.xof.expand_into_vec(
        self.flp.field,
        k_prove,
        self.domain_separation_tag(USAGE_PROVE_RANDOMNESS),
        byte(self.PROOFS),
        self.flp.PROVE_RAND_LEN * self.PROOFS,
    )

def query_rands(self, verify_key: bytes, nonce: bytes) -> list[F]:
    return self.xof.expand_into_vec(
        self.flp.field,
        verify_key,
        self.domain_separation_tag(USAGE_QUERY_RANDOMNESS),
        byte(self.PROOFS) + nonce,
        self.flp.QUERY_RAND_LEN * self.PROOFS,
    )

def joint_rand_part(
        self,
        agg_id: int,
        k_blind: bytes,
        meas_share: list[F],
        nonce: bytes) -> bytes:
    return self.xof.derive_seed(
        k_blind,
        self.domain_separation_tag(USAGE_JOINT_RAND_PART),
        byte(agg_id) + nonce + self.flp.field.encode_vec(meas_share),
    )

def joint_rand_seed(self, k_joint_rand_parts: list[bytes]) -> bytes:
    """Derive the joint randomness seed from its parts."""
    return self.xof.derive_seed(
        zeros(self.xof.SEED_SIZE),
        self.domain_separation_tag(USAGE_JOINT_RAND_SEED),
        concat(k_joint_rand_parts),
    )

def joint_rands(self, k_joint_rand_seed: bytes) -> list[F]:
    """Derive the joint randomness from its seed."""
    return self.xof.expand_into_vec(
        self.flp.field,
        k_joint_rand_seed,
        self.domain_separation_tag(USAGE_JOINT_RANDOMNESS),
        byte(self.PROOFS),
        self.flp.JOINT_RAND_LEN * self.PROOFS,
    )
]]></sourcecode>
        </section>
        <section anchor="prio3-encode">
          <name>Message Serialization</name>
          <t>This section defines serialization formats for messages exchanged over the
network while executing Prio3. It is <bcp14>RECOMMENDED</bcp14> that implementations provide
serialization methods for them.</t>
          <t>Message structures are defined following <xref section="3" sectionFormat="of" target="RFC8446"/>). In the
remainder we use <tt>S</tt> as an alias for <tt>Prio3.xof.SEED_SIZE</tt> and <tt>F</tt> as an alias
for <tt>Prio3.field.ENCODED_SIZE</tt>. XOF seeds are represented as follows:</t>
          <sourcecode type="tls-presentation"><![CDATA[
opaque Prio3Seed[S];
]]></sourcecode>
          <t>Field elements are encoded in little-endian byte order (as defined in
<xref target="field"/>) and represented as follows:</t>
          <sourcecode type="tls-presentation"><![CDATA[
opaque Prio3Field[F];
]]></sourcecode>
          <section anchor="public-share">
            <name>Public Share</name>
            <t>The encoding of the public share depends on whether joint randomness is
required for the underlying FLP (i.e., <tt>Prio3.flp.JOINT_RAND_LEN &gt; 0</tt>). If
joint randomness is not used, then the public share is the empty string. If
joint randomness is used, then the public share encodes the joint randomness
parts as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Seed k_joint_rand_parts[S * Prio3.SHARES];
} Prio3PublicShareWithJointRand;
]]></sourcecode>
          </section>
          <section anchor="input-share">
            <name>Input share</name>
            <t>Just as for the public share, the encoding of the input shares depends on
whether joint randomness is used. If so, then each input share includes the
Aggregator's blind for generating its joint randomness part.</t>
            <t>In addition, the encoding of the input shares depends on which aggregator is
receiving the message. If the aggregator ID is <tt>0</tt>, then the input share
includes the full measurement and share of proof(s). Otherwise, if the aggregator ID
is greater than <tt>0</tt>, then the measurement and shares of proof(s) are represented
by XOF seeds. We shall call the former the "Leader" and the latter the
"Helpers".</t>
            <t>In total there are four variants of the input share. When joint randomness is
not used, the Leader's share is structured as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Field meas_share[F * Prio3.flp.MEAS_LEN];
    Prio3Field proofs_share[F * Prio3.flp.PROOF_LEN * Prio3.PROOFS];
} Prio3LeaderShare;
]]></sourcecode>
            <t>When joint randomness is not used, the Helpers' shares are structured
as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Seed k_meas_share;
    Prio3Seed k_proofs_share;
} Prio3HelperShare;
]]></sourcecode>
            <t>When joint randomness is used, the Leader's input share is structured as
follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3LeaderShare inner;
    Prio3Seed k_blind;
} Prio3LeaderShareWithJointRand;
]]></sourcecode>
            <t>Finally, when joint randomness is used, the Helpers' shares are structured as
follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3HelperShare inner;
    Prio3Seed k_blind;
} Prio3HelperShareWithJointRand;
]]></sourcecode>
          </section>
          <section anchor="prep-share">
            <name>Prep Share</name>
            <t>When joint randomness is not used, the prep share is structured as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Field verifiers_share[
        F * Prio3.flp.VERIFIER_LEN * Prio3.PROOFS
    ];
} Prio3PrepShare;
]]></sourcecode>
            <t>When joint randomness is used, the prep share includes the Aggregator's joint
randomness part and is structured as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Field verifiers_share[
        F * Prio3.flp.VERIFIER_LEN * Prio3.PROOFS
    ];
    Prio3Seed k_joint_rand_part;
} Prio3PrepShareWithJointRand;
]]></sourcecode>
          </section>
          <section anchor="prep-message">
            <name>Prep Message</name>
            <t>When joint randomness is not used, the prep message is the empty string.
Otherwise the prep message consists of the joint randomness seed computed by
the Aggregators:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Seed k_joint_rand;
} Prio3PrepMessageWithJointRand;
]]></sourcecode>
          </section>
          <section anchor="aggregation-1">
            <name>Aggregation</name>
            <t>Aggregate shares are structured as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Field agg_share[F * Prio3.flp.OUTPUT_LEN];
} Prio3AggShare;
]]></sourcecode>
          </section>
        </section>
      </section>
      <section anchor="flp-bbcggi19">
        <name>The FLP of <xref target="BBCGGI19"/></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-bbcggi19-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-bbcggi19-construction"/>.</t>
        <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-bbcggi19-overview">
          <name>Overview</name>
          <t>In the proof system of <xref target="BBCGGI19"/>, validity is defined via an arithmetic
circuit evaluated over the encoded measurement: If the circuit output is zero,
then the measurement is deemed valid; otherwise, if the circuit output is
non-zero, then the measurement is deemed invalid. Thus the goal of the proof
system is merely to allow the verifier to evaluate the validity circuit over
the measurement. For our application (<xref target="prio3"/>), this computation is
distributed among multiple Aggregators, each of which has only a share of the
measurement.</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 a measurement <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 measurement 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 measurement 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-bbcggi19-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 measurement 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-bbcggi19-construction"/>.</t>
          <section anchor="flp-bbcggi19-overview-extensions">
            <name>Extensions</name>
            <t>The FLP described in the next section extends the proof system of <xref target="BBCGGI19"/>,
Section 4.2 in a few ways.</t>
            <t>First, the validity circuit in our construction includes an additional, random
input (this is the "joint randomness" derived from the measurement 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(meas, r) = r * Range2(meas[0]) + ... + r^N * Range2(meas[N-1])
]]></artwork>
            <t>(Note that this is a special case of <xref target="BBCGGI19"/>, Theorem 5.2.) Here <tt>meas</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>meas</tt> is valid (i.e., each <tt>meas[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>meas[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.) This provides additional flexibility for designing
circuits by allowing multiple, non-affine sub-components. For example, the
following circuit is allowed:</t>
            <artwork><![CDATA[
C(meas, r) = r * Range2(meas[0]) + ... + r^L * Range2(meas[L-1]) + \
            r^(L+1) * Range3(meas[L]) + ... + r^N * Range3(meas[N-1])
]]></artwork>
            <t>where <tt>Range3(x) = x^3 - 3x^2 + 2x</tt>. This circuit checks that the first <tt>L</tt>
inputs are in range <tt>[0,2)</tt> and the last <tt>N-L</tt> inputs are in range <tt>[0,3)</tt>. Of
course, the same circuit can be expressed using a sub-component that the
gadgets have in common, namely <tt>Mul</tt>, but the resulting proof would be longer.</t>
            <t>Third, <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>
            <t>Finally, the validity circuit in our FLP may have any number of outputs (at
least one). The input is said to be valid if each of the outputs is zero. To
save bandwidth, we take a random linear combination of the outputs. If each of
the outputs is zero, then the reduced output will be zero; but if one of the
outputs is non-zero, then the reduced output will be non-zero with high
probability.</t>
          </section>
        </section>
        <section anchor="flp-bbcggi19-valid">
          <name>Validity Circuits</name>
          <t>The FLP described in <xref target="flp-bbcggi19-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>MEAS_LEN</tt></td>
                <td align="left">Length of the measurement</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>EVAL_OUTPUT_LEN</tt></td>
                <td align="left">Length of the circuit output</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">Class object for the field</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-bbcggi19-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>Gadgets provide a method to evaluate their circuit on a list of inputs,
<tt>eval()</tt>. The inputs can either belong to the validity circuit's field, or the
polynomial ring over that field.</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>
              <t><tt>valid.encode(measurement: Measurement) -&gt; list[F]</tt> returns a vector of
length <tt>MEAS_LEN</tt> representing a measurement.</t>
            </li>
            <li>
              <t><tt>valid.truncate(meas: list[F]) -&gt; list[F]</tt> returns a vector of length
<tt>OUTPUT_LEN</tt> representing an aggregatable output.</t>
            </li>
            <li>
              <t><tt>valid.decode(output: list[F], num_measurements: int) -&gt; AggResult</tt>
returns an aggregate result.</t>
            </li>
          </ul>
          <t>Finally, the following methods are derived for each concrete <tt>Valid</tt>:</t>
          <figure>
            <name>Derived methods for validity circuits.</name>
            <sourcecode type="python"><![CDATA[
def prove_rand_len(self) -> int:
    """Length of the prover randomness."""
    return sum(g.ARITY for g in self.GADGETS)

def query_rand_len(self) -> int:
    """Length of the query randomness."""
    query_rand_len = len(self.GADGETS)
    if self.EVAL_OUTPUT_LEN > 1:
        query_rand_len += 1
    return query_rand_len

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

def verifier_len(self) -> int:
    """Length of the verifier message."""
    length = 1
    for g in self.GADGETS:
        length += g.ARITY + 1
    return length

def check_valid_eval(
        self,
        meas: list[F],
        joint_rand: list[F]) -> None:
    if len(meas) != self.MEAS_LEN:
        raise ValueError('incorrect measurement length')
    if len(joint_rand) != self.JOINT_RAND_LEN:
        raise ValueError('incorrect joint randomness length')
]]></sourcecode>
          </figure>
        </section>
        <section anchor="flp-bbcggi19-construction">
          <name>Construction</name>
          <t>This section specifies 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-bbcggi19-valid"/>.</t>
          <t>The parameters are defined in <xref target="flp-bbcggi19-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>
              <t>Let <tt>H = len(valid.GADGETS)</tt></t>
            </li>
            <li>
              <t>For each <tt>i</tt> in <tt>[H]</tt>:
              </t>
              <ul spacing="normal">
                <li>
                  <t>Let <tt>G_i = valid.GADGETS[i]</tt></t>
                </li>
                <li>
                  <t>Let <tt>L_i = valid.GADGETS[i].ARITY</tt></t>
                </li>
                <li>
                  <t>Let <tt>M_i = valid.GADGET_CALLS[i]</tt></t>
                </li>
                <li>
                  <t>Let <tt>P_i = next_power_of_2(M_i+1)</tt></t>
                </li>
                <li>
                  <t>Let <tt>alpha_i = field.gen()^(field.GEN_ORDER / P_i)</tt></t>
                </li>
              </ul>
            </li>
          </ul>
          <table anchor="flp-bbcggi19-param">
            <name>Parameters of FLP of BBCGGI19.</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-bbcggi19-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-bbcggi19-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>MEAS_LEN</tt></td>
                <td align="left">
                  <tt>valid.MEAS_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-bbcggi19-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>VERIFIER_LEN</tt></td>
                <td align="left">
                  <tt>valid.verifier_len()</tt> (see <xref target="flp-bbcggi19-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>valid.Measurement</tt></td>
              </tr>
            </tbody>
          </table>
          <section anchor="flp-bbcggi19-construction-prove">
            <name>Proof Generation</name>
            <t>On input of <tt>meas</tt>, <tt>prove_rand</tt>, and <tt>joint_rand</tt>, the proof is computed as
follows:</t>
            <ol spacing="normal" type="1"><li>
                <t>For each <tt>i</tt> in <tt>[H]</tt> create an empty table <tt>wire_i</tt>.</t>
              </li>
              <li>
                <t>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.</t>
              </li>
              <li>
                <t>Evaluate <tt>Valid</tt> on input of <tt>meas</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>.</t>
              </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>
                    <t>Let <tt>w = [seed_i[j-1], wire_i[j-1,0], ..., wire_i[j-1,M_i-1]]</tt>.</t>
                  </li>
                  <li>
                    <t>Let <tt>padded_w = w + field.zeros(P_i - len(w))</tt>.</t>
                  </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>
                    <t>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>.</t>
                  </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>
                    <t>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>.)</t>
                  </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-bbcggi19-construction-query">
            <name>Query Generation</name>
            <t>On input of <tt>meas</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>
                <t>For every <tt>i</tt> in <tt>[H]</tt> create an empty table <tt>wire_i</tt>.</t>
              </li>
              <li>
                <t>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-bbcggi19-construction-prove"/>.</t>
              </li>
              <li>
                <t>Evaluate <tt>Valid</tt> on input of <tt>meas</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>out</tt> denote the output of the circuit
evaluation.</t>
              </li>
              <li>
                <t>Next, reduce <tt>out</tt> as follows. If <tt>EVAL_OUTPUT_LEN &gt; 1</tt>, then consume the
first element of <tt>query_rand</tt> by letting <tt>[r], query_rand = front(1,
query_rand)</tt>. Then let <tt>v = r*out[0] + r**2*out[1] + r**3*out[2] + ...</tt>.
That is, interpret the outputs as coefficients of a polynomial <tt>f(x)</tt> and
evaluate polynomial <tt>f(x)*x</tt> at a random point <tt>r</tt>.</t>
              </li>
              <li>
                <t>Compute the wire polynomials just as in the prover's step (4.).</t>
              </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>
                    <t>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.)</t>
                  </li>
                  <li>
                    <t>Let <tt>y_i = poly_gadget_i(t)</tt>.</t>
                  </li>
                  <li>
                    <t>For each <tt>j</tt> in <tt>[0,L_i)</tt> let <tt>x_i[j-1] = poly_wire_i[j-1](t)</tt>.</t>
                  </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 measurement is valid
as follows:</t>
            <ol spacing="normal" type="1"><li>
                <t>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-bbcggi19-construction-query"/>.</t>
              </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>
                    <t>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.</t>
                  </li>
                  <li>
                    <t>If <tt>z != y_i</tt>, then return <tt>False</tt> and halt.</t>
                  </li>
                </ul>
              </li>
              <li>
                <t>Return <tt>True</tt> if <tt>v == 0</tt> and <tt>False</tt> otherwise.</t>
              </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 is determined by a field (<xref target="field"/>), a validity circuit
(<xref target="flp-bbcggi19-valid"/>), an XOF (<xref target="xof"/>). and the number of proofs to
generate and verify. Test vectors for each can be found in <xref target="test-vectors"/>.</t>
        <section anchor="prio3count">
          <name>Prio3Count</name>
          <table>
            <name>Parameters for Prio3Count.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>Valid</tt></td>
                <td align="left">
                  <tt>Count(Field64)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field64</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Xof</tt></td>
                <td align="left">
                  <tt>XofTurboShake128</tt> (<xref target="xof-turboshake128"/>)</td>
              </tr>
            </tbody>
          </table>
          <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>Its validity circuit, denoted <tt>Count</tt>, uses the following degree-2, arity-2
gadget, denoted <tt>Mul</tt>:</t>
          <sourcecode type="python"><![CDATA[
def eval(self, _field: type[F], inp: list[F]) -> F:
    self.check_gadget_eval(inp)
    return inp[0] * inp[1]
]]></sourcecode>
          <t>The call to <tt>check_gadget_eval()</tt> raises an error if the length of the input is
not equal to the gadget's <tt>ARITY</tt> parameter.</t>
          <t>The <tt>Count</tt> validity circuit is defined as</t>
          <sourcecode type="python"><![CDATA[
def eval(
        self,
        meas: list[F],
        joint_rand: list[F],
        _num_shares: int) -> list[F]:
    self.check_valid_eval(meas, joint_rand)
    squared = self.GADGETS[0].eval(self.field, [meas[0], meas[0]])
    return [squared - meas[0]]
]]></sourcecode>
          <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>MEAS_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>EVAL_OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>int</tt> in <tt>range(2)</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">
                  <tt>int</tt></td>
              </tr>
            </tbody>
          </table>
        </section>
        <section anchor="prio3sum">
          <name>Prio3Sum</name>
          <table>
            <name>Parameters for Prio3Sum.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>Valid</tt></td>
                <td align="left">
                  <tt>Sum(Field128, bits)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Xof</tt></td>
                <td align="left">
                  <tt>XofTurboShake128</tt> (<xref target="xof-turboshake128"/>)</td>
              </tr>
            </tbody>
          </table>
          <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>The validity circuit is denoted <tt>Sum</tt>. 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>
          <sourcecode type="python"><![CDATA[
def encode(self, measurement: int) -> list[F]:
    if 0 > measurement or measurement >= 2 ** self.MEAS_LEN:
        raise ValueError('measurement out of range')

    return self.field.encode_into_bit_vector(measurement,
                                             self.MEAS_LEN)

def truncate(self, meas: list[F]) -> list[F]:
    return [self.field.decode_from_bit_vector(meas)]

def decode(
        self,
        output: list[F],
        _num_measurements: int) -> int:
    return output[0].as_unsigned()
]]></sourcecode>
          <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>
          <sourcecode type="python"><![CDATA[
def eval(self, _field: type[F], inp: list[F]) -> F:
    self.check_gadget_eval(inp)
    return inp[0] * inp[0] - inp[0]
]]></sourcecode>
          <t>The <tt>Sum</tt> validity circuit is defined as</t>
          <sourcecode type="python"><![CDATA[
def eval(
        self,
        meas: list[F],
        joint_rand: list[F],
        _num_shares: int) -> list[F]:
    self.check_valid_eval(meas, joint_rand)
    out = self.field(0)
    r = joint_rand[0]
    for b in meas:
        out += r * self.GADGETS[0].eval(self.field, [b])
        r *= joint_rand[0]
    return [out]
]]></sourcecode>
          <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>MEAS_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>EVAL_OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>int</tt> in <tt>range(2**bits)</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">
                  <tt>int</tt></td>
              </tr>
            </tbody>
          </table>
        </section>
        <section anchor="prio3sumvec">
          <name>Prio3SumVec</name>
          <table>
            <name>Parameters for Prio3SumVec.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>Valid</tt></td>
                <td align="left">
                  <tt>Sum(Field128, length, bits, chunk_lengh)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Xof</tt></td>
                <td align="left">
                  <tt>XofTurboShake128</tt> (<xref target="xof-turboshake128"/>)</td>
              </tr>
            </tbody>
          </table>
          <t>This instance of Prio3 supports summing a vector of integers. It has three
parameters, <tt>length</tt>, <tt>bits</tt>, and <tt>chunk_length</tt>. Each measurement is a vector
of positive integers with length equal to the <tt>length</tt> parameter. Each element
of the measurement is an integer in the range <tt>[0, 2^bits)</tt>. It is <bcp14>RECOMMENDED</bcp14>
to set <tt>chunk_length</tt> to an integer near the square root of <tt>length * bits</tt>
(see <xref target="parallel-sum-chunk-length"/>).</t>
          <t>The validity circuit is denoted <tt>SumVec</tt>. Measurements are encoded as a vector
of field elements with length <tt>length * bits</tt>. The field elements in the
encoded vector represent all the bits of the measurement vector's elements,
consecutively, in LSB to MSB order:</t>
          <sourcecode type="python"><![CDATA[
def encode(self, measurement: list[int]) -> list[F]:
    if len(measurement) != self.length:
        raise ValueError('incorrect measurement length')

    encoded = []
    for val in measurement:
        if val not in range(2**self.bits):
            raise ValueError(
                'entry of measurement vector is out of range'
            )

        encoded += self.field.encode_into_bit_vector(val, self.bits)
    return encoded

def truncate(self, meas: list[F]) -> list[F]:
    truncated = []
    for i in range(self.length):
        truncated.append(self.field.decode_from_bit_vector(
            meas[i * self.bits: (i + 1) * self.bits]
        ))
    return truncated

def decode(
        self,
        output: list[F],
        _num_measurements: int) -> list[int]:
    return [x.as_unsigned() for x in output]
]]></sourcecode>
          <t>This validity circuit uses a <tt>ParallelSum</tt> gadget to achieve a smaller proof
size. This optimization for "parallel-sum circuits" is described in
<xref target="BBCGGI19"/>, section 4.4. Briefly, for circuits that add up the output of
multiple identical subcircuits, it is possible to achieve smaller proof sizes
(on the order of O(sqrt(MEAS_LEN)) instead of O(MEAS_LEN)) by packaging more
than one such subcircuit into a gadget.</t>
          <t>The <tt>ParallelSum</tt> gadget is parameterized with an arithmetic subcircuit, and a
<tt>count</tt> of how many times it evaluates that subcircuit. It takes in a list of
inputs and passes them through to instances of the subcircuit in the same order.
It returns the sum of the subcircuit outputs. Note that only the <tt>ParallelSum</tt>
gadget itself, and not its subcircuit, participates in the FLP's wire recording
during evaluation, gadget consistency proofs, and proof validation, even though
the subcircuit is provided to <tt>ParallelSum</tt> as an implementation of the
<tt>Gadget</tt> interface.</t>
          <sourcecode type="python"><![CDATA[
def eval(self, field: type[F], inp: list[F]) -> F:
    self.check_gadget_eval(inp)
    out = field(0)
    for i in range(self.count):
        start_index = i * self.subcircuit.ARITY
        end_index = (i + 1) * self.subcircuit.ARITY
        out += self.subcircuit.eval(
            field,
            inp[start_index:end_index],
        )
    return out
]]></sourcecode>
          <t>The <tt>SumVec</tt> validity circuit checks that the encoded measurement consists of
ones and zeros. Rather than use the <tt>Range2</tt> gadget on each element, as in the
<tt>Sum</tt> validity circuit, it instead uses <tt>Mul</tt> subcircuits and "free" constant
multiplication and addition gates to simultaneously evaluate the same range
check polynomial on each element, and multiply by a constant. One of the two
<tt>Mul</tt> subcircuit inputs is equal to a measurement element multiplied by a power
of the joint randomness value, and the other is equal to the same measurement
element minus one. These <tt>Mul</tt> subcircuits are evaluated by a <tt>ParallelSum</tt>
gadget, and the results are added up both within the <tt>ParallelSum</tt> gadget and
after it.</t>
          <sourcecode type="python"><![CDATA[
def eval(
        self,
        meas: list[F],
        joint_rand: list[F],
        num_shares: int) -> list[F]:
    self.check_valid_eval(meas, joint_rand)

    out = self.field(0)
    r = joint_rand[0]
    r_power = r
    shares_inv = self.field(num_shares).inv()

    for i in range(self.GADGET_CALLS[0]):
        inputs: list[Optional[F]]
        inputs = [None] * (2 * self.chunk_length)
        for j in range(self.chunk_length):
            index = i * self.chunk_length + j
            if index < len(meas):
                meas_elem = meas[index]
            else:
                meas_elem = self.field(0)

            inputs[j * 2] = r_power * meas_elem
            inputs[j * 2 + 1] = meas_elem - shares_inv

            r_power *= r

        out += self.GADGETS[0].eval(
            self.field,
            cast(list[F], inputs),
        )

    return [out]
]]></sourcecode>
          <table>
            <name>Parameters of validity circuit SumVec.</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>[ParallelSum(Mul(), chunk_length)]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[(length * bits + chunk_length - 1) // chunk_length]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>MEAS_LEN</tt></td>
                <td align="left">
                  <tt>length * bits</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>length</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>EVAL_OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>list[int]</tt>, each element in <tt>range(2**bits)</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">
                  <tt>list[int]</tt></td>
              </tr>
            </tbody>
          </table>
          <section anchor="parallel-sum-chunk-length">
            <name>Selection of <tt>ParallelSum</tt> chunk length</name>
            <t>The <tt>chunk_length</tt> parameter provides a trade-off between the arity of the
<tt>ParallelSum</tt> gadget and the number of times the gadget is called. The proof
length is asymptotically minimized when the chunk length is near the square root
of the length of the measurement. However, the relationship between VDAF
parameters and proof length is complicated, involving two forms of rounding (the
circuit pads the inputs to its last <tt>ParallelSum</tt> gadget call, up to the chunk
length, and proof system rounds the degree of wire polynomials -- determined by
the number of times a gadget is called -- up to the next power of two).
Therefore, the optimal choice of <tt>chunk_length</tt> for a concrete measurement size
will vary, and must be found through trial and error. Setting <tt>chunk_length</tt>
equal to the square root of the appropriate measurement length will result in
proofs up to 50% larger than the optimal proof size.</t>
          </section>
        </section>
        <section anchor="prio3histogram">
          <name>Prio3Histogram</name>
          <table>
            <name>Parameters for Prio3Histogram.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>Valid</tt></td>
                <td align="left">
                  <tt>Sum(Field128, length, chunk_lengh)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Xof</tt></td>
                <td align="left">
                  <tt>XofTurboShake128</tt> (<xref target="xof-turboshake128"/>)</td>
              </tr>
            </tbody>
          </table>
          <t>This instance of Prio3 allows for estimating the distribution of some quantity
by computing a simple histogram. Each measurement increments one histogram
bucket, out of a set of fixed buckets. (Bucket indexing begins at <tt>0</tt>.) For
example, the buckets might quantize the real numbers, and each measurement would
report the bucket that the corresponding client's real-numbered value falls
into. The aggregate result counts the number of measurements in each bucket.</t>
          <t>The validity circuit is denoted <tt>Histogram</tt>. It has two parameters, <tt>length</tt>,
the number of histogram buckets, and <tt>chunk_length</tt>, which is used by by a
circuit optimization described below. It is <bcp14>RECOMMENDED</bcp14> to set <tt>chunk_length</tt>
to an integer near the square root of <tt>length</tt> (see
<xref target="parallel-sum-chunk-length"/>).</t>
          <t>The measurement is encoded as a one-hot vector representing the bucket into
which the measurement falls:</t>
          <sourcecode type="python"><![CDATA[
def encode(self, measurement: int) -> list[F]:
    encoded = [self.field(0)] * self.length
    encoded[measurement] = self.field(1)
    return encoded

def truncate(self, meas: list[F]) -> list[F]:
    return meas

def decode(
        self,
        output: list[F],
        _num_measurements: int) -> list[int]:
    return [bucket_count.as_unsigned() for bucket_count in output]
]]></sourcecode>
          <t>The <tt>Histogram</tt> validity circuit checks for one-hotness in two steps, by
checking that the encoded measurement consists of ones and zeros, and by
checking that the sum of all elements in the encoded measurement is equal to
one. All the individual checks are combined together in a random linear
combination.</t>
          <t>As in the <tt>SumVec</tt> validity circuit (<xref target="prio3sumvec"/>), the first part of the
validity circuit uses the <tt>ParallelSum</tt> gadget to perform range checks while
achieving a smaller proof size. The <tt>ParallelSum</tt> gadget uses <tt>Mul</tt> subcircuits
to evaluate a range check polynomial on each element, and includes an additional
constant multiplication. One of the two <tt>Mul</tt> subcircuit inputs is equal to a
measurement element multiplied by a power of the first joint randomness value,
and the other is equal to the same measurement element minus one. The results
are added up both within the <tt>ParallelSum</tt> gadget and after it.</t>
          <sourcecode type="python"><![CDATA[
def eval(
        self,
        meas: list[F],
        joint_rand: list[F],
        num_shares: int) -> list[F]:
    self.check_valid_eval(meas, joint_rand)

    # Check that each bucket is one or zero.
    range_check = self.field(0)
    r = joint_rand[0]
    r_power = r
    shares_inv = self.field(num_shares).inv()
    for i in range(self.GADGET_CALLS[0]):
        inputs: list[Optional[F]]
        inputs = [None] * (2 * self.chunk_length)
        for j in range(self.chunk_length):
            index = i * self.chunk_length + j
            if index < len(meas):
                meas_elem = meas[index]
            else:
                meas_elem = self.field(0)

            inputs[j * 2] = r_power * meas_elem
            inputs[j * 2 + 1] = meas_elem - shares_inv

            r_power *= r

        range_check += self.GADGETS[0].eval(
            self.field,
            cast(list[F], inputs),
        )

    # Check that the buckets sum to 1.
    sum_check = -shares_inv
    for b in meas:
        sum_check += b

    out = joint_rand[1] * range_check + \
        joint_rand[1] ** 2 * sum_check
    return [out]
]]></sourcecode>
          <t>Note that this circuit depends on the number of shares into which the
measurement 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>[ParallelSum(Mul(), chunk_length)]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[(length + chunk_length - 1) // chunk_length]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>MEAS_LEN</tt></td>
                <td align="left">
                  <tt>length</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>length</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>EVAL_OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>int</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">
                  <tt>list[int]</tt></td>
              </tr>
            </tbody>
          </table>
        </section>
        <section anchor="prio3multihotcountvec">
          <name>Prio3MultihotCountVec</name>
          <table>
            <name>Parameters for Prio3MultihotCountVec.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>Valid</tt></td>
                <td align="left">
                  <tt>Sum(Field128, length, max_eight chunk_lengh)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Xof</tt></td>
                <td align="left">
                  <tt>XofTurboShake128</tt> (<xref target="xof-turboshake128"/>)</td>
              </tr>
            </tbody>
          </table>
          <t>For this instance of Prio3, each measurement is a vector of ones and zeros,
where the number of ones is bounded. This provides a functionality similar to
Prio3Histogram except that more than one entry may be non-zero. This allows
Prio3MultihotCountVec to be composed with a randomized response mechanism, like
<xref target="EPK14"/>, for providing differential privacy. (For example, each Client would
set each entry to one with some small probability.)</t>
          <t>Prio3MultihotCountVec uses XofTurboShake128 (<xref target="xof-turboshake128"/>) as its XOF.
Its validity circuit is denoted <tt>MultihotCountVec</tt>. It has three parameters:
<tt>length</tt>, the number of of entries in the count vector; <tt>max_weight</tt>, the
maximum number of non-zero entries (i.e., the weight must be at most
<tt>max_weight</tt>); and <tt>chunk_length</tt>, used the same way as in <xref target="prio3sumvec"/> and
<xref target="prio3histogram"/>.</t>
          <t>Validation works as follows. Let</t>
          <ul spacing="normal">
            <li>
              <t><tt>bits_for_weight = max_weight.bit_length()</tt></t>
            </li>
            <li>
              <t><tt>offset = 2**bits_for_weight - 1 - max_weight</tt></t>
            </li>
          </ul>
          <t>The Client reports the weight of the count vector by adding <tt>offset</tt> to it and
bit-encoding the result. Observe that only a weight of at most <tt>max_weight</tt> can
be encoded with <tt>bits_for_weight</tt> bits.</t>
          <t>The verifier checks that each entry of the encoded measurement is a bit (i.e.,
either one or zero). It then decodes the reported weight and subtracts it from
<tt>offset + sum(count_vec)</tt>, where <tt>count_vec</tt> is the count vector. The result is
zero if and only if the reported weight is equal to the true weight.</t>
          <t>Encoding, truncation, and decoding are defined as follows:</t>
          <sourcecode type="python"><![CDATA[
def encode(self, measurement: list[int]) -> list[F]:
    if len(measurement) != self.length:
        raise ValueError('invalid Client measurement length')

    # The first part is the vector of counters.
    count_vec = list(map(self.field, measurement))

    # The second part is the reported weight.
    weight_reported = sum(count_vec, self.field(0))

    encoded = []
    encoded += count_vec
    encoded += self.field.encode_into_bit_vector(
        (self.offset + weight_reported).as_unsigned(),
        self.bits_for_weight)
    return encoded

def truncate(self, meas: list[F]) -> list[F]:
    return meas[:self.length]

def decode(
        self,
        output: list[F],
        _num_measurements: int) -> list[int]:
    return [bucket_count.as_unsigned() for bucket_count in output]
]]></sourcecode>
          <t>Circuit evaluation is defined as follows:</t>
          <sourcecode type="python"><![CDATA[
def eval(
        self,
        meas: list[F],
        joint_rand: list[F],
        num_shares: int) -> list[F]:
    self.check_valid_eval(meas, joint_rand)

    # Check that each entry in the input vector is one or zero.
    range_check = self.field(0)
    r = joint_rand[0]
    r_power = r
    shares_inv = self.field(num_shares).inv()
    for i in range(self.GADGET_CALLS[0]):
        inputs: list[Optional[F]]
        inputs = [None] * (2 * self.chunk_length)
        for j in range(self.chunk_length):
            index = i * self.chunk_length + j
            if index < len(meas):
                meas_elem = meas[index]
            else:
                meas_elem = self.field(0)

            inputs[j * 2] = r_power * meas_elem
            inputs[j * 2 + 1] = meas_elem - shares_inv

            r_power *= r

        range_check += self.GADGETS[0].eval(
            self.field,
            cast(list[F], inputs),
        )

    # Check that the weight `offset` plus the sum of the counters
    # is equal to the value claimed by the Client.
    count_vec = meas[:self.length]
    weight = sum(count_vec, self.field(0))
    weight_reported = \
        self.field.decode_from_bit_vector(meas[self.length:])
    weight_check = self.offset*shares_inv + weight - \
        weight_reported

    out = joint_rand[1] * range_check + \
        joint_rand[1] ** 2 * weight_check
    return [out]
]]></sourcecode>
          <table>
            <name>Parameters of validity circuit MultihotCountVec.</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>[ParallelSum(Mul(), chunk_length)]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[(length + bits_for_weight + chunk_length - 1) // chunk_length]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>MEAS_LEN</tt></td>
                <td align="left">
                  <tt>length + bits_for_weight</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>length</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>list[int]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">
                  <tt>list[int]</tt></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 bit-string of length <tt>BITS</tt> and the Aggregators hold a sequence 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 measurements
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>
          <t>Each Client splits its string into input shares and sends one share to each
Aggregator.</t>
        </li>
        <li>
          <t>The Aggregators agree on an initial set of candidate prefixes, say <tt>0</tt> and
<tt>1</tt>.</t>
        </li>
        <li>
          <t>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.</t>
        </li>
        <li>
          <t>The Aggregators send their aggregate shares to the Collector, who combines
them to recover the counts of each candidate prefix.</t>
        </li>
        <li>
          <t>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.</t>
        </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 arithmetic sketch of <xref target="BBCGGI21"/>, Section
4.2. (The paper calls this a "secure sketch", but the underlying technique was
later generalized in <xref target="BBCGGI23"/>, where it is called "arithmetic sketching".)
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 at most 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-bbcggi21"/>. 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 a constant.
Indices into the IDPF tree are encoded as integers in range <tt>[0, 2^BITS)</tt>. (In
Poplar1, each Client's bit string is encoded as an index; see
<xref target="poplar1-idpf-index-encoding"/> for details.) 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, L)</tt> denote the least significant <tt>L</tt> bits of positive integer <tt>x</tt>. A
positive integer <tt>0 &lt;= x &lt; 2^L</tt> is defined 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>FieldInner</tt>), and one for leaf nodes (<tt>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>Output</tt> as shorthand for the type
<tt>Union[list[list[FieldInner]], list[list[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>
            <t><tt>idpf.gen(alpha: int, beta_inner: list[list[FieldInner]], beta_leaf:
list[FieldLeaf], binder: bytes, rand: bytes) -&gt; tuple[bytes,
list[bytes]]</tt> is the randomized IDPF-key generation algorithm. Its inputs are the index <tt>alpha</tt>
the values <tt>beta</tt>, and a binder string.  </t>
            <t>
The output is a public part that is sent to all Aggregators
and a vector of private IDPF keys, one for each aggregator. The binder string
is used to derive the key in the underlying XofFixedKeyAes128 XOF that is used
for expanding seeds at each level.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>alpha</tt> <bcp14>MUST</bcp14> be in <tt>range(2**BITS)</tt>.</t>
              </li>
              <li>
                <t><tt>beta_inner</tt> <bcp14>MUST</bcp14> have length <tt>BITS - 1</tt>.</t>
              </li>
              <li>
                <t><tt>beta_inner[level]</tt> <bcp14>MUST</bcp14> have length <tt>VALUE_LEN</tt> for each <tt>level</tt> in
 <tt>range(BITS - 1)</tt>.</t>
              </li>
              <li>
                <t><tt>beta_leaf</tt> <bcp14>MUST</bcp14> have length <tt>VALUE_LEN</tt>.</t>
              </li>
              <li>
                <t><tt>rand</tt> <bcp14>MUST</bcp14> be generated by a CSPRNG and have length <tt>RAND_SIZE</tt>.</t>
              </li>
              <li>
                <t><tt>binder</tt> <bcp14>MUST</bcp14> be chosen uniformly at random by the Client (see
<xref target="nonce-requirements"/>).      </t>
                <ul empty="true">
                  <li>
                    <t>TODO If the binder needs to be random, then we need to specify its
length so that the user knows how many bytes to sample.</t>
                  </li>
                </ul>
              </li>
            </ul>
            <ul empty="true">
              <li>
                <t>TODO(issue #255) Decide whether to treat the public share as an opaque byte
string or to replace it with an explicit type.</t>
              </li>
            </ul>
          </li>
          <li>
            <t><tt>idpf.eval(agg_id: int, public_share: bytes, key: bytes, level:
int, prefixes: tuple[int, ...], binder: bytes) -&gt; Output</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 (i.e., <tt>Output</tt>) depends on the value of <tt>level</tt>: If <tt>level &lt;
BITS-1</tt>, the output is the value for an inner node, which has type
<tt>list[list[FieldInner]]</tt>; otherwise, if <tt>level == BITS-1</tt>, then the output is
the value for a leaf node, which has type <tt>list[list[FieldLeaf]]</tt>.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>agg_id</tt> <bcp14>MUST</bcp14> be in <tt>range(SHARES)</tt> and match the index of <tt>key</tt> in
the sequence of IDPF keys output by the Client.</t>
              </li>
              <li>
                <t><tt>level</tt> <bcp14>MUST</bcp14> be in <tt>range(0, BITS)</tt>.</t>
              </li>
              <li>
                <t>Each <tt>prefix</tt> in <tt>prefixes</tt> <bcp14>MUST</bcp14> be distinct and in <tt>range(2**level)</tt>.</t>
              </li>
            </ul>
          </li>
        </ul>
        <t>In addition, the following method is derived for each concrete <tt>Idpf</tt>:</t>
        <sourcecode type="python"><![CDATA[
def current_field(
        self,
        level: int) -> Union[type[FieldInner], type[FieldLeaf]]:
    if level < self.BITS - 1:
        return self.field_inner
    return self.field_leaf
]]></sourcecode>
        <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-bbcggi21"/> 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. Equal to twice the XOF's seed size.</td>
            </tr>
            <tr>
              <td align="left">KEY_SIZE</td>
              <td align="left">Size in bytes of each IDPF key</td>
            </tr>
            <tr>
              <td align="left">FieldInner</td>
              <td align="left">Implementation of <tt>Field</tt> (<xref target="field"/>) used for values of inner nodes</td>
            </tr>
            <tr>
              <td align="left">FieldLeaf</td>
              <td align="left">Implementation of <tt>Field</tt> used for values of leaf nodes</td>
            </tr>
            <tr>
              <td align="left">Output</td>
              <td align="left">Alias of <tt>Union[list[list[FieldInner]], list[list[FieldLeaf]]]</tt></td>
            </tr>
            <tr>
              <td align="left">FieldVec</td>
              <td align="left">Alias of <tt>Union[list[FieldInner], list[FieldLeaf]]</tt></td>
            </tr>
          </tbody>
        </table>
        <section anchor="poplar1-idpf-index-encoding">
          <name>Encoding inputs as indices</name>
          <t>How data are represented as IDPF indices is up to the application. When the
inputs are fixed-length byte strings, the most natural choice of encoder is
<tt>from_be_bytes()</tt>. This ensures that, when a string is a prefix of another, so
too is its index. (Index prefixes are defined in <xref target="idpf"/>). For example,</t>
          <sourcecode type="python"><![CDATA[
from_be_bytes(b"\x01\x02") == 0x0102
]]></sourcecode>
          <t>is a prefix of</t>
          <sourcecode type="python"><![CDATA[
from_be_bytes(b"\x01\x02\x03") == 0x010203
]]></sourcecode>
          <t>When the inputs are variable length, it is necessary to pad each input to some
fixed length. Further, the padding scheme must be non-ambiguous. For example,
each input could be padded with <tt>b"\x01"</tt> followed by as many <tt>b"\x00"</tt> bytes
as needed.</t>
        </section>
      </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>SHARES == 2</tt> and <tt>VALUE_LEN == 2</tt> and an implementation of <tt>Xof</tt>
(<xref target="xof"/>). 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>Xof.SEED_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>RAND_SIZE</tt></td>
              <td align="left">
                <tt>Xof.SEED_SIZE * 3 + Idpf.RAND_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>int</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggParam</tt></td>
              <td align="left">
                <tt>tuple[int, Sequence[int]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PublicShare</tt></td>
              <td align="left">
                <tt>bytes</tt> (IDPF public share)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>InputShare</tt></td>
              <td align="left">
                <tt>tuple[bytes, bytes, list[FieldInner], list[FieldLeaf]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>OutShare</tt></td>
              <td align="left">
                <tt>FieldVec</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggShare</tt></td>
              <td align="left">
                <tt>FieldVec</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">
                <tt>list[int]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepState</tt></td>
              <td align="left">
                <tt>tuple[bytes, int, FieldVec]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepShare</tt></td>
              <td align="left">
                <tt>FieldVec</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepMessage</tt></td>
              <td align="left">
                <tt>Optional[FieldVec]</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">USAGE_SHARD_RAND: int</td>
              <td align="left">1</td>
            </tr>
            <tr>
              <td align="left">USAGE_CORR_INNER: int</td>
              <td align="left">2</td>
            </tr>
            <tr>
              <td align="left">USAGE_CORR_LEAF: int</td>
              <td align="left">3</td>
            </tr>
            <tr>
              <td align="left">USAGE_VERIFY_RAND: int</td>
              <td align="left">4</td>
            </tr>
          </tbody>
        </table>
        <section anchor="sharding-1">
          <name>Sharding</name>
          <t>The Client's measurement is an IDPF index, denoted <tt>alpha</tt>. (See
<xref target="poplar1-idpf-index-encoding"/> for guidelines on index encoding.) 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 arithmetic 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.</t>
          <figure anchor="poplar1-mes2inp">
            <name>The sharding algorithm for Poplar1.</name>
            <sourcecode type="python"><![CDATA[
def shard(
        self,
        measurement: int,
        nonce: bytes,
        rand: bytes) -> tuple[bytes, list[Poplar1InputShare]]:
    if len(nonce) != self.NONCE_SIZE:
        raise ValueError("incorrect nonce size")
    if len(rand) != self.RAND_SIZE:
        raise ValueError("incorrect size of random bytes argument")

    l = self.xof.SEED_SIZE

    # Split the random input into the random input for IDPF key
    # generation, correlated randomness, and sharding.
    if len(rand) != self.RAND_SIZE:
        raise ValueError('incorrect rand size')
    idpf_rand, rand = front(self.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)

    xof = self.xof(
        k_shard,
        self.domain_separation_tag(USAGE_SHARD_RAND),
        nonce,
    )

    # 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
    # evaluate the sketch during preparation. This sketch is used
    # to verify the one-hotness of their output shares.
    beta_inner = [
        [self.idpf.field_inner(1), k]
        for k in xof.next_vec(self.idpf.field_inner,
                              self.idpf.BITS - 1)
    ]
    beta_leaf = [self.idpf.field_leaf(1)] + \
        xof.next_vec(self.idpf.field_leaf, 1)

    # Generate the IDPF keys.
    (public_share, keys) = self.idpf.gen(
        measurement,
        beta_inner,
        beta_leaf,
        nonce,
        idpf_rand,
    )

    # Generate correlated randomness used by the Aggregators to
    # evaluate the sketch over their output shares. Seeds are used
    # to encode shares of the `(a, b, c)` triples. (See [BBCGGI21,
    # Appendix C.4].)
    corr_offsets: list[Field] = vec_add(
        self.xof.expand_into_vec(
            self.idpf.field_inner,
            corr_seed[0],
            self.domain_separation_tag(USAGE_CORR_INNER),
            byte(0) + nonce,
            3 * (self.idpf.BITS - 1),
        ),
        self.xof.expand_into_vec(
            self.idpf.field_inner,
            corr_seed[1],
            self.domain_separation_tag(USAGE_CORR_INNER),
            byte(1) + nonce,
            3 * (self.idpf.BITS - 1),
        ),
    )
    corr_offsets += vec_add(
        self.xof.expand_into_vec(
            self.idpf.field_leaf,
            corr_seed[0],
            self.domain_separation_tag(USAGE_CORR_LEAF),
            byte(0) + nonce,
            3,
        ),
        self.xof.expand_into_vec(
            self.idpf.field_leaf,
            corr_seed[1],
            self.domain_separation_tag(USAGE_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: list[list[Field64]] = [[], []]
    for level in range(self.idpf.BITS):
        field = cast(type[Field], self.idpf.current_field(level))
        k = beta_inner[level][1] if level < self.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 = xof.next_vec(field, 2)
        corr0 = vec_sub([A, B], corr1)
        if level < self.idpf.BITS - 1:
            corr_inner[0] += cast(list[Field64], corr0)
            corr_inner[1] += cast(list[Field64], corr1)
        else:
            corr_leaf = [
                cast(list[Field255], corr0),
                cast(list[Field255], corr1),
            ]

    # Each input share consists of the Aggregator's IDPF key
    # and a share of the correlated randomness.
    input_shares = list(zip(keys, corr_seed, corr_inner, corr_leaf))
    return (public_share, input_shares)
]]></sourcecode>
          </figure>
        </section>
        <section anchor="poplar1-prep">
          <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>
          <figure anchor="poplar1-prep-state">
            <name>Preparation state for Poplar1.</name>
            <sourcecode type="python"><![CDATA[
def prep_init(
        self,
        verify_key: bytes,
        agg_id: int,
        agg_param: Poplar1AggParam,
        nonce: bytes,
        public_share: bytes,
        input_share: Poplar1InputShare) -> tuple[
            Poplar1PrepState,
            FieldVec]:
    (level, prefixes) = agg_param
    (key, corr_seed, corr_inner, corr_leaf) = input_share
    field = self.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 ValueError('out of order prefix')

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

    # Get shares of the correlated randomness for evaluating the
    # Aggregator's share of the sketch.
    if level < self.idpf.BITS - 1:
        corr_xof = self.xof(
            corr_seed,
            self.domain_separation_tag(USAGE_CORR_INNER),
            byte(agg_id) + nonce,
        )
        # Fast-forward the XOF state to the current level.
        corr_xof.next_vec(field, 3 * level)
    else:
        corr_xof = self.xof(
            corr_seed,
            self.domain_separation_tag(USAGE_CORR_LEAF),
            byte(agg_id) + nonce,
        )
    (a_share, b_share, c_share) = corr_xof.next_vec(field, 3)
    if level < self.idpf.BITS - 1:
        (A_share, B_share) = cast(
            list[Field],
            corr_inner[2 * level:2 * (level + 1)],
        )
    else:
        (A_share, B_share) = cast(list[Field], corr_leaf)

    # Evaluate the Aggregator's share of the sketch. These are
    # called the "masked input values" [BBCGGI21, Appendix C.4].
    verify_rand_xof = self.xof(
        verify_key,
        self.domain_separation_tag(USAGE_VERIFY_RAND),
        nonce + to_be_bytes(level, 2),
    )
    verify_rand = cast(
        list[Field],
        verify_rand_xof.next_vec(field, len(prefixes)),
    )
    sketch_share = [a_share, b_share, c_share]
    out_share = []
    for (i, r) in enumerate(verify_rand):
        data_share = cast(Field, value[i][0])
        auth_share = cast(Field, value[i][1])
        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 = [A_share, B_share, field(agg_id)] + out_share
    return (
        (
            b'evaluate sketch',
            level,
            cast(FieldVec, prep_mem),
        ),
        cast(FieldVec, sketch_share),
    )

def prep_next(
        self,
        prep_state: Poplar1PrepState,
        prep_msg: Optional[FieldVec]) -> Union[
            tuple[Poplar1PrepState, FieldVec],
            FieldVec]:
    prev_sketch = cast(list[Field], prep_msg)
    (step, level, prep_mem) = prep_state

    if step == b'evaluate sketch':
        if prev_sketch is None:
            raise ValueError('expected value, got none')
        elif len(prev_sketch) != 3:
            raise ValueError('incorrect sketch length')
        A_share = cast(Field, prep_mem[0])
        B_share = cast(Field, prep_mem[1])
        agg_id = cast(Field, prep_mem[2])
        prep_mem = 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 cast(
            tuple[Poplar1PrepState, FieldVec],
            (
                (
                    b'reveal sketch',
                    level,
                    prep_mem,
                ),
                sketch_share,
            )
        )

    elif step == b'reveal sketch':
        if prev_sketch is None:
            return prep_mem  # Output shares
        else:
            raise ValueError('invalid prep message')

    raise ValueError('invalid prep state')

def prep_shares_to_prep(
        self,
        agg_param: Poplar1AggParam,
        prep_shares: list[FieldVec]) -> Optional[FieldVec]:
    if len(prep_shares) != 2:
        raise ValueError('incorrect number of prep shares')
    (level, _) = agg_param
    field = self.idpf.current_field(level)
    sketch = vec_add(
        cast(list[Field], prep_shares[0]),
        cast(list[Field], prep_shares[1]),
    )
    if len(sketch) == 3:
        return cast(FieldVec, sketch)
    elif len(sketch) == 1:
        if sketch == field.zeros(1):
            # In order to reduce communication overhead, let `None`
            # denote a successful sketch verification.
            return None
        else:
            raise ValueError('sketch verification failed')
    else:
        raise ValueError('incorrect sketch length')
]]></sourcecode>
          </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. This function checks that levels are
increasing between calls, and also enforces that the prefixes at each level are
suffixes of the previous level's prefixes.</t>
          <figure anchor="poplar1-validity-scope">
            <name>Validity of aggregation parameters for Poplar1.</name>
            <sourcecode type="python"><![CDATA[
def get_ancestor(
        index: int,
        this_level: int,
        last_level: int) -> int:
    """
    Helper function to determine the prefix of `index` at
    `last_level`.
    """
    return index >> (this_level - last_level)

def is_valid(
        self,
        agg_param: Poplar1AggParam,
        previous_agg_params: list[Poplar1AggParam]) -> bool:
    """
    Checks that levels are increasing between calls, and also
    enforces that the prefixes at each level are suffixes of the
    previous level's prefixes.
    """
    if len(previous_agg_params) < 1:
        return True

    (level, prefixes) = agg_param
    (last_level, last_prefixes) = previous_agg_params[-1]
    last_prefixes_set = set(last_prefixes)

    # Check that level increased.
    if level <= last_level:
        return False

    # Check that prefixes are suffixes of the last level's prefixes.
    for prefix in prefixes:
        last_prefix = get_ancestor(prefix, level, last_level)
        if last_prefix not in last_prefixes_set:
            # Current prefix not a suffix of last level's prefixes.
            return False
    return True
]]></sourcecode>
          </figure>
        </section>
        <section anchor="aggregation-2">
          <name>Aggregation</name>
          <t>Aggregation involves simply adding up the output shares.</t>
          <figure anchor="poplar1-out2agg">
            <name>Aggregation algorithm for Poplar1.</name>
            <sourcecode type="python"><![CDATA[
def aggregate(
        self,
        agg_param: Poplar1AggParam,
        out_shares: list[FieldVec]) -> FieldVec:
    (level, prefixes) = agg_param
    field = self.idpf.current_field(level)
    agg_share = cast(list[Field], field.zeros(len(prefixes)))
    for out_share in out_shares:
        agg_share = vec_add(agg_share, cast(list[Field], out_share))
    return cast(FieldVec, agg_share)
]]></sourcecode>
          </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>
            <sourcecode type="python"><![CDATA[
def unshard(
        self,
        agg_param: Poplar1AggParam,
        agg_shares: list[FieldVec],
        _num_measurements: int) -> list[int]:
    (level, prefixes) = agg_param
    field = self.idpf.current_field(level)
    agg = cast(list[Field], field.zeros(len(prefixes)))
    for agg_share in agg_shares:
        agg = vec_add(agg, cast(list[Field], agg_share))
    return [x.as_unsigned() for x in agg]
]]></sourcecode>
          </figure>
        </section>
        <section anchor="poplar1-encode">
          <name>Message Serialization</name>
          <t>This section defines serialization formats for messages exchanged over the
network while executing <tt>Poplar1</tt>. It is <bcp14>RECOMMENDED</bcp14> that implementations
provide serialization methods for them.</t>
          <t>Message structures are defined following <xref section="3" sectionFormat="of" target="RFC8446"/>). In the
remainder we use <tt>S</tt> as an alias for <tt>Poplar1.xof.SEED_SIZE</tt>, <tt>Fi</tt> as an alias
for <tt>Poplar1.idpf.field_inner</tt> and <tt>Fl</tt> as an alias for
<tt>Poplar1.idpf.field_leaf</tt>. XOF seeds are represented as follows:</t>
          <sourcecode type="tls-presentation"><![CDATA[
opaque Poplar1Seed[S];
]]></sourcecode>
          <t>Elements of the inner field are encoded in little-endian byte order (as defined
in <xref target="field"/>) and are represented as follows:</t>
          <sourcecode type="tls-presentation"><![CDATA[
opaque Poplar1FieldInner[Fi];
]]></sourcecode>
          <t>Likewise, elements of the leaf field are encoded in little-endian byte order
(as defined in <xref target="field"/>) and are represented as follows:</t>
          <sourcecode type="tls-presentation"><![CDATA[
opaque Poplar1FieldLeaf[Fl];
]]></sourcecode>
          <section anchor="public-share-1">
            <name>Public Share</name>
            <t>The public share is equal to the IDPF public share, which is a byte string.
(See <xref target="idpf"/>.)</t>
          </section>
          <section anchor="input-share-1">
            <name>Input Share</name>
            <t>Each input share is structured as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    opaque idpf_key[Poplar1.Idpf.KEY_SIZE];
    Poplar1Seed corr_seed;
    Poplar1FieldInner corr_inner[Fi * 2 * (Poplar1.Idpf.BITS - 1)];
    Poplar1FieldLeaf corr_leaf[Fl * 2];
} Poplar1InputShare;
]]></sourcecode>
          </section>
          <section anchor="prep-share-1">
            <name>Prep Share</name>
            <t>Encoding of the prep share depends on the round of sketching: if the first
round, then each sketch share has three field elements; if the second round,
then each sketch share has one field element. The field that is used depends on
the level of the IDPF tree specified by the aggregation parameter, either the
inner field or the leaf field.</t>
            <t>For the first round and inner field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldInner sketch_share[Fi * 3];
} Poplar1PrepShareRoundOneInner;
]]></sourcecode>
            <t>For the first round and leaf field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldLeaf sketch_share[Fl * 3];
} Poplar1PrepShareRoundOneLeaf;
]]></sourcecode>
            <t>For the second round and inner field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldInner sketch_share;
} Poplar1PrepShareRoundTwoInner;
]]></sourcecode>
            <t>For the second round and leaf field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldLeaf sketch_share;
} Poplar1PrepShareRoundTwoLeaf;
]]></sourcecode>
          </section>
          <section anchor="prep-message-1">
            <name>Prep Message</name>
            <t>Likewise, the structure of the prep message for Poplar1 depends on the
sketching round and field. For the first round and inner field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldInner[Fi * 3];
} Poplar1PrepMessageRoundOneInner;
]]></sourcecode>
            <t>For the first round and leaf field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldLeaf sketch[Fl * 3];
} Poplar1PrepMessageRoundOneLeaf;
]]></sourcecode>
            <t>Note that these messages have the same structures as the prep shares for the
first round.</t>
            <t>The second-round prep message is the empty string. This is because the sketch
shares are expected to sum to a particular value if the output shares are
valid; we represent a successful preparation with the empty string and
otherwise return an error.</t>
          </section>
          <section anchor="aggregate-share">
            <name>Aggregate Share</name>
            <t>The encoding of the aggregate share depends on whether the inner or leaf field
is used, and the number of candidate prefixes. Both of these are determined by
 the aggregation parameter.</t>
            <t>Let <tt>prefix_count</tt> denote the number of candidate prefixes. For the inner field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldInner agg_share[Fi * prefix_count];
} Poplar1AggShareInner;
]]></sourcecode>
            <t>For the leaf field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldLeaf agg_share[Fl * prefix_count];
} Poplar1AggShareLeaf;
]]></sourcecode>
          </section>
          <section anchor="aggregation-parameter">
            <name>Aggregation Parameter</name>
            <t>The aggregation parameter is encoded as follows:</t>
            <ul empty="true">
              <li>
                <t>TODO(issue #255) Express the aggregation parameter encoding in TLS syntax.
Decide whether to RECOMMEND this encoding, and if so, add it to test vectors.</t>
              </li>
            </ul>
            <sourcecode type="python"><![CDATA[
def encode_agg_param(self, agg_param: Poplar1AggParam) -> bytes:
    level, prefixes = agg_param
    if level not in range(2 ** 16):
        raise ValueError('level out of range')
    if len(prefixes) not in range(2 ** 32):
        raise ValueError('number of prefixes out of range')
    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 = ((level + 1) * len(prefixes) + 7) // 8
    encoded += to_be_bytes(packed, l)
    return encoded

def decode_agg_param(self, encoded: bytes) -> Poplar1AggParam:
    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 = ((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 ValueError('trailing bytes')
    return (level, tuple(prefixes))
]]></sourcecode>
            <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>
          </section>
        </section>
      </section>
      <section anchor="idpf-bbcggi21">
        <name>The IDPF scheme of <xref target="BBCGGI21"/></name>
        <t>In this section we specify a concrete IDPF suitable for instantiating
Poplar1. The scheme gets its name from the name of the protocol of
<xref target="BBCGGI21"/>.</t>
        <t>The constant and type definitions required by the <tt>Idpf</tt> interface are given in
<xref target="idpf-bbcggi21-param"/>.</t>
        <t>Our IDPF requires an XOF for deriving the output shares, as well as a variety of
other artifacts used internally. For performance reasons, we instantiate this
object using XofFixedKeyAes128 (<xref target="xof-fixed-key-aes128"/>). See <xref target="xof-vs-ro"/> for
justification of this choice.</t>
        <table anchor="idpf-bbcggi21-param">
          <name>Constants and type definitions for the IDPF of BBCGGI21.</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>Xof.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-bbcggi21-helper-functions"/>. In the following, we let <tt>Field2</tt> denote the
field <tt>GF(2)</tt>.</t>
          <figure anchor="idpf-bbcggi21-gen">
            <name>IDPF-key generation algorithm of BBCGGI21.</name>
            <sourcecode type="python"><![CDATA[
def gen(
        self,
        alpha: int,
        beta_inner: list[list[Field64]],
        beta_leaf: list[Field255],
        binder: bytes,
        rand: bytes) -> tuple[bytes, list[bytes]]:
    if alpha not in range(2 ** self.BITS):
        raise ValueError("alpha out of range")
    if len(beta_inner) != self.BITS - 1:
        raise ValueError("incorrect beta_inner length")
    if len(rand) != self.RAND_SIZE:
        raise ValueError("incorrect rand size")

    key = [
        rand[:XofFixedKeyAes128.SEED_SIZE],
        rand[XofFixedKeyAes128.SEED_SIZE:],
    ]

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

        (s0, t0) = self.extend(seed[0], binder)
        (s1, t1) = self.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) = self.convert(level, x0, binder)
        (seed[1], w1) = self.convert(level, x1, binder)
        ctrl[0] = t0[keep] + ctrl[0] * ctrl_cw[keep]
        ctrl[1] = t1[keep] + ctrl[1] * ctrl_cw[keep]

        if level < self.BITS - 1:
            b = cast(list[Field], beta_inner[level])
        else:
            b = cast(list[Field], beta_leaf)
        if len(b) != self.VALUE_LEN:
            raise ValueError(
                "length of beta must match the value length"
            )

        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 = self.encode_public_share(correction_words)
    return (public_share, key)
]]></sourcecode>
          </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-bbcggi21-helper-functions"/>.</t>
          <figure anchor="idpf-bbcggi21-eval">
            <name>IDPF-evaluation generation algorithm of BBCGGI21.</name>
            <sourcecode type="python"><![CDATA[
def eval(
        self,
        agg_id: int,
        public_share: bytes,
        key: bytes,
        level: int,
        prefixes: Sequence[int],
        binder: bytes) -> Union[
            list[list[Field64]],
            list[list[Field255]]]:
    if agg_id not in range(self.SHARES):
        raise ValueError('aggregator id out of range')
    if level not in range(self.BITS):
        raise ValueError('level out of range')
    if len(set(prefixes)) != len(prefixes):
        raise ValueError('prefixes must be unique')

    correction_words = self.decode_public_share(public_share)
    out_share = []
    for prefix in prefixes:
        if prefix not in range(2 ** (level + 1)):
            raise ValueError('prefix out of range')

        # 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 control bit (`ctrl`).
        seed = key
        ctrl = Field2(agg_id)
        y: FieldVec
        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 the IDPF 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) = self.eval_next(
                seed,
                ctrl,
                correction_words[current_level],
                current_level,
                bit,
                binder,
            )
        if agg_id == 0:
            out_share.append(cast(list[Field], y))
        else:
            out_share.append(vec_neg(cast(list[Field], y)))
    return cast(
        Union[list[list[Field64]], list[list[Field255]]],
        out_share,
    )

def eval_next(
        self,
        prev_seed: bytes,
        prev_ctrl: Field2,
        correction_word: CorrectionWordTuple,
        level: int,
        bit: int,
        binder: bytes) -> tuple[bytes, Field2, FieldVec]:
    """
    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.
    """

    field = self.current_field(level)
    seed_cw = correction_word[0]
    ctrl_cw = correction_word[1]
    w_cw = cast(list[Field], correction_word[2])
    (s, t) = self.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]
    convert_output = self.convert(level, s[bit], binder)
    next_seed = convert_output[0]
    y = cast(list[Field], convert_output[1])
    # 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 = cast(Field, field(next_ctrl.as_unsigned()))
    for i in range(len(y)):
        y[i] += w_cw[i] * mask

    return (next_seed, next_ctrl, cast(FieldVec, y))
]]></sourcecode>
          </figure>
        </section>
        <section anchor="idpf-bbcggi21-helper-functions">
          <name>Auxiliary Functions</name>
          <figure anchor="idpf-bbcggi21-helpers">
            <name>Helper functions for the IDPF.</name>
            <sourcecode type="python"><![CDATA[
def extend(
        self,
        seed: bytes,
        binder: bytes) -> tuple[list[bytes], list[Field2]]:
    xof = XofFixedKeyAes128(seed, format_dst(1, 0, 0), binder)
    s = [
        bytearray(xof.next(XofFixedKeyAes128.SEED_SIZE)),
        bytearray(xof.next(XofFixedKeyAes128.SEED_SIZE)),
    ]
    # Use the least significant bits as the control bit correction,
    # and then zero it out. This gives effectively 127 bits of
    # security, but reduces the number of AES calls needed by 1/3.
    t = [Field2(s[0][0] & 1), Field2(s[1][0] & 1)]
    s[0][0] &= 0xFE
    s[1][0] &= 0xFE
    return ([bytes(s[0]), bytes(s[1])], t)

def convert(
        self,
        level: int,
        seed: bytes,
        binder: bytes) -> tuple[bytes, FieldVec]:
    xof = XofFixedKeyAes128(seed, format_dst(1, 0, 1), binder)
    next_seed = xof.next(XofFixedKeyAes128.SEED_SIZE)
    field = self.current_field(level)
    w = xof.next_vec(field, self.VALUE_LEN)
    return (next_seed, cast(FieldVec, w))

def encode_public_share(
        self,
        correction_words: list[CorrectionWordTuple]) -> bytes:
    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 = cast(type[Field], self.current_field(level))
        encoded += seed_cw
        encoded += field.encode_vec(cast(list[Field], w_cw))
    return encoded

def decode_public_share(
        self,
        encoded: bytes) -> list[CorrectionWordTuple]:
    l = (2 * self.BITS + 7) // 8
    encoded_ctrl, encoded = encoded[:l], encoded[l:]
    control_bits = unpack_bits(encoded_ctrl, 2 * self.BITS)
    correction_words = []
    for level in range(self.BITS):
        field = self.current_field(level)
        ctrl_cw = (
            control_bits[level * 2],
            control_bits[level * 2 + 1],
        )
        l = XofFixedKeyAes128.SEED_SIZE
        seed_cw, encoded = encoded[:l], encoded[l:]
        l = field.ENCODED_SIZE * self.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 ValueError('trailing bytes')
    return correction_words
]]></sourcecode>
          </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 the IDPF in <xref target="idpf-bbcggi21"/> (<tt>VALUE_LEN
== 2</tt>) and XofTurboShake128 (<xref target="xof-turboshake128"/>). 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>
          <t>Privacy: An attacker that controls 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. We assume the attacker
controls the entire network except for channels between honest Clients and
honest Aggregators. In particular, it cannot forge or prevent transmission
of messages on these channels.</t>
        </li>
        <li>
          <t>Robustness: An attacker that controls a subset of Clients cannot cause the
Collector to compute anything other than the aggregate of the measurements
of honest Clients. We assume the attacker eavesdrops on the network but does
not control transmission of messages between honest parties.</t>
        </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>
          <t>Securely distributing the long-lived parameters, in particular the
verification key.</t>
        </li>
        <li>
          <t>Establishing secure channels:  </t>
          <ul spacing="normal">
            <li>
              <t>Confidential and authentic channels among Aggregators, and between the
Aggregators and the Collector; and</t>
            </li>
            <li>
              <t>Confidential and Aggregator-authenticated channels between Clients and
Aggregators.</t>
            </li>
          </ul>
        </li>
        <li>
          <t>Enforcing the non-collusion properties required of the specific VDAF in use.</t>
        </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 provide:</t>
      <ol spacing="normal" type="1"><li>
          <t>Mitigation of 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>
        </li>
        <li>
          <t>Differential privacy <xref target="Dwo06"/>. Depending on the distribution of the
measurements, the aggregate result itself can still leak a significant
amount of information about an individual measurement or the person that
generated it.</t>
        </li>
        <li>
          <t>Robustness in the presence of a malicious Aggregator. An Aggregator can,
without detection, manipulate the aggregate result by modifying its own
aggregate share.</t>
        </li>
        <li>
          <t>Guaranteed output delivery <xref target="GSZ20"/>. An attacker that controls transmission
of messages between honest parties can prevent computation of the aggregate
result by dropping messages.</t>
        </li>
      </ol>
      <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>
            <t>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.</t>
          </li>
          <li>
            <t>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.</t>
          </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 report 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-public-share">
        <name>Requirements for the Public Share</name>
        <t>The Aggregators <bcp14>MUST</bcp14> ensure they have both received the same public share from
the Client. It is sufficient, for example, to exchange a hash of the public
share over a secure channel.</t>
      </section>
      <section anchor="requirements-for-aggregation-parameters">
        <name>Requirements for 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 anchor="agg-param-privacy">
          <name>Additional Privacy Considerations</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>A malicious adversary controlling the Collector and one of the Aggregators can
further turn arbitrary non-heavy prefixes into heavy ones by tampering with the
IDPF output at any position. While our construction ensures that the nodes
evaluated at one level are children of the nodes evaluated at the previous
level, this still may allow an adversary to discover individual non-heavy
strings.</t>
          <t>The only practical, general-purpose approach to mitigating these leakages is via
differential privacy, which is <bcp14>RECOMMENDED</bcp14> for all protocols using Poplar1 for
heavy-hitter type applications.</t>
        </section>
        <section anchor="safe-usage-of-idpf-outputs">
          <name>Safe Usage of IDPF Outputs</name>
          <t>The arithmetic sketch described in <xref target="poplar1"/> is used by the Aggregators to check
that the shares of the vector obtained by evaluating a Client's IDPF at a
sequence of candidate prefixes has at most one non-zero value, and that the
non-zero value is <tt>1</tt>. Depending on how the values are used, the arithmetic sketch
on its own may not be sufficient for robustness of the application. In
particular, a malicious Client may attempt to influence the computation by
choosing an IDPF that evaluates to <tt>1</tt> at more than one node at a given
level of the tree.</t>
          <t>This issue can be mitigated by using an IDPF that is extractable as defined in
in Appendix D of <xref target="BBCGGI21"/>. Extractability ensures that, for a particular
level of the tree, it is infeasible for an attacker to control values of the
IDPF such that it takes on chosen non-zero values at more than one node. (It
can practically only achieve the zero function, a point function, or a
pseudorandom function.)</t>
          <t>The IDPF specified in <xref target="idpf"/> only guarantees extractability at the last level
of the tree. (This is by virtue of using a larger field for the leaves than for
the inner nodes.) For intermediate levels, it is feasible for a client to
produce IDPF shares with two controlled non-zero nodes.</t>
          <t>This is not an issue for running heavy hitters, since (1) each node in the
prefix tree is a child of a previously traversed node, (2) the arithmetic sketch
would detect double voting at every level of the prefix tree, and (3) the IDPF
is extractable at the last level of the tree. However, the lack of
extractability at intermediate levels may result in attacks on the robustness
of certain applications.</t>
          <t>Thus applications <bcp14>SHOULD NOT</bcp14> use prefix counts for intermediate levels for any
purpose beyond the heavy-hitters tree traversal.</t>
        </section>
      </section>
      <section anchor="xof-vs-ro">
        <name>Requirements for XOFs</name>
        <t>As described in <xref target="xof"/>, our constructions rely on eXtendable
Output Functions (XOFs). In the security analyses of our protocols, these are
usually modeled as random oracles. XofTurboShake128 is designed to be
indifferentiable from a random oracle <xref target="MRH04"/>, making it a suitable choice
for most situations.</t>
        <t>The one exception is the IDPF of <xref target="idpf-bbcggi21"/>. Here, a random oracle is not
needed to prove privacy, since the analysis of <xref target="BBCGGI21"/>, Proposition 1, only
requires a Pseudorandom Generator (PRG). As observed in <xref target="GKWY20"/>, a PRG can be
instantiated from a correlation-robust hash function <tt>H</tt>. Informally,
correlation robustness requires that for a random <tt>r</tt>, <tt>H(xor(r, x))</tt> is
computationally indistinguishable from a random function of <tt>x</tt>. A PRG can
therefore be constructed as</t>
        <artwork><![CDATA[
PRG(r) = H(xor(r, 1)) || H(xor(r, 2)) || ...
]]></artwork>
        <t>since each individual hash function evaluation is indistinguishable from a random
function.</t>
        <t>Our construction at <xref target="xof-fixed-key-aes128"/> implements a correlation-robust
hash function using fixed-key AES. For security, it assumes that AES with a
fixed key can be modeled as a random permutation <xref target="GKWY20"/>. Additionally, we
use a different AES key for every client, which in the ideal cipher model leads
to better concrete security <xref target="GKWWY20"/>.</t>
        <t>We note that for robustness, the analysis of <xref target="BBCGGI21"/> still assumes a random
oracle to make the Idpf extractable. While XofFixedKeyAes128 has been shown
to be differentiable from a random oracle <xref target="GKWWY20"/>, there are no known
attacks exploiting this difference.
We also stress that even if the Idpf is not extractable, Poplar1 guarantees
that every client can contribute to at most one prefix among the ones being
evaluated by the helpers.</t>
      </section>
      <section anchor="security-multiproof">
        <name>Choosing the Field Size</name>
        <t>Prio3 and other systems built from FLPs (<xref target="flp-bbcggi19"/> in particular) may
benefit from choosing a field size that is as small as possible. Generally
speaking, a smaller field results in lower communication and storage costs.
Care must be taken, however, since a smaller field also results in degraded (or
even vacuous) robustness.</t>
        <t>Different variants of Prio3 (<xref target="prio3"/>) use different field sizes: Prio3Count
uses Field64; but Prio3Sum, Prio3SumVec, and Prio3Histogram use Field128, a
field that is twice as large as Field64. This is due to the use of joint
randomness (<xref target="flp"/>) in the latter variants. Joint randomness allows for more
flexible circuit design (see <xref target="flp-bbcggi19-overview-extensions"/>), but opens up
Prio3 to precomputation attacks, which the larger field mitigates. (See
<xref target="DPRS23"/>, Theorem 1.) Note that privacy is not susceptible to such attacks.</t>
        <t>Another way to mitigate this issue (or improve robustness in general) is to
generate and verify multiple, independent proofs. (See <xref target="multiproofs"/>.) For
Prio3, the <tt>PROOFS</tt> parameter controls the number of proofs (at least one) that
are generated and verified.</t>
        <t>In general, Field128 is <bcp14>RECOMMENDED</bcp14> for use in Prio3 when the circuit uses
joint randomness (<tt>JOINT_RAND_LEN &gt; 0</tt>) and <tt>PROOFS == 1</tt>. Field64 <bcp14>MAY</bcp14> be used
instead, but <tt>PROOFS</tt> <bcp14>MUST</bcp14> be set to at least <tt>3</tt>. Breaking robustness for
<tt>PROOFS == 2</tt> is feasible, if impractical; but <tt>PROOFS == 1</tt> is completely
broken for such a small field.</t>
      </section>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>A codepoint for each (V)DAF in this document is defined in the table below. Note
that <tt>0xFFFF0000</tt> through <tt>0xFFFFFFFF</tt> are reserved for private use.</t>
      <table anchor="codepoints">
        <name>Unique identifiers for (V)DAFs.</name>
        <thead>
          <tr>
            <th align="left">Value</th>
            <th align="left">Scheme</th>
            <th align="left">Type</th>
            <th align="left">Reference</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>0x00000000</tt></td>
            <td align="left">Prio3Count</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3count"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000001</tt></td>
            <td align="left">Prio3Sum</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3sum"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000002</tt></td>
            <td align="left">Prio3SumVec</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3sumvec"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000003</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>0x00000004</tt></td>
            <td align="left">Prio3MultihotCountVec</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3multihotcountvec"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000005</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 anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <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"/>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
        <reference anchor="RFC8446">
          <front>
            <title>The Transport Layer Security (TLS) Protocol Version 1.3</title>
            <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
            <date month="August" year="2018"/>
            <abstract>
              <t>This document specifies version 1.3 of the Transport Layer Security (TLS) protocol. TLS allows client/server applications to communicate over the Internet in a way that is designed to prevent eavesdropping, tampering, and message forgery.</t>
              <t>This document updates RFCs 5705 and 6066, and obsoletes RFCs 5077, 5246, and 6961. This document also specifies new requirements for TLS 1.2 implementations.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8446"/>
          <seriesInfo name="DOI" value="10.17487/RFC8446"/>
        </reference>
        <reference anchor="TurboSHAKE">
          <front>
            <title>KangarooTwelve and TurboSHAKE</title>
            <author fullname="Benoît Viguier" initials="B." surname="Viguier">
              <organization>ABN AMRO Bank</organization>
            </author>
            <author fullname="David Wong" initials="D." surname="Wong">
              <organization>zkSecurity</organization>
            </author>
            <author fullname="Gilles Van Assche" initials="G." surname="Van Assche">
              <organization>STMicroelectronics</organization>
            </author>
            <author fullname="Quynh Dang" initials="Q." surname="Dang">
              <organization>National Institute of Standards and Technology</organization>
            </author>
            <author fullname="Joan Daemen" initials="J." surname="Daemen">
              <organization>Radboud University</organization>
            </author>
            <date day="9" month="May" year="2024"/>
            <abstract>
              <t>   This document defines four eXtendable Output Functions (XOF), hash
   functions with output of arbitrary length, named TurboSHAKE128,
   TurboSHAKE256, KT128 and KT256.

   All four functions provide efficient and secure hashing primitives,
   and the last two are able to exploit the parallelism of the
   implementation in a scalable way.

   This document is a product of the Crypto Forum Research Group.  It
   builds up on the definitions of the permutations and of the sponge
   construction in [FIPS 202], and is meant to serve as a stable
   reference and an implementation guide.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-kangarootwelve-14"/>
        </reference>
      </references>
      <references anchor="sec-informative-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="BBCGGI23" target="https://ia.cr/2023/1012">
          <front>
            <title>Arithmetic Sketching</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="2023"/>
          </front>
          <seriesInfo name="CRYPTO 2023" 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="GSZ20" target="https://link.springer.com/chapter/10.1007/978-3-030-56880-1_22">
          <front>
            <title>Guaranteed Output Delivery Comes Free in Honest Majority MPC</title>
            <author initials="V." surname="Goyal">
              <organization/>
            </author>
            <author initials="Y." surname="Song">
              <organization/>
            </author>
            <author initials="C." surname="Zhu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <seriesInfo name="CRYPTO 2020" 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 initials="C." surname="Guo">
              <organization/>
            </author>
            <author initials="J." surname="Katz">
              <organization/>
            </author>
            <author initials="X." surname="Wang">
              <organization/>
            </author>
            <author initials="C." surname="Weng">
              <organization/>
            </author>
            <author initials="Y." surname="Yu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <seriesInfo name="CRYPTO 2020" value=""/>
        </reference>
        <reference anchor="GKWY20" target="https://eprint.iacr.org/2019/074">
          <front>
            <title>Efficient and Secure Multiparty Computation from Fixed-Key Block Ciphers</title>
            <author initials="C." surname="Guo">
              <organization/>
            </author>
            <author initials="J." surname="Katz">
              <organization/>
            </author>
            <author initials="X." surname="Wang">
              <organization/>
            </author>
            <author initials="Y." surname="Yu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <seriesInfo name="S&amp;P 2020" value=""/>
        </reference>
        <reference anchor="MPRV09" target="https://link.springer.com/chapter/10.1007/978-3-642-03356-8_8">
          <front>
            <title>Computational Differential Privacy</title>
            <author initials="I." surname="Mironov">
              <organization/>
            </author>
            <author initials="O." surname="Pandey">
              <organization/>
            </author>
            <author initials="O." surname="Reingold">
              <organization/>
            </author>
            <author initials="S." surname="Vadhan">
              <organization/>
            </author>
            <date>n.d.</date>
          </front>
          <seriesInfo name="CRYPTO 2009" value=""/>
        </reference>
        <reference anchor="MRH04" target="https://doi.org/10.1007/978-3-540-24638-1_2">
          <front>
            <title>Indifferentiability, impossibility results on reductions, and applications to the random oracle methodology</title>
            <author initials="U." surname="Maurer" fullname="Ueli Maurer">
              <organization>ETH Zurich</organization>
            </author>
            <author initials="R." surname="Renner" fullname="Renato Renner">
              <organization>ETH Zurich</organization>
            </author>
            <author initials="C." surname="Holenstein" fullname="Clemens Holenstein">
              <organization>ETH Zurich</organization>
            </author>
            <date year="2004" month="February"/>
          </front>
          <seriesInfo name="In" value="TCC 2004: Theory of Cryptography"/>
          <seriesInfo name="pages" value="21-39"/>
          <seriesInfo name="DOI" value="10.1007/978-3-540-24638-1_2"/>
        </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="Brandon Pitman" initials="B." surname="Pitman">
              <organization>ISRG</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="21" month="May" year="2024"/>
            <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-11"/>
        </reference>
      </references>
    </references>
    <?line 5464?>

<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 Junye Chen, Henry Corrigan-Gibbs, Armando Faz-Hernández, Simon
Friedberger, Tim Geoghegan, Albert Liu, Brandon Pitman, Mariana Raykova, Jacob
Rothstein, Shan Wang, Xiao Wang, Bas Westerbaan, and Christopher Wood for
useful feedback on and contributions to the spec.</t>
    </section>
    <section numbered="false" anchor="test-vectors">
      <name>Test Vectors</name>
      <t>(TO BE REMOVED BY RFC EDITOR: Machine-readable test vectors can be found at
https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec.)</t>
      <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>
        <ul empty="true">
          <li>
            <t>TODO Copy the machine readable vectors from the source repository
(https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec) and
format them for humans.</t>
          </li>
        </ul>
      </section>
      <section numbered="false" anchor="testvec-prio3sum">
        <name>Prio3Sum</name>
        <ul empty="true">
          <li>
            <t>TODO Copy the machine readable vectors from the source repository
(https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec) and
format them for humans.</t>
          </li>
        </ul>
      </section>
      <section numbered="false" anchor="testvec-prio3sumvec">
        <name>Prio3SumVec</name>
        <ul empty="true">
          <li>
            <t>TODO Copy the machine readable vectors from the source repository
(https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec) and
format them for humans.</t>
          </li>
        </ul>
      </section>
      <section numbered="false" anchor="testvec-prio3histogram">
        <name>Prio3Histogram</name>
        <ul empty="true">
          <li>
            <t>TODO Copy the machine readable vectors from the source repository
(https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec) and
format them for humans.</t>
          </li>
        </ul>
      </section>
      <section numbered="false" anchor="testvec-poplar1">
        <name>Poplar1</name>
        <ul empty="true">
          <li>
            <t>TODO Copy the machine readable vectors from the source repository
(https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec) and
format them for humans.</t>
          </li>
        </ul>
      </section>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA+y96XYbR5Yw+D+fIgyfrw1YAERSi2Wq7G6Ki8yyJPIjablc
ajWRABJkWgASlZkgiZLcDzK/5llmXmzuFhE3MhMUJdf29RmeU2UByIzlxo27
L71eLyrTcppsm9brJE8naTycJmYvLco8HS7LZGx2Li7y5CIu02xuDpbzEf6j
aEXxcJgnV/ja3s5BKxpno3k8g2HGeTwpe2leTnqjSX7RuxrHk97mRjSKy+Qi
y1fbJp1PsihKF/m2KfNlUW5tbHy7sRXFeRJvm8OTs4OoWA5naVHAROVqkciX
11n+7iLPlotts3tw8jx6l6zgqzH8Oi+TfJ6UvT2cOoqKMp6Pz+NpNodXV0kR
FbM4L8//sszKpNg28yxapNvmTZmNuqbI8jJPJgX8azXDf7yNonhZXmb5dmR6
kYE/3tZJOrqM87F50TfPYpitoN+y/CKep38l4MCy0mKU0ffJLE6n2yafDv8j
XVz1i5twsL34Kh2b3Sx71zDK4SlsTg0yTq+S/CKZl+P4KvmPC/yyP8pm4Yi7
lzkcWba4THJzHJdlNm9a3zRbjidTALQef4SvLuide2lSTtZNcXyZTqfpYmFO
R5fZYjGL501zPM+yi2kwfuEe/48L+pGGjhAL8hm8dZVsR/D8zvM/Hh1vbW7T
qxYlj/M0uwdT5+lVPFrBf5Miya/S+YXDysScljBIUaajwlylsXmWZdMknptT
OK4E8BSHcydKfz3AQMCD077ZGY/j+bs0/P7Hvnke58Mk/Ha/b/4YTyaVb0/6
5ghuSnZVvFuFv+z0zXE2XQFws3kaj7Ml/TyGBW+brY2tTd5mDAdbbpvLslwU
2/fvp3F/lN/Hn+8/+uYxQuXZs93nzw83vw3B8uckz3o/zrPraTK+SAAsWTYp
DNzP02SUw0WgvY8BzcqYYHKwnE5X5kU6T2JAj93j28CyBwgON+eytv1n2Wpa
2f4PfUDiPE8BAXrP0+GwCH9+BZBMp8MsDr/+pW8Oi8s4DSCy+S19hONNkwJx
A9D15JfjsyP/2zpobX57f/PJEw+tKhK9SC8uy+sE/9+cJaPLefqXZVIYQD9G
LMChH5L4amV+SEugJP+CwBF00cA53N/fN6f/dnwnZNrY/EaB50EInp08LS9n
CVwgc/ouKUeXcL3+BUHwYD1+yG9rAfDg/ubG5hZCYPf5s81v6iRm2yJC15xk
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
hR7G3DYt2BisbXxgWx+4EhaWk6LW78pXyDx9tSlMHT6H1X7GvqT9Q3AGQHZO
sc4JYFePK32Gi7V9HgOQdgZ0TsFAFFgfNoKJayfJsoD7lk9OsIxsh8uC2t5T
JkiCdWuwHaeNHJzXln5Y6eGiEDbyCOLWJN1/JjYQOudqYJWNcK3cJcgjF9Jt
Aat4iqMbnunHxbn9tU2gpytgYc5Rdlz5sxbOHZnKZDQighP7g7KMFfadsndA
oX/su0pkeW0386i6dOveDmZWF6Vtt0i45HcykO8HAfWhKxsMhXlyeK7ceYCr
lsqLFpPn2bw3p/DQKxarp1igmq6LYJbQJNdCqgYAsnNdYx3BHAYZh9deNZKx
QeUK9yt4U6M6YjLjQnecLSYhqPoCVZCvVhVFrHx4N0dTWBH8Y1vdynUtovYt
bVy73AH8MmgglXoUG/fxHU8hahju5Qb5J66lYo4cm3ugO2eg3J3zKzchYncB
wkVf0/rA+GnNi9wkKwm33hCL4QERbv84zotbd09xKxJhMh6Eu34B+62u0pq4
MUnT2mHM/4JHyaXktadba2N8xaGnQp1ny4Lqp8bwr2mZLqbOa1FI30bA46/C
ASyQg918JaocbDbMolW5+xvdYOld86JTO7rzG3hd/v0m3U7vvfBqO/6EMPMH
614KbCg35nsGnpUGQl20Cp6vrGSAuUJYi+grPxpsx+bZwoDtm06AKfCry/Yi
aPTkCvdsMojkeu013WwCTyA1UcKXi7hsoI+heKDHcXRM7jYRLJBkw0ayIQJ2
XcImm97dGHQf09KiAmHMWqqAJPgcnj5nPPfYhvfFAzKecsqI+wZeKZp4fCMN
oQCltGzIIhrAyCIlYsFp4PFmgEMPRGRjj8qEpusyqVl3Ie9QIAgmQ+TaCIr6
4NDqW7t0wER5fMt8/TXv170Gulo8p8reWPHPahCkWZUqWUpvj7elRlAyaVoG
dV+qZXdeBU9yRlYJB0gleYP5WsFdCf5aDhcs++1L6R5PotXFn/qLj5PWr7q+
WG2CFKBBx/yb2ex8lB4TGVBIt5Yt4b9CjNpLHEaFAourylZHtK5xUak0xq1o
xFwtJOcE9u+kbNPIOSsVkcLd81O3E/OGsyyzzIAaxiYFIOa3nWFF2+KVCwG0
x2mjK4mItjc8w21PuzgpVTvCcFoqMU0b8gu2L9/jtzfNH/6Ap0r4r09VnqvQ
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
o4nsJ60kADvyJGTOh9T1pih236MI6B1NhFPDiOa1wptjuH0bKNdl4xcudxPf
aSuYk+aQCPqj2CU5FcITyjbxuYM22i39+5TBNRDPMdMAA3ih/X4QsM+NhVID
jDeCCTetxRhGPcn2YUJHpqc+BaIn+6k1Hjab8fzS9tTvV7Y+XZoXi5vsNrYw
o5BAwHBhnNisiTZRRMa4JjM0YqFTd8fHrjqlxIQpQN0m1sxs76jBJ919S+ep
51ClF4/7xfuJbbS0Xn9j2YcBhCn4/4LOPJn5XiPbhXcZ4wVjnw3CK9FJtQeS
bYWnt+E73U9/5rrSRXALfzQQC0K0EUyLsIEpfJWYBK3CI5uZYeTN2g20RBNB
/hLPmTwTsOitgKfDwGvvvozy7ntvi5fufYxZfAPIlxHHR5FF2PXJzA/IDzIm
iEF4LCIFf1Fi8hM9mo4/9dPCQ5ta61kTql0tsY6CN5mzb8a/52b8U19IsPa1
PCEKAxogyHJWREJFQYevCeIIpVIkBW2kpp9Va4XHyb2oUCv5gEu2UYrzU1rX
M6COZLveQo9tKmzHeREZRiZJuFjFUhgyBSMW47cS8+TMKAcSPsKPt2ViB57N
l3+iHtODXGX9MFRZP1xWp70UdMBFguDwxPzXH7Q7VQxBA+12C5CPVYmPZNZM
+w+4Ng5mIV0cL/mWX960YGYHitWWaP0yBti7LN9HGqJbIb2dH6bIHDt3sDW7
waksy5PIGmEnDRevHNdR60wXax6Ou08ev01kplpfcyGRidWvMzxL22jb++LU
0PVzxR24/VTD02pSunlX1IoQAheZX0n44h95DDk97k7HMEImWXcW84fPRS2u
OYHejMyL0XY1RT6jP2B1nPn69guUArLcwKw4a7k9lNisvGahOl0Yt2LzRH8t
r1ug2BvyDFjLwt/yS85+88R7ce6j8m61pgkgTcflqKsJ/yayH0ex0KY7dtK1
jDRaPYCpbt5OpXDTB91vHRQJOZMVF0Z87om6uH7lnAwbZe6nJ+2Wa4nvu1ex
iGG1zNkjOlaqya0SjrjzSN6wQLY2ZKbpWpqP4HLJ+D5quT6K3yXGoewxRi2A
IXKlINceLBEWOorDmBxyfUZub6J3uNh2IxVNuBiwqw+s1bCKWb28mi/OJRiN
qxihsM0KRcmYvG93n77+4YfdV892n0kUYgShafVxi3gMPn0L+sJKWjpBKzAe
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
1rLETsZsgm8tPLadpBNutjtY251XOTW3w3IiYK+GtAm72Y4sOG5cra3MbmMy
kRZBxdzbd8Ury5uGKlUnwbLqOtf7KsAWI6frTUBA7uOFYbmbPTcmd18EKVVn
9pyHSDsG9wVitgY+bVJ119Nb7mk/F9FNXXf3BWK29eRW5knSvfOPb9PjbmS+
YVufYUXk1gvNCs2TKHVBmKv76akZsASgXAXt8PNIQFCFLhy8mCXdM5M0D/le
fNKZ2OLDb4v6E8KJ6ujyJtTkYb8swYRl8iISYZe8SA/QZbCzRvzi0TSnO2U7
eMXlVkQTYvmu1WYQ49ZKd9Dj+0Mx5ec4mI5I2DsiiXmRgdeufOzmVygrJ9Sx
x48zm5RKUzYCEOERiPgmEar+cFkTfhGXqytP5+RZVh8o/tRT8a665snJ+vCm
xp1fmQdlYOz6zpPsCdXViM7zt+sf9YeZz0DXk9vuSXei7HtvaktZXDRh6QYu
O7cyyDwiBhD/bPpN8pbBdY/5EePPl7Zu98u46+Sxb935x5/wvXCD9lV/xzPQ
a02g/Qn+HN2DcWIt4Cxz0Z8Mk9Ef3Z72txnznN+2+NuwkAqlP43OVzzKO54u
XlOjKRAyXntrwRrTZHdJA2ytvOB4PFVubniaeMc9z04FZRmEB/yzi7HeRrF2
zXnnoHHVNrONYl7c68RCtm8XmhGKt/AEqQFhIyoGHba16VvqxIFici7ODkbO
Y0AONbjlo1sHkfQkK6L89HHET/3xTC/NfqDbpIGtiF51So95HYZUZam3lcDA
I8CSaNCUYn28GpPz5wJ0f7FToe3yrK5IFlyWIyT8UdKGwNFUZbMaoy0J09ik
f2/yGubOC7Z3p6ORaZisaPXxvZyCcZd7KbVo4/5tiuIp0MvOUs1f5OzZPykk
M5DsE2e6DsDNwW4ambQ17QQPM6fxsqnCG6gnmILlLeJFsIhbsiOVIWIlDPN+
jzB5cmVlquwJ3+5RDT3WQ7K3X53Np7UPeikvoZmaDbyvXlMyLaar+1Ja49oP
2dc3TkDeyKDEmnsZoSRH1XroAVqPgkraVw0Xo+dEUAK8EyyPaTNX23BTJnh/
dQJyQe01qxP+ytB+6veT+arhR+41Hr41MWee1stDrHPWRAVTKG42sVOiGfUw
JPS6JF841e4L4pvwL1PsxsYG/ft9PUVcvwCWOg9mVzc9MnxT7yOYJ705Cu2L
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
+EOMVUW8YJDqYfF/H90/h1fs18VuAwA=

-->

</rfc>
