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

<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 invalid
measurement. Two concrete VDAFs are specified, one for general-purpose
aggregation (Prio3) and another for heavy hitters (Poplar1).</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/cfrg/draft-irtf-cfrg-vdaf"/>.</t>
    </note>
  </front>
  <middle>
    <?line 269?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>(RFC EDITOR: remove this paragraph.) The source for this draft 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>Another way of constructing a privacy-preserving measurement system is to use
multi-party computation (MPC). The goal of such a system is that 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 not 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 result.</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_M) =
    G(agg_param, meas_1) + ... + G(agg_param, meas_M)
]]></artwork>
      <t>where <tt>meas_1, ..., meas_M</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. 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, making them 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>Provide higher-level protocols, like <xref target="DAP"/>, with
a simple, uniform interface for accessing privacy-preserving measurement
schemes, document relevant operational and security requirements, and
specify 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 parties 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>Provide cryptographers with design criteria that provide a clear deployment
roadmap for new constructions of privacy-preserving measurement systems.</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 a problem known as private
heavy-hitters. In this problem, 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"/> (denoted <tt>G</tt> 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 in the remainder of the document; <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"/> specifies
Prio3; <xref target="poplar1"/> specifies Poplar1; and <xref target="security"/> enumerates security
considerations for DAFs and VDAFs in general and our constructions in
particular.</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>13:</t>
        <ul spacing="normal">
          <li>
            <t>(V)DAF: Replace the one-shot aggregation API with a streaming API. Each
Aggregator initializes aggregation, then updates its aggregate share as
output shares are produced. The scheme also specifies a method for merging
multiple aggregate shares.</t>
          </li>
          <li>
            <t>Poplar1: Move prefix uniqueness and ordering checks from <tt>prep_init()</tt> to
<tt>is_valid()</tt>.</t>
          </li>
          <li>
            <t>Poplar1: Use <tt>bool</tt> to represent control bits instead of <tt>Field2</tt>.</t>
          </li>
          <li>
            <t>Prio3MultihotCountVec: Change the measurement type from <tt>list[int]</tt> to
<tt>list[bool]</tt>.</t>
          </li>
          <li>
            <t>Security considerations: Define our threat model for side channel attacks and
enumerate the parts of the spec that are most relevant to implementers.</t>
          </li>
          <li>
            <t>Improve the specification of each Prio3 variant by listing each
implementation of <tt>Valid</tt> and <tt>Gadget</tt> in full. Gadgets are listed in a new
appendix section.</t>
          </li>
          <li>
            <t>Improve the specification of the FLP system by listing the proof-generation,
query, and decision algorithms in full. The wrapper gadgets are listed in the
new section of the appendix for gadgets.</t>
          </li>
          <li>
            <t>Add a section with a high-level overview of the IDPF construction.</t>
          </li>
          <li>
            <t>Move some sections around: move ping-pong and star topologies under
communication patterns for VDAF preparation; move FLP proof generation,
query, and decision algorithms up one level; move privacy considerations for
aggregation parameters up one level; and move safe usage of IDPF outputs up
one level.</t>
          </li>
        </ul>
        <t>12:</t>
        <ul spacing="normal">
          <li>
            <t>(V)DAF: Add an application context string parameter to sharding and
preparation. The motivation for this change is to harden Prio3 against
offline attacks. More generally, however, it allows designing schemes for
which correct execution requires agreement on the application context.
Accordingly, both Prio3 and Poplar1 have been modified to include the context
in the domain separation tag of each XOF invocation. (*)</t>
          </li>
          <li>
            <t>Prio3: Improve soundness of the base proof system and the circuits of some
variants. Generally speaking, wherever we evaluate a univariate polynomial at
a random point, we can instead evaluate a multivariate polynomial of lower
degree. (*)</t>
          </li>
          <li>
            <t>Prio3: Replace the helper's measurement and proof share seeds with a single
seed. (*)</t>
          </li>
          <li>
            <t>Prio3Sum: Update the circuit to support a more general range check and avoid
using joint randomness. (*)</t>
          </li>
          <li>
            <t>Prio3Histogram, Prio3MultihotCountVec: Move the final reduction of the
intermediate outputs out of the circuit. (*)</t>
          </li>
          <li>
            <t>IDPF: Add the application context string to key generation and evaluation and
bind it to the fixed AES key. (*)</t>
          </li>
          <li>
            <t>IDPF: Use XofTurboShake128 for deriving the leaf nodes in order to ensure the
construction is extractable. (*)</t>
          </li>
          <li>
            <t>IDPF: Simplify the public share encoding. (*)</t>
          </li>
          <li>
            <t>XofTurboShake128: Change <tt>SEED_SIZE</tt> from 16 bytes to 32 to mitigate offline
attacks on Prio3 robustness. In addition, allow seeds of different lengths so
that we can continue to use XofTurboShake128 with IDPF. (*)</t>
          </li>
          <li>
            <t>XofTurboShake128, XofFixedKeyAes128: Increase the length prefix for the
domain separation tag from one by to two bytes. This is to accommodate the
application context. (*)</t>
          </li>
          <li>
            <t>Reassign codepoints for all Prio3 variants and Poplar1. (*)</t>
          </li>
          <li>
            <t>Security considerations: Add a section on defense-in-depth measures taken by
Prio3 and Poplar1 and more discussion about choosing FLP parameters.</t>
          </li>
        </ul>
        <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 multiple 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 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</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 (compatible with Python 3.12
or later). 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>In Python, array indexing starts with <tt>0</tt>, e.g., <tt>x[0]</tt> is the first element
and <tt>x[len(x)-1]</tt> is the last of <tt>x</tt>. We can also index from the end of the
list, e.g., <tt>x[-1]</tt> is the last element of <tt>x</tt>.</t>
      <t>Exponentiation is denoted by <tt>x ** y</tt> in Python. We also sometimes use more
conventional notation for exponentiation, namely <tt>x^y</tt>.</t>
      <t>Division of <tt>x</tt> by <tt>y</tt> is denoted by <tt>x / y</tt>. Python includes a similar
operator, <tt>x // y</tt>, which is short for <tt>floor(x / y)</tt>.</t>
      <t>Type hints are used to define input and output types:</t>
      <ul spacing="normal">
        <li>
          <t>The type variable <tt>F</tt> is used in signatures to signify any type that is a
subclass of <tt>Field</tt> (<xref target="field"/>).</t>
        </li>
        <li>
          <t><tt>bytes</tt> is a byte string.</t>
        </li>
        <li>
          <t><tt>int</tt> is an integer.</t>
        </li>
        <li>
          <t><tt>Generic</tt> is used in class definitions to explicitly declare type variables
of generic classes.</t>
        </li>
        <li>
          <t><tt>Any</tt> is the universal supertype, which admits values of any type.</t>
        </li>
        <li>
          <t><tt>Optional[T]</tt> is shorthand for <tt>T | None</tt>. Its value may be <tt>None</tt> or have
type <tt>T</tt>.</t>
        </li>
        <li>
          <t><tt>Self</tt> represents the containing class of the method definition in which it
appears.</t>
        </li>
        <li>
          <t><tt>Sequence[T]</tt> is either a list or tuple of values of type <tt>T</tt>.</t>
        </li>
      </ul>
      <t>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>12</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 transmitted from one party to another, this document prescribes
a particular encoding of that quantity as a byte string.</t>
      <t>Some common functionalities:</t>
      <ul spacing="normal">
        <li>
          <t><tt>additive_secret_share(x: list[F], num_shares: int, field: type[F]) -&gt;
list[list[F]]</tt> takes a vector <tt>x</tt> of field elements and returns <tt>num_shares</tt>
vectors of length <tt>len(x)</tt> such that they all add up to the input vector.
Note that this function is not used normatively in this document.</t>
        </li>
        <li>
          <t><tt>byte(x: int) -&gt; bytes</tt> returns the representation of the integer <tt>x</tt> in the
range <tt>[0, 256)</tt> as a single-byte byte string.</t>
        </li>
        <li>
          <t><tt>cast(typ: type[T], x: object) -&gt; T</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>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>from_be_bytes(encoded: bytes) -&gt; int</tt> decodes a big-endian byte string,
i.e., returns the integer <tt>x</tt> for which <tt>to_be_bytes(x, len(encoded)) ==
encoded</tt>.</t>
        </li>
        <li>
          <t><tt>from_le_bytes(encoded: bytes) -&gt; int</tt> decodes a little-endian byte string,
i.e., returns the integer <tt>x</tt> for which <tt>to_le_bytes(x, len(encoded)) ==
encoded</tt>.</t>
        </li>
        <li>
          <t><tt>front(len: int, x: list[Any]) -&gt; tuple[list[Any], list[Any]]</tt> splits <tt>x</tt>
into two vectors, where the first vector is made up of the first <tt>len</tt>
elements of <tt>x</tt> and the second is made up of the remaining elements. This
function is equivalent to <tt>(x[:len], x[len:])</tt>.</t>
        </li>
        <li>
          <t><tt>gen_rand(len: int) -&gt; bytes</tt> returns a byte array of the requested length
(<tt>len</tt>) generated by a cryptographically secure pseudorandom number generator
(CSPRNG).</t>
        </li>
        <li>
          <t><tt>next_power_of_2(x: int) -&gt; int</tt> returns the smallest integer
greater than or equal to <tt>x</tt> that is also a power of two.</t>
        </li>
        <li>
          <t><tt>range(stop: int)</tt> or <tt>range(start: int, stop: int[, step: int])</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>
        <li>
          <t><tt>to_be_bytes(x: int, len: int) -&gt; bytes</tt> converts an integer <tt>x</tt> whose value
is in the range <tt>[0, 2^(8*len))</tt> to a big-endian byte string of length <tt>len</tt>.</t>
        </li>
        <li>
          <t><tt>to_le_bytes(x: int, len: int) -&gt; bytes</tt> converts an integer <tt>x</tt> whose value
is in the range <tt>[0, 2^(8*len))</tt> to a little-endian byte string of length
<tt>len</tt>.</t>
        </li>
        <li>
          <t><tt>poly_eval(field: type[F], p: list[F], x: F) -&gt; F</tt> returns the result of
evaluating the polynomial, <tt>p(x)</tt>. The coefficients of polynomials are stored
in lists in ascending order of degree, starting with the constant
coefficient. The <tt>field</tt> parameter is the class object for <tt>F</tt> and is used by
the implementation to construct field elements. (See <xref target="field"/>.)</t>
        </li>
        <li>
          <t><tt>poly_interp(field: type[F], inputs: list[F], outputs: list[F]) -&gt; list[F]</tt>
returns the coefficients of the lowest degree polynomial <tt>p</tt> for which
<tt>p(inputs[k]) == outputs[k]</tt> for all <tt>k</tt>. Normally this will be computed
using the Number Theoretic Transform (NTT) <xref target="SML24"/>.</t>
        </li>
        <li>
          <t><tt>poly_mul(field: type[F], p: list[F], q: list[F]) -&gt; list[F]</tt> returns
the product of two polynomials.</t>
        </li>
        <li>
          <t><tt>poly_strip(field: type[F], p: list[F]) -&gt; list[F]</tt> strips the zeros from the
end of the input polynomial's list of coefficients. That is, it returns
<tt>p[:i]</tt> where <tt>i</tt> is the index of the highest-degree non-zero coefficient of
<tt>p</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>zeros(len: int) -&gt; bytes</tt> returns an array of bytes of the requested
length (<tt>len</tt>). Each element of the array is set to zero.</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 |----+
     input |     +--------------+    | aggregate
    shares |             ^           | shares
           |             |           |
           |             V           |
           |     +--------------+    |
           | +-->| Aggregator 1 |--+ |
           | |   +--------------+  | |
+--------+-+ |           ^         | +->+-----------+
| Client |---+           |         +--->| Collector |--> aggregate
+--------+-+                         +->+-----------+
           |            ...          |
           |                         |
           |             |           |
           |             V           |
           |    +----------------+   |
           +--->| Aggregator N-1 |---+
                +----------------+
]]></artwork>
      </figure>
      <t>In a DAF- or VDAF-based private measurement system, we distinguish between
three types of actors: Clients, Aggregators, and the Collector.  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>As each Aggregator recovers output shares, it accumulates them into an
"aggregate share" for the batch of measurements.</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
validity of the aggregate results 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 disseminate 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 by the Collector on the batch of measurements. For example, the
aggregation parameter is used to represent the candidate prefixes in the
Poplar1 VDAF (<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. In addition to the input shares, the
client generates a "public share" during this step that is disseminated to
all of 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 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 the algorithm for the computation needed in each of
these stages. The interface, denoted <tt>Daf</tt>, 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 the range <tt>[0, 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 associated with the report.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>RAND_SIZE: int</tt></td>
            <td align="left">Size of the random byte string consumed by the 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 the 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>The types in this table 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 standard encoding
for the <tt>PublicShare</tt>, <tt>InputShare</tt>, <tt>AggParam</tt>, and <tt>AggShare</tt> types.</t>
      <section anchor="sec-daf-shard">
        <name>Sharding</name>
        <figure anchor="shard-flow">
          <name>Illustration of the sharding algorithm.</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>
        <t>The sharding algorithm run by each Client is defined as follows:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.shard(ctx: bytes, measurement: Measurement, nonce: bytes, rand: bytes)
-&gt; tuple[PublicShare, list[InputShare]]</tt> consumes the "application context"
(defined below), a measurement, and a nonce and produces the public share,
distributed to each of the Aggregators, and the 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>daf.NONCE_SIZE</tt> and <bcp14>MUST</bcp14> be generated
using a cryptographically secure random number generator (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>daf.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>daf.SHARES</tt>.</t>
              </li>
            </ul>
          </li>
        </ul>
        <t>Sharding is bound to a specific "application context". The application context
is a string intended to uniquely identify an instance of the higher level
protocol that uses the DAF. The goal of binding the application to DAF
execution is to ensure that aggregation succeeds only if the Clients and
Aggregators agree on the application context. (Preparation binds the
application context, too; see <xref target="sec-daf-prepare"/>.) Note that, unlike VDAFs
(<xref target="vdaf"/>), there is no explicit signal of disagreement; it may only manifest
as a garbled aggregate result.</t>
        <t>The nonce is a public random value associated with the report. It is referred
to as a nonce because normally it will also be used as a unique identifier for
that report in the context of some application. The randomness requirement is
especially important for VDAFs, where it may be used by the Aggregators to
derive per-report randomness for verification of the computation. See
<xref target="nonce-requirements"/> for details.</t>
      </section>
      <section anchor="sec-daf-prepare">
        <name>Preparation</name>
        <figure anchor="daf-prep-flow">
          <name>Illustration of preparation.</name>
          <artwork><![CDATA[
    Aggregator 0   Aggregator 1           Aggregator SHARES-1
    ============   ============           ===================

    input_share_0  input_share_1          input_share_[SHARES-1]
      |              |                 ...  |
      V              V                      V
    +-----------+  +-----------+          +-----------+
    | prep      |  | prep      |          | prep      |
    +-----------+  +-----------+          +-----------+
      |              |                 ...  |
      V              V                      V
    out_share_0    out_share_1         out_share_[SHARES-1]
]]></artwork>
        </figure>
        <t>Once an Aggregator has received the public share and its input share, the next
step is to prepare the input share for aggregation. This is accomplished using
the preparation algorithm:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.prep(ctx: bytes, agg_id: int, agg_param: AggParam, nonce: bytes,
public_share: PublicShare, input_share: InputShare) -&gt; OutShare</tt> consumes the
public share and one of the input shares generated by the Client, the
application context, the Aggregator's unique identifier, the aggregation
parameter selected by the Collector, and the report 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 the range <tt>[0, daf.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>daf.NONCE_SIZE</tt>.</t>
              </li>
            </ul>
          </li>
        </ul>
        <t>The Aggregators <bcp14>MUST</bcp14> agree on the value of the aggregation parameter.
Otherwise, the aggregate result may be computed incorrectly by the Collector.</t>
      </section>
      <section anchor="sec-daf-validity-scopes">
        <name>Validity of Aggregation Parameters</name>
        <t>In general, it is permissible to aggregate a batch of reports multiple times.
However, to prevent privacy violations, DAFs may impose certain restrictions on
the aggregation parameters selected by the Collector. Restrictions are
expressed by the aggregation parameter validity function:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.is_valid(agg_param: AggParam, previous_agg_params: list[AggParam]) -&gt;
bool</tt> returns <tt>True</tt> if <tt>agg_param</tt> is allowed given the sequence
<tt>previous_agg_params</tt> of previously accepted aggregation parameters.</t>
          </li>
        </ul>
        <t>Prior to accepting an aggregation parameter from the Collector and beginning
preparation, each Aggregator <bcp14>MUST</bcp14> validate it using this function.</t>
      </section>
      <section anchor="sec-daf-aggregate">
        <name>Aggregation</name>
        <figure anchor="aggregate-flow">
          <name>Illustration of aggregation. The number of measurements in the batch is denoted by M.</name>
          <artwork><![CDATA[
    Aggregator j
    ============

    +------------+    +------------+
    | agg_init   |--->| agg_update |<--- out_share_0
    +------------+    +------------+
                         |
                         V
                      +------------+
                      | agg_update |<--- out_share_1,
                      +------------+
                        |
                        V
                       ...
                        |
                        V
                      +------------+
                      | agg_update |<--- out_share_M
                      +------------+
                        |
                        V
                      agg_share_j
]]></artwork>
        </figure>
        <t>Once an Aggregator holds an output share, it adds it into its aggregate share
for the batch. This streaming aggregation process is implemented by the
following pair of algorithms:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.agg_init(agg_param: AggParam) -&gt; AggShare</tt> returns an empty aggregate
share. It is called to initialize aggregation of a batch of measurements.</t>
          </li>
          <li>
            <t><tt>daf.agg_update(agg_param: AggParam, agg_share: AggShare, out_share:
OutShare) -&gt; AggShare</tt> accumulates an output share into an aggregate share
and returns the updated aggregate share.</t>
          </li>
        </ul>
        <t>In many situations it is desirable to split an aggregate share across multiple
storage elements, then merge the aggregate shares together just before
releasing the completed aggregate share to the Collector. DAFs facilitate this
with the following method:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.merge(agg_param: AggParam, agg_shares: list[AggShare]) -&gt; AggShare</tt>
merges a sequence of aggregate shares into a single aggregate share.</t>
          </li>
        </ul>
        <section anchor="agg-order">
          <name>Aggregation Order</name>
          <t>For most DAFs and VDAFs, the outcome of aggregation is not sensitive to the
order in which output shares are aggregated. This means that aggregate shares
can be updated or merged with other aggregate shares in any order. For
instance, for both Prio3 (<xref target="prio3"/>) and Poplar1 (<xref target="poplar1"/>), the aggregate
shares and output shares both have the same type, a vector over some finite
field (<xref target="field"/>); and aggregation involves simply adding vectors together.</t>
          <t>In theory, however, there may be a DAF or VDAF for which correct execution
requires each Aggregator to aggregate output shares in the same order.</t>
        </section>
      </section>
      <section anchor="sec-daf-unshard">
        <name>Unsharding</name>
        <figure anchor="unshard-flow">
          <name>Illustration of unsharding.</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>
        <t>After the Aggregators have aggregated all measurements in the batch, each sends
its aggregate share to the Collector, who runs the unsharding algorithm to
recover the aggregate result:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.unshard(agg_param: AggParam, agg_shares: list[AggShare],
num_measurements: int) -&gt; AggResult</tt> consumes the aggregate shares
and produces the aggregate result.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t>The length of <tt>agg_shares</tt> <bcp14>MUST</bcp14> be <tt>SHARES</tt>.</t>
              </li>
              <li>
                <t><tt>num_measurements</tt> <bcp14>MUST</bcp14> equal the number of measurements in the batch.</t>
              </li>
            </ul>
          </li>
        </ul>
      </section>
      <section anchor="daf-execution">
        <name>Execution of a DAF</name>
        <t>Secure execution of a DAF involves simulating the following procedure over an
insecure network.</t>
        <sourcecode type="python"><![CDATA[
def run_daf(
        daf: Daf[
            Measurement,
            AggParam,
            PublicShare,
            InputShare,
            OutShare,
            AggShare,
            AggResult,
        ],
        ctx: bytes,
        agg_param: AggParam,
        measurements: list[Measurement]) -> AggResult:
    agg_shares: list[AggShare]
    agg_shares = [daf.agg_init(agg_param)
                  for _ in range(daf.SHARES)]
    for measurement in measurements:
        # Sharding
        nonce = gen_rand(daf.NONCE_SIZE)
        rand = gen_rand(daf.RAND_SIZE)
        (public_share, input_shares) = \
            daf.shard(ctx, measurement, nonce, rand)

        # Preparation, aggregation
        for j in range(daf.SHARES):
            out_share = daf.prep(ctx, j, agg_param, nonce,
                                 public_share, input_shares[j])
            agg_shares[j] = daf.agg_update(agg_param,
                                           agg_shares[j],
                                           out_share)

    # Unsharding
    num_measurements = len(measurements)
    agg_result = daf.unshard(agg_param, agg_shares,
                             num_measurements)
    return agg_result
]]></sourcecode>
        <t>The inputs to this procedure include the parameters of the aggregation function
computed by the DAF: an aggregation parameter and a sequence of measurements.
They also include the application context. 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>VDAFs are identical to DAFs except that preparation is an interactive process
carried out by the Aggregators. If successful, this process results in each
Aggregator computing an output share. The process will fail if, for example,
the underlying measurement is invalid.</t>
      <t>Failure manifests as an exception raised by one of the algorithms defined in
this section. If an exception is raised during preparation, the Aggregators
<bcp14>MUST</bcp14> remove the report from the batch and not attempt to aggregate it.
Otherwise, a malicious Client can cause the Collector to compute a malformed
aggregate result.</t>
      <t>The remainder of this section defines the VDAF interface, which we denote by
<tt>Vdaf</tt>. The attributes 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: int</tt></td>
            <td align="left">Algorithm identifier for this VDAF, in the range <tt>[0, 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>ROUNDS: int</tt></td>
            <td align="left">Number of rounds of communication during preparation.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>NONCE_SIZE: int</tt></td>
            <td align="left">Size of the report nonce.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>RAND_SIZE: int</tt></td>
            <td align="left">Size of the random byte string consumed during sharding.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>VERIFY_KEY_SIZE: int</tt></td>
            <td align="left">Size of the verification key used during preparation.</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 the 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">Type of the prep state.</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 the types in the table above need to be written to the network in
order to carry out the computation. 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>AggParam</tt>, <tt>AggShare</tt>, <tt>PrepShare</tt>, and
<tt>PrepMessage</tt> types.</t>
      <t>Each VDAF is identified by a unique 32-bit integer, denoted <tt>ID</tt>. Identifiers
for each VDAF specified in this document are defined in <xref target="codepoints"/>. The
following method is used by both Prio3 and Poplar1:</t>
      <sourcecode type="python"><![CDATA[
def domain_separation_tag(self, usage: int, ctx: bytes) -> bytes:
    """
    Format domain separation tag for this VDAF with the given
    application context and usage.

    Pre-conditions:

        - `usage` in the range `[0, 2^16)`
    """
    return format_dst(0, self.ID, usage) + ctx
]]></sourcecode>
      <t>The output, called the "domain separation tag", is used in our constructions
for domain separation. Function <tt>format_dst()</tt> is defined in <xref target="dst-binder"/>.</t>
      <section anchor="sec-vdaf-shard">
        <name>Sharding</name>
        <t>Sharding is as described for DAFs in <xref target="sec-daf-shard"/>. The public share and
input shares encode additional information used during preparation to validate
the output shares before they are aggregated (e.g., the "proof shares" in
<xref target="prio3"/>).</t>
        <t>Like DAFs, sharding is bound to the application context via the application
context string. Again, this is intended to ensure that aggregation succeeds
only if the Clients and Aggregators agree on the application context. Unlike
DAFs, however, disagreement on the context should manifest as a preparation
failure, causing the report to be rejected without garbling the aggregate
result. The application context also provides some defense-in-depth against
cross protocol attacks; see <xref target="deep"/>.</t>
      </section>
      <section anchor="sec-vdaf-prepare">
        <name>Preparation</name>
        <figure anchor="prep-flow">
          <name>Illustration of interactive VDAF preparation.</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       V     | x ROUNDS
    +-----------+  +-----------+          +-----------+   |
    | prep_next |  | prep_next |          | prep_next |   |
    +-----------+  +-----------+          +-----------+   |
      |       |      |       |         ...  |       |     |
      V       V      V       V              V       V     /
     ...            ...                    ...
      |              |                 ...  |
      V              V                      V
    out_share_0    out_share_1         out_share_[SHARES-1]
]]></artwork>
        </figure>
        <t>Preparation is organized into a number of rounds. The number of rounds depends
on the VDAF: Prio3 (<xref target="prio3"/>) has one round and Poplar1 (<xref target="poplar1"/>) has two.</t>
        <t>Aggregators retain some local state between successive rounds of preparation.
This is referred to as "preparation state" or "prep state" for short.</t>
        <t>During each round, each Aggregator broadcasts a message called a
"preparation share", or "prep share" for short. The prep shares are then
combined into a single message called the "preparation message", or "prep
message". The prep message <bcp14>MAY</bcp14> be computed by any one of the Aggregators.</t>
        <t>The prep message is disseminated to each of the Aggregators to begin the next
round. An Aggregator begins the first round with its input share and it begins
each subsequent round with the current prep state and 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>Just as for DAFs (<xref target="sec-daf-prepare"/>), preparation involves an aggregation
parameter. The aggregation parameter is consumed by each Aggregator before the
first round of communication.</t>
        <t>Unlike DAFs, VDAF preparation involves a secret "verification key" held by each
of the Aggregators. This key is used to verify validity of the output shares
they compute. 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>Preparation is implemented by the following set of algorithms:</t>
        <ul spacing="normal">
          <li>
            <t><tt>vdaf.prep_init(verify_key: bytes, ctx: 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. It consumes the shared
verification key, the application context, the Aggregator's unique
identifier, the aggregation parameter chosen by the Collector, the report
nonce, the public share, and one of the input shares generated by the Client.
It produces the Aggregator's initial prep state and prep share.  </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 the range <tt>[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_shares_to_prep(ctx: bytes, agg_param: AggParam, prep_shares:
list[PrepShare]) -&gt; PrepMessage</tt> is the deterministic preparation message
pre-processing algorithm. It combines the prep shares produced by the
Aggregators in the previous round into the prep message consumed by each
Aggregator to start the next round.</t>
          </li>
          <li>
            <t><tt>vdaf.prep_next(ctx: bytes, 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 prep state (<tt>prep_state</tt>) and returns either its next prep state
and prep share for the next round or, if this is the last round, its output
share.</t>
          </li>
        </ul>
        <t>An exception may be raised by one of these algorithms, in which case the report
<bcp14>MUST</bcp14> be deemed invalid and not processed any further.</t>
        <t>Implementation note: The preparation process 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 the underlying data 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>Aggregation parameter validation is as described for DAFs in
<xref target="sec-daf-validity-scopes"/>. Again, each Aggregator <bcp14>MUST</bcp14> validate each
aggregation parameter received from the Collector before beginning preparation
with that parameter.</t>
      </section>
      <section anchor="sec-vdaf-aggregate">
        <name>Aggregation</name>
        <t>Aggregation is identical to DAF aggregation as described in
<xref target="sec-daf-aggregate"/>. As with DAFs, computation of the VDAF aggregate is not
usually sensitive to the order in which output shares are aggregated. See
<xref target="agg-order"/>.</t>
      </section>
      <section anchor="sec-vdaf-unshard">
        <name>Unsharding</name>
        <t>Unsharding is identical to DAF unsharding as described in <xref target="sec-daf-unshard"/>.</t>
      </section>
      <section anchor="vdaf-execution">
        <name>Execution of a VDAF</name>
        <t>Secure execution of a VDAF involves simulating the following procedure over an
insecure network.</t>
        <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,
        ctx: bytes,
        measurements: list[Measurement]) -> AggResult:
    """
    Pre-conditions:

        - `len(verify_key) == vdaf.VERIFY_KEY_SIZE`
    """
    agg_shares = [vdaf.agg_init(agg_param)
                  for _ in range(vdaf.SHARES)]
    for measurement in measurements:
        # Sharding
        nonce = gen_rand(vdaf.NONCE_SIZE)
        rand = gen_rand(vdaf.RAND_SIZE)
        (public_share, input_shares) = \
            vdaf.shard(ctx, measurement, nonce, rand)

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

        # Complete preparation
        for i in range(vdaf.ROUNDS - 1):
            prep_msg = vdaf.prep_shares_to_prep(ctx,
                                                agg_param,
                                                outbound_prep_shares)

            outbound_prep_shares = []
            for j in range(vdaf.SHARES):
                out = vdaf.prep_next(ctx, prep_states[j], prep_msg)
                assert isinstance(out, tuple)
                (prep_states[j], prep_share) = out
                outbound_prep_shares.append(prep_share)

        prep_msg = vdaf.prep_shares_to_prep(ctx,
                                            agg_param,
                                            outbound_prep_shares)

        # Aggregation
        for j in range(vdaf.SHARES):
            out_share = vdaf.prep_next(ctx, prep_states[j], prep_msg)
            assert not isinstance(out_share, tuple)
            agg_shares[j] = vdaf.agg_update(agg_param,
                                            agg_shares[j],
                                            out_share)

    # Unsharding
    num_measurements = len(measurements)
    agg_result = vdaf.unshard(agg_param, agg_shares,
                              num_measurements)
    return agg_result
]]></sourcecode>
        <t>The inputs to this algorithm are the verification key, application context,
aggregation parameter, and a list of measurements. 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>The only stage of VDAF execution that requires interaction is preparation
(<xref target="sec-vdaf-prepare"/>). There are a number of ways to coordinate this
interaction; the best strategy depends largely on the number of Aggregators
(i.e., <tt>vdaf.SHARES</tt>). This section describes two strategies, one specialized
for two Aggregators and another that is suitable for any number of Aggregators.</t>
        <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. Our goal in this section is to realize this broadcast
channel.</t>
        <t>The state machine of each Aggregator is shown below.</t>
        <figure anchor="vdaf-prep-state-machine">
          <name>State machine of 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 Aggregator's
local inputs and/or messages sent by its co-Aggregators. The initial state is
<tt>Start</tt>. The terminal states are: <tt>Rejected</tt>, indicating that the report cannot
be processed any further; and <tt>Finished(out_share)</tt>, indicating that the
Aggregator has recovered an output share <tt>out_share</tt>. For completeness, we
define these states in <xref target="topo-states"/>.</t>
        <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 schemes specified in
<xref target="prio3-encode"/> and <xref target="poplar1-encode"/> respectively.</t>
        <section anchor="ping-pong-topo">
          <name>The Ping-Pong Topology (Only Two Aggregators)</name>
          <t>For VDAFs with precisely two Aggregators (i.e., <tt>vdaf.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 Aggregator the "Leader" and the responding
Aggregator 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 in <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 in <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 are <tt>ceil((vdaf.ROUNDS+1)/2)</tt>
requests sent.</t>
          <t>We specify protocol messages in the presentation language of TLS; see <xref section="3" sectionFormat="of" target="RFC8446"/>. Each message is structured as follows:</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 trigger all transitions in the state machine in
<xref target="vdaf-prep-state-machine"/>, except for the Leader's initial transition. The
Leader's state is initialized using its local inputs with the following method
on class <tt>Vdaf</tt>:</t>
          <sourcecode type="python"><![CDATA[
def ping_pong_leader_init(
        self,
        vdaf_verify_key: bytes,
        ctx: 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,
            ctx,
            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. The function
<tt>encode</tt>  is used to encode the outbound message, which has the message type of
<tt>initialize</tt> (identified by the number <tt>0</tt>).</t>
          <t>To continue processing the report, 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,
        ctx: 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,
            ctx,
            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(
            ctx,
            self.decode_agg_param(agg_param),
            prep_shares,
            prep_state,
            0,
        )
    except:
        return (Rejected(), None)
]]></sourcecode>
          <t>The procedure <tt>decode()</tt> decodes the inbound message and returns the
MessageType variant (<tt>initialize</tt>, <tt>continue</tt>, or <tt>finish</tt>) and the fields of
the message. The 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,
        ctx: bytes,
        agg_param: AggParam,
        prep_shares: list[PrepShare],
        prep_state: PrepState,
        prep_round: int) -> tuple[State, bytes]:
    prep_msg = self.prep_shares_to_prep(ctx,
                                        agg_param,
                                        prep_shares)
    encoded_prep_msg = self.encode_prep_msg(prep_msg)
    out = self.prep_next(ctx, 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>To continue processing, the Helper sends the outbound message to the Leader.
The Leader computes its next state transition using the following method on
class <tt>Vdaf</tt>:</t>
          <sourcecode type="python"><![CDATA[
def ping_pong_leader_continued(
    self,
    ctx: bytes,
    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, ctx, agg_param, state, inbound)

def ping_pong_continued(
    self,
    is_leader: bool,
    ctx: bytes,
    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(ctx, 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(
                ctx,
                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 following method on class <tt>Vdaf</tt>:</t>
          <sourcecode type="python"><![CDATA[
def ping_pong_helper_continued(
    self,
    ctx: bytes,
    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, ctx, 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, when one party reaches the
<tt>Finished</tt> state, there may be one more message to send before the peer can
also finish processing (i.e., the outbound message is not <tt>None</tt>).</t>
        </section>
        <section anchor="star-topo">
          <name>The Star Topology (Any Number of Aggregators)</name>
          <t>The ping-pong topology of the previous section is only suitable for applications
of VDAFs involving exactly two Aggregators. In applications with more than two
Aggregators, 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>vdaf.prep_shares_to_prep()</tt>) and broadcasts it to the
Helpers. At this point, each Aggregator runs <tt>vdaf.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 another round is 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>
    <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>Concrete fields, i.e., subclasses of <tt>Field</tt>, implement the following class
methods:</t>
        <ul spacing="normal">
          <li>
            <t><tt>Field.zeros(length: int) -&gt; list[Self]</tt> returns a vector of zeros of the
requested length.  </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 and has the same pre- and post-conditions as for <tt>Field.zeros()</tt>.
Note that this function is not used normatively in the specification of
either Prio3 or Poplar1.</t>
          </li>
        </ul>
        <t>A field element is an instance of a concrete <tt>Field</tt>. Addition,
subtraction, multiplication, division, negation, and inversion are denoted,
respectively, <tt>x + y</tt>, <tt>x - y</tt>, <tt>x * y</tt>, <tt>x / y</tt>, <tt>-x</tt>, and <tt>x.inv()</tt>.</t>
        <t>We sometimes need to convert a field element to an <tt>int</tt>, which we denote by
<tt>x.int()</tt>. Likewise, each concrete <tt>Field</tt> implements a constructor for
converting an 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 in the range <tt>(-Field.MODULUS, Field.MODULUS)</tt>;
negative values are treated as negations.</t>
          </li>
        </ul>
        <section anchor="auxiliary-functions">
          <name>Auxiliary Functions</name>
          <t>The following class methods on <tt>Field</tt> are used to encode and decode vectors of
field elements as byte strings:</t>
          <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.int(), cls.ENCODED_SIZE)
    return encoded

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

    vec = []
    while len(encoded) > 0:
        (encoded_x, encoded) = front(cls.ENCODED_SIZE, encoded)
        x = from_le_bytes(encoded_x)
        if x >= cls.MODULUS:
            raise ValueError('modulus overflow')
        vec.append(cls(x))
    return vec
]]></sourcecode>
          <t><tt>Field</tt> provides the following class methods for representing an integer as a
sequence of field elements, each of which represents a bit of the input. These
are used to encode measurements in some variants of Prio3
(<xref target="prio3-instantiations"/>).</t>
          <sourcecode type="python"><![CDATA[
def encode_into_bit_vec(
        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_vec(cls, vec: list[Self]) -> Self:
    """
    Decode the field element from the bit representation, expressed
    as a vector of field elements `vec`.

    This may also be used with secret shares of a bit representation,
    since it is linear.
    """
    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>
          <t>Finally, the following functions define arithmetic on vectors over a finite
field. Note that an exception is raised by each function if the operands are
not the same length.</t>
          <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>
        </section>
        <section anchor="field-ntt-friendly">
          <name>NTT-Friendly Fields</name>
          <t>Some VDAFs, including Prio3, require fields that are suitable for efficient
computation of the number theoretic transform (NTT) <xref target="SML24"/>, as this allows
for fast polynomial interpolation. Specifically, a field is said to be
"NTT-friendly" if, in addition to the interface described in <xref target="field"/>, it
provides the following interface:</t>
          <ul spacing="normal">
            <li>
              <t><tt>Field.gen() -&gt; Self</tt> is a class method that 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.</t>
            </li>
            <li>
              <t><tt>GEN_ORDER: int</tt> is the order of the multiplicative subgroup generated by
<tt>Field.gen()</tt>. This is the smallest positive integer for which
<tt>Field.gen()**Field.GEN_ORDER == Field(1)</tt>.</t>
            </li>
          </ul>
          <t>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>
        </section>
        <section anchor="parameters">
          <name>Parameters</name>
          <t><xref target="fields"/> defines 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 (XOFs)</name>
        <t>VDAFs in this specification use eXtendable Output Functions (XOFs) for two
purposes:</t>
        <ol spacing="normal" type="1"><li>
            <t>Extracting short, pseudorandom strings we call "seeds" from high entropy
inputs</t>
          </li>
          <li>
            <t>Expanding seeds into long, pseudorandom outputs</t>
          </li>
        </ol>
        <t>Concrete XOFs implement a class <tt>Xof</tt> providing the following interface:</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 the
XOF from the given seed and a domain separation tag and binder string as
defined in <xref target="dst-binder"/>. The length of the seed will typically be
<tt>SEED_SIZE</tt>, but some XOFs may support multiple seed sizes. The seed <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 chunk of the output of the
initialized XOF as a byte string. The length of the chunk <bcp14>MUST</bcp14> be <tt>length</tt>.</t>
          </li>
        </ul>
        <t>The following methods are provided for all concrete XOFs. The first is a class
method used to derive a fresh seed from an existing one. The second is an
instance method used to compute a sequence of field elements. The third is a
class method that provides a one-shot interface for expanding a seed into a
field vector.</t>
        <sourcecode type="python"><![CDATA[
def derive_seed(cls,
                seed: bytes,
                dst: bytes,
                binder: bytes) -> bytes:
    """
    Derive a new seed.

    Pre-conditions:

        - `len(seed) == cls.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 a vector of `length` field elements.

    Pre-conditions:

        - `field` is sub-class of `Field`
        - `len(seed) == cls.SEED_SIZE`
        - `length > 0`
    """
    xof = cls(seed, dst, binder)
    return xof.next_vec(field, length)
]]></sourcecode>
        <section anchor="xof-turboshake128">
          <name>XofTurboShake128</name>
          <t>This section describes XofTurboShake128, an XOF based on the TurboSHAKE128
function specified in <xref target="TurboSHAKE"/>. This
XOF is <bcp14>RECOMMENDED</bcp14> for all use cases for DAFs and VDAFs.</t>
          <ul empty="true">
            <li>
              <t>TODO Update the <xref target="TurboSHAKE"/> reference to point to the RFC instead of the
draft.</t>
            </li>
          </ul>
          <t>Pre-conditions:</t>
          <ul spacing="normal">
            <li>
              <t>The default seed length is <tt>32</tt>. The seed <bcp14>MAY</bcp14> have a different length, but it
<bcp14>MUST</bcp14> not exceed 255. Otherwise initialization will raise an exception.</t>
            </li>
            <li>
              <t>The length of the domain separation string <tt>dst</tt> passed to XofTurboShake128
<bcp14>MUST NOT</bcp14> exceed 65535 bytes. Otherwise initialization will raise an
exception.</t>
            </li>
          </ul>
          <sourcecode type="python"><![CDATA[
class XofTurboShake128(Xof):
    """XOF wrapper for TurboSHAKE128."""

    # Associated parameters
    SEED_SIZE = 32

    def __init__(self, seed: bytes, dst: bytes, binder: bytes):
        self.l = 0
        self.m = \
            to_le_bytes(len(dst), 2) + dst \
            to_le_bytes(len(seed), 1) + 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>
        </section>
        <section anchor="xof-fixed-key-aes128">
          <name>XofFixedKeyAes128</name>
          <t>The XOF in the previous section can be used safely wherever a XOF is needed in
this document. However, there are some situations where TurboSHAKE128 creates a
performance bottleneck and a more efficient XOF can be used safely instead.</t>
          <t>This section describes XofFixedKeyAes128, which is used to implement the IDPF
of Poplar1 (<xref target="idpf-bbcggi21"/>). It is <bcp14>NOT RECOMMENDED</bcp14> to use this XOF for any
other purpose. See <xref target="xof-vs-ro"/> for a more detailed discussion.</t>
          <t>XofFixedKeyAes128 uses the AES-128 blockcipher <xref target="AES"/> for most of the
computation, thereby taking advantage of the hardware implementations of this
blockcipher that are widely available. AES-128 is used in a fixed-key mode of
operation; the key is derived during initialization using TurboSHAKE128.</t>
          <t>Pre-conditions:</t>
          <ul spacing="normal">
            <li>
              <t>The length of the seed <bcp14>MUST</bcp14> be <tt>16</tt>.</t>
            </li>
            <li>
              <t>The length of the domain separation string <tt>dst</tt> passed to XofFixedKeyAes128
<bcp14>MUST NOT</bcp14> exceed 65535 bytes. Otherwise initialization will raise an
exception.</t>
            </li>
          </ul>
          <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), 2)
        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="dst-binder">
          <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, derivation is 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., DAF, VDAF, or IDPF as
defined in <xref target="idpf"/>);</t>
            </li>
            <li>
              <t>A unique identifier for the algorithm (e.g., <tt>VDAF.ID</tt>); 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.

    Pre-conditions:

        - `algo_class` in the range `[0, 2^8)`
        - `algo` in the range `[0, 2^32)`
        - `usage` in the 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 general-purpose aggregation. Prio3 is
suitable for a wide variety of aggregation functions, including (but not
limited to) sum, mean, standard deviation, histograms, and linear regression.
It 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. (We specify these in full detail in
<xref target="flp-bbcggi19-valid"/>.)</t>
        </li>
        <li>
          <t>The aggregate result is obtained by summing up the encoded measurements and
computing some function of the sum.</t>
        </li>
      </ul>
      <t>Clients protect the privacy of their measurements by secret sharing them and
distributing the shares among the Aggregators. To ensure each measurement is
valid, the Aggregators run a multi-party computation on their shares, the
result of which is the output of the arithmetic circuit. This involves
verification of a "Fully Linear Proof (FLP)" (<xref target="flp"/>) generated by the Client.
FLPs are the core component of Prio3, as they specify the types of
measurements and how they are encoded, verified, and aggregated. In fact Prio3
can be thought of as a transformation of an FLP into a VDAF.</t>
      <t>Prio3 does not have an aggregation parameter. Instead, each output share is
derived from each input share by applying a fixed map. See <xref target="poplar1"/> for an
example of a VDAF that makes meaningful use of the aggregation parameter.</t>
      <t>The remainder of this section is structured as follows. The interface of 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, variants of Prio3
for various types of aggregation tasks are specified in
<xref target="prio3-instantiations"/>. Test vectors for each variant can be found in
<xref target="test-vectors"/>.</t>
      <section anchor="flp">
        <name>Fully Linear Proofs (FLPs)</name>
        <t>Conceptually, an FLP is a two-party protocol executed by a prover and a
verifier. The verifier is restricted to only access the messages it receives
from the prover via linear queries. In actual use in Prio3, 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. During preparation, each Aggregator performs some computation
on its measurement share and proof share locally, then broadcasts the result in
its prep share. The validity decision is then made by the
<tt>prep_shares_to_prep()</tt> algorithm (<xref target="sec-vdaf-prepare"/>).</t>
        <t>As usual, we describe the interface implemented by a concrete FLP in terms of
an abstract base class, denoted <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"/>. A
concrete 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 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 linear query algorithm run by the
verifier on the encoded 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 the number of shares (more on this
below).</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 algorithm outputs a
share of the verifier message (hereafter the "verifier share"). Furthermore,
the privacy property of the FLP system ensures that the verifier message
reveals nothing about the measurement other than the fact that it is valid.
Therefore, to decide if a measurement is valid, the Aggregators will run the
query algorithm locally, exchange verifier shares, combine them to recover the
verifier message, and run the decision algorithm.</t>
        <t>The query algorithm includes a parameter <tt>num_shares</tt> that specifies the number
of shares of the measurement and proof that were generated. If these data are
not secret shared, then <tt>num_shares == 1</tt>. This parameter is useful for
normalizing constants in arithmetic circuits so that each Aggregator properly
computes a secret share of the circuit's output. See <xref target="flp-bbcggi19"/> for
details.</t>
        <t>An FLP is executed by the prover and verifier as follows:</t>
        <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>
        <t>The proof system is designed so that, if <tt>meas</tt> is valid, then <tt>run_flp(flp,
meas, num_shares)</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 the VDAF
that uses it. In particular, soundness of the FLP is necessary, but
insufficient for robustness of Prio3 (<xref target="prio3"/>). See <xref target="security-multiproof"/>
for details.</t>
        <t>We remark that <xref target="BBCGGI19"/> defines a 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>
        <table anchor="flp-param">
          <name>FLP parameters.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>PROVE_RAND_LEN: int</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: int</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: int</tt></td>
              <td align="left">Length of the joint randomness, the number of random field elements shared by the prover and verifier.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>MEAS_LEN: int</tt></td>
              <td align="left">Length of the encoded measurement (<xref target="flp-encode"/>).</td>
            </tr>
            <tr>
              <td align="left">
                <tt>OUTPUT_LEN: int</tt></td>
              <td align="left">Length of the aggregatable output (<xref target="flp-encode"/>).</td>
            </tr>
            <tr>
              <td align="left">
                <tt>PROOF_LEN: int</tt></td>
              <td align="left">Length of the proof.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VERIFIER_LEN: int</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: type[F]</tt></td>
              <td align="left">Class object for the field (<xref target="field"/>).</td>
            </tr>
          </tbody>
        </table>
        <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.  </t>
              <t>
Post-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The encoded measurement <bcp14>MUST</bcp14> have length <tt>flp.MEAS_LEN</tt>.</t>
                </li>
              </ul>
            </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 <tt>Sum</tt> type defined in <xref target="prio3sum"/>
for which each measurement is an integer in the range <tt>[0, max_measurement]</tt>.
The range check requires encoding the measurement with several field elements,
though just one is needed for aggregation. Thus the FLP defines an algorithm
for truncating the encoded measurement to the length of the aggregatable 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).  </t>
              <t>
Pre-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The length of the input <bcp14>MUST</bcp14> be <tt>flp.MEAS_LEN</tt></t>
                </li>
              </ul>
              <t>
Post-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The length of the output <bcp14>MUST</bcp14> be <tt>flp.OUTPUT_LEN</tt>.</t>
                </li>
              </ul>
            </li>
          </ul>
          <t>Once the aggregate shares have been transmitted to the Collector, 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.
Either way, this functionality is implemented by the following method:</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 the output <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 were
aggregated.</t>
                </li>
              </ul>
            </li>
          </ul>
          <t>We remark that, taken together, these three functionalities correspond 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)
without sacrificing soundness. This is useful because it reduces the overall
communication of the protocol. (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 fresh prover and joint
randomness. The verifier checks each proof independently, each time with fresh
query randomness. It accepts the measurement only if the decision algorithm
accepts on each proof.</t>
          <t>See <xref target="security-multiproof"/> for guidance on choosing the field size and number
of proofs.</t>
        </section>
      </section>
      <section anchor="prio3-construction">
        <name>Specification</name>
        <t>This section specifies <tt>Prio3</tt>, an implementation of the <tt>Vdaf</tt> interface
defined in <xref target="vdaf"/>. The parameters 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>Parameters for Prio3.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>flp</tt></td>
              <td align="left">An instance of <tt>Flp</tt> (<xref target="flp"/>).</td>
            </tr>
            <tr>
              <td align="left">
                <tt>xof</tt></td>
              <td align="left">
                <tt>XofTurboShake128</tt> (<xref target="xof-turboshake128"/>)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>PROOFS</tt></td>
              <td align="left">Any <tt>int</tt> in the range <tt>[1, 256)</tt>.</td>
            </tr>
            <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 * SHARES if flp.JOINT_RAND_LEN == 0 else 2 * xof.SEED_SIZE * 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">Any <tt>int</tt> in the range <tt>[2, 256)</tt>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">As defined by <tt>flp</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, 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">As defined by <tt>flp</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 as specified by 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>Generate the proof using the derived joint randomness</t>
            </li>
            <li>
              <t>Shard the proof into a sequence of proof shares</t>
            </li>
          </ol>
          <t>As described in <xref target="multiproofs"/>, robustness of Prio3 can be amplified by
generating and verifying multiple proofs. To support this:</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).</t>
          <t>The sharding algorithm is specified below:</t>
          <sourcecode type="python"><![CDATA[
def shard(
        self,
        ctx: bytes,
        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(ctx, meas, nonce, seeds)
    else:
        return self.shard_without_joint_rand(ctx, meas, seeds)
]]></sourcecode>
          <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="prio3-shard-without-joint-rand">
            <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>. It consists of the following steps:</t>
            <ol spacing="normal" type="1"><li>
                <t>Shard the encoded measurement into shares</t>
              </li>
              <li>
                <t>Generate proofs and shard each into shares</t>
              </li>
              <li>
                <t>Encode each measurement share and shares of each proof into an input share</t>
              </li>
            </ol>
            <t>Only one pair of measurement and proof(s) share (called the "Leader" shares)
are vectors of field elements. The other shares (called the "Helper"
shares) are represented instead by an XOF seed, which is expanded into vectors
of field elements. The methods on <tt>Prio3</tt> for deriving the prover randomness,
measurement shares, and proof shares are defined in <xref target="prio3-auxiliary"/>.</t>
            <sourcecode type="python"><![CDATA[
def shard_without_joint_rand(
        self,
        ctx: bytes,
        meas: list[F],
        seeds: list[bytes]) -> tuple[
            Optional[list[bytes]],
            list[Prio3InputShare[F]]]:
    helper_shares, seeds = front(self.SHARES - 1, seeds)
    (prove_seed,), 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(ctx, j + 1, helper_shares[j]),
        )

    # Generate and shard each proof into shares.
    prove_rands = self.prove_rands(ctx, prove_seed)
    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(
                ctx,
                j + 1,
                helper_shares[j],
            ),
        )

    # Each Aggregator's input share contains its measurement share
    # and its share of the 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((
            helper_shares[j],
            None,
        ))
    return (None, input_shares)
]]></sourcecode>
          </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>. Joint randomness derivation involves an
additional XOF seed for each Aggregator called the "blind". The 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 save a round of communication between the Aggregators later, the
Client encodes the joint randomness parts in the public share. (See
<xref target="prio3-preparation"/> for details.)</t>
            <t>All functions used in the following listing are defined in <xref target="prio3-auxiliary"/>:</t>
            <sourcecode type="python"><![CDATA[
def shard_with_joint_rand(
        self,
        ctx: bytes,
        meas: list[F],
        nonce: bytes,
        seeds: list[bytes]) -> tuple[
            Optional[list[bytes]],
            list[Prio3InputShare[F]]]:
    helper_seeds, seeds = front((self.SHARES - 1) * 2, seeds)
    helper_shares = [
        helper_seeds[i]
        for i in range(0, (self.SHARES - 1) * 2, 2)
    ]
    helper_blinds = [
        helper_seeds[i]
        for i in range(1, (self.SHARES - 1) * 2, 2)
    ]
    (leader_blind, prove_seed), seeds = front(2, seeds)

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

    # Generate each proof and shard it into proof shares.
    prove_rands = self.prove_rands(ctx, prove_seed)
    joint_rands = self.joint_rands(
        ctx, self.joint_rand_seed(ctx, 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(
                ctx,
                j + 1,
                helper_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,
        leader_blind,
    ))
    for j in range(self.SHARES - 1):
        input_shares.append((
            helper_shares[j],
            helper_blinds[j],
        ))
    return (joint_rand_parts, input_shares)
]]></sourcecode>
          </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 share and proof(s) share(s) locally, then broadcasts its verifier
share(s) in its prep share. The shares of verifier(s) are then combined into
the verifier message(s) used to decide whether to accept.</t>
          <t>In addition, the Aggregators must recompute the same joint randomness used by
the Client to generate the proof(s). In order to avoid an extra round of
communication, the Client includes the joint randomness parts in the public
share. 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 prep 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 measurement share, then
truncate the measurement share to get the output share.</t>
          <t>All functions used in the following listing are defined in <xref target="prio3-auxiliary"/>:</t>
          <sourcecode type="python"><![CDATA[
def prep_init(
        self,
        verify_key: bytes,
        ctx: bytes,
        agg_id: int,
        _agg_param: None,
        nonce: bytes,
        public_share: Optional[list[bytes]],
        input_share: Prio3InputShare[F]) -> tuple[
            Prio3PrepState[F],
            Prio3PrepShare[F]]:
    joint_rand_parts = public_share
    (meas_share, proofs_share, blind) = \
        self.expand_input_share(ctx, agg_id, input_share)
    out_share = self.flp.truncate(meas_share)

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

    # Query the measurement and proof(s) share(s).
    query_rands = self.query_rands(verify_key, ctx, 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, corrected_joint_rand_seed)
    prep_share = (verifiers_share, joint_rand_part)
    return (prep_state, prep_share)

def prep_shares_to_prep(
        self,
        ctx: bytes,
        _agg_param: None,
        prep_shares: list[Prio3PrepShare[F]]) -> Optional[bytes]:
    # Unshard each set of verifier shares into each verifier message.
    verifiers = self.flp.field.zeros(
        self.flp.VERIFIER_LEN * self.PROOFS)
    joint_rand_parts = []
    for (verifiers_share, joint_rand_part) in prep_shares:
        verifiers = vec_add(verifiers, verifiers_share)
        if self.flp.JOINT_RAND_LEN > 0:
            assert joint_rand_part is not None
            joint_rand_parts.append(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.
    joint_rand_seed = None
    if self.flp.JOINT_RAND_LEN > 0:
        joint_rand_seed = self.joint_rand_seed(ctx, joint_rand_parts)
    return joint_rand_seed

def prep_next(
    self,
    _ctx: bytes,
    prep_state: Prio3PrepState[F],
    prep_msg: Optional[bytes]
) -> tuple[Prio3PrepState[F], Prio3PrepShare[F]] | list[F]:
    joint_rand_seed = prep_msg
    (out_share, corrected_joint_rand_seed) = prep_state

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

    return out_share
]]></sourcecode>
        </section>
        <section anchor="validity-of-aggregation-parameters">
          <name>Validity of Aggregation Parameters</name>
          <t><tt>Prio3</tt> only permits a report to be aggregated once.</t>
          <sourcecode type="python"><![CDATA[
def is_valid(
        self,
        _agg_param: None,
        previous_agg_params: list[None]) -> bool:
    return len(previous_agg_params) == 0
]]></sourcecode>
        </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>
          <sourcecode type="python"><![CDATA[
def agg_init(self, _agg_param: None) -> list[F]:
    return self.flp.field.zeros(self.flp.OUTPUT_LEN)

def agg_update(self,
               _agg_param: None,
               agg_share: list[F],
               out_share: list[F]) -> list[F]:
    return vec_add(agg_share, out_share)

def merge(self,
          _agg_param: None,
          agg_shares: list[list[F]]) -> list[F]:
    agg = self.agg_init(None)
    for agg_share in agg_shares:
        agg = vec_add(agg, agg_share)
    return agg
]]></sourcecode>
        </section>
        <section anchor="unsharding">
          <name>Unsharding</name>
          <t>To unshard a set of aggregate shares, the Collector first adds up the vectors
element-wise, then decodes the aggregate result from the sum according to the
FLP (<xref target="flp-encode"/>).</t>
          <sourcecode type="python"><![CDATA[
def unshard(
        self,
        _agg_param: None,
        agg_shares: list[list[F]],
        num_measurements: int) -> AggResult:
    agg = self.merge(None, agg_shares)
    return self.flp.decode(agg, num_measurements)
]]></sourcecode>
        </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>
          <sourcecode type="python"><![CDATA[
def helper_meas_share(
        self,
        ctx: bytes,
        agg_id: int,
        share: bytes) -> list[F]:
    return self.xof.expand_into_vec(
        self.flp.field,
        share,
        self.domain_separation_tag(USAGE_MEAS_SHARE, ctx),
        byte(agg_id),
        self.flp.MEAS_LEN,
    )

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

def expand_input_share(
        self,
        ctx: bytes,
        agg_id: int,
        input_share: Prio3InputShare[F]) -> tuple[
            list[F],
            list[F],
            Optional[bytes]]:
    if agg_id > 0:
        assert len(input_share) == 2
        (share, blind) = input_share
        meas_share = self.helper_meas_share(ctx, agg_id, share)
        proofs_share = self.helper_proofs_share(ctx, agg_id, share)
    else:
        assert len(input_share) == 3
        (meas_share, proofs_share, blind) = input_share
    return (meas_share, proofs_share, blind)

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

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

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

def joint_rand_seed(self,
                    ctx: bytes,
                    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, ctx),
        concat(joint_rand_parts),
    )

def joint_rands(self,
                ctx: bytes,
                joint_rand_seed: bytes) -> list[F]:
    """Derive the joint randomness from its seed."""
    return self.xof.expand_into_vec(
        self.flp.field,
        joint_rand_seed,
        self.domain_separation_tag(USAGE_JOINT_RANDOMNESS, ctx),
        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. Messages are defined in the presentation
language of TLS as defined in <xref section="3" sectionFormat="of" target="RFC8446"/>.</t>
          <t>Let <tt>prio3</tt> denote an instance of <tt>Prio3</tt>. 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 contents of the public share depend 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.
Otherwise, if joint randomness is used, then the public share encodes the joint
randomness parts as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Seed 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 content 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 share and proofs(s) share(s). Otherwise, if the
aggregator ID is greater than <tt>0</tt>, then the measurement and shares of proof(s)
are represented by an XOF seed. 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 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 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 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 * V];
} Prio3PrepShare;
]]></sourcecode>
            <t>where <tt>V = prio3.flp.VERIFIER_LEN * prio3.PROOFS</tt>. 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 * V];
    Prio3Seed 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 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>FLP Specification</name>
        <t>This section specifies an implementation of the <tt>Flp</tt> interface (<xref target="flp"/>) based
on the construction from <xref target="BBCGGI19"/>, Section 4.2. The types and parameters
required by this interface are listed in the table below.</t>
        <t>We begin in <xref target="flp-bbcggi19-overview"/> with an overview of the proof system and
some extensions to it. <xref target="flp-bbcggi19-valid"/> defines validity circuits, the
core component of the proof system that determines measurement validity and how
measurements are aggregated. The proof-generation algorithm, query algorithm,
and decision algorithm are defined in <xref target="flp-bbcggi19-construction-prove"/>,
<xref target="flp-bbcggi19-construction-query"/>, and <xref target="flp-bbcggi19-construction-decide"/>
respectively.</t>
        <table anchor="flp-bbcggi19-param">
          <name>FLP parameters for a validity circuit.</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">An instance of <tt>Valid</tt> (<xref target="flp-bbcggi19-valid"/>).</td>
            </tr>
            <tr>
              <td align="left">
                <tt>field</tt></td>
              <td align="left">
                <tt>valid.field</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PROVE_RAND_LEN</tt></td>
              <td align="left">
                <tt>valid.prove_rand_len()</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>QUERY_RAND_LEN</tt></td>
              <td align="left">
                <tt>valid.query_rand_len()</tt></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></td>
            </tr>
            <tr>
              <td align="left">
                <tt>VERIFIER_LEN</tt></td>
              <td align="left">
                <tt>valid.verifier_len()</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">As defined by <tt>valid</tt>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">As defined by <tt>valid</tt>.</td>
            </tr>
          </tbody>
        </table>
        <section anchor="flp-bbcggi19-overview">
          <name>Overview</name>
          <t>An FLP is a type of "zero-knowledge proof". A conventional zero-knowledge proof
system involves 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 a
commitment to 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</tt> is in the range
<tt>[0, 2)</tt>.</t>
          <t>The goal of the proof system is to allow each Aggregator to privately and
correctly compute a share of <tt>C(x)</tt> from its share of <tt>x</tt>. Then all they need
to do to determine validity is to broadcast their shares of <tt>C(x)</tt>.</t>
          <t>Suppose for a moment that <tt>C</tt> is an affine arithmetic circuit, 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
arithmetic 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 then sends shares of <tt>x</tt> and
shares of 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
arithmetic operations. We refer to this sub-circuit as the "gadget".</t>
          <t>Finally, the proof system has one more important component. 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-prove"/>.</t>
          <section anchor="flp-bbcggi19-overview-extensions">
            <name>Extensions</name>
            <t>The FLP described in <xref target="flp-bbcggi19"/> 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
the range <tt>[0, 2)</tt>, then the circuit will evaluate to zero regardless of the
value of <tt>r</tt>; but if some <tt>x[j]</tt> is not in the range <tt>[0, 2)</tt>, then the output
will be non-zero with high probability.</t>
            <t>The second extension implemented by our FLP allows the validity circuit to
contain multiple gadget types. (This generalization was suggested in
<xref target="BBCGGI19"/>, Remark 4.5.) This provides additional flexibility for designing
circuits by allowing multiple, non-affine sub-circuits. For example, the
following circuit is allowed:</t>
            <artwork><![CDATA[
C(x, r) = r * Range2(x[0]) + ... + r^L * Range2(x[L-1]) + \
            r^(L+1) * Range3(x[L]) + ... + r^N * Range3(x[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 the range <tt>[0, 2)</tt> and the last <tt>N-L</tt> inputs are in the 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 roots 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. Note that the roots of unity are powers of the generator for the
NTT-friendly field (see <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>An instance of the proof system is defined in terms of a validity circuit that
implements the <tt>Valid</tt> interface specified in this section. The parameters are
listed in the table below.</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: list[Gadget]</tt></td>
                <td align="left">A list of gadgets.</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS: list[int]</tt></td>
                <td align="left">Number of times each gadget is called.</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>MEAS_LEN: int</tt></td>
                <td align="left">Length of the measurement.</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN: int</tt></td>
                <td align="left">Length of the joint randomness.</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>EVAL_OUTPUT_LEN: int</tt></td>
                <td align="left">Length of the circuit output.</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN: int</tt></td>
                <td align="left">Length of the aggregatable output.</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: type[F]</tt></td>
                <td align="left">Class object for the field (<xref target="field-ntt-friendly"/>)</td>
              </tr>
            </tbody>
          </table>
          <t>The circuit is invoked with the following method:</t>
          <ul spacing="normal">
            <li>
              <t><tt>valid.eval(meas: list[F], joint_rand: list[F], num_shares: int) -&gt; list[F]</tt>
evaluates the arithmetic circuit on a measurement and joint randomness. The
output is a list of field elements: if every element is equal to
<tt>valid.field(0)</tt>, then the circuit is said to "accept" the measurement;
otherwise, if any element is not equal to <tt>valid.field(0)</tt>, then the circuit
is said to "reject" the measurement.  </t>
              <t>
This method can also be called on a secret share of the measurement, in which
case it produces a secret share of the output.  </t>
              <t>
The circuit must be composed of affine gates and gadget calls, so that the
verifier may check the prover's proof and circuit evaluation using linear
queries. This means that all non-affine multiplications in the circuit must
be encapsulated in gadget calls. Additions of constants must be rescaled by
the inverse of <tt>num_shares</tt>.  </t>
              <t>
Pre-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The length of <tt>meas</tt> <bcp14>MUST</bcp14> be <tt>valid.MEAS_LEN</tt>.</t>
                </li>
                <li>
                  <t>The length of <tt>joint_rand</tt> <bcp14>MUST</bcp14> be <tt>valid.JOINT_RAND_LEN</tt>.</t>
                </li>
                <li>
                  <t><tt>num_shares</tt> <bcp14>MUST</bcp14> be the number of secret shares of <tt>meas</tt>, or <tt>1</tt> if
<tt>meas</tt> is not secret shared.</t>
                </li>
              </ul>
              <t>
Post-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The length of the output <bcp14>MUST</bcp14> be <tt>valid.EVAL_OUTPUT_LEN</tt>.</t>
                </li>
              </ul>
            </li>
          </ul>
          <t>Each circuit has a list of gadgets, denoted <tt>GADGETS</tt>, that are invoked by
<tt>valid.eval()</tt>. The circuit evaluated by the gadget should be non-affine, and <bcp14>MUST</bcp14>
be arithmetic, i.e., composed only of multiplication, addition, and subtraction
gates. An instance of class <tt>Gadget</tt> has the following interface:</t>
          <ul spacing="normal">
            <li>
              <t><tt>ARITY: int</tt> is the number of input wires. For example, the multiplication
gadget <tt>Mul(x,y) = x*y</tt> has arity of 2.</t>
            </li>
            <li>
              <t><tt>DEGREE: int</tt> is the arithmetic degree of the gadget circuit. This is defined
to be the degree of the polynomial that computes it. This exists
because the circuit is arithmetic. For example, <tt>Mul</tt> has degree 2.</t>
            </li>
            <li>
              <t><tt>gadget.eval(field: type[F], inp: list[F]) -&gt; F</tt> evaluates the gadget over
the given inputs and field.</t>
            </li>
            <li>
              <t><tt>gadget.eval_poly(field: type[F], inp_poly: list[list[F]]) -&gt; list[F]</tt> is the
same as <tt>gadget.eval()</tt> except it evaluates the circuit over the polynomial
ring of the field. This is well defined because the circuit is arithmetic.</t>
            </li>
          </ul>
          <t>In addition to the list of gadgets, the validity circuit specifies how many
times each gadget is called (<tt>GADGET_CALLS</tt>). The circuit needs to define an
ordering of the calls it makes to each gadget, so that all parties agree on how
to identify recorded wire values. It also specifies the length of the circuit's
input (<tt>MEAS_LEN</tt>), the length of the joint randomness (<tt>JOINT_RAND_LEN</tt>), and
the length of the circuit's output (<tt>EVAL_OUTPUT_LEN</tt>).</t>
          <t>A validity circuit also specifies parameters and methods needed for Prio3
aggregation. These are used to implement the interface in <xref target="flp-encode"/>:</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 of type <tt>Measurement</tt>.</t>
            </li>
            <li>
              <t><tt>valid.truncate(meas: list[F]) -&gt; list[F]</tt> returns a vector of length
<tt>OUTPUT_LEN</tt> representing (a share of) an aggregatable output.</t>
            </li>
            <li>
              <t><tt>valid.decode(agg: list[F], num_measurements: int) -&gt; AggResult</tt> returns an
aggregate result of type <tt>AggResult</tt>. This computation may depend on the
number of outputs aggregated.</t>
            </li>
          </ul>
          <t>Finally, the following are helper methods used to instantiate parameters of the
<tt>Flp</tt> interface (<xref target="flp"/>):</t>
          <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 += self.EVAL_OUTPUT_LEN
    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
]]></sourcecode>
        </section>
        <section anchor="flp-bbcggi19-construction-prove">
          <name>Generating the Proof</name>
          <figure>
            <name>Components of the proof generation algorithm.</name>
            <artwork><![CDATA[
+------------------+
| Prove            |
| +-------------+  |
| | Valid       |<---- meas
| | +--------+  |<---- joint rand
| | | Gadget |  |  |<- prove rand
| | +--------+  |  |
| +-------------+  |
+------------------+
 |
 V proof
]]></artwork>
          </figure>
          <t>The proof generation algorithm invokes the validity circuit on the encoded
measurement and joint randomness. The validity circuit in turn invokes the
gadgets defined by the circuit. The prove randomness is used to construct the
gadget polynomials that the verifier will use to compute the outputs of each
gadget.</t>
          <t>To generate the gadget polynomials, the prover evaluates the validity circuit,
and records the values on each input wire of each call to each gadget. This is
accomplished by "wrapping" each gadget in a class <tt>ProveGadget</tt> that records
the wire inputs. We list this class in <xref target="gadget-wrappers"/>. We denote the value
of the <tt>j</tt>-th wire for the <tt>k</tt>-th invocation of gadget <tt>g</tt> as <tt>g.wires[j][k]</tt>.</t>
          <t>Next, we compute each of the "wire polynomials" for each gadget. The <tt>j</tt>-th
wire polynomial is the lowest degree polynomial that evaluates to
<tt>g.wire[j][k]</tt> at a sequence of fixed points. We obtain the gadget polynomial by
evaluating the gadget on the wire polynomials.</t>
          <sourcecode type="python"><![CDATA[
def prove(self,
          meas: list[F],
          prove_rand: list[F],
          joint_rand: list[F]) -> list[F]:
    # Evaluate the validity circuit, recording the value of each
    # input wire for each evaluation of each gadget.
    valid = ProveGadget.wrap(self.valid, prove_rand)
    valid.eval(meas, joint_rand, 1)

    # Construct the proof, which consists of the wire seeds and
    # gadget polynomial for each gadget.
    proof = []
    for g in cast(list[ProveGadget[F]], valid.GADGETS):
        p = len(g.wires[0])

        # Compute the wire polynomials for this gadget. For each `j`,
        # find the lowest degree polynomial `wire_poly` for which
        # `wire_poly(alpha^k) = g.wires[j][k]` for all `k`. Note that
        # each `g.wires[j][0]` is set to the seed of wire `j`, which
        # is included in the prove randomness.
        #
        # Implementation note: `alpha` is a root of unity, which
        # means `poly_interp()` can be evaluated using the NTT. Note
        # that `g.wires[j]` is padded with 0s to a power of 2.
        alpha = self.field.gen() ** (self.field.GEN_ORDER // p)
        wire_inp = [alpha ** k for k in range(p)]
        wire_polys = []
        for j in range(g.ARITY):
            wire_poly = poly_interp(self.field, wire_inp, g.wires[j])
            wire_polys.append(wire_poly)

        # Compute the gadget polynomial by evaluating the gadget on
        # the wire polynomials. By construction we have that
        # `gadget_poly(alpha^k)` is the `k`-th output.
        gadget_poly = g.eval_poly(self.field, wire_polys)

        for j in range(g.ARITY):
            proof.append(g.wires[j][0])
        proof += gadget_poly

    return proof
]]></sourcecode>
        </section>
        <section anchor="flp-bbcggi19-construction-query">
          <name>Querying the Proof</name>
          <figure>
            <name>Components of the query algorithm.</name>
            <artwork><![CDATA[
      proof (share)
+---------|--------+
| Query   |        |
| +-------|-----+  |
| | Valid |     |<---- meas (share)
| | +-----V--+  |<---- joint rand
| | | Gadget |  |  |<- query rand
| | +--------+  |  |
| +-------------+  |
+------------------+
 |
 V verifier (share)
]]></artwork>
          </figure>
          <t>The query algorithm invokes the validity circuit on the encoded measurement and
joint randomness. It evaluates the gadget polynomials 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 gadget tests consume the query randomness.</t>
          <t>The goal of each gadget test is to ensure the inputs used by the prover to
generate the gadget polynomial match the inputs we used to evaluate it. We do
this by partially reconstructing the gadget polynomial and evaluating it at a random
point: when we evaluate the gadget polynomial at the same point, we expect to
get the same result.</t>
          <t>To start a gadget test, we first construct the (shares of the) wire polynomials
just as the prover did. First, we record the input (share) of the <tt>j</tt>-th wire
of the <tt>k</tt>-th invocation of the gadget as <tt>g.wires[j][k]</tt>. Again, this is
accomplished by a wrapper gadget, <tt>QueryGadget</tt>, listed in <xref target="gadget-wrappers"/>.
This gadget also evaluates the gadget polynomial for each gadget invocation in
order to produce the gadget's output. Then we compute the wire polynomials from
the recorded values.</t>
          <t>Next, we choose a random point <tt>t</tt> (parsed from the query randomness), evaluate
each wire polynomial at <tt>t</tt>, and evaluate the gadget polynomial at <tt>t</tt>. The
results are recorded in the verifier message passed to the decision algorithm,
where we finish the test.</t>
          <t>The random point <tt>t</tt> <bcp14>MUST NOT</bcp14> be one of the fixed evaluation points used to
interpolate the wire polynomials. Otherwise, the verifier message may partially
leak the encoded measurement.</t>
          <sourcecode type="python"><![CDATA[
def query(self,
          meas: list[F],
          proof: list[F],
          query_rand: list[F],
          joint_rand: list[F],
          num_shares: int) -> list[F]:
    # Evaluate the validity circuit, recording the value of each
    # input wire for each evaluation of each gadget. Use the gadget
    # polynomials encoded by `proof` to compute the gadget outputs.
    valid = QueryGadget.wrap(self.valid, proof)
    out = valid.eval(meas, joint_rand, num_shares)

    # Reduce the output.
    if self.valid.EVAL_OUTPUT_LEN > 1:
        (rand, query_rand) = front(
            self.valid.EVAL_OUTPUT_LEN,
            query_rand,
        )
        v = self.field(0)
        for (r, out_elem) in zip(rand, out):
            v += r * out_elem
    else:
        [v] = out

    # Construct the verifier message, which consists of the reduced
    # circuit output and each gadget test.
    verifier = [v]
    for (g, t) in zip(cast(list[QueryGadget[F]], valid.GADGETS),
                      query_rand):
        p = len(g.wires[0])

        # Abort if `t` is one of the inputs used to compute the wire
        # polynomials so that the verifier message doesn't leak the
        # gadget output. It suffices to check if `t` is a root of
        # unity, which implies it is a power of `alpha`.
        if t ** p == self.field(1):
            raise ValueError('test point is a root of unity')

        # To test the gadget, we re-compute the wire polynomials and
        # check for consistency with the gadget polynomial provided
        # by the prover. To start, evaluate the gadget polynomial and
        # each of the wire polynomials at the random point `t`.
        wire_checks = []
        wire_inp = [g.alpha ** k for k in range(p)]
        for j in range(g.ARITY):
            wire_poly = poly_interp(self.field, wire_inp, g.wires[j])
            wire_checks.append(poly_eval(self.field, wire_poly, t))

        gadget_check = poly_eval(self.field, g.poly, t)

        verifier += wire_checks
        verifier.append(gadget_check)

    return verifier
]]></sourcecode>
        </section>
        <section anchor="flp-bbcggi19-construction-decide">
          <name>Deciding Validity</name>
          <figure>
            <name>Components of the decision algorithm.</name>
            <artwork><![CDATA[
 | verifier
 V
+------------------+
| Decide           |
+------------------+
 |
 V is_valid
]]></artwork>
          </figure>
          <t>The decision algorithm consumes the verifier message. (Each of the Aggregators
computes an additive share of the verifier message after the previous step.) The
verifier message consists of the reduced circuit output and the gadget tests.</t>
          <t>To finish each gadget test, we evaluate the gadget on the wire checks: if the
encoded measurement and joint randomness used to generate the proof are the
same as the measurement (share) and joint randomness used to verify the proof,
then the output of the gadget will be equal to the gadget check; otherwise, the
output will not equal the gadget check with high probability.</t>
          <sourcecode type="python"><![CDATA[
def decide(self, verifier: list[F]) -> bool:
    # Check the output of the validity circuit.
    ([v], verifier) = front(1, verifier)
    if v != self.field(0):
        return False

    # Complete each gadget test.
    for g in self.valid.GADGETS:
        (wire_checks, verifier) = front(g.ARITY, verifier)
        ([gadget_check], verifier) = front(1, verifier)
        if g.eval(self.field, wire_checks) != gadget_check:
            return False

    return True
]]></sourcecode>
        </section>
      </section>
      <section anchor="prio3-instantiations">
        <name>Variants</name>
        <t>This section specifies instantiations of Prio3 for various aggregation tasks.
Each variant is determined by a field (<xref target="field"/>), a validity circuit
(<xref target="flp-bbcggi19-valid"/>),and the number of proofs to generate and verify. All
gadgets are listed in <xref target="gadgets"/>. 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>field</tt></td>
                <td align="left">
                  <tt>Field64</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Valid</tt></td>
                <td align="left">
                  <tt>Count(field)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
            </tbody>
          </table>
          <t>Our first variant of Prio3 is for a simple counter: each measurement is either
one or zero and the aggregate result is the sum of the measurements. Its
validity circuit uses the multiplication gadget <tt>Mul</tt> specified in
<xref target="gadget-mul"/>, which takes two inputs and multiplies them. The circuit is
specified below:</t>
          <sourcecode type="python"><![CDATA[
class Count(Valid[int, int, F]):
    GADGETS: list[Gadget[F]] = [Mul()]
    GADGET_CALLS = [1]
    MEAS_LEN = 1
    JOINT_RAND_LEN = 0
    OUTPUT_LEN = 1
    EVAL_OUTPUT_LEN = 1

    # Class object for the field.
    field: type[F]

    def __init__(self, field: type[F]):
        self.field = field

    def encode(self, measurement: int) -> list[F]:
        return [self.field(measurement)]

    def eval(
            self,
            meas: list[F],
            joint_rand: list[F],
            _num_shares: int) -> list[F]:
        squared = self.GADGETS[0].eval(self.field,
                                       [meas[0], meas[0]])
        return [squared - meas[0]]

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

    def decode(self, output: list[F], _num_measurements: int) -> int:
        return output[0].int()
]]></sourcecode>
        </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>field</tt></td>
                <td align="left">
                  <tt>Field64</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Valid</tt></td>
                <td align="left">
                  <tt>Sum(field, max_measurement)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
            </tbody>
          </table>
          <t>The next variant of Prio3 supports summing of integers in a pre-determined
range. Each measurement is an integer in the range <tt>[0, max_measurement]</tt>,
where <tt>max_measurement</tt> defines the largest valid measurement.</t>
          <t>The range check is accomplished by encoding the measurement as a bit vector,
encoding the measurement plus an offset as a bit vector, then checking that the
two encoded integers are consistent. Let</t>
          <ul spacing="normal">
            <li>
              <t><tt>bits = max_measurement.bit_length()</tt>, the number of bits needed to encode
the largest valid measurement</t>
            </li>
            <li>
              <t><tt>offset = 2^bits - 1 - max_measurement</tt></t>
            </li>
          </ul>
          <t>The first bit-encoded integer is the measurement itself. Note that only
measurements between <tt>0</tt> and <tt>2^bits - 1</tt> can be encoded this way with as many
bits. The second bit-encoded integer is the sum of the measurement and
<tt>offset</tt>. Observe that this sum can only be encoded this way if it is between
<tt>0</tt> and <tt>2^bits - 1</tt>, which implies that the measurement is between <tt>-offset</tt>
and <tt>max_measurement</tt>.</t>
          <t>The circuit first checks that each entry of both bit vectors is a one or a
zero. It then decodes both the measurement and the offset measurement, and
subtracts the offset from the latter. It then checks if these two values are
equal. Since both the measurement and the measurement plus <tt>offset</tt> are in the
same range of <tt>[0, 2^bits)</tt>, this means that the measurement itself is between
<tt>0</tt> and <tt>max_measurement</tt>.</t>
          <t>The circuit uses the polynomial-evaluation gadget <tt>PolyEval</tt> specified in
<xref target="gadget-poly-eval"/>. The polynomial is <tt>p(x) = x^2 - x</tt>, which is equal to <tt>0</tt>
if and only if <tt>x</tt> is in the range <tt>[0, 2)</tt>. The complete circuit is specified
below:</t>
          <t>Note that decoding a sequence of bits into an integer is a linear operation,
specifically, a linear combination with a sequence of powers of two, so it can
be done within a validity circuit using "free" affine gates. Furthermore,
decoding secret shares of a bit-encoded integer will produce secret shares of
the original integer.</t>
          <artwork><![CDATA[
class Sum(Valid[int, int, F]):
    GADGETS: list[Gadget[F]] = [PolyEval([0, -1, 1])]
    JOINT_RAND_LEN = 0
    OUTPUT_LEN = 1
    field: type[F]

    def __init__(self, field: type[F], max_measurement: int):
        self.field = field
        self.bits = max_measurement.bit_length()
        self.offset = self.field(2**self.bits - 1 - max_measurement)
        self.max_measurement = max_measurement
        self.GADGET_CALLS = [2 * self.bits]
        self.MEAS_LEN = 2 * self.bits
        self.EVAL_OUTPUT_LEN = 2 * self.bits + 1

    def encode(self, measurement: int) -> list[F]:
        encoded = []
        encoded += self.field.encode_into_bit_vec(
            measurement,
            self.bits
        )
        encoded += self.field.encode_into_bit_vec(
            measurement + self.offset.int(),
            self.bits
        )
        return encoded

    def eval(
            self,
            meas: list[F],
            joint_rand: list[F],
            num_shares: int) -> list[F]:
        shares_inv = self.field(num_shares).inv()

        out = []
        for b in meas:
            out.append(self.GADGETS[0].eval(self.field, [b]))

        range_check = self.offset * shares_inv + \
            self.field.decode_from_bit_vec(meas[:self.bits]) - \
            self.field.decode_from_bit_vec(meas[self.bits:])
        out.append(range_check)
        return out

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

    def decode(self, output: list[F], _num_measurements: int) -> int:
        return output[0].int()
]]></artwork>
        </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>field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Valid</tt></td>
                <td align="left">
                  <tt>SumVec(field, length, bits, chunk_length)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
            </tbody>
          </table>
          <t>This instance of Prio3 supports summing vectors 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 circuit is denoted <tt>SumVec</tt>. Each measurement is encoded as a vector of
field elements with a length of <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>
          <t>The validity circuit uses the <tt>ParallelSum</tt> gadget in <xref target="gadget-parallel-sum"/>.
This gadget applies an arithmetic subcircuit to multiple inputs in parallel,
then sums the results. Along with the subcircuit, the
parallel-sum gadget is parameterized by an integer, denoted <tt>count</tt>, specifying
how many times to call the 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.</t>
          <t>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> gadget as an implementation of the <tt>Gadget</tt> interface.</t>
          <t>The <tt>SumVec</tt> validity circuit checks that the encoded measurement consists of
ones and zeros. Rather than use the <tt>PolyEval</tt> gadget on each element, as in
the <tt>Sum</tt> validity circuit, it instead uses <tt>Mul</tt> subcircuits (<xref target="gadget-mul"/>)
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 one of the elements of the joint randomness
vector, 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>
          <t>The complete circuit is specified below:</t>
          <sourcecode type="python"><![CDATA[
class SumVec(Valid[list[int], list[int], F]):
    EVAL_OUTPUT_LEN = 1
    length: int
    bits: int
    chunk_length: int
    field: type[F]

    def __init__(self,
                 field: type[F],
                 length: int,
                 bits: int,
                 chunk_length: int):
        """
        Instantiate the `SumVec` circuit for measurements with
        `length` elements, each in the range `[0, 2^bits)`.
        """
        self.field = field
        self.length = length
        self.bits = bits
        self.chunk_length = chunk_length
        self.GADGETS = [ParallelSum(Mul(), chunk_length)]
        self.GADGET_CALLS = [
            (length * bits + chunk_length - 1) // chunk_length
        ]
        self.MEAS_LEN = length * bits
        self.OUTPUT_LEN = length
        self.JOINT_RAND_LEN = self.GADGET_CALLS[0]

    def encode(self, measurement: list[int]) -> list[F]:
        encoded = []
        for val in measurement:
            encoded += self.field.encode_into_bit_vec(
                val, self.bits)
        return encoded

    def eval(
            self,
            meas: list[F],
            joint_rand: list[F],
            num_shares: int) -> list[F]:
        out = self.field(0)
        shares_inv = self.field(num_shares).inv()
        for i in range(self.GADGET_CALLS[0]):
            r = joint_rand[i]
            r_power = r
            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]

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

    def decode(
            self,
            output: list[F],
            _num_measurements: int) -> list[int]:
        return [x.int() for x in output]
]]></sourcecode>
          <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 (<xref target="gadget-parallel-sum"/>) 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 encoded measurement.
However, the relationship between VDAF parameters and proof length is
complicated, involving two forms of rounding:</t>
            <ul spacing="normal">
              <li>
                <t>The circuit pads the inputs to its last <tt>ParallelSum</tt> gadget call, up to
the chunk length.</t>
              </li>
              <li>
                <t>The 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.</t>
              </li>
            </ul>
            <t>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>field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Valid</tt></td>
                <td align="left">
                  <tt>Histogram(field, length, chunk_length)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
            </tbody>
          </table>
          <t>This variant 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 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. The 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. The individual checks constitute the output of the circuit.</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> (<xref target="gadget-parallel-sum"/>) gadget to
perform range checks while achieving a smaller proof size. The <tt>ParallelSum</tt>
gadget uses <tt>Mul</tt> subcircuits (<xref target="gadget-mul"/>) 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 an element of the joint randomness vector, 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[
class Histogram(Valid[int, list[int], F]):
    EVAL_OUTPUT_LEN = 2
    field: type[F]
    length: int
    chunk_length: int

    def __init__(self,
                 field: type[F],
                 length: int,
                 chunk_length: int):
        """
        Instantiate an instance of the `Histogram` circuit with the
        given `length` and `chunk_length`.
        """
        self.field = field
        self.length = length
        self.chunk_length = chunk_length
        self.GADGETS = [ParallelSum(Mul(), chunk_length)]
        self.GADGET_CALLS = [
            (length + chunk_length - 1) // chunk_length]
        self.MEAS_LEN = self.length
        self.OUTPUT_LEN = self.length
        self.JOINT_RAND_LEN = self.GADGET_CALLS[0]

    def encode(self, measurement: int) -> list[F]:
        encoded = [self.field(0)] * self.length
        encoded[measurement] = self.field(1)
        return encoded

    def eval(
            self,
            meas: list[F],
            joint_rand: list[F],
            num_shares: int) -> list[F]:
        # Check that each bucket is one or zero.
        range_check = self.field(0)
        shares_inv = self.field(num_shares).inv()
        for i in range(self.GADGET_CALLS[0]):
            r = joint_rand[i]
            r_power = r
            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

        return [range_check, sum_check]

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

    def decode(
            self,
            output: list[F],
            _num_measurements: int) -> list[int]:
        return [bucket_count.int()
                for bucket_count in output]
]]></sourcecode>
        </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>field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Valid</tt></td>
                <td align="left">
                  <tt>MultihotCountVec(field, length, max_weight, chunk_length)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
            </tbody>
          </table>
          <t>For this instance of Prio3, each measurement is a vector of Boolean
values, where the number of <tt>True</tt> values is bounded. This provides a
functionality similar to Prio3Histogram except that more than one entry (or none
at all) 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 with some small
probability.)</t>
          <t>The validity circuit is denoted <tt>MultihotCountVec</tt> and has three parameters:
<tt>length</tt>, the number of entries in the count vector; <tt>max_weight</tt>, the maximum
number of <tt>True</tt> 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. The two
checks constitute the output of the circuit. The complete circuit is defined
below.</t>
          <sourcecode type="python"><![CDATA[
class MultihotCountVec(Valid[list[bool], list[int], F]):
    EVAL_OUTPUT_LEN = 2
    field: type[F]

    def __init__(self,
                 field: type[F],
                 length: int,
                 max_weight: int,
                 chunk_length: int):
        """
        Instantiate an instance of the this circuit with the given
        `length`, `max_weight`, and `chunk_length`.

        Pre-conditions:

            - `length > 0`
            - `0 < max_weight` and `max_weight <= length`
            - `chunk_length > 0`
        """
        self.field = field

        # Compute the number of bits to represent `max_weight`.
        self.bits_for_weight = max_weight.bit_length()
        self.offset = self.field(
            2**self.bits_for_weight - 1 - max_weight)

        # Make sure `offset + length` doesn't overflow the field
        # modulus. Otherwise we may not correctly compute the sum
        # measurement vector entries during circuit evaluation.
        if self.field.MODULUS - self.offset.int() <= length:
            raise ValueError('length and max_weight are too large '
                             'for the current field size')

        self.length = length
        self.max_weight = max_weight
        self.chunk_length = chunk_length
        self.GADGETS: list[Gadget[F]] = [
            ParallelSum(Mul(), chunk_length),
        ]
        self.GADGET_CALLS = [
            (length + self.bits_for_weight + chunk_length - 1)
            // chunk_length
        ]
        self.MEAS_LEN = self.length + self.bits_for_weight
        self.OUTPUT_LEN = self.length
        self.JOINT_RAND_LEN = self.GADGET_CALLS[0]

    def encode(self, measurement: list[bool]) -> list[F]:
        if len(measurement) != self.length:
            raise ValueError('invalid Client measurement length')

        # The first part is the vector of counters.
        count_vec = [self.field(int(x)) for x in 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_vec(
            (self.offset + weight_reported).int(),
            self.bits_for_weight)
        return encoded

    def eval(
            self,
            meas: list[F],
            joint_rand: list[F],
            num_shares: int) -> list[F]:
        # Check that each entry in the input vector is one or zero.
        range_check = self.field(0)
        shares_inv = self.field(num_shares).inv()
        for i in range(self.GADGET_CALLS[0]):
            r = joint_rand[i]
            r_power = r
            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_vec(meas[self.length:])
        weight_check = self.offset*shares_inv + weight - \
            weight_reported

        return [range_check, weight_check]

    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.int() for
                bucket_count in output]
]]></sourcecode>
        </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 Collector chooses a sequence of
<tt>L</tt>-bit strings, where <tt>L &lt;= BITS</tt>. We will refer to the latter as the
"candidate prefixes". The goal is to count how many of the Clients' inputs
begin with each candidate prefix.</t>
      <t>This functionality is the core component of the heavy hitters protocol of
<xref target="BBCGGI21"/>. The goal of this protocol is to compute the subset of inputs held
by at least <tt>T</tt> Clients for some threshold <tt>T</tt>. It invokes Poplar1 as follows:</t>
      <ol spacing="normal" type="1"><li>
          <t>Each Client shards its string into secret shares and uploads one share to
each of the Aggregators.</t>
        </li>
        <li>
          <t>The Collector picks an initial set of candidate prefixes, say <tt>0</tt> and <tt>1</tt>,
and sends them to the Aggregators.</t>
        </li>
        <li>
          <t>The Aggregators run VDAF preparation and aggregation on each of the reports
and send their aggregate shares to the Collector.</t>
        </li>
        <li>
          <t>The Collector unshards the aggregate result, which consists of the hit count
for each candidate prefix. For each prefix <tt>p</tt> with hit count at least <tt>T</tt>,
the Collector adds <tt>p || 0</tt> and <tt>p || 1</tt> to the next generation of
candidate prefixes and repeats Step 2.</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 with hit count at least <tt>T</tt>. We shall
refer to this structure as the "prefix tree" for the batch of measurements and
target threshold. To compute the <tt>T</tt>-heavy-hitters for the batch, 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 leaks more
information about the set than the heavy hitters themselves; see
<xref target="agg-param-security"/> for more discussion.</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".)
The sketch ensures that evaluating a set of input shares on a set of unique
candidate prefixes results in shares of a zero vector or a "one-hot" vector,
i.e., a vector that is zero everywhere except for in at most one position.
Moreover, the value at that position should be one.</t>
      <t>The remainder of this section is structured as follows. The syntax of IDPFs is
defined in <xref target="idpf"/>. The Poplar1 VDAF is defined in <xref target="poplar1-construction"/> in
terms of a generic IDPF. A specification of the IDPF of <xref target="BBCGGI21"/> is given in
<xref target="idpf-bbcggi21"/>. Test vectors for Poplar1 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 bit strings. (In Poplar1, each Client's bit
string is 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 the 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>prefix</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>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-construction"/>) 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. See <xref target="idpf-extract"/> for details.)</t>
        <t>A concrete IDPF defines the types and parameters 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: tuple[bool, ...], beta_inner: list[list[FieldInner]], beta_leaf:
list[FieldLeaf], ctx: bytes, nonce: bytes, rand: bytes) -&gt; tuple[PublicShare,
list[bytes]]</tt> is the IDPF-key generation algorithm. Its inputs are the index
<tt>alpha</tt>, the values <tt>beta</tt>, the application context, and the report nonce.  </t>
            <t>
The output is a public part (of type <tt>PublicShare</tt>) that is sent to each
Aggregator and a vector of private IDPF keys, one for each Aggregator. The
nonce and application context are used to derive the fixed AES key for
XofFixedKeyAes128 (<xref target="xof-fixed-key-aes128"/>). Looking ahead, this key is used
for extending a node's seed into the seeds for the child nodes at each level
of the tree; see <xref target="idpf-bbcggi21"/>.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>alpha</tt> <bcp14>MUST</bcp14> have length <tt>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
 the range <tt>[0, 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 generated by a CSPRNG (see <xref target="nonce-requirements"/> for
details) and have length <tt>idpf.NONCE_SIZE</tt>.</t>
              </li>
            </ul>
            <t>
Post-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t>The number of IDPF keys <bcp14>MUST</bcp14> be <tt>idpf.SHARES</tt>.</t>
              </li>
            </ul>
          </li>
          <li>
            <t><tt>idpf.eval(agg_id: int, public_share: PublicShare, key: bytes, level: int,
prefixes: Sequence[tuple[bool, ...]], ctx: bytes, nonce: bytes) -&gt; Output</tt> is
the 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, the application context, and the
report nonce. It returns the share of the value corresponding to each
candidate prefix.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>agg_id</tt> <bcp14>MUST</bcp14> be in the range <tt>[0, idpf.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 the range <tt>[0, BITS)</tt>.</t>
              </li>
              <li>
                <t>Each prefix <bcp14>MUST</bcp14> be distinct and have length <tt>level + 1</tt>.</t>
              </li>
              <li>
                <t>The length of the nonce <bcp14>MUST</bcp14> be <tt>idpf.NONCE_SIZE</tt>.</t>
              </li>
            </ul>
            <t>
Post-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t>The length of the output <bcp14>MUST</bcp14> be <tt>len(prefixes)</tt></t>
              </li>
              <li>
                <t>The length of each element of the output <bcp14>MUST</bcp14> be <tt>idpf.VALUE_LEN</tt></t>
              </li>
              <li>
                <t>If <tt>level == idpf.BITS - 1</tt>, then the output field <bcp14>MUST</bcp14> be <tt>FieldLeaf</tt> and
 <tt>FieldInner</tt> otherwise</t>
              </li>
            </ul>
          </li>
        </ul>
        <t>In addition, the IDPF provides the following method:</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 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">
                <tt>SHARES: int</tt></td>
              <td align="left">Number of IDPF keys output by IDPF-key generator.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>BITS: int</tt></td>
              <td align="left">Length in bits of each input string.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VALUE_LEN: int</tt></td>
              <td align="left">Number of field elements of each output value.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>RAND_SIZE: int</tt></td>
              <td align="left">Size of the random string consumed by the IDPF-key generator.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>NONCE_SIZE: int</tt></td>
              <td align="left">Size of the random nonce generated by the Client.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>KEY_SIZE: int</tt></td>
              <td align="left">Size in bytes of each IDPF key.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>FieldInner</tt></td>
              <td align="left">Implementation of <tt>Field</tt> (<xref target="field"/>) used for values of inner nodes.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>FieldLeaf</tt></td>
              <td align="left">Implementation of <tt>Field</tt> used for values of leaf nodes.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>PublicShare</tt></td>
              <td align="left">Type of public share for this IDPF.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>Output</tt></td>
              <td align="left">Alias of <tt>list[list[FieldInner]] | list[list[FieldLeaf]]</tt>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>FieldVec</tt></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 representation
is as a bit string formed from all the bits of the byte string, first ordered by
byte position, then ordered from most significant bit to least significant bit
within each byte. This ensures that, when a byte string is a prefix of another,
so too is its corresponding index. (Index prefixes are defined in <xref target="idpf"/>.) For
example,</t>
          <artwork><![CDATA[
Byte string: 01 02
Bit string: 00000001 00000010
]]></artwork>
          <t>is a prefix of</t>
          <artwork><![CDATA[
Byte string: 01 02 03
Bit string: 00000001 00000010 00000011
]]></artwork>
          <t>Additionally, lexicographic ordering is preserved by this mapping from a byte
string to a bit string.</t>
          <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>Specification</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 the <tt>Idpf</tt> implementation of
<xref target="idpf-bbcggi21"/> with <tt>SHARES == 2</tt> and <tt>VALUE_LEN == 2</tt> and
<tt>XofTurboShake128</tt> as specified in <xref target="xof-turboshake128"/>. 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>idpf</tt></td>
              <td align="left">As specified in <xref target="idpf-bbcggi21"/>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>xof</tt></td>
              <td align="left">
                <tt>XofTurboShake128</tt> (<xref target="xof-turboshake128"/>)</td>
            </tr>
            <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>tuple[bool, ...]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggParam</tt></td>
              <td align="left">
                <tt>tuple[int, Sequence[tuple[bool, ...]]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PublicShare</tt></td>
              <td align="left">As defined by <tt>idpf</tt>.</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>, whose type is a
sequence of bits <tt>tuple[bool, ...]</tt> (See <xref target="poplar1-idpf-index-encoding"/> for
guidelines on index encoding.)</t>
          <t>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 Aggregators use the sketching
protocol to verify that they hold shares of a zero vector or a one-hot vector at
a given level of the IDPF tree.</t>
          <t>In addition to programming <tt>k</tt> into the IDPF output, for each level of the
tree, the Client 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 each of the
Aggregators. These help the Aggregators evaluate the sketch during preparation.</t>
          <t>Putting everything together, the sharding algorithm is defined as
follows.</t>
          <sourcecode type="python"><![CDATA[
def shard(
    self,
    ctx: bytes,
    measurement: tuple[bool, ...],
    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)
    (shard_seed,), seeds = front(1, seeds)

    xof = self.xof(
        shard_seed,
        self.domain_separation_tag(USAGE_SHARD_RAND, ctx),
        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,
        ctx,
        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, ctx),
            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, ctx),
            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, ctx),
            byte(0) + nonce,
            3,
        ),
        self.xof.expand_into_vec(
            self.idpf.field_leaf,
            corr_seed[1],
            self.domain_separation_tag(USAGE_CORR_LEAF, ctx),
            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>
        </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 zero vector or 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>is_valid()</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>
          <sourcecode type="python"><![CDATA[
def prep_init(
        self,
        verify_key: bytes,
        ctx: 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)

    # Evaluate the IDPF key at the given set of prefixes.
    value = self.idpf.eval(
        agg_id, public_share, key, level, prefixes, ctx, 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, ctx),
            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, ctx),
            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, ctx),
        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,
    _ctx: bytes,
    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,
        _ctx: bytes,
        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>
        </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 candidate
prefixes are unique and lexicographically sorted, 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>
          <sourcecode type="python"><![CDATA[
def is_valid(
        self,
        agg_param: Poplar1AggParam,
        previous_agg_params: list[Poplar1AggParam]) -> bool:
    """
    Checks that candidate prefixes are unique and lexicographically
    sorted, checks that levels are increasing between calls, and also
    enforces that the prefixes at each level are suffixes of the
    previous level's prefixes.
    """
    (level, prefixes) = agg_param

    # 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]:
            return False

    if len(previous_agg_params) < 1:
        return True

    (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, last_level)
        if last_prefix not in last_prefixes_set:
            # Current prefix not a suffix of last level's prefixes.
            return False
    return True

def get_ancestor(
        index: tuple[bool, ...],
        level: int) -> tuple[bool, ...]:
    """
    Helper function to determine the prefix of `index` at
    `level`.
    """
    return index[:level + 1]
]]></sourcecode>
        </section>
        <section anchor="aggregation-2">
          <name>Aggregation</name>
          <t>Aggregation involves simply adding up the output shares.</t>
          <sourcecode type="python"><![CDATA[
def agg_init(self, agg_param: Poplar1AggParam) -> FieldVec:
    (level, prefixes) = agg_param
    field = self.idpf.current_field(level)
    return field.zeros(len(prefixes))

def agg_update(self,
               agg_param: Poplar1AggParam,
               agg_share: FieldVec,
               out_share: FieldVec) -> FieldVec:
    a = cast(list[Field], agg_share)
    o = cast(list[Field], out_share)
    return cast(FieldVec, vec_add(a, o))

def merge(self,
          agg_param: Poplar1AggParam,
          agg_shares: list[FieldVec]) -> FieldVec:
    (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 cast(FieldVec, agg)
]]></sourcecode>
        </section>
        <section anchor="unsharding-1">
          <name>Unsharding</name>
          <t>Finally, the Collector unshards the aggregate result by adding up the aggregate
shares.</t>
          <sourcecode type="python"><![CDATA[
def unshard(
        self,
        agg_param: Poplar1AggParam,
        agg_shares: list[FieldVec],
        _num_measurements: int) -> list[int]:
    agg = self.merge(agg_param, agg_shares)
    return [x.int() for x in agg]
]]></sourcecode>
        </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>. Messages are defined in the presentation
language of TLS as defined in <xref section="3" sectionFormat="of" target="RFC8446"/>.</t>
          <t>Let <tt>poplar1</tt> be an instance of <tt>Poplar1</tt>. In the remainder we use <tt>Fi</tt> as an
alias for <tt>poplar1.idpf.field_inner.ENCODED_SIZE</tt>, <tt>Fl</tt> as an alias for
<tt>poplar1.idpf.field_leaf.ENCODED_SIZE</tt>, and <tt>B</tt> as an alias for
<tt>poplar1.idpf.BITS</tt>.</t>
          <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[bool, bool]</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 a straightforward structure of arrays, 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 {
    opaque packed_control_bits[packed_len];
    opaque seed[poplar1.idpf.KEY_SIZE*B];
    Poplar1FieldInner payload_inner[Fi*poplar1.idpf.VALUE_LEN*(B-1)];
    Poplar1FieldLeaf payload_leaf[Fl*poplar1.idpf.VALUE_LEN];
} Poplar1PublicShare;
]]></sourcecode>
            <t>Here <tt>packed_len = (2*B + 7) // 8</tt> is the length of the packed control bits.
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 << (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(bool(
        (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];
    opaque corr_seed[poplar1.xof.SEED_SIZE];
    Poplar1FieldInner corr_inner[Fi * 2 * (B- 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 encoded_prefixes[prefixes_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>encoded_prefixes</tt>, the sequence of prefixes encoded into a byte string of
length <tt>prefixes_len</tt>. Each prefix is packed into a byte string, with the bits
assigned in MSB-to-LSB order, and then the byte strings for each prefix are
concatenated together. The prefixes are encoded with the following procedure:</t>
            <sourcecode type="python"><![CDATA[
prefixes_len = ((level + 1) + 7) // 8 * len(prefixes)
encoded_prefixes = bytearray()
for prefix in prefixes:
    for chunk in itertools.batched(prefix, 8):
        byte_out = 0
        for (bit_position, bit) in enumerate(chunk):
            byte_out |= bit << (7 - bit_position)
        encoded_prefixes.append(byte_out)
]]></sourcecode>
            <t>Decoding involves the following procedure:</t>
            <sourcecode type="python"><![CDATA[
prefixes = []
bytes_per_prefix = ((level + 1) + 7) // 8
for chunk in itertools.batched(encoded_prefixes, bytes_per_prefix):
    prefix = []
    for i in range(level + 1):
        byte_index = i // 8
        bit_offset = 7 - (i % 8)
        bit = (chunk[byte_index] >> bit_offset) & 1 != 0
        prefix.append(bit)
    prefixes.append(tuple(prefix))
]]></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>IDPF Specification</name>
        <t>In this section we specify a concrete IDPF suitable for instantiating Poplar1.
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"/>) wherever
possible. See <xref target="xof-vs-ro"/> for security considerations.</t>
        <table anchor="idpf-bbcggi21-param">
          <name>Constants and type definitions for our concrete IDPF.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>xof</tt></td>
              <td align="left">
                <tt>XofFixedKeyAes128</tt> (<xref target="xof-fixed-key-aes128"/>)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>SHARES</tt></td>
              <td align="left">
                <tt>2</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>BITS</tt></td>
              <td align="left">Any positive integer.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VALUE_LEN</tt></td>
              <td align="left">Any positive integer.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>KEY_SIZE</tt></td>
              <td align="left">
                <tt>xof.SEED_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>FieldInner</tt></td>
              <td align="left">
                <tt>Field64</tt> (<xref target="fields"/>)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>FieldLeaf</tt></td>
              <td align="left">
                <tt>Field255</tt> (<xref target="fields"/>)</td>
            </tr>
          </tbody>
        </table>
        <section anchor="overview-1">
          <name>Overview</name>
          <t>At a high level, the IDPF maps a key generator's input <tt>(alpha, beta_1, ...,
beta_BITS)</tt> onto a binary tree with <tt>BITS+1</tt> levels, where each edge going from
a parent node to a left child is labeled <tt>0</tt>, and each right edge is labeled
<tt>1</tt>. Then each leaf node corresponds to a bit string of length <tt>BITS</tt>, where the
labels on the path from the root to <tt>x</tt> contain the individual bits.  Finally,
all nodes in the tree have an assigned value, with the nodes on the path
from the root to <tt>alpha</tt> having values <tt>beta_1, ..., beta_BITS</tt>, and all other
nodes having value <tt>0</tt>.</t>
          <t>The IDPF construction now boils down to secret-sharing the values at each node
of that tree in an efficient way. Note that explicitly representing the tree
requires <tt>O(2^BITS)</tt> space, so the generator cannot just compute additive shares
of it and send them to the two evaluators. Instead, the evaluators will
re-generate shares of values at selected nodes of the tree using a XOF
(<xref target="xof"/>).</t>
          <t>The basic observation is that if both evaluators have the same seed <tt>s</tt> of
length <tt>KEY_SIZE</tt>, then expanding <tt>s</tt> using a XOF will also result in the same
expansion. If we set the length of the XOF expansion to <tt>2*KEY_SIZE</tt>, it can
then be split again into two seeds <tt>s_l</tt>, <tt>s_r</tt>, that can again serve as XOF
seeds. Now if we view seeds as XOR-shares of integers, and if evaluators have
the same seed at the root of the tree, then their expanded trees will form a
secret-shared tree of zeros. The actual construction will additionally use a
<tt>convert()</tt> function before each expansion, which maps seeds into the
appropriate output domain (see <xref target="idpf-bbcggi21-helper-functions"/>), generating
a new seed for the next level in the process.</t>
          <t>The open task now is to ensure that evaluators have different seeds at nodes
that lie on the path to <tt>alpha</tt>, while having the same seeds on all other nodes.
This is done using so-called "correction words" included in the public share.
The correction words are conditionally added to the XOF output by both
evaluators.  The condition here is a secret-shared bit, called a "control bit",
which indicates whether the current node is on the path to <tt>alpha</tt> or not. On
the path, the control bits add up to <tt>1</tt>, meaning only one evaluator will add
the correction word to its XOF output. Off the path, either none or both
evaluators add the correction word, and so the seeds at the next level stay the
same.</t>
          <t>What remains is to turn the (now pseudorandom) values on the path to <tt>alpha</tt>
into the desired <tt>beta</tt> values. This is done by including "value correction
words" in the public share, which are chosen such that when added with the
pseudorandom shares at the <tt>i</tt>th node on the path to <tt>alpha</tt>, they add up to
shares of <tt>beta_i</tt>.</t>
          <t>In the following two sections we describe the algorithms for key generation in
full detail.</t>
        </section>
        <section anchor="key-generation">
          <name>Key Generation</name>
          <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"/>.</t>
          <sourcecode type="python"><![CDATA[
def gen(
        self,
        alpha: tuple[bool, ...],
        beta_inner: list[list[Field64]],
        beta_leaf: list[Field255],
        ctx: bytes,
        nonce: bytes,
        rand: bytes) -> tuple[list[CorrectionWord], list[bytes]]:
    if len(alpha) != self.BITS:
        raise ValueError("incorrect alpha length")
    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 = [False, True]
    public_share = []
    for level in range(self.BITS):
        bit = alpha[level]
        keep = int(bit)
        lose = 1 - keep

        (s0, t0) = self.extend(level, seed[0], ctx, nonce)
        (s1, t1) = self.extend(level, seed[1], ctx, nonce)
        seed_cw = xor(s0[lose], s1[lose])
        ctrl_cw = (
            t0[0] ^ t1[0] ^ (not bit),
            t0[1] ^ t1[1] ^ bit,
        )

        # Implementation note: these conditional XORs and
        # input-dependent array indices should be replaced with
        # constant-time selects in practice in order to reduce
        # leakage via timing side channels.
        if ctrl[0]:
            x0 = xor(s0[keep], seed_cw)
            ctrl[0] = t0[keep] ^ ctrl_cw[keep]
        else:
            x0 = s0[keep]
            ctrl[0] = t0[keep]
        if ctrl[1]:
            x1 = xor(s1[keep], seed_cw)
            ctrl[1] = t1[keep] ^ ctrl_cw[keep]
        else:
            x1 = s1[keep]
            ctrl[1] = t1[keep]
        (seed[0], w0) = self.convert(level, x0, ctx, nonce)
        (seed[1], w1) = self.convert(level, x1, ctx, nonce)

        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: this conditional negation should be
        # replaced with a constant time select or a constant time
        # multiplication in practice in order to reduce leakage via
        # timing side channels.
        if ctrl[1]:
            for i in range(len(w_cw)):
                w_cw[i] = -w_cw[i]

        public_share.append((seed_cw, ctrl_cw, w_cw))
    return (public_share, key)
]]></sourcecode>
        </section>
        <section anchor="key-evaluation">
          <name>Key Evaluation</name>
          <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>
          <sourcecode type="python"><![CDATA[
def eval(
        self,
        agg_id: int,
        public_share: list[CorrectionWord],
        key: bytes,
        level: int,
        prefixes: Sequence[tuple[bool, ...]],
        ctx: bytes,
        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 len(prefix) != level + 1:
            raise ValueError('incorrect prefix length')

        # 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 = bool(agg_id)
        y: FieldVec
        for current_level in range(level + 1):
            bit = int(prefix[current_level])

            # 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,
                ctx,
                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: bool,
        correction_word: CorrectionWord,
        level: int,
        bit: int,
        ctx: bytes,
        nonce: bytes) -> tuple[bytes, bool, 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.
    """

    seed_cw = correction_word[0]
    ctrl_cw = correction_word[1]
    w_cw = cast(list[Field], correction_word[2])
    (s, t) = self.extend(level, prev_seed, ctx, nonce)

    # Implementation note: these conditional operations and
    # input-dependent array indices should be replaced with
    # constant-time selects in practice in order to reduce leakage
    # via timing side channels.
    if prev_ctrl:
        s[0] = xor(s[0], seed_cw)
        s[1] = xor(s[1], seed_cw)
        t[0] ^= ctrl_cw[0]
        t[1] ^= ctrl_cw[1]

    next_ctrl = t[bit]
    convert_output = self.convert(level, s[bit], ctx, nonce)
    next_seed = convert_output[0]
    y = cast(list[Field], convert_output[1])
    # Implementation note: this conditional addition should be
    # replaced with a constant-time select in practice in order to
    # reduce leakage via timing side channels.
    if next_ctrl:
        for i in range(len(y)):
            y[i] += w_cw[i]

    return (next_seed, next_ctrl, cast(FieldVec, y))
]]></sourcecode>
        </section>
        <section anchor="idpf-bbcggi21-helper-functions">
          <name>Auxiliary Functions</name>
          <sourcecode type="python"><![CDATA[
def extend(
        self,
        level: int,
        seed: bytes,
        ctx: bytes,
        nonce: bytes) -> tuple[list[bytes], list[bool]]:
    xof = self.current_xof(
        level,
        seed,
        format_dst(1, 0, 0) + ctx,
        nonce,
    )
    s = [
        bytearray(xof.next(self.KEY_SIZE)),
        bytearray(xof.next(self.KEY_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 = [bool(s[0][0] & 1), bool(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,
        ctx: bytes,
        nonce: bytes) -> tuple[bytes, FieldVec]:
    xof = self.current_xof(
        level,
        seed,
        format_dst(1, 0, 1) + ctx,
        nonce,
    )
    next_seed = xof.next(self.KEY_SIZE)
    field = self.current_field(level)
    w = xof.next_vec(field, self.VALUE_LEN)
    return (next_seed, cast(FieldVec, w))

def current_xof(self,
                level: int,
                seed: bytes,
                dst: bytes,
                nonce: bytes) -> Xof:
    if level < self.BITS-1:
        return XofFixedKeyAes128(seed, dst, nonce)
    return XofTurboShake128(seed, dst, nonce)
]]></sourcecode>
        </section>
      </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, plus valid measurements from some of the
attacker-controlled 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 result, 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="the-verification-key">
        <name>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, the attacker 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 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 <bcp14>SHOULD</bcp14> bind the verification key to the
application context. 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>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. Uniqueness of the nonce is not sufficient because the verification key
is controlled by the attacker.</t>
        <t>Applications will need to protect against replay attacks to prevent disallowed
re-use of reports (see <xref target="agg-param-security"/>). Furthermore, in applications
that aim to achieve differential privacy, it is necessary to limit how much
each party contributes to a single batch or 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="the-public-share">
        <name>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="agg-param-security">
        <name>The Aggregation Parameter</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 reports.
For Prio3, reports should only be aggregated once; for Poplar1, reports may be
aggregated multiple times, but never twice at the same level of the tree.
Otherwise, we risk re-using correlated randomness, which might compromise
confidentiality of the Client's measurement.</t>
        <t>Higher level applications that use DAFs or VDAFs <bcp14>MUST</bcp14> enforce aggregation
parameter validity. In particular, prior to beginning preparation with an
aggregation parameter provided by the Collector, they <bcp14>MUST</bcp14> invoke <tt>is_valid()</tt>
to decide if the parameter is valid given the sequence of previously accepted
parameters.</t>
        <t>Note that aggregating a batch of reports multiple times, even with a valid
sequence of aggregation parameters, can 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. We call this a "steering attack".</t>
        <t>The only practical, general-purpose defense against steering attacks is to
compose Poplar1 with some mechanism for differential privacy. It is therefore
<bcp14>RECOMMENDED</bcp14> to use differential privacy for any heavy-hitter type application.</t>
      </section>
      <section anchor="idpf-extract">
        <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 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
inner nodes and using an XOF to derive leaves that is safe to model as a random
oracle. See <xref target="xof-vs-ro"/>.) 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 computing the prefix tree for heavy hitters.</t>
      </section>
      <section anchor="xof-vs-ro">
        <name>Safe Usage of XOFs</name>
        <t>In the security analyses of our protocols, XOFs (<xref target="xof"/>) 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>XofFixedKeyAes128 in <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. We therefore use XofTurboShake128
instead for the last level of the tree. It is important that XofTurboShake128
supports many seed lengths, in particular 16 bytes, as this is the seed size
for the inner levels.</t>
        <t>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 FLP Parameters</name>
        <t>Prio3 and other systems built from the FLP of <xref target="flp-bbcggi19"/> 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
and Prio3Sum use Field64; but Prio3SumVec, Prio3Histogram, and
Prio3MultihotCountVec all 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 offline attacks in
which the attacker searches for input shares for an invalid measurement that
derive joint randomness that causes the circuit to accept. Choosing a large
enough field ensures this computation is too expensive to be feasible. (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. In general the soundness error of the FLP is given
by the following formula:</t>
        <artwork><![CDATA[
(circuit_soundness + flp_soundness)^PROOFS
]]></artwork>
        <t>where:</t>
        <ul spacing="normal">
          <li>
            <t><tt>circuit_soundness</tt> is the soundness of the validity circuit
(<xref target="flp-bbcggi19-valid"/>)</t>
          </li>
          <li>
            <t><tt>flp_soundness</tt> is the base soundness of the proof system (<xref target="BBCGGI19"/>,
Theorem 4.3)</t>
          </li>
        </ul>
        <t>For circuits involving joint randomness, we aim for the soundness error to be
close to <tt>2^-128</tt> in order to mitigate offline attacks. Such circuits <bcp14>MUST</bcp14> use
Field128 with at least one proof or Field64 with at least three proofs.
Depending on the circuit, Field64 with two proofs might have significantly
lower soundness than Field128 with one proof.</t>
        <t>We stress that weak parameters (too small a field, too few proofs, or both) can
be exploited to attack any aggregation task using those parameters. To
mitigate offline attacks, it is necessary to disable all tasks that use the
weak parameters.</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 anchor="deep">
        <name>Defense-in-Depth Measures</name>
        <t>Prio3 and Poplar1 are designed to resist some attacks that fall outside the
main threat model for VDAFs.</t>
        <t>Broadly speaking, domain separation is used to prevent cross protocol attacks,
in which data from evaluation of one VDAF translates to an attack against another.
For example:</t>
        <ol spacing="normal" type="1"><li>
            <t>Weak entropy sources: the VDAF algorithm ID is bound to each XOF invocation,
thereby ensuring the outputs are different between VDAF invocations, even if
the underlying randomness is the same. For example, two different instances
of Prio3 would compute different measurement shares.</t>
          </li>
          <li>
            <t>Weak parameters: Prio3 variants that require joint randomness are subject to
offline attacks against robustness. These attacks are feasible if the field
size or number of proofs is sufficiently small. (See
<xref target="security-multiproof"/>.) The joint randomness derivation is bound to both
the field (via the algorithm ID) and the number of proofs, thereby ensuring
that joint randomness derived for weak parameters is not reused for stronger
parameters. In addition, the joint randomness is bound to the application
context, meaning any work the attacker does to attack some application is
not useful for other applications that use the same parameters.</t>
          </li>
        </ol>
        <t>There are also some important limitations to be aware of. For example, Prio3
provides domain separation between families of circuits, but does not provide
domain separation between instances of a circuit. Concretely, it is possible
for Aggregators to accept a report for Prio3SumVec from a Client who disagrees
with them on the value of <tt>bits</tt> and <tt>length</tt> (so long as the encoded
measurement is the same size). This is because there is no
binding of the circuit parameters to the computation.</t>
      </section>
      <section anchor="side-channel-resistance">
        <name>Side-Channel Resistance</name>
        <t>Implementations of VDAFs should incorporate defenses against side-channel
attacks. For side-channel attacks against the privacy security goal, the
relevant threat model includes an attacker that may control the Collector, a
subset of Clients, and a subset of Aggregators, and monitor side-channel
signals from the honest Clients and Aggregators. Side-channel attacks by third
parties may indirectly target robustness by trying to leak the Aggregators'
verification key. Thus, implementations of Clients and Aggregators should treat
measurements, input shares, output shares, and the verification key as secret,
and avoid leaking those secret values or any intermediate computations that
depend on them.</t>
        <t>For example, the following routines should all be implemented in a side-channel
resistant manner.</t>
        <ul spacing="normal">
          <li>
            <t>Finite field arithmetic</t>
          </li>
          <li>
            <t>XOFs</t>
          </li>
          <li>
            <t>IDPF generation and evaluation, including handling of control bits</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>IANA is requested to make one new registry:</t>
      <ul spacing="normal">
        <li>
          <t>DAF and VDAF Identifiers</t>
        </li>
      </ul>
      <t>This registry should be created under the heading "Verifiable Distributed
Aggregation Functions (VDAF)", and administered under the Specification Required
policy <xref target="RFC8126"/>.</t>
      <t>The "VDAF Identifiers" registry lists identifiers for Distributed Aggregation
Functions (DAFs) and Verifiable Distributed Aggregation Functions (VDAFs). These
identifiers are four-byte values, so the minimum possible value is <tt>0x00000000</tt>
and the maximum possible value is <tt>0xffffffff</tt>.</t>
      <t>Template:</t>
      <ul spacing="normal">
        <li>
          <t>Value: The four-byte identifier for the DAF or VDAF</t>
        </li>
        <li>
          <t>Scheme: The name of the DAF or VDAF</t>
        </li>
        <li>
          <t>Type: Either "DAF" for a Distributed Aggregation Function or "VDAF" for a
Verifiable Distributed Aggregation Function</t>
        </li>
        <li>
          <t>Reference: Where the algorithm is defined</t>
        </li>
      </ul>
      <t>The initial contents of the registry are as follows:</t>
      <table anchor="codepoints">
        <name>Verifiable Distributed Aggregation Function Identifiers Registry</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">Reserved</td>
            <td align="left">n/a</td>
            <td align="left">RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000001</tt></td>
            <td align="left">Prio3Count</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3count"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000002</tt></td>
            <td align="left">Prio3Sum</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3sum"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000003</tt></td>
            <td align="left">Prio3SumVec</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3sumvec"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000004</tt></td>
            <td align="left">Prio3Histogram</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3histogram"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000005</tt></td>
            <td align="left">Prio3MultihotCountVec</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3multihotcountvec"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000006</tt></td>
            <td align="left">Poplar1</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="poplar1-construction"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0xFFFF0000</tt> to <tt>0xFFFFFFFF</tt></td>
            <td align="left">Reserved for Private Use</td>
            <td align="left">n/a</td>
            <td align="left">n/a</td>
          </tr>
        </tbody>
      </table>
      <t>(RFC EDITOR: Please replace "RFC XXXX" above with the RFC number assigned to
this document.)</t>
      <t>VDAF identifiers are used for domain separation, as described in
<xref target="dst-binder"/>. Domain separation guards against cross protocol attacks and
certain failures of entropy sources. See <xref target="deep"/>.</t>
      <t>The benefits of domain separation are undermined if different VDAFs are used
with the same VDAF Identifier.  The "Reserved for Private Use" code points
should thus be used judiciously, because they provide no defense against such
collisions.  Applications <bcp14>SHOULD</bcp14> prefer the use of registered code points.</t>
    </section>
  </middle>
  <back>
    <references anchor="sec-combined-references">
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="AES" target="https://www.nist.gov/publications/advanced-encryption-standard-aes">
          <front>
            <title>Advanced Encryption Standard (AES)</title>
            <author initials="M. J." surname="Dworkin" fullname="Morris J. Dworkin">
              <organization/>
            </author>
            <author initials="E." surname="Barker" fullname="Elaine Barker">
              <organization/>
            </author>
            <author initials="J. R." surname="Nechvatal" fullname="James R. Nechvatal">
              <organization/>
            </author>
            <author initials="J." surname="Foti" fullname="James Foti">
              <organization/>
            </author>
            <author initials="L. E." surname="Bassham" fullname="Lawrence E. Bassham">
              <organization/>
            </author>
            <author initials="E." surname="Roback" fullname="E. Roback">
              <organization/>
            </author>
            <author initials="J." surname="Dray Jr" fullname="James F. Dray Jr.">
              <organization/>
            </author>
            <date year="2001"/>
          </front>
        </reference>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <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>
        <reference anchor="RFC8126">
          <front>
            <title>Guidelines for Writing an IANA Considerations Section in RFCs</title>
            <author fullname="M. Cotton" initials="M." surname="Cotton"/>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <author fullname="T. Narten" initials="T." surname="Narten"/>
            <date month="June" year="2017"/>
            <abstract>
              <t>Many protocols make use of points of extensibility that use constants to identify various protocol parameters. To ensure that the values in these fields do not have conflicting uses and to promote interoperability, their allocations are often coordinated by a central record keeper. For IETF protocols, that role is filled by the Internet Assigned Numbers Authority (IANA).</t>
              <t>To make assignments in a given registry prudently, guidance describing the conditions under which new values should be assigned, as well as when and how modifications to existing values can be made, is needed. This document defines a framework for the documentation of these guidelines by specification authors, in order to assure that the provided guidance for the IANA Considerations is clear and addresses the various issues that are likely in the operation of a registry.</t>
              <t>This is the third edition of this document; it obsoletes RFC 5226.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="26"/>
          <seriesInfo name="RFC" value="8126"/>
          <seriesInfo name="DOI" value="10.17487/RFC8126"/>
        </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" fullname="Surya Addanki">
              <organization/>
            </author>
            <author initials="K." surname="Garbe" fullname="Kevin Garbe">
              <organization/>
            </author>
            <author initials="E." surname="Jaffe" fullname="Eli Jaffe">
              <organization/>
            </author>
            <author initials="R." surname="Ostrovsky" fullname="Rafail Ostrovsky">
              <organization/>
            </author>
            <author initials="A." surname="Polychroniadou" fullname="Antigoni Polychroniadou">
              <organization/>
            </author>
            <date year="2022"/>
          </front>
          <refcontent>Security and Cryptography for Networks (SCN)</refcontent>
        </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" fullname="Dan Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle" fullname="Elette Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs" fullname="Henry Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa" fullname="Niv Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai" fullname="Yuval Ishai">
              <organization/>
            </author>
            <date year="2019"/>
          </front>
          <refcontent>Crypto</refcontent>
        </reference>
        <reference anchor="BBCGGI21" target="https://ia.cr/2021/017">
          <front>
            <title>Lightweight Techniques for Private Heavy Hitters</title>
            <author initials="D." surname="Boneh" fullname="Dan Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle" fullname="Elette Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs" fullname="Henry Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa" fullname="Niv Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai" fullname="Yuval Ishai">
              <organization/>
            </author>
            <date year="2021"/>
          </front>
          <refcontent>IEEE Security &amp; Privacy (S&amp;P)</refcontent>
        </reference>
        <reference anchor="BBCGGI23" target="https://ia.cr/2023/1012">
          <front>
            <title>Arithmetic Sketching</title>
            <author initials="D." surname="Boneh" fullname="Dan Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle" fullname="Elette Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs" fullname="Henry Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa" fullname="Niv Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai" fullname="Yuval Ishai">
              <organization/>
            </author>
            <date year="2023"/>
          </front>
          <refcontent>Crypto</refcontent>
        </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" fullname="Elette Boyle">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa" fullname="Niv Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai" fullname="Yuval Ishai">
              <organization/>
            </author>
            <date year="2015"/>
          </front>
          <refcontent>Eurocrypt</refcontent>
        </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="D." surname="Boneh" fullname="Dan Boneh">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs" fullname="Henry Corrigan-Gibbs">
              <organization/>
            </author>
            <date year="2017"/>
          </front>
          <refcontent>USENIX Symposium on Networked Systems Design and Implementation (NSDI)</refcontent>
        </reference>
        <reference anchor="Dou02" target="https://doi.org/10.1007/3-540-45748-8_24">
          <front>
            <title>The Sybil Attack</title>
            <author initials="J. R." surname="Douceur" fullname="John R. Douceur">
              <organization/>
            </author>
            <date year="2002"/>
          </front>
          <refcontent>International Workshop on Peer-to-Peer Systems (IPTPS)</refcontent>
        </reference>
        <reference anchor="DPRS23" target="https://ia.cr/2023/130">
          <front>
            <title>Verifiable Distributed Aggregation Functions</title>
            <author initials="" surname="Hannah Davis">
              <organization/>
            </author>
            <author initials="" surname="Christopher Patton">
              <organization/>
            </author>
            <author initials="" surname="Mike Rosulek">
              <organization/>
            </author>
            <author initials="" surname="Phillipp Schoppmann">
              <organization/>
            </author>
            <date year="2023"/>
          </front>
          <refcontent>Privacy Enhancing Technologies Symposium (PETS)</refcontent>
        </reference>
        <reference anchor="Dwo06" target="https://link.springer.com/chapter/10.1007/11787006_1">
          <front>
            <title>Differential Privacy</title>
            <author initials="" surname="Cynthia Dwork">
              <organization/>
            </author>
            <date year="2006"/>
          </front>
          <refcontent>International Colloquium on Automata, Languages, and Programming (ICALP)</refcontent>
        </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" fullname="Úlfar Erlingsson">
              <organization/>
            </author>
            <author initials="V." surname="Pihur" fullname="Vasyl Pihur">
              <organization/>
            </author>
            <author initials="A." surname="Korolova" fullname="Aleksandra Korolova">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <refcontent>ACM Conference on Computer and Communications Security (CCS)</refcontent>
        </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" fullname="Niv Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai" fullname="Yuval Ishai">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <refcontent>Eurocrypt</refcontent>
        </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" fullname="Vipul Goyal">
              <organization/>
            </author>
            <author initials="Y." surname="Song" fullname="Yifan Song">
              <organization/>
            </author>
            <author initials="C." surname="Zhu" fullname="Chenzhi Zhu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <refcontent>Crypto</refcontent>
        </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" fullname="Chun Guo">
              <organization/>
            </author>
            <author initials="J." surname="Katz" fullname="Jonathan Katz">
              <organization/>
            </author>
            <author initials="X." surname="Wang" fullname="Xiao Wang">
              <organization/>
            </author>
            <author initials="C." surname="Weng" fullname="Chenkai Weng">
              <organization/>
            </author>
            <author initials="Y." surname="Yu" fullname="Yu Yu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <refcontent>Crypto</refcontent>
        </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" fullname="Chun Guo">
              <organization/>
            </author>
            <author initials="J." surname="Katz" fullname="Jonathan Katz">
              <organization/>
            </author>
            <author initials="X." surname="Wang" fullname="Xiao Wang">
              <organization/>
            </author>
            <author initials="Y." surname="Yu" fullname="Yu Yu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <refcontent>IEEE Security &amp; Privacy (S&amp;P)</refcontent>
        </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" fullname="Dimitris Mouris">
              <organization/>
            </author>
            <author initials="C." surname="Patton" fullname="Christopher Patton">
              <organization/>
            </author>
            <author initials="H." surname="Davis" fullname="Hannah Davis">
              <organization/>
            </author>
            <author initials="P." surname="Sarkar" fullname="Pratik Sarkar">
              <organization/>
            </author>
            <author initials="N. G." surname="Tsoutsos" fullname="Nektarios Georgios Tsoutsos">
              <organization/>
            </author>
            <date year="2025"/>
          </front>
          <refcontent>Privacy Enhancing Technologies Symposium (PETS)</refcontent>
        </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" fullname="Ilya Mironov">
              <organization/>
            </author>
            <author initials="O." surname="Pandey" fullname="Omkant Pandey">
              <organization/>
            </author>
            <author initials="O." surname="Reingold" fullname="Omer Reingold">
              <organization/>
            </author>
            <author initials="S." surname="Vadhan" fullname="Salil Vadhan">
              <organization/>
            </author>
            <date year="2009"/>
          </front>
          <refcontent>Crypto</refcontent>
        </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/>
            </author>
            <author initials="R." surname="Renner" fullname="Renato Renner">
              <organization/>
            </author>
            <author initials="C." surname="Holenstein" fullname="Clemens Holenstein">
              <organization/>
            </author>
            <date year="2004"/>
          </front>
          <refcontent>Theory of Cryptography (TCC)</refcontent>
        </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" fullname="Ardianto Satriawan">
              <organization/>
            </author>
            <author initials="R." surname="Mareta" fullname="Rella Mareta">
              <organization/>
            </author>
            <author initials="H." surname="Lee" fullname="Hanho Lee">
              <organization/>
            </author>
            <date year="2024"/>
          </front>
          <refcontent>IEEE Access, vol. 11</refcontent>
        </reference>
        <reference anchor="TestVectors" target="https://github.com/cfrg/draft-irtf-cfrg-vdaf">
          <front>
            <title>Test vectors for Prio3 and Poplar1</title>
            <author>
              <organization/>
            </author>
            <date year="2024" month="October"/>
          </front>
          <refcontent>commit hash c8cdc96</refcontent>
        </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>Independent</organization>
            </author>
            <author fullname="Christopher A. Wood" initials="C. A." surname="Wood">
              <organization>Cloudflare</organization>
            </author>
            <date day="10" month="October" 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-12"/>
        </reference>
      </references>
    </references>
    <?line 6006?>

<section anchor="gadgets">
      <name>FLP Gadgets</name>
      <t>This section defines gadgets used to specify variants of Prio3 defined in
<xref target="prio3-instantiations"/> and to construct FLPs as defined in <xref target="flp-bbcggi19"/>.</t>
      <section anchor="gadget-mul">
        <name>Multiplication</name>
        <t>The multiplication gadget takes in a pair of inputs and multiplies them
together. The degree of this circuit is <tt>2</tt>.</t>
        <sourcecode type="python"><![CDATA[
class Mul(Gadget[F]):
    ARITY = 2
    DEGREE = 2

    def eval(self, _field: type[F], inp: list[F]) -> F:
        return inp[0] * inp[1]

    def eval_poly(self,
                  field: type[F],
                  inp_poly: list[list[F]]) -> list[F]:
        return poly_mul(field, inp_poly[0], inp_poly[1])
]]></sourcecode>
      </section>
      <section anchor="gadget-poly-eval">
        <name>Polynomial Evaluation</name>
        <t>The polynomial-evaluation gadget takes in a single input <tt>x</tt> and returns
<tt>p(x)</tt>, where <tt>p</tt> is a polynomial specified by the user. Its degree is the same
as <tt>p</tt>.</t>
        <sourcecode type="python"><![CDATA[
class PolyEval(Gadget[F]):
    ARITY = 1
    p: list[int]  # polynomial coefficients

    def __init__(self, p: list[int]):
        """
        Instantiate this gadget with the given polynomial.
        """
        # Strip leading zeros.
        for i in reversed(range(len(p))):
            if p[i] != 0:
                p = p[:i+1]
                break
        if len(p) < 1:
            raise ValueError('invalid polynomial: zero length')

        self.p = p
        self.DEGREE = len(p) - 1

    def eval(self, field: type[F], inp: list[F]) -> F:
        p = [field(coeff) for coeff in self.p]
        return poly_eval(field, p, inp[0])

    def eval_poly(self,
                  field: type[F],
                  inp_poly: list[list[F]]) -> list[F]:
        p = [field(coeff) for coeff in self.p]
        out = [field(0)] * (self.DEGREE * len(inp_poly[0]))
        out[0] = p[0]
        x = inp_poly[0]
        for i in range(1, len(p)):
            for j in range(len(x)):
                out[j] += p[i] * x[j]
            x = poly_mul(field, x, inp_poly[0])
        return poly_strip(field, out)
]]></sourcecode>
      </section>
      <section anchor="gadget-parallel-sum">
        <name>Parallel Sum</name>
        <t>The parallel-sum gadget applies a subcircuit to multiple inputs in parallel,
then returns the sum of the results. The arity of the gadget is equal to <tt>count</tt>
times the arity of the subcircuit, where <tt>count</tt> denotes the number of times the
subcircuit is called. The degree of the gadget is equal to the degree of the
subcircuit.</t>
        <sourcecode type="python"><![CDATA[
class ParallelSum(Gadget[F]):
    subcircuit: Gadget[F]
    count: int

    def __init__(self, subcircuit: Gadget[F], count: int):
        self.subcircuit = subcircuit
        self.count = count
        self.ARITY = subcircuit.ARITY * count
        self.DEGREE = subcircuit.DEGREE

    def eval(self, field: type[F], inp: list[F]) -> F:
        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

    def eval_poly(self,
                  field: type[F],
                  inp_poly: list[list[F]]) -> list[F]:
        output_poly_length = self.DEGREE * (len(inp_poly[0]) - 1) + 1
        out_sum = [field(0) for _ in range(output_poly_length)]
        for i in range(self.count):
            start_index = i * self.subcircuit.ARITY
            end_index = (i + 1) * self.subcircuit.ARITY
            out_current = self.subcircuit.eval_poly(
                field,
                inp_poly[start_index:end_index]
            )
            for j in range(output_poly_length):
                out_sum[j] += out_current[j]
        return poly_strip(field, out_sum)
]]></sourcecode>
      </section>
      <section anchor="gadget-wrappers">
        <name>Shims for Generating and Querying Proofs</name>
        <t>This section specifies two "shim" gadgets, one for generating an FLP as
specified in <xref target="flp-bbcggi19-construction-prove"/> and another for querying an FLP
as specified in <xref target="flp-bbcggi19-construction-query"/>.</t>
        <sourcecode type="python"><![CDATA[
class ProveGadget(Gadget[F]):
    """
    Gadget wrapper that records the input wires for each evaluation.
    """

    def __init__(self,
                 field: type[F],
                 wire_seeds: list[F],
                 g: Gadget[F],
                 g_calls: int):
        p = next_power_of_2(1 + g_calls)
        self.inner = g
        self.ARITY = g.ARITY
        self.DEGREE = g.DEGREE
        self.wires = []
        self.k = 0  # evaluation counter
        for s in wire_seeds:
            wire = field.zeros(p)
            wire[0] = s  # set the wire seed
            self.wires.append(wire)

    def eval(self, field: type[F], inp: list[F]) -> F:
        self.k += 1
        for j in range(len(inp)):
            self.wires[j][self.k] = inp[j]
        return self.inner.eval(field, inp)

    def eval_poly(self,
                  field: type[F],
                  inp_poly: list[list[F]]) -> list[F]:
        return self.inner.eval_poly(field, inp_poly)

    @classmethod
    def wrap(cls,
             valid: Valid[Measurement, AggResult, F],
             prove_rand: list[F],
             ) -> Valid[Measurement, AggResult, F]:
        """
        Make a copy of `valid` with each gadget wrapped for recording
        the wire inputs. `prove_rand` is used to produce the wire
        seeds for each gadget.
        """
        wrapped_gadgets: list[Gadget[F]] = []
        for (g, g_calls) in zip(valid.GADGETS, valid.GADGET_CALLS):
            (wire_seeds, prove_rand) = front(g.ARITY, prove_rand)
            wrapped = cls(valid.field, wire_seeds, g, g_calls)
            wrapped_gadgets.append(wrapped)
        wrapped_valid = deepcopy(valid)
        wrapped_valid.GADGETS = wrapped_gadgets
        return wrapped_valid

class QueryGadget(Gadget[F]):
    """
    Gadget wrapper that records the input wires for each evaluation.
    Rather than evaluate the circuit, use the provided gadget
    polynomial to produce the output.
    """

    def __init__(
            self,
            field: type[F],
            wire_seeds: list[F],
            gadget_poly: list[F],
            g: Gadget[F],
            g_calls: int):
        p = next_power_of_2(1 + g_calls)
        self.alpha = field.gen() ** (field.GEN_ORDER // p)
        self.poly = gadget_poly
        self.ARITY = g.ARITY
        self.DEGREE = g.DEGREE
        self.wires = []
        self.k = 0
        for s in wire_seeds:
            wire = field.zeros(p)
            wire[0] = s  # set the wire seed
            self.wires.append(wire)

    def eval(self, field: type[F], inp: list[F]) -> F:
        self.k += 1
        for j in range(len(inp)):
            self.wires[j][self.k] = inp[j]
        return poly_eval(field, self.poly, self.alpha ** self.k)

    @classmethod
    def wrap(cls,
             valid: Valid[Measurement, AggResult, F],
             proof: list[F]) -> Valid[Measurement, AggResult, F]:
        wrapped_gadgets: list[Gadget[F]] = []
        for (g, g_calls) in zip(valid.GADGETS, valid.GADGET_CALLS):
            p = next_power_of_2(1 + g_calls)
            gadget_poly_len = g.DEGREE * (p - 1) + 1
            (wire_seeds, proof) = front(g.ARITY, proof)
            (gadget_poly, proof) = front(gadget_poly_len, proof)
            wrapped = cls(valid.field,
                          wire_seeds,
                          gadget_poly,
                          g,
                          g_calls)
            wrapped_gadgets.append(wrapped)
        wrapped_valid = deepcopy(valid)
        wrapped_valid.GADGETS = wrapped_gadgets
        return wrapped_valid
]]></sourcecode>
      </section>
    </section>
    <section anchor="topo-states">
      <name>VDAF Preparation State</name>
      <t>This section lists the classes used to define each Aggregator's state during
VDAF preparation (<xref target="vdaf-prep-comm"/>).</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>
    </section>
    <section anchor="test-vectors">
      <name>Test Vectors</name>
      <t>Test vectors for Prio3 (<xref target="prio3"/>) and Poplar1 (<xref target="poplar1"/>) are available at
<xref target="TestVectors"/>. The test vector directory, <tt>test_vec/vdaf</tt>, contains a set of
JSON files. Each file contains a test vector for an instance of class <tt>Vdaf</tt> as
defined in <xref target="vdaf"/>. A test vector covers sharding, preparation, aggregation,
and unsharding of a batch of several measurements. The test vector schema is
defined below.</t>
      <section anchor="schema">
        <name>Schema</name>
        <dl>
          <dt><tt>ctx</tt>:</dt>
          <dd>
            <t>The application context string encoded in hexadecimal.</t>
          </dd>
          <dt><tt>verify_key</tt>:</dt>
          <dd>
            <t>The verification key encoded in hexadecimal.</t>
          </dd>
          <dt><tt>agg_param</tt>:</dt>
          <dd>
            <t>The aggregation parameter encoded in hexadecimal.</t>
          </dd>
          <dt><tt>prep</tt>:</dt>
          <dd>
            <t>A list of objects with the following schema:
</t>
            <dl>
              <dt><tt>measurement</tt>:</dt>
              <dd>
                <t>The measurement of type <tt>Measurement</tt> defined by the VDAF.</t>
              </dd>
              <dt><tt>nonce</tt>:</dt>
              <dd>
                <t>The nonce encoded in hexadecimal.</t>
              </dd>
              <dt><tt>rand</tt>:</dt>
              <dd>
                <t>The sharding randomness encoded in hexadecimal.</t>
              </dd>
              <dt><tt>public_share</tt>:</dt>
              <dd>
                <t>The expected public share encoded in hexadecimal.</t>
              </dd>
              <dt><tt>input_shares</tt>:</dt>
              <dd>
                <t>The expected list of input shares, each encoded in hexadecimal.</t>
              </dd>
              <dt><tt>prep_shares</tt>:</dt>
              <dd>
                <t>The expected list of prep shares generated by each Aggregator at each
round of preparation, encoded in hexadecimal.</t>
              </dd>
              <dt><tt>prep_messages</tt>:</dt>
              <dd>
                <t>The expected list of prep messages for each round of preparation, encoded
in hexadecimal.</t>
              </dd>
              <dt><tt>out_shares</tt>:</dt>
              <dd>
                <t>The expected list of output shares, encoded in hexadecimal.</t>
              </dd>
            </dl>
          </dd>
          <dt><tt>agg_shares</tt>:</dt>
          <dd>
            <t>The expected aggregate shares encoded in hexadecimal.</t>
          </dd>
          <dt><tt>agg_result</tt>:</dt>
          <dd>
            <t>The expected aggregate result of type <tt>AggResult</tt> defined by the VDAF.</t>
          </dd>
        </dl>
        <t>The schema also includes whatever parameters are required to instantiate the
VDAF. These are listed in the subsections below.</t>
        <section anchor="prio3count-1">
          <name>Prio3Count</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3sum-1">
          <name>Prio3Sum</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>max_measurement</tt>:</dt>
            <dd>
              <t>The largest valid measurement, an integer. Each measurement is in the range
  <tt>[0, max_measurement]</tt>.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3sumvec-1">
          <name>Prio3SumVec</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>length</tt>:</dt>
            <dd>
              <t>The length of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>a parameter of the ParallelSum gadget, an integer.</t>
            </dd>
            <dt><tt>bits</tt>:</dt>
            <dd>
              <t>the bit length of each element of the vector, an integer. Each element is in
the range <tt>[0, 2^bits)</tt>.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3histogram-1">
          <name>Prio3Histogram</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>length</tt>:</dt>
            <dd>
              <t>The length of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>a parameter of the ParallelSum gadget, an integer.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3multihotcountvec-1">
          <name>Prio3MultihotCountVec</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>length</tt>:</dt>
            <dd>
              <t>The length of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>a parameter of the ParallelSum gadget, an integer.</t>
            </dd>
            <dt><tt>max_weight</tt>:</dt>
            <dd>
              <t>The largest vector weight, an integer. The sum of the elements of the
measurement must be in the range <tt>[0, max_weight]</tt>.</t>
            </dd>
          </dl>
        </section>
        <section anchor="poplar1-test-vec-param">
          <name>Poplar1</name>
          <dl>
            <dt><tt>bits</tt>:</dt>
            <dd>
              <t>The length of each input in bits, an integer.</t>
            </dd>
          </dl>
        </section>
      </section>
    </section>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The impetus of this work is the success of recent deployments of predecessors
of Prio3. These include the Mozilla Origin Telemetry project
<xref target="OriginTelemetry"/> and the Exposure Notification Private Analytics system
<xref target="ENPA"/> developed jointly by ISRG, Google, Apple, and others. Together these
systems have 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,
Michael Rosenberg, Jacob Rothstein, Shan Wang, Xiao Wang, Bas Westerbaan, and
Christopher Wood for useful feedback on and contributions to the spec.</t>
    </section>
  </back>
  <!-- ##markdown-source:
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
axIZJ6jMXW3LLgJCintw3rcEbBRW62lmaWwLxdfSrNYNvAGerwt06U4Ryzgu
rRWV8quskxie44pw1KkjmmJSJCdDd3uDBc/S+DjvExl1ikruy4MpGs3eGLGH
q3hfV1zG/l20FjS7w4ITREFObiodGTfmc7FcB5zDdkhkam+va9xjRtwyaGdX
ZVwV0aiLdJvXejZAVnBbc875Y+QemLCKV9H0Cy4s6X/sHfZFUVCNLyhfI1eJ
hrqZzvUM++I/gDN5dvLipAVlQgcUX1ZyHcbJweHGgAMxyISjTUSQ446dA6yG
aax1/owjimnY60Yv8+1Zh+U2wZ5Ts6w3qYu5kKo5khLJZtmjkF81zXxgeQTI
GqDL4YGer+mC1qxBQrNvOa3KeqY2V7aqSXThwuUfzh4//J9H93/DNy7QKQ7a
8ziIUwDAVZNX8Tdm5m6gPgI+cwMFfxPton+C+R0TbIaqaWW+Y9a2SB0ec11u
oehQaw8rsdguYvxnDM+69+Ge/l1mdpQWxYf9j8/0j0sQlkTJtHW874zPfMx6
WBxIHGIwGbGcaoMAl4KNK3ltWQT4kdZTr3creuZUQAIO6LsDvY791JqhDd7B
g5Cx+DNWnHo+K/WC5jh/Y6UnnZJYxXArphZOEdL8c0vz47AKIxlWeRrlEcDH
+ESJ2B91hXp/wrLQ/8IY9zUij7drzXZqy+7/WX/6VHXapEqto6yeoZMGILf7
3Z+WXxf8xOOH+Z/o785J5WlXR31dxauOzk98tn/M1VvC4SoI6Zr1dp521VMz
98d4jdL9Ke2q2S72d9Tu6pu7uoLK+Kmu3peTvb2lXf16b1fh1ueOrm7smf7e
0q7+cW9Xncuknq4W+gzvWXd+aVe/6e1KnSs9P8Wu5Jmxj95uz027ekx/Quxw
C8tn/F16YlddHw4yRgwMxM7/++SfVCWGEs8hjI0VI/4ZLM1LMhqXcCXUJR5g
RqePnr1+eXacv4J3OYCs5gc22wMBl4k5nfhBjeNQIpeThbkI3mTL6UJDgUDL
2/IqGL0dk2uUuu3YVTdtNmOYH+WasTY6VhqDhEQVv99JxTeWFtU2K6r5VoOn
Wy4lC39kl5ypAnrxzM93rUSeEYYneMDVzHlpxKCxOQczTsyuloKhmDYH+4jm
IAcBSBBrk5najIg8Szv8nhS9iYQzjrwVtzMbF4EJnTh85EvGXOk2DIsG+CFQ
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

-->

</rfc>
