<?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.18 (Ruby 3.3.3) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-irtf-cfrg-vdaf-11" 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-11"/>
    <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="August" day="22"/>
    <area>IRTF</area>
    <workgroup>CFRG</workgroup>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <?line 245?>

<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 255?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>(RFC EDITOR: remove this paragraph.) 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>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 aggregate. 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
aggregate. MPC achieves this goal by distributing the computation of the
aggregate across multiple aggregation servers, one of which is presumed to be
honest, i.e., not under control of the attacker. Moreover, MPC can be composed
with various DP mechanisms to ensure the aggregate itself does leak too much
information about any one of the measurements <xref target="MPRV09"/>.</t>
      <t>This document describes two classes of MPC protocols, each aiming for a
different set of goals.</t>
      <t>In a Distributed Aggregation Function (DAF, <xref target="daf"/>), each client splits its
measurement into multiple secret shares, one for each aggregation
server. DAFs require two properties of the secret sharing scheme. First, we can
reconstruct the underlying measurement by simply adding up all of the shares.
(Typically the shares are vectors over some finite field.) Second, given all
but one of the shares, it is impossible to learn anything about the underlying
measurement. These properties give rise to a simple strategy for privately
aggregating the measurements: each aggregation server adds up its measurement
shares locally before revealing their sum to the data collector; then all
the data collector has to do is add up these sums to get the aggregate.</t>
      <t>This strategy is compatible with any aggregation function that can be
represented as the sum of some encoding of the measurements. Examples include:
summary statistics such as sum, mean, and standard deviation; estimation of
quantiles, e.g., median; histograms; linear regression; or counting data
structures, e.g., Bloom filters. However, not all functions fit into this
rubric, as it is constrained to linear computations over the encoded
measurements.</t>
      <t>In fact, our framework admits DAFs with slightly more
functionality, computing aggregation functions of the form</t>
      <artwork><![CDATA[
f(agg_param, meas_1, ..., meas_N) =
    g(agg_param, meas_1) + ... + g(agg_param, meas_N)
]]></artwork>
      <t>where <tt>meas_1, ..., meas_N</tt> are the measurements, <tt>g</tt> is a possibly non-linear
function, and <tt>agg_param</tt> is a parameter of that function chosen by the data
collector. This paradigm, known as function secret sharing <xref target="BGI15"/>, allows
for more sophisticated data analysis tasks, such as grouping metrics by private
client attributes <xref target="MPDST25"/> or computing heavy hitters <xref target="BBCGGI21"/>. (More
on the latter task below.)</t>
      <t>The second class of protocols defined in this document are called Verifiable
Distributed Aggregation Functions (VDAFs, <xref target="vdaf"/>). In addition to being
private, VDAFs are verifiable in the following sense. By design, a secret
sharing of a valid measurement, e.g., a number between 1 and 10, is
indistinguishable from a secret sharing of an invalid measurement, e.g., a
number larger than 10. This means that DAFs are vulnerable to attacks from
malicious clients attempting to disrupt the computation by submitting invalid
measurements. Thus VDAFs are designed to allow the servers to detect and remove
these measurements prior to aggregation. We refer to this property as
robustness.</t>
      <t>Achieving robustness without sacrificing privacy requires the servers to
interact with one another over a number of rounds of communication. DAFs on the
other hand are non-interactive, and are therefore easier to deploy; but they do
not provide robustness on their own. This may be tolerable in some
applications. For instance, if the client's software is executed in a trusted
execution environment, it may be reasonable to assume that no client is
malicious.</t>
      <t>The DAF and VDAF abstractions encompass a variety of MPC techniques 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"/> (RFC
EDITOR: remove this reference if not published before the current document)
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 Prio system <xref target="CGB17"/> allows for the privacy-preserving computation of a
variety of aggregate statistics, combining additive secret sharing as described
above with a mechanism for checking the validity of each measurement. In
<xref target="prio3"/> we specify 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>The Poplar protocol <xref target="BBCGGI21"/> solves the heavy-hitters problem in a
privacy-preserving manner. Here each client holds a bit-string, and the goal
of the aggregation servers is to compute the set of strings that occur at
least <tt>t</tt> times for some threshold <tt>t</tt>. The core primitive in their protocol
is a secret sharing of a point function <xref target="GI14"/> (<tt>g</tt> in the notation above)
that allows the servers to privately count how many of the clients' strings
begin with a given prefix (<tt>agg_param</tt> in the notation above). In <xref target="poplar1"/>
we specify a VDAF called Poplar1 that implements this functionality.</t>
        </li>
      </ul>
      <t>The remainder of this document is organized as follows: <xref target="conventions"/> lists
definitions and conventions used for specification; <xref target="overview"/> gives a brief
overview of DAFs and VDAFs, the parties involved in the computation, and the
requirements for non-collusion; <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 DAFs and VDAFs.</t>
      <section anchor="change-log">
        <name>Change Log</name>
        <t>(RFC EDITOR: remove this section.)</t>
        <t>(*) Indicates a change that breaks wire compatibility with the previous draft.</t>
        <t>11:</t>
        <ul spacing="normal">
          <li>
            <t>Define message formats for the Poplar1 aggregation parameter and IDPF public
share.</t>
          </li>
          <li>
            <t>IDPF: Require the IDPF binder must be a random nonce.</t>
          </li>
          <li>
            <t>VDAF: Replace the pseudocode description of the ping-ping topology with
Python and sketch the star topology.</t>
          </li>
          <li>
            <t>DAF: Align aggregation parameter validation with VDAF.</t>
          </li>
          <li>
            <t>Replace <tt>Union[A, B]</tt> type with <tt>A | B</tt>.</t>
          </li>
          <li>
            <t>Rename FFT ("Fast Fourier Transform") with NTT ("Number Theoretic
Transform").</t>
          </li>
        </ul>
        <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">
      <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; see <xref target="num-aggregators"/>), 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: 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-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>
        <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 and nonce into a public share and input shares
as it does in DAFs (cf. <xref target="sec-daf-shard"/>):</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       V              V       |     | x ROUNDS
    +-----------+  +-----------+          +-----------+   |
    | prep_next |  | prep_next |          | prep_next |   |
    +-----------+  +-----------+          +-----------+   |
      |       |      |                 ...  |       |     |
      V       V      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;
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, prep_round) --> 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="python"><![CDATA[
class State:
    pass

class Start(State):
    pass

class Continued(State, Generic[PrepState]):
    def __init__(self, prep_state: PrepState, prep_round: int):
        self.prep_state = prep_state
        self.prep_round = prep_round

    def __eq__(self, other: object) -> bool:
        return isinstance(other, Continued) and \
            self.prep_state == other.prep_state and \
            self.prep_round == other.prep_round

class Finished(State, Generic[OutShare]):
    def __init__(self, out_share: OutShare):
        self.out_share = out_share

    def __eq__(self, other: object) -> bool:
        return isinstance(other, Finished) and \
            self.out_share == other.out_share

class Rejected(State):
    pass
]]></sourcecode>
        <t>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.</t>
        <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"/>. The Leader's initial transition is computed with the
following method, implemented on <tt>Vdaf</tt>:</t>
        <sourcecode type="python"><![CDATA[
def ping_pong_leader_init(
        self,
        vdaf_verify_key: bytes,
        agg_param: bytes,
        nonce: bytes,
        public_share: bytes,
        input_share: bytes) -> tuple[State, Optional[bytes]]:
    """Called by the leader to initialize ping-ponging."""
    try:
        (prep_state, prep_share) = self.prep_init(
            vdaf_verify_key,
            0,
            self.decode_agg_param(agg_param),
            nonce,
            self.decode_public_share(public_share),
            self.decode_input_share(0, input_share),
        )
        encoded_prep_share = self.encode_prep_share(prep_share)
        return (
            Continued(prep_state, 0),
            encode(0, encoded_prep_share),  # initialize
        )
    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. Function
<tt>encode</tt>  is used to encode the outbound message, here the <tt>initialize</tt> variant
(hence <tt>0</tt>).</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="python"><![CDATA[
def ping_pong_helper_init(
        self,
        vdaf_verify_key: bytes,
        agg_param: bytes,
        nonce: bytes,
        public_share: bytes,
        input_share: bytes,
        inbound: bytes) -> tuple[State, Optional[bytes]]:
    """
    Called by the helper in response to the leader's initial
    message.
    """
    try:
        (prep_state, prep_share) = self.prep_init(
            vdaf_verify_key,
            1,
            self.decode_agg_param(agg_param),
            nonce,
            self.decode_public_share(public_share),
            self.decode_input_share(1, input_share),
        )

        (inbound_type, inbound_items) = decode(inbound)
        if inbound_type != 0:  # initialize
            return (Rejected(), None)

        encoded_prep_share = inbound_items[0]
        prep_shares = [
            self.decode_prep_share(prep_state, encoded_prep_share),
            prep_share,
        ]
        return self.ping_pong_transition(
            self.decode_agg_param(agg_param),
            prep_shares,
            prep_state,
            0,
        )
    except:
        return (Rejected(), None)
]]></sourcecode>
        <t>Procedure <tt>decode</tt> decodes the inbound message and returns the MessageType
variant (<tt>initialize</tt>, <tt>continue</tt>, or <tt>finalize</tt>) and the sequence of fields.
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="python"><![CDATA[
def ping_pong_transition(
        self,
        agg_param: AggParam,
        prep_shares: list[PrepShare],
        prep_state: PrepState,
        prep_round: int) -> tuple[State, bytes]:
    prep_msg = self.prep_shares_to_prep(agg_param,
                                        prep_shares)
    encoded_prep_msg = self.encode_prep_msg(prep_msg)
    out = self.prep_next(prep_state, prep_msg)
    if prep_round+1 == self.ROUNDS:
        return (
            Finished(out),
            encode(2, encoded_prep_msg),  # finalize
        )
    (prep_state, prep_share) = cast(
        tuple[PrepState, PrepShare], out)
    encoded_prep_share = self.encode_prep_share(prep_share)
    return (
        Continued(prep_state, prep_round+1),
        encode(1, encoded_prep_msg, encoded_prep_share)  # continue
    )
]]></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="python"><![CDATA[
def ping_pong_leader_continued(
    self,
    agg_param: bytes,
    state: State,
    inbound: bytes,
) -> tuple[State, Optional[bytes]]:
    """
    Called by the leader to start the next step of ping-ponging.
    """
    return self.ping_pong_continued(
        True, agg_param, state, inbound)

def ping_pong_continued(
    self,
    is_leader: bool,
    agg_param: bytes,
    state: State,
    inbound: bytes,
) -> tuple[State, Optional[bytes]]:
    try:
        if not isinstance(state, Continued):
            return (Rejected(), None)
        prep_round = state.prep_round

        (inbound_type, inbound_items) = decode(inbound)
        if inbound_type == 0:  # initialize
            return (Rejected(), None)

        encoded_prep_msg = inbound_items[0]
        prep_msg = self.decode_prep_msg(
            state.prep_state,
            encoded_prep_msg,
        )
        out = self.prep_next(state.prep_state, prep_msg)
        if prep_round+1 < self.ROUNDS and \
                inbound_type == 1:  # continue
            (prep_state, prep_share) = cast(
                tuple[PrepState, PrepShare], out)
            encoded_prep_share = inbound_items[1]
            prep_shares = [
                self.decode_prep_share(
                    prep_state,
                    encoded_prep_share,
                ),
                prep_share,
            ]
            if is_leader:
                prep_shares.reverse()
            return self.ping_pong_transition(
                self.decode_agg_param(agg_param),
                prep_shares,
                prep_state,
                prep_round+1,
            )
        elif prep_round+1 == self.ROUNDS 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="python"><![CDATA[
def ping_pong_helper_continued(
    self,
    agg_param: bytes,
    state: State,
    inbound: bytes,
) -> tuple[State, Optional[bytes]]:
    """Called by the helper to continue ping-ponging."""
    return self.ping_pong_continued(
        False, agg_param, state, inbound)
]]></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-topo">
        <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 the VDAF supports more than two
Aggregators, then the star topology described in this section can
be used instead.</t>
        <t>We again designate an Aggregator to initiate the computation. We refer to this
Aggregator as the Leader and to all other Aggregators as Helpers.</t>
        <t>At the start of each round, the Leader requests from each Helper its prep
share. After gathering each of the prep shares, the Leader computes the next
prep message (via <tt>prep_shares_to_prep()</tt>) and broadcasts it to the Helpers. At
this point, each Aggregator runs <tt>prep_next()</tt> locally to either recover an
output share or, if more rounds of preparation are required, compute its updated state
and prep share. If more are required, then the Helper responds to the broadcast
message with its next prep share.</t>
        <t>The Aggregators proceed in this way until each recovers an output share or some
step of the computation fails.</t>
      </section>
    </section>
    <section anchor="prelim">
      <name>Preliminaries</name>
      <t>This section describes the primitives that are common to the VDAFs specified in
this document.</t>
      <section anchor="field">
        <name>Finite Fields</name>
        <t>Both Prio3 and Poplar1 use finite fields of prime order. Finite field
elements are represented by a class <tt>Field</tt> with the following associated
parameters:</t>
        <ul spacing="normal">
          <li>
            <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-ntt-friendly">
          <name>NTT-Friendly Fields</name>
          <t>Some VDAFs require fields that are suitable for efficient computation of the
number theoretic transform (NTT) <xref target="SML24"/>, 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
"NTT-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 NTT-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>NTT-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>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>NttField ({{ntt-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>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>Implementation note: the preparation state for Prio3 includes the output share
that will be released once preparation is complete. In some situations, it may be
necessary for the Aggregator to encode this state as bytes and store it for
retrieval later on. For all but the first Aggregator, it is possible to save
storage by storing the measurement share rather than output share itself. It is
relatively inexpensive to expand this seed into the input share, then truncate
the input share to get the output share.</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],
    ) -> 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 <xref target="BBCGGI19"/>,
Section 4.2. We begin in <xref target="flp-bbcggi19-overview"/> with an overview of their
proof system and some extensions to it. The construction is specified in
<xref target="flp-bbcggi19-construction"/>.</t>
        <section anchor="flp-bbcggi19-overview">
          <name>Overview</name>
          <t>Conventional zero-knowledge proof systems involve two parties:</t>
          <ul spacing="normal">
            <li>
              <t>The prover, who holds a measurement and generates a proof of the
measurement's validity</t>
            </li>
            <li>
              <t>The verifier who holds an encryption of, or commitment to, the measurement
and checks the proof</t>
            </li>
          </ul>
          <t>Our proof system is much the same, except the verifier is split across multiple
Aggregators, each of which has a secret share of the measurement rather than an
encryption of it.</t>
          <t>Validity is defined in terms of an arithmetic circuit evaluated over the
measurement. The inputs to this circuit are elements of a finite field that
comprise the encoded measurement; the gates of the circuit are multiplication,
addition, and subtraction operations; and the output of the circuit is a single
field element. If the value is zero, then the measurement is deemed valid;
otherwise, if the output is non-zero, then the measurement is deemed invalid.</t>
          <t>For example, the simplest circuit specified in this document is the following
(<xref target="prio3count"/>):</t>
          <artwork><![CDATA[
C(x) = x * (x-1)
]]></artwork>
          <t>This circuit contains one subtraction gate (<tt>x - 1</tt>) and one multiplication
gate (<tt>x * (x - 1)</tt>). Observe that <tt>C(x) = 0</tt> if and only if <tt>x in range(2)</tt>.</t>
          <t>Our goal is to allow each Aggregator, who holds a secret share of <tt>x</tt>, to
correctly compute a secret share of <tt>C(x)</tt>. This allows the Aggregators to
determine validity by combining their shares of the output.</t>
          <t>Suppose for a moment that the validity circuit <tt>C</tt> is affine, meaning its only
operations are addition, subtraction, and multiplication-by-constant. (The
circuit above is non-affine because it contains a multiplication gate with
two non-constant inputs.) Then each Aggregator can compute its share locally, since</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 is necessary to scale any addition of
a constant in the circuit by <tt>1/SHARES</tt>.) However, this is not the case if <tt>C</tt>
contains multiplication gates with two non-constant inputs. Thus our goal is to
transform these multiplication gates into computations on secret shared data
that each Aggregator can perform locally.</t>
          <t>The key idea is to have the prover construct a polynomial <tt>p</tt> such that <tt>p(j)</tt>
is equal to the output of the <tt>j</tt>-th multiplication gate. Polynomial evaluation
is fully linear, which means the coefficients of the polynomial can be secret
shared in a way that allows each Aggregator to compute a share of <tt>p(j)</tt> for
any <tt>j</tt>. These intermediate results can then be combined with the affine
operations of the validity circuit to produce the final output.</t>
          <t>Applying this idea to the example circuit <tt>C</tt> above:</t>
          <ol spacing="normal" type="1"><li>
              <t>The Client, given its measurement <tt>x</tt>, constructs the lowest degree
polynomial <tt>p</tt> for which <tt>p(0) = s</tt> and <tt>p(1) = x * (x - 1)</tt>, where <tt>s</tt> is a
random blinding value generated by the Client. (The blinding value is to
protect the privacy of the measurement.) It sends secret shares of <tt>x</tt> and
the coefficients of <tt>p</tt> to each of the Aggregators.</t>
            </li>
            <li>
              <t>Each Aggregator locally computes and broadcasts its share of <tt>p(1)</tt>, which
is equal to its share of <tt>C(x)</tt>.</t>
            </li>
          </ol>
          <t>In fact, our FLP is slightly more general than this. We can replace the
multiplication gate with any non-affine sub-circuit and apply the same idea.
For example, in <xref target="prio3sum"/>, the validity circuit uses the following
sub-circuit multiple times:</t>
          <artwork><![CDATA[
Range2(x) = x * (x - 1) = x^2 - x
]]></artwork>
          <t>(This is the same functionality computed by the example circuit <tt>C</tt> above.)
Here again we can interpolate the lowest degree polynomial <tt>p</tt> for which <tt>p(j)</tt>
is the value of the <tt>j</tt>-th call to <tt>Range2</tt> in the validity circuit. Each
validity circuit defines a sub-circuit that encapsulates its non-affine
functionality. We refer to this sub-circuit as the "gadget".</t>
          <t>This idea provides the needed functionality, but it has one more problem: it is
possible for a malicious Client to produce a gadget polynomial <tt>p</tt> that would
result in <tt>C(x)</tt> being computed incorrectly, potentially resulting in an
invalid measurement being accepted. To prevent this, the Aggregators perform a
probabilistic test to check that the gadget polynomial was constructed
properly. This "gadget test", and the procedure for constructing the
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 {#flp-bbcggi19-construction} 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(x, r) = r * Range2(x[0]) + ... + r^N * Range2(x[N-1])
]]></artwork>
            <t>(Note that this is a special case of <xref target="BBCGGI19"/>, Theorem 5.2.) Here <tt>x</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>x</tt> is valid (i.e., each <tt>x[j]</tt> is in
<tt>range(2)</tt>), then the circuit will evaluate to 0 regardless of the value of
<tt>r</tt>; but if some <tt>x[j]</tt> is not in <tt>range(2)</tt>, then 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-circuits. 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>. The
same circuit can be expressed using a simpler gadget, namely multiplication,
but the resulting proof would be longer.</t>
            <t>Third, rather than interpolate the gadget polynomial at inputs <tt>1</tt>, <tt>2</tt>, ...,
<tt>j</tt>, ..., where <tt>j</tt> is the <tt>j</tt>-th invocation of the gadget, we use powers of
<tt>alpha</tt>, where <tt>alpha</tt> is a root of unity for the field. This allows us to
construct each gadget polynomial via the number theoretic transform <xref target="SML24"/>,
which is far more efficient than  generic formulas. This requires the field to
be "NTT-friendly" as defined in <xref target="field-ntt-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>
            <figure anchor="flp-bbcggi19-prove-illustration">
              <name>The proof generation algorithm invokes the validity circuit on the encoded measurement and joint randomness. The validity circuit in turn invokes the gadget(s) defined by the circuit. The prove randomness is used to construct the gadget polynomial(s).</name>
              <artwork><![CDATA[
+------------------+
| Prove            |
| +-------------+  |
| | Valid       |<---- meas
| | +--------+  |<---- joint rand
| | | Gadget |  |  |<- prove rand
| | +--------+  |  |
| +-------------+  |
+------------------+
 |
 V proof
]]></artwork>
            </figure>
            <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>
                  <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>
            <figure anchor="flp-bbcggi19-query-illustration">
              <name>The query generation algorithm invokes the validity circuit on the encoded measurement and joint randomness. It evaluates the gadget polynomials(s) encoded by the proof (share) to produce (a share of) each gadget output. The verifier (share) consists of (a share of) the validity circuit's output and (a share of) each gadget test. The tests consume the query randomness.</name>
              <artwork><![CDATA[
 | proof (share)
 +--------+
 V        |
+---------|--------+
| Query   |        |
| +-------|-----+  |
| | Valid |     |<---- meas (share)
| | +-----|--+  |<---- joint rand
| | |     V  |  |  |<- query rand
| | +--------+  |  |
| +-------------+  |
+------------------+
 |
 V verifier (share)
]]></artwork>
            </figure>
            <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>
            <figure anchor="flp-bbcggi19-decide-illustration">
              <name>The decision algorithm consumes the verifier, consisting of the reduced output of the validity circuit and each gadget test. The verifier is produced by adding up the verifier shares output by each Aggregator.</name>
              <artwork><![CDATA[
 | verifier
 V
+------------------+
| Decide           |
+------------------+
 |
 V is_valid
]]></artwork>
            </figure>
            <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>SumVec(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>Histogram(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>MultihotCountVec(Field128, length, max_weight, 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>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], nonce: bytes, rand: bytes) -&gt; tuple[PublicShare,
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 nonce string.  </t>
            <t>
The output is a public part (of type <tt>PublicShare</tt>) 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>nonce</tt> <bcp14>MUST</bcp14> be of length <tt>Idpf.NONCE_SIZE</tt> and chosen uniformly at
random by the Client (see <xref target="nonce-requirements"/>).</t>
              </li>
            </ul>
          </li>
          <li>
            <t><tt>idpf.eval(agg_id: int, public_share: PublicShare, key: bytes, level: int,
prefixes: tuple[int, ...], nonce: 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 nonce 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) -> 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">NONCE_SIZE</td>
              <td align="left">Size of the randon nonce generated by the Client.</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">PublicShare</td>
              <td align="left">Type of public share for this IDPF</td>
            </tr>
            <tr>
              <td align="left">Output</td>
              <td align="left">Alias of <tt>list[list[FieldInner]] | list[list[FieldLeaf]]</tt></td>
            </tr>
            <tr>
              <td align="left">FieldVec</td>
              <td align="left">Alias of <tt>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">same as the IDPF</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[Poplar1PublicShare, 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: Poplar1PublicShare,
        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]
    ) -> 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.ENCODED_SIZE</tt> and <tt>Fl</tt> as an alias for
<tt>poplar1.idpf.field_leaf.ENCODED_SIZE</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 of the IDPF scheme in <xref target="idpf-bbcggi21"/> consists of a sequence
of "correction words". A correction word has three components:</t>
            <ol spacing="normal" type="1"><li>
                <t>the XOF seed of type <tt>bytes</tt>;</t>
              </li>
              <li>
                <t>the control bits of type <tt>tuple[Field2, Field2]</tt>; and</t>
              </li>
              <li>
                <t>the payload of type <tt>list[Field64]</tt> for the first <tt>BITS-1</tt> words and
<tt>list[Field255]</tt> for the last word.</t>
              </li>
            </ol>
            <t>The encoding is straightforward, except that the control bits are packed as
tightly as possible. The encoded public share is structured as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1Seed seed;
    Poplar1FieldInner payload[Fi * Poplar1.Idpf.VALUE_LEN];
} Poplar1CWSeedAndPayloadInner;

struct {
    Poplar1Seed seed;
    Poplar1FieldLeaf payload[Fl * Poplar1.Idpf.VALUE_LEN];
} Poplar1CWSeedAndPayloadLeaf;

struct {
    opaque packed_control_bits[packed_len];
    Poplar1CWSeedAndPayloadInner inner[Ci * (Poplar1.Idpf.BITS-1)];
    Poplar1CWSeedAndPayloadLeaf leaf;
} Poplar1PublicShare;
]]></sourcecode>
            <t>Here <tt>Ci</tt> denotes the length of <tt>Poplar1CWSeedAndPayloadInner</tt> and
<tt>packed_len = (2*Poplar1.Idpf.BITS + 7) // 8</tt> is the length of the packed
control bits.</t>
            <t>Field <tt>packed_control_bits</tt> is encoded with the following function:</t>
            <sourcecode type="python"><![CDATA[
packed_control_buf = [int(0)] * packed_len
for i, bit in enumerate(control_bits):
    packed_control_buf[i // 8] |= bit.as_unsigned() << (i % 8)
packed_control_bits = bytes(packed_control_buf)
]]></sourcecode>
            <t>It encodes 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. Decoding 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>
            <sourcecode type="python"><![CDATA[
control_bits = []
for i in range(length):
    control_bits.append(Field2(
        (packed_control_bits[i // 8] >> (i % 8)) & 1
    ))
leftover_bits = packed_control_bits[-1] >> (
    (length + 7) % 8 + 1
)
if (length + 7) // 8 != len(packed_control_bits) or \
        leftover_bits != 0:
    raise ValueError('trailing bits')
]]></sourcecode>
          </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>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    uint16_t level;
    uint32_t num_prefixes;
    opaque packed_prefixes[packed_len];
} Poplar1AggParam;
]]></sourcecode>
            <t>The fields in this struct are: <tt>level</tt>, the level of the IDPF tree of each
prefixes; <tt>num_prefixes</tt>, the number of prefixes to evaluate; and
<tt>packed_prefixes</tt>, the sequence of prefixes packed into a byte string of
length <tt>packed_len</tt>. The prefixes are encoded with the following procedure:</t>
            <sourcecode type="python"><![CDATA[
packed = 0
for (i, prefix) in enumerate(prefixes):
    packed |= prefix << ((level + 1) * i)
packed_len = ((level + 1) * len(prefixes) + 7) // 8
packed_prefixes = to_be_bytes(packed, packed_len)
]]></sourcecode>
            <t>Decoding involves the following procedure:</t>
            <sourcecode type="python"><![CDATA[
packed = from_be_bytes(packed_prefixes)
prefixes = []
m = 2 ** (level + 1) - 1
for i in range(num_prefixes):
    prefixes.append(packed >> ((level + 1) * i) & m)
]]></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> and <tt>convert()</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],
        nonce: bytes,
        rand: bytes) -> tuple[list[CorrectionWord], 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")
    if len(nonce) != self.NONCE_SIZE:
        raise ValueError("incorrect nonce size")

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

    seed = key.copy()
    ctrl = [Field2(0), Field2(1)]
    public_share = []
    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], nonce)
        (s1, t1) = self.extend(seed[1], nonce)
        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, nonce)
        (seed[1], w1) = self.convert(level, x1, nonce)
        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

        public_share.append((seed_cw, ctrl_cw, w_cw))
    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> and <tt>convert()</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: list[CorrectionWord],
        key: bytes,
        level: int,
        prefixes: Sequence[int],
        nonce: bytes,
    ) -> 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')

    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,
                public_share[current_level],
                current_level,
                bit,
                nonce,
            )
        if agg_id == 0:
            out_share.append(cast(list[Field], y))
        else:
            out_share.append(vec_neg(cast(list[Field], y)))
    return cast(
        list[list[Field64]] | list[list[Field255]],
        out_share,
    )

def eval_next(
        self,
        prev_seed: bytes,
        prev_ctrl: Field2,
        correction_word: CorrectionWord,
        level: int,
        bit: int,
        nonce: 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, nonce)
    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], nonce)
    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,
        nonce: bytes) -> tuple[list[bytes], list[Field2]]:
    xof = XofFixedKeyAes128(seed, format_dst(1, 0, 0), nonce)
    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,
        nonce: bytes) -> tuple[bytes, FieldVec]:
    xof = XofFixedKeyAes128(seed, format_dst(1, 0, 1), nonce)
    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))
]]></sourcecode>
          </figure>
        </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 (<xref target="vdaf"/>) 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 anchor="num-aggregators">
        <name>Choosing the Number of Aggregators</name>
        <t>Two Aggregators are required for privacy in our threat model, but some (V)DAFs,
including Prio3 (<xref target="prio3"/>), allow for any number of Aggregators, only one of
which needs to be trusted in order for the computation to be private. To hedge
against corruptions that happen during the course of the attack, deployments
may consider involving more than two Aggregators as described for example in
<xref target="star-topo"/>. Note however that some schemes are not compatible with this mode of operation,
such as Poplar1.</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 anchor="sec-combined-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="BGI15" target="https://www.iacr.org/archive/eurocrypt2015/90560300/90560300.pdf">
          <front>
            <title>Function Secret Sharing</title>
            <author initials="E." surname="Boyle">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2015"/>
          </front>
          <seriesInfo name="EUROCRYPT 2015" 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 year="2023"/>
          </front>
          <seriesInfo name="PETS 2023" value=""/>
        </reference>
        <reference anchor="Dwo06" target="https://link.springer.com/chapter/10.1007/11787006_1">
          <front>
            <title>Differential Privacy</title>
            <author initials="C." surname="Dwork">
              <organization/>
            </author>
            <date year="2006"/>
          </front>
          <seriesInfo name="ICALP 2006" value=""/>
        </reference>
        <reference anchor="EPK14" target="https://dl.acm.org/doi/10.1145/2660267.2660348">
          <front>
            <title>RAPPOR: Randomized Aggregatable Privacy-Preserving Ordinal Response</title>
            <author initials="Ú." surname="Erlingsson">
              <organization/>
            </author>
            <author initials="V." surname="Pihur">
              <organization/>
            </author>
            <author initials="A." surname="Korolova">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <seriesInfo name="CCS 2014" value=""/>
        </reference>
        <reference anchor="ENPA" target="https://covid19-static.cdn-apple.com/applications/covid19/current/static/contact-tracing/pdf/ENPA_White_Paper.pdf">
          <front>
            <title>Exposure Notification Privacy-preserving Analytics (ENPA) White Paper</title>
            <author>
              <organization/>
            </author>
            <date year="2021"/>
          </front>
        </reference>
        <reference anchor="GI14" target="https://link.springer.com/chapter/10.1007/978-3-642-55220-5_35">
          <front>
            <title>Distributed Point Functions and Their Applications</title>
            <author initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <seriesInfo name="EUROCRYPT 2014" value=""/>
        </reference>
        <reference anchor="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="MPDST25" target="https://eprint.iacr.org/2024/221">
          <front>
            <title>Mastic: Private Weighted Heavy-Hitters and Attribute-Based Metrics</title>
            <author initials="D." surname="Mouris">
              <organization/>
            </author>
            <author initials="C." surname="Patton">
              <organization/>
            </author>
            <author initials="H." surname="Davis">
              <organization/>
            </author>
            <author initials="P." surname="Sarkar">
              <organization/>
            </author>
            <author initials="N. G." surname="Tsoutsos">
              <organization/>
            </author>
            <date year="2025"/>
          </front>
          <seriesInfo name="PETS 2025" 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://web.archive.org/web/20221025174046/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="SML24" target="https://eprint.iacr.org/2024/585">
          <front>
            <title>A Complete Beginner Guide to the Number Theoretic Transform (NTT)</title>
            <author initials="A." surname="Satriawan">
              <organization/>
            </author>
            <author initials="R." surname="Mareta">
              <organization/>
            </author>
            <author initials="H." surname="Lee">
              <organization/>
            </author>
            <date year="2024"/>
          </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 5568?>

<section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The impetus of this work is the success of recent deployments of predecessors
of Prio3. 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"/> have
together aggregated data from hundreds of millions of users.</t>
      <t>As the name implies, Prio3 is a descendant of the original Prio construction
<xref target="CGB17"/>. 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 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:
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
17c3vb5de32n8vrOptd3fLhiEInZ8Ftdr33zaeWbTzd982mzuN0Y8BkIoeqv
+puu1bSLOw2/a8+IIuMPxceG35QSpK/9hm/9vVaOR9ZpA8Fvh/rqmtIJnBDu
1hcI4prgVZ1efTN4OqC4zJFtJaOKDFSMMypWDKVp9MNyVagRtRe+SZjdOHvd
VVpolwwGsrYwlLG4ykqKmpvZXCnseb2euMZc7xx1iLGJVXYRhnL2zQtM4yWW
hT5DDMeJbMF2+GCBRb5nVL5Pf1EFWEqQYMKCJtVqooGj6Dgs+DLPSpB9XagB
JRSDEk+fbrv+Oh1bSyorVT0pCjwIWAr1O8ikEkvVE2njZH0bcdUwpR+dVwK4
dAv1WZJf1iMaVV9Vv3ja7xXG7VAfUn6TzbD0Bpderr4X1NarmFcpokh4B0Xe
uRJsWS2wdXMneXKs6S4xwhbFxQxzTYIm9qVKoRFZoIdZbX1ztuQCfhT6h3Oi
KiRUo8Z3bCJ/amMIAIgMylvqJQYpNgIHYW9SSiClDnSjs6BqgmFuuS0spUxD
AVzYIx6xqznV9UjWuJo57hNYb7FOJ8TALGG8lUf4y154kAU1iw6O8Ci5jUWH
LldTudDEwieOKc+GlxGCJZjU25MjoyOF1hRSqQD668A6HCTz+kmrpFhrcgOV
pzJrp76uK7PiTLXrLK21oiKsxGsDMHmmlVD1TyH9fDHr+Xvyw8+0MzpJQPC4
Ydymvy+yaXpJILDBIogYUxmsDsfDHfIMW6YasOv9sLEnnVkq3dV8GnyYiKCc
GLoaIpcoBLHnKsHCc2eUcQ501BeClxA7S2eT2XLq6K8iHsQ0x9zIFFZjFpQz
h3U68JBfwIfaTjTlcvnx5E2QW6N9MMENR3SCq9oYFdzwtqjw+knjVUu2aleZ
SvnLb/0/mwiiuxmSPSKNamVqFDKwNKS/u2/v0qOtVov++2opiT9cHR3fqmqZ
fcayRiMT/vXMAJ22nqB3AAdxN/rO6V57Vo3vng7iFJyxxENvMNMPYOxHQFX1
NzAbnwDhBtfuIOdqstYoHIvh1jxKQcPgT/3FziCAZIo17ldt9enfVT9tW02O
yBQnQ++6T1KuO9q9lskhloBpt6i7LIatylvYRKTVsZ/T8/tdw/w2jBygZSus
TWZ9gQU38mQJw0fFMesrWm6ITkW1tcgXqv5vKw+ZJ+bNm7cEkV+cYbKN8BKr
JL9AZQFnNT9qB1/5a7poh+7fGki/CuIjvUP40/4BNcRtgyQ9tAGET4wr5IGL
ci6/jnusrQ3hgeUb8c38e7BHjR7mri3DjZ/pRNVVKx4u3gBe+yZ3gBtj/cbs
BhPzO/rml7d9rFQFKw6esNMnZ8EvykVgp1972v2thxB8rCMrrq/WMSteb5OS
okrXySDVEEwXxKwjLvFRL+4hDns0/RS0vGTzi2HK0GBH2wCMdUDv1L9Q2I1Q
33TQ8iKxyAXVEFEbBoqPV4VX00BnKkKJLK4m52vp/hPLrH6VP8GGay3+WAEH
ZAFUlqxsUxdKbICRjSay+ZhOvnDZUaTxxyFIdECy1RyokBY+RG1V43U9VdmR
o70lYU4VZ37JJCJfPonqGLk8BJabOIwmNq1hMk8v5y2TzK/TPJsLEfOFoWxF
5igeU4vDfOUaALiOPmSS4PBBT85c/g0r2+mCYrhQqYts1SAM38EsUe6VhdmT
82RakIYu/b+6otvbeyrIKvJxT2yiJn28ZVsb2c+3pOoFbMOHD/96sHf65Lh3
0Ke2V700KSe9xWIG+7349dduJL3UpQ9Y5cvsj3H9kIJaSL7RPMz+RZYnuMxu
xBYCrECmJGOtcLfh4EheRcem5fhOk+xZviYTBwrOUSmNyV0twGECDDUl73KQ
MxK2Zw4aKQiaYSyaa1YqO4t1WxUa8ASoNrLKI8T3qzCmXSkiVa5ZoqAbMote
S2rRNecWPcdkHroUVDhkBJJ2RhL13LX9yDfku0Qq36XxxPlsF5+a2PM+2VBW
PfQldenwvw70DHfCKbVCogVj379610WkdaNTXYFcWTfZMOWNNX3zfXaDhdXY
I6xd//QByjiOXDsajO4T7GqUI7ShAlOTMCUKqXKQIhXVU6S+djlOXIV4z5XM
ZbVKCu3bb1MatEwqosKsI/S9cDo0yvy2ZEDY0kO6y0sBv6o5qDlFhVVN7thW
TUtZm65fSzmhuqF5IakFYUXSqhOaGqcrph/dPuEEzieXLGQqX8v52Cf/mTRH
3JzkoYUMSXypZGysG6w5XaMitFgTwPGcbUUSkeISkBsw0bWlB+ZwY1M2OU/C
ZatFZVy8263Bt7Qp7ypBb52njc1RYvCOfF18NHqHptYK2Dg3P6PMYC4NbS7j
fDgN0tldlsp5Jd+imsroUyqECKguTNRT2gr1uDOordg41WsX0Iwm29CpGsYu
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
pZlugWbv8MxQCCq2bpwmfarkN89uuMUj3sK4SOm4JMqIix5Oxbd3PF6gBTSF
//z6axTiGi7Ahi7yI2IlxbaN1uwGRC80vWVS21CIcjxf8QIxQ6KB6DZogs1E
N6pvuaW6pkZ1sXq1ObPlrvczWrDEkdWrWgvsubg1jDNOi9ESoJrN15DvcB4h
/ab/BmwO1J80Hy2xN+QIFPgUB+6B8pXSBqMCpzxZKCqyJ1FvtPcU/cOIv3hk
WKz5nWTYeAPD5uAR1YuH+IC04qnQdsKLC9cDGPmMIlU/wpAhvdPaLAJKuaaV
dqiGQPmwUanUPkccAM8WjmgrrOtwgiQRqz88saCi6kDdRHGdr7iGpOq3eiNq
6ViNIVUuzfHB6VEXzVLWz6Imz5+IbdAm1e/4DHYk7dCShaVqo5j8YvEozxCJ
T47UCAkGwkiUJc1thivxXYvICuY/DuhyIYd4PeMP95awmbo+VblGgDhqZCs3
MDhCvWCnUhjlYVMqJH2XsO0JWzm+QObIJpMicRmVVQT9H3jA7KOgsXugND5+
xwou9pXhNBu9u6DgD3iHg0CChTUOc/dusODKt+ku2rfXQaR+yvzb/rghUYIN
oxmuKXqCj/AD7fdwxB24uwFKpIALDzudMOfQRbwpCLgHapVPMBI0LtvBlDpv
eGt2+T93eP5v/R6r2fFO07/XmF/wz5Ju/EMuRa6anjNogr4RvyMjtCLmQNHY
E9nLsyHGCOJX3SiOpqNQ+eyHn376eWfrLdoz+er9/k5HDGU4NleQYgutGwIP
DBElmMWqYIMZ8gyr2yCf0YfXCmzAENwY3NKLO0DwkS5c2T2+Z5Vf/POSNNBA
PJ/UjYqA13EGZLjVQwJMl0fpAktBNwJymnXNVYpBqfjkm91Hb2WsN492/T4X
6eUs5s1CvZe3+80VoA4iFv53mnXe1qRJvCmTDGlMV4/YCX9xDh2KkAj5A2YG
Z54ZnMccDfyUqfAZsxBvpLdm0Fm8EDulkdhqcoowd+kaLjqrjaxsLWY7RIMl
Eh2t0qe5xqHYY0qszlXnnJNjgr3PnDQn3SaodQ3MeUlpoevY3Xmj5AW3Io4Z
qnqcKVIS7SHb9l3pQYLZO9Sel8zmg9eHr86OT14OOo/tky2Smlqu3afrUOFz
Q8XCLZV6UYzm1/ekGYm0aQWI5c4J5cZ5TG4PeJrCFmz9Uz51th+KrwhC2ycf
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
AwA=

-->

</rfc>
