<?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.29 (Ruby 3.4.4) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-irtf-cfrg-vdaf-17" category="info" submissionType="IRTF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.30.2 -->
  <?v3xml2rfc silence="Found SVG with width or height specified"?>
  <front>
    <title abbrev="VDAF">Verifiable Distributed Aggregation Functions</title>
    <seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-vdaf-17"/>
    <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="2025" month="October" day="17"/>
    <area>IRTF</area>
    <workgroup>CFRG</workgroup>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <?line 271?>

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

<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, one
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, this document's 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 interact with one
another in order to detect and remove these measurements prior to
aggregation. This document refers to this property as verifiability. (This is
also called robustness in prior work <xref target="CGB17"/>, <xref target="DPRS23"/>.)</t>
      <t>Achieving verifiability using the cryptographic techniques described in this
document requires a significant amount of interaction between the servers. DAFs
on the other hand are non-interactive, making them easier to deploy; but they
do not on their own allow for verifying the validity of the measurements. 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. <xref target="prio3"/> specifies 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). <xref target="poplar1"/>
specifies a VDAF called Poplar1 that implements this prefix counting
functionality and describe how it is used in the heavy hitters protocol.</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 the constructions defined in this document;
<xref target="prio3"/> specifies Prio3; <xref target="poplar1"/> specifies Poplar1; and <xref target="security"/>
enumerates security considerations for DAFs and VDAFs in general and the
Prio3 and Poplar1 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>17:</t>
        <ul spacing="normal">
          <li>
            <t>Rename VDAF preparation to VDAF verification.</t>
          </li>
          <li>
            <t>Update the reference for TurboSHAKE128 to <xref target="RFC9861"/>.</t>
          </li>
          <li>
            <t>Prio3: Acknowledge an optimization pointed out in <xref target="Faz25"/>.</t>
          </li>
        </ul>
        <t>16:</t>
        <ul spacing="normal">
          <li>
            <t>Align document with guidelines for ASCII-safe mathematical notation from
<xref section="3.3.1.6" sectionFormat="of" target="I-D.draft-irtf-cfrg-cryptography-specification-02"/>.</t>
          </li>
          <li>
            <t>Address feedback from Crypto Review Panel <xref target="PANEL-FEEDBACK"/>.</t>
          </li>
        </ul>
        <t>15:</t>
        <ul spacing="normal">
          <li>
            <t>Simplify the ping-pong API for 2-party preparation by merging the outbound
message into the state object. This reduces the number of cases the caller
has to handle.</t>
          </li>
          <li>
            <t>Update the test vector format. First, enrich the test vector schema to
express negative test cases. Second, change the encoding of output shares to
match the aggregate shares.</t>
          </li>
        </ul>
        <t>14:</t>
        <ul spacing="normal">
          <li>
            <t>Poplar1: When decoding an aggregation parameter, require the padding bits
after each prefix to be cleared.</t>
          </li>
        </ul>
        <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>. It is also possible to index from the end
of the list, e.g., <tt>x[-1]</tt> is the last element of <tt>x</tt>.</t>
      <t>Python uses the symbols <tt>+</tt>, <tt>-</tt>, <tt>*</tt>, and <tt>/</tt> as binary operators. When the
operands are integers, these have the usual meaning, except:</t>
      <ul spacing="normal">
        <li>
          <t>Division results in a floating point number. Python includes a similar
operator, <tt>x // y</tt>, which is short for <tt>floor(x / y)</tt>.</t>
        </li>
        <li>
          <t>When <tt>x</tt> and <tt>y</tt> are byte strings, <tt>x + y</tt> denotes their concatenation, i.e.,
<tt>concat(x, y)</tt> as defined below.</t>
        </li>
      </ul>
      <t>Finite field arithmetic overloads these operators; see <xref target="field"/>.</t>
      <t>Exponentiation is denoted by <tt>x ** y</tt> in Python.</t>
      <t>Bitwise exclusive or is denoted by <tt>x ^ y</tt> in Python.</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 anchor="mathematical-notation">
        <name>Mathematical Notation</name>
        <t>The following symbols are used in mathematical notation.</t>
        <table anchor="mathematical-operators-and-symbols">
          <name>Mathematical Operators and Symbols</name>
          <thead>
            <tr>
              <th align="left">ASCII glyph(s)</th>
              <th align="left">Description</th>
              <th align="left">Comment</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">+, -</td>
              <td align="left">Addition / subtraction</td>
              <td align="left">Needs to be constant time. Used for addition and subtraction of field elements as well as numbers.</td>
            </tr>
            <tr>
              <td align="left">*</td>
              <td align="left">Addition / subtraction</td>
              <td align="left">Needs to be constant time. Used for multiplication of field elements as well as numbers.</td>
            </tr>
            <tr>
              <td align="left">**</td>
              <td align="left">Exponentiation</td>
              <td align="left">Needs to be constant time. Used for exponentiation of field elements as well as numbers.</td>
            </tr>
            <tr>
              <td align="left">/</td>
              <td align="left">Division</td>
              <td align="left">Needs to be constant time. Used for division of field elements (i.e. multiplication by inverse) as well as numbers.</td>
            </tr>
            <tr>
              <td align="left">||</td>
              <td align="left">Concatenation</td>
              <td align="left">Used for concatenation of byte strings and bit strings.</td>
            </tr>
          </tbody>
        </table>
      </section>
    </section>
    <section anchor="overview">
      <name>Overview</name>
      <figure anchor="overall-flow">
        <name>Overall data flow of a (V)DAF.</name>
        <artset>
          <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="336" width="536" viewBox="0 0 536 336" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
              <path d="M 8,176 L 8,208" fill="none" stroke="black"/>
              <path d="M 80,176 L 80,208" fill="none" stroke="black"/>
              <path d="M 96,48 L 96,176" fill="none" stroke="black"/>
              <path d="M 96,208 L 96,304" fill="none" stroke="black"/>
              <path d="M 112,144 L 112,192" fill="none" stroke="black"/>
              <path d="M 136,288 L 136,320" fill="none" stroke="black"/>
              <path d="M 144,32 L 144,64" fill="none" stroke="black"/>
              <path d="M 144,128 L 144,160" fill="none" stroke="black"/>
              <path d="M 208,72 L 208,120" fill="none" stroke="black"/>
              <path d="M 208,168 L 208,192" fill="none" stroke="black"/>
              <path d="M 208,272 L 208,280" fill="none" stroke="black"/>
              <path d="M 264,32 L 264,64" fill="none" stroke="black"/>
              <path d="M 264,128 L 264,160" fill="none" stroke="black"/>
              <path d="M 272,288 L 272,320" fill="none" stroke="black"/>
              <path d="M 288,144 L 288,192" fill="none" stroke="black"/>
              <path d="M 304,48 L 304,176" fill="none" stroke="black"/>
              <path d="M 304,208 L 304,304" fill="none" stroke="black"/>
              <path d="M 328,176 L 328,208" fill="none" stroke="black"/>
              <path d="M 424,176 L 424,208" fill="none" stroke="black"/>
              <path d="M 144,32 L 264,32" fill="none" stroke="black"/>
              <path d="M 96,48 L 136,48" fill="none" stroke="black"/>
              <path d="M 264,48 L 304,48" fill="none" stroke="black"/>
              <path d="M 144,64 L 264,64" fill="none" stroke="black"/>
              <path d="M 144,128 L 264,128" fill="none" stroke="black"/>
              <path d="M 112,144 L 136,144" fill="none" stroke="black"/>
              <path d="M 272,144 L 288,144" fill="none" stroke="black"/>
              <path d="M 144,160 L 264,160" fill="none" stroke="black"/>
              <path d="M 8,176 L 96,176" fill="none" stroke="black"/>
              <path d="M 304,176 L 424,176" fill="none" stroke="black"/>
              <path d="M 80,192 L 112,192" fill="none" stroke="black"/>
              <path d="M 288,192 L 320,192" fill="none" stroke="black"/>
              <path d="M 424,192 L 448,192" fill="none" stroke="black"/>
              <path d="M 8,208 L 96,208" fill="none" stroke="black"/>
              <path d="M 304,208 L 424,208" fill="none" stroke="black"/>
              <path d="M 136,288 L 272,288" fill="none" stroke="black"/>
              <path d="M 96,304 L 128,304" fill="none" stroke="black"/>
              <path d="M 280,304 L 304,304" fill="none" stroke="black"/>
              <path d="M 136,320 L 272,320" fill="none" stroke="black"/>
              <polygon class="arrowhead" points="456,192 444,186.4 444,197.6" fill="black" transform="rotate(0,448,192)"/>
              <polygon class="arrowhead" points="328,208 316,202.4 316,213.6" fill="black" transform="rotate(0,320,208)"/>
              <polygon class="arrowhead" points="328,192 316,186.4 316,197.6" fill="black" transform="rotate(0,320,192)"/>
              <polygon class="arrowhead" points="328,176 316,170.4 316,181.6" fill="black" transform="rotate(0,320,176)"/>
              <polygon class="arrowhead" points="216,280 204,274.4 204,285.6" fill="black" transform="rotate(90,208,280)"/>
              <polygon class="arrowhead" points="216,168 204,162.4 204,173.6" fill="black" transform="rotate(270,208,168)"/>
              <polygon class="arrowhead" points="216,120 204,114.4 204,125.6" fill="black" transform="rotate(90,208,120)"/>
              <polygon class="arrowhead" points="216,72 204,66.4 204,77.6" fill="black" transform="rotate(270,208,72)"/>
              <polygon class="arrowhead" points="144,144 132,138.4 132,149.6" fill="black" transform="rotate(0,136,144)"/>
              <polygon class="arrowhead" points="144,48 132,42.4 132,53.6" fill="black" transform="rotate(0,136,48)"/>
              <polygon class="arrowhead" points="136,304 124,298.4 124,309.6" fill="black" transform="rotate(0,128,304)"/>
              <g class="text">
                <text x="196" y="52">Aggregator</text>
                <text x="248" y="52">0</text>
                <text x="64" y="68">input</text>
                <text x="352" y="68">aggregate</text>
                <text x="60" y="84">shares</text>
                <text x="340" y="84">shares</text>
                <text x="196" y="148">Aggregator</text>
                <text x="248" y="148">1</text>
                <text x="44" y="196">Client</text>
                <text x="376" y="196">Collector</text>
                <text x="496" y="196">aggregate</text>
                <text x="484" y="212">result</text>
                <text x="208" y="228">...</text>
                <text x="208" y="260">|</text>
                <text x="188" y="308">Aggregator</text>
                <text x="248" y="308">N-1</text>
              </g>
            </svg>
          </artwork>
          <artwork type="ascii-art"><![CDATA[
                 +--------------+
           +---->| Aggregator 0 +----+
     input |     +--------------+    | aggregate
    shares |             ^           | shares
           |             |           |
           |             V           |
           |     +--------------+    |
           | +-->| Aggregator 1 |--+ |
           | |   +--------------+  | |
+--------+-+ |           ^         | +->+-----------+
| Client +---+           |         +--->| Collector +--> aggregate
+--------+-+                         +->+-----------+    result
           |            ...          |
           |                         |
           |             |           |
           |             V           |
           |    +----------------+   |
           +--->| Aggregator N-1 |---+
                +----------------+
]]></artwork>
        </artset>
      </figure>
      <t>There are three types of actors in a DAF- or VDAF-based private measurement
system: Clients, Aggregators, and the Collector. The overall flow of the
measurement process is illustrated in <xref target="overall-flow"/>. The steps are as
follows:</t>
      <ol spacing="normal" type="1"><li>
          <t>To submit an individual measurement, a Client shards its measurement into
"input shares" and sends one input share to each Aggregator. This document
sometimes refers to this sequence of input shares collectively as the
Client's "report". (The report contains a few more items needed to process
the measurement; these are described in <xref target="daf"/>.)</t>
        </li>
        <li>
          <t>Once an Aggregator receives an input share from each Client, it processes
the input shares into a value called an "aggregate share" and sends it the
Collector. The aggregate share is a secret share of the aggregate
representation of the measurements.</t>
        </li>
        <li>
          <t>Once the Collector has received an aggregate share from each Aggregator, it
combines them into the aggregate representation of the measurements, called
the "aggregate result".</t>
        </li>
      </ol>
      <t>For DAFs, this second step involves a process called "preparation" in which the
Aggregator refines each input share into an intermediate representation called
an "output share". The output shares are then combined into the aggregate share
as shown in <xref target="overall-flow-prep"/>.</t>
      <figure anchor="overall-flow-prep">
        <name>DAF preparation of input shares into output shares and aggregation of output shares into an aggregate share. Executed by each Aggregator. M denotes the number of measurements being aggregated.</name>
        <artset>
          <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="304" width="416" viewBox="0 0 416 304" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
              <path d="M 8,80 L 8,112" fill="none" stroke="black"/>
              <path d="M 8,208 L 8,240" fill="none" stroke="black"/>
              <path d="M 24,48 L 24,72" fill="none" stroke="black"/>
              <path d="M 24,112 L 24,144" fill="none" stroke="black"/>
              <path d="M 24,168 L 24,200" fill="none" stroke="black"/>
              <path d="M 64,80 L 64,112" fill="none" stroke="black"/>
              <path d="M 128,80 L 128,112" fill="none" stroke="black"/>
              <path d="M 144,48 L 144,72" fill="none" stroke="black"/>
              <path d="M 144,112 L 144,144" fill="none" stroke="black"/>
              <path d="M 144,168 L 144,200" fill="none" stroke="black"/>
              <path d="M 144,240 L 144,272" fill="none" stroke="black"/>
              <path d="M 184,80 L 184,112" fill="none" stroke="black"/>
              <path d="M 280,80 L 280,112" fill="none" stroke="black"/>
              <path d="M 296,48 L 296,72" fill="none" stroke="black"/>
              <path d="M 296,112 L 296,144" fill="none" stroke="black"/>
              <path d="M 296,168 L 296,200" fill="none" stroke="black"/>
              <path d="M 336,80 L 336,112" fill="none" stroke="black"/>
              <path d="M 336,208 L 336,240" fill="none" stroke="black"/>
              <path d="M 8,80 L 64,80" fill="none" stroke="black"/>
              <path d="M 128,80 L 184,80" fill="none" stroke="black"/>
              <path d="M 280,80 L 336,80" fill="none" stroke="black"/>
              <path d="M 8,112 L 64,112" fill="none" stroke="black"/>
              <path d="M 128,112 L 184,112" fill="none" stroke="black"/>
              <path d="M 280,112 L 336,112" fill="none" stroke="black"/>
              <path d="M 8,208 L 336,208" fill="none" stroke="black"/>
              <path d="M 8,240 L 336,240" fill="none" stroke="black"/>
              <polygon class="arrowhead" points="304,200 292,194.4 292,205.6" fill="black" transform="rotate(90,296,200)"/>
              <polygon class="arrowhead" points="304,144 292,138.4 292,149.6" fill="black" transform="rotate(90,296,144)"/>
              <polygon class="arrowhead" points="304,72 292,66.4 292,77.6" fill="black" transform="rotate(90,296,72)"/>
              <polygon class="arrowhead" points="152,272 140,266.4 140,277.6" fill="black" transform="rotate(90,144,272)"/>
              <polygon class="arrowhead" points="152,200 140,194.4 140,205.6" fill="black" transform="rotate(90,144,200)"/>
              <polygon class="arrowhead" points="152,144 140,138.4 140,149.6" fill="black" transform="rotate(90,144,144)"/>
              <polygon class="arrowhead" points="152,72 140,66.4 140,77.6" fill="black" transform="rotate(90,144,72)"/>
              <polygon class="arrowhead" points="32,200 20,194.4 20,205.6" fill="black" transform="rotate(90,24,200)"/>
              <polygon class="arrowhead" points="32,144 20,138.4 20,149.6" fill="black" transform="rotate(90,24,144)"/>
              <polygon class="arrowhead" points="32,72 20,66.4 20,77.6" fill="black" transform="rotate(90,24,72)"/>
              <g class="text">
                <text x="56" y="36">input_share_0</text>
                <text x="176" y="36">input_share_1</text>
                <text x="256" y="36">...</text>
                <text x="344" y="36">input_share_[M-1]</text>
                <text x="36" y="100">prep</text>
                <text x="156" y="100">prep</text>
                <text x="308" y="100">prep</text>
                <text x="48" y="164">out_share_0</text>
                <text x="168" y="164">out_share_1</text>
                <text x="256" y="164">...</text>
                <text x="336" y="164">out_share_[M-1]</text>
                <text x="56" y="228">aggregate</text>
                <text x="160" y="292">agg_share</text>
              </g>
            </svg>
          </artwork>
          <artwork type="ascii-art"><![CDATA[
input_share_0  input_share_1  ... input_share_[M-1]
  |              |                  |
  v              v                  v
+------+       +------+           +------+
| prep |       | prep |           | prep |
+-+----+       +-+----+           +-+----+
  |              |                  |
  v              v                  v
out_share_0    out_share_1    ... out_share_[M-1]
  |              |                  |
  v              v                  v
+----------------------------------------+
| aggregate                              |
+----------------+-----------------------+
                 |
                 v
               agg_share
]]></artwork>
        </artset>
      </figure>
      <t>In the case of VDAFs (<xref target="vdaf"/>), this process is instead called "verification"
and involves interacting with the other Aggregators. It will fail if the
underlying measurement is invalid, in which case the report is rejected and not
included in the aggregate result.</t>
      <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>This document describes 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, it is assumed 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 prefixes in the prefix-counting
functionality of of Poplar1 discussed in <xref target="introduction"/>.</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 each report.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>RAND_SIZE: int</tt></td>
            <td align="left">Size of each 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 each 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>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="384" width="432" viewBox="0 0 432 384" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,144 L 8,176" fill="none" stroke="black"/>
                <path d="M 24,96 L 24,136" fill="none" stroke="black"/>
                <path d="M 24,176 L 24,272" fill="none" stroke="black"/>
                <path d="M 24,304 L 24,336" fill="none" stroke="black"/>
                <path d="M 64,240 L 64,272" fill="none" stroke="black"/>
                <path d="M 64,296 L 64,336" fill="none" stroke="black"/>
                <path d="M 144,176 L 144,272" fill="none" stroke="black"/>
                <path d="M 144,304 L 144,336" fill="none" stroke="black"/>
                <path d="M 192,240 L 192,272" fill="none" stroke="black"/>
                <path d="M 192,304 L 192,336" fill="none" stroke="black"/>
                <path d="M 264,176 L 264,272" fill="none" stroke="black"/>
                <path d="M 264,304 L 264,336" fill="none" stroke="black"/>
                <path d="M 312,176 L 312,192" fill="none" stroke="black"/>
                <path d="M 312,224 L 312,272" fill="none" stroke="black"/>
                <path d="M 312,304 L 312,336" fill="none" stroke="black"/>
                <path d="M 384,144 L 384,176" fill="none" stroke="black"/>
                <path d="M 8,46 L 48,46" fill="none" stroke="black"/>
                <path d="M 8,50 L 48,50" fill="none" stroke="black"/>
                <path d="M 8,144 L 384,144" fill="none" stroke="black"/>
                <path d="M 8,176 L 384,176" fill="none" stroke="black"/>
                <path d="M 64,240 L 136,240" fill="none" stroke="black"/>
                <path d="M 152,240 L 256,240" fill="none" stroke="black"/>
                <path d="M 272,240 L 312,240" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="320,336 308,330.4 308,341.6" fill="black" transform="rotate(90,312,336)"/>
                <polygon class="arrowhead" points="272,336 260,330.4 260,341.6" fill="black" transform="rotate(90,264,336)"/>
                <polygon class="arrowhead" points="272,272 260,266.4 260,277.6" fill="black" transform="rotate(90,264,272)"/>
                <polygon class="arrowhead" points="200,336 188,330.4 188,341.6" fill="black" transform="rotate(90,192,336)"/>
                <polygon class="arrowhead" points="152,336 140,330.4 140,341.6" fill="black" transform="rotate(90,144,336)"/>
                <polygon class="arrowhead" points="152,272 140,266.4 140,277.6" fill="black" transform="rotate(90,144,272)"/>
                <polygon class="arrowhead" points="72,336 60,330.4 60,341.6" fill="black" transform="rotate(90,64,336)"/>
                <polygon class="arrowhead" points="32,336 20,330.4 20,341.6" fill="black" transform="rotate(90,24,336)"/>
                <polygon class="arrowhead" points="32,272 20,266.4 20,277.6" fill="black" transform="rotate(90,24,272)"/>
                <polygon class="arrowhead" points="32,136 20,130.4 20,141.6" fill="black" transform="rotate(90,24,136)"/>
                <g class="text">
                  <text x="28" y="36">Client</text>
                  <text x="48" y="84">measurement</text>
                  <text x="40" y="164">shard</text>
                  <text x="232" y="212">...</text>
                  <text x="348" y="212">public_share</text>
                  <text x="64" y="292">input_share_0</text>
                  <text x="184" y="292">input_share_1</text>
                  <text x="340" y="292">input_share_[SHARES-1]</text>
                  <text x="232" y="324">...</text>
                  <text x="44" y="356">Aggregator</text>
                  <text x="96" y="356">0</text>
                  <text x="164" y="356">Aggregator</text>
                  <text x="216" y="356">1</text>
                  <text x="292" y="356">Aggregator</text>
                  <text x="372" y="356">SHARES-1</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![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>
          </artset>
        </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-verify-flow">
          <name>Illustration of preparation.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="240" width="488" viewBox="0 0 488 240" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,128 L 8,160" fill="none" stroke="black"/>
                <path d="M 24,96 L 24,120" fill="none" stroke="black"/>
                <path d="M 24,160 L 24,192" fill="none" stroke="black"/>
                <path d="M 104,128 L 104,160" fill="none" stroke="black"/>
                <path d="M 128,128 L 128,160" fill="none" stroke="black"/>
                <path d="M 144,96 L 144,120" fill="none" stroke="black"/>
                <path d="M 144,160 L 144,192" fill="none" stroke="black"/>
                <path d="M 224,128 L 224,160" fill="none" stroke="black"/>
                <path d="M 312,128 L 312,160" fill="none" stroke="black"/>
                <path d="M 328,96 L 328,120" fill="none" stroke="black"/>
                <path d="M 328,160 L 328,192" fill="none" stroke="black"/>
                <path d="M 408,128 L 408,160" fill="none" stroke="black"/>
                <path d="M 8,46 L 96,46" fill="none" stroke="black"/>
                <path d="M 8,50 L 96,50" fill="none" stroke="black"/>
                <path d="M 128,46 L 216,46" fill="none" stroke="black"/>
                <path d="M 128,50 L 216,50" fill="none" stroke="black"/>
                <path d="M 312,46 L 456,46" fill="none" stroke="black"/>
                <path d="M 312,50 L 456,50" fill="none" stroke="black"/>
                <path d="M 8,128 L 104,128" fill="none" stroke="black"/>
                <path d="M 128,128 L 224,128" fill="none" stroke="black"/>
                <path d="M 312,128 L 408,128" fill="none" stroke="black"/>
                <path d="M 8,160 L 104,160" fill="none" stroke="black"/>
                <path d="M 128,160 L 224,160" fill="none" stroke="black"/>
                <path d="M 312,160 L 408,160" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="336,192 324,186.4 324,197.6" fill="black" transform="rotate(90,328,192)"/>
                <polygon class="arrowhead" points="336,120 324,114.4 324,125.6" fill="black" transform="rotate(90,328,120)"/>
                <polygon class="arrowhead" points="152,192 140,186.4 140,197.6" fill="black" transform="rotate(90,144,192)"/>
                <polygon class="arrowhead" points="152,120 140,114.4 140,125.6" fill="black" transform="rotate(90,144,120)"/>
                <polygon class="arrowhead" points="32,192 20,186.4 20,197.6" fill="black" transform="rotate(90,24,192)"/>
                <polygon class="arrowhead" points="32,120 20,114.4 20,125.6" fill="black" transform="rotate(90,24,120)"/>
                <g class="text">
                  <text x="44" y="36">Aggregator</text>
                  <text x="96" y="36">0</text>
                  <text x="164" y="36">Aggregator</text>
                  <text x="216" y="36">1</text>
                  <text x="348" y="36">Aggregator</text>
                  <text x="428" y="36">SHARES-1</text>
                  <text x="56" y="84">input_share_0</text>
                  <text x="176" y="84">input_share_1</text>
                  <text x="396" y="84">input_share_[SHARES-1]</text>
                  <text x="296" y="100">...</text>
                  <text x="36" y="148">prep</text>
                  <text x="156" y="148">prep</text>
                  <text x="340" y="148">prep</text>
                  <text x="296" y="180">...</text>
                  <text x="48" y="212">out_share_0</text>
                  <text x="168" y="212">out_share_1</text>
                  <text x="388" y="212">out_share_[SHARES-1]</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![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>
          </artset>
        </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>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="432" width="424" viewBox="0 0 424 432" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,80 L 8,112" fill="none" stroke="black"/>
                <path d="M 112,80 L 112,112" fill="none" stroke="black"/>
                <path d="M 152,80 L 152,112" fill="none" stroke="black"/>
                <path d="M 152,160 L 152,192" fill="none" stroke="black"/>
                <path d="M 152,320 L 152,352" fill="none" stroke="black"/>
                <path d="M 176,112 L 176,152" fill="none" stroke="black"/>
                <path d="M 176,192 L 176,224" fill="none" stroke="black"/>
                <path d="M 176,288 L 176,312" fill="none" stroke="black"/>
                <path d="M 176,352 L 176,384" fill="none" stroke="black"/>
                <path d="M 256,80 L 256,112" fill="none" stroke="black"/>
                <path d="M 256,160 L 256,192" fill="none" stroke="black"/>
                <path d="M 256,320 L 256,352" fill="none" stroke="black"/>
                <path d="M 8,46 L 96,46" fill="none" stroke="black"/>
                <path d="M 8,50 L 96,50" fill="none" stroke="black"/>
                <path d="M 8,80 L 112,80" fill="none" stroke="black"/>
                <path d="M 152,80 L 256,80" fill="none" stroke="black"/>
                <path d="M 112,96 L 144,96" fill="none" stroke="black"/>
                <path d="M 264,96 L 288,96" fill="none" stroke="black"/>
                <path d="M 8,112 L 112,112" fill="none" stroke="black"/>
                <path d="M 152,112 L 256,112" fill="none" stroke="black"/>
                <path d="M 152,160 L 256,160" fill="none" stroke="black"/>
                <path d="M 264,176 L 288,176" fill="none" stroke="black"/>
                <path d="M 152,192 L 256,192" fill="none" stroke="black"/>
                <path d="M 152,320 L 256,320" fill="none" stroke="black"/>
                <path d="M 264,336 L 288,336" fill="none" stroke="black"/>
                <path d="M 152,352 L 256,352" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="272,336 260,330.4 260,341.6" fill="black" transform="rotate(180,264,336)"/>
                <polygon class="arrowhead" points="272,176 260,170.4 260,181.6" fill="black" transform="rotate(180,264,176)"/>
                <polygon class="arrowhead" points="272,96 260,90.4 260,101.6" fill="black" transform="rotate(180,264,96)"/>
                <polygon class="arrowhead" points="184,384 172,378.4 172,389.6" fill="black" transform="rotate(90,176,384)"/>
                <polygon class="arrowhead" points="184,312 172,306.4 172,317.6" fill="black" transform="rotate(90,176,312)"/>
                <polygon class="arrowhead" points="184,224 172,218.4 172,229.6" fill="black" transform="rotate(90,176,224)"/>
                <polygon class="arrowhead" points="184,152 172,146.4 172,157.6" fill="black" transform="rotate(90,176,152)"/>
                <polygon class="arrowhead" points="152,96 140,90.4 140,101.6" fill="black" transform="rotate(0,144,96)"/>
                <g class="text">
                  <text x="44" y="36">Aggregator</text>
                  <text x="96" y="36">j</text>
                  <text x="52" y="100">agg_init</text>
                  <text x="204" y="100">agg_update</text>
                  <text x="344" y="100">out_share_0</text>
                  <text x="204" y="180">agg_update</text>
                  <text x="344" y="180">out_share_1</text>
                  <text x="176" y="260">...</text>
                  <text x="204" y="340">agg_update</text>
                  <text x="360" y="340">out_share_[M-1]</text>
                  <text x="200" y="404">agg_share_j</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
    Aggregator j
    ============

    +------------+    +------------+
    | agg_init   +--->| agg_update |<--- out_share_0
    +------------+    +--+---------+
                         |
                         v
                      +------------+
                      | agg_update |<--- out_share_1
                      +--+---------+
                         |
                         v

                        ...

                         |
                         v
                      +------------+
                      | agg_update |<--- out_share_[M-1]
                      +--+---------+
                         |
                         v
                       agg_share_j
]]></artwork>
          </artset>
        </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>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="288" width="456" viewBox="0 0 456 288" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,128 L 8,160" fill="none" stroke="black"/>
                <path d="M 24,88 L 24,120" fill="none" stroke="black"/>
                <path d="M 24,160 L 24,192" fill="none" stroke="black"/>
                <path d="M 152,88 L 152,120" fill="none" stroke="black"/>
                <path d="M 312,88 L 312,120" fill="none" stroke="black"/>
                <path d="M 392,128 L 392,160" fill="none" stroke="black"/>
                <path d="M 8,46 L 96,46" fill="none" stroke="black"/>
                <path d="M 8,50 L 96,50" fill="none" stroke="black"/>
                <path d="M 136,46 L 224,46" fill="none" stroke="black"/>
                <path d="M 136,50 L 224,50" fill="none" stroke="black"/>
                <path d="M 296,46 L 440,46" fill="none" stroke="black"/>
                <path d="M 296,50 L 440,50" fill="none" stroke="black"/>
                <path d="M 8,128 L 392,128" fill="none" stroke="black"/>
                <path d="M 8,160 L 392,160" fill="none" stroke="black"/>
                <path d="M 8,254 L 72,254" fill="none" stroke="black"/>
                <path d="M 8,258 L 72,258" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="320,120 308,114.4 308,125.6" fill="black" transform="rotate(90,312,120)"/>
                <polygon class="arrowhead" points="160,120 148,114.4 148,125.6" fill="black" transform="rotate(90,152,120)"/>
                <polygon class="arrowhead" points="32,192 20,186.4 20,197.6" fill="black" transform="rotate(90,24,192)"/>
                <polygon class="arrowhead" points="32,120 20,114.4 20,125.6" fill="black" transform="rotate(90,24,120)"/>
                <g class="text">
                  <text x="44" y="36">Aggregator</text>
                  <text x="96" y="36">0</text>
                  <text x="172" y="36">Aggregator</text>
                  <text x="224" y="36">1</text>
                  <text x="332" y="36">Aggregator</text>
                  <text x="412" y="36">SHARES-1</text>
                  <text x="48" y="84">agg_share_0</text>
                  <text x="176" y="84">agg_share_1</text>
                  <text x="372" y="84">agg_share_[SHARES-1]</text>
                  <text x="48" y="148">unshard</text>
                  <text x="44" y="212">agg_result</text>
                  <text x="40" y="244">Collector</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![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>
          </artset>
        </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 the non-interactive preparation process
is replaced by an interactive process called "verification" in which, in
addition to refining their input shares into output shares, the Aggregators
also verify that they hold valid output shares.</t>
      <t>Failure manifests as an exception raised by one of the algorithms defined in
this section. If an exception is raised during verification, 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, denoted 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 verification.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>NONCE_SIZE: int</tt></td>
            <td align="left">Size of each report nonce.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>RAND_SIZE: int</tt></td>
            <td align="left">Size of each 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 verification.</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 each 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>VerifyState</tt></td>
            <td align="left">Type of each verification state.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>VerifierShare</tt></td>
            <td align="left">Type of each verifier share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>VerifierMessage</tt></td>
            <td align="left">Type of each verifier 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>VerifierShare</tt>, and
<tt>VerifierMessage</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 the 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 verification 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 verification
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-verify">
        <name>Verification</name>
        <figure anchor="verify-flow">
          <name>Illustration of interactive VDAF verification.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="496" width="520" viewBox="0 0 520 496" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,128 L 8,160" fill="none" stroke="black"/>
                <path d="M 8,208 L 8,240" fill="none" stroke="black"/>
                <path d="M 8,288 L 8,320" fill="none" stroke="black"/>
                <path d="M 24,96 L 24,120" fill="none" stroke="black"/>
                <path d="M 24,160 L 24,200" fill="none" stroke="black"/>
                <path d="M 24,240 L 24,280" fill="none" stroke="black"/>
                <path d="M 24,320 L 24,352" fill="none" stroke="black"/>
                <path d="M 24,416 L 24,448" fill="none" stroke="black"/>
                <path d="M 104,160 L 104,280" fill="none" stroke="black"/>
                <path d="M 104,320 L 104,352" fill="none" stroke="black"/>
                <path d="M 120,128 L 120,160" fill="none" stroke="black"/>
                <path d="M 120,288 L 120,320" fill="none" stroke="black"/>
                <path d="M 144,128 L 144,160" fill="none" stroke="black"/>
                <path d="M 144,288 L 144,320" fill="none" stroke="black"/>
                <path d="M 160,96 L 160,120" fill="none" stroke="black"/>
                <path d="M 160,160 L 160,200" fill="none" stroke="black"/>
                <path d="M 160,240 L 160,280" fill="none" stroke="black"/>
                <path d="M 160,320 L 160,352" fill="none" stroke="black"/>
                <path d="M 160,416 L 160,448" fill="none" stroke="black"/>
                <path d="M 240,160 L 240,208" fill="none" stroke="black"/>
                <path d="M 240,240 L 240,280" fill="none" stroke="black"/>
                <path d="M 240,320 L 240,352" fill="none" stroke="black"/>
                <path d="M 256,128 L 256,160" fill="none" stroke="black"/>
                <path d="M 256,288 L 256,320" fill="none" stroke="black"/>
                <path d="M 328,128 L 328,160" fill="none" stroke="black"/>
                <path d="M 328,288 L 328,320" fill="none" stroke="black"/>
                <path d="M 344,96 L 344,120" fill="none" stroke="black"/>
                <path d="M 344,160 L 344,200" fill="none" stroke="black"/>
                <path d="M 344,240 L 344,280" fill="none" stroke="black"/>
                <path d="M 344,320 L 344,352" fill="none" stroke="black"/>
                <path d="M 344,416 L 344,448" fill="none" stroke="black"/>
                <path d="M 424,160 L 424,280" fill="none" stroke="black"/>
                <path d="M 424,320 L 424,352" fill="none" stroke="black"/>
                <path d="M 440,128 L 440,160" fill="none" stroke="black"/>
                <path d="M 440,288 L 440,320" fill="none" stroke="black"/>
                <path d="M 448,208 L 448,240" fill="none" stroke="black"/>
                <path d="M 480,224 L 480,336" fill="none" stroke="black"/>
                <path d="M 8,46 L 96,46" fill="none" stroke="black"/>
                <path d="M 8,50 L 96,50" fill="none" stroke="black"/>
                <path d="M 128,46 L 216,46" fill="none" stroke="black"/>
                <path d="M 128,50 L 216,50" fill="none" stroke="black"/>
                <path d="M 312,46 L 456,46" fill="none" stroke="black"/>
                <path d="M 312,50 L 456,50" fill="none" stroke="black"/>
                <path d="M 8,128 L 120,128" fill="none" stroke="black"/>
                <path d="M 144,128 L 256,128" fill="none" stroke="black"/>
                <path d="M 328,128 L 440,128" fill="none" stroke="black"/>
                <path d="M 8,160 L 120,160" fill="none" stroke="black"/>
                <path d="M 144,160 L 256,160" fill="none" stroke="black"/>
                <path d="M 328,160 L 440,160" fill="none" stroke="black"/>
                <path d="M 8,208 L 96,208" fill="none" stroke="black"/>
                <path d="M 112,208 L 232,208" fill="none" stroke="black"/>
                <path d="M 248,208 L 416,208" fill="none" stroke="black"/>
                <path d="M 432,208 L 448,208" fill="none" stroke="black"/>
                <path d="M 8,240 L 96,240" fill="none" stroke="black"/>
                <path d="M 112,240 L 232,240" fill="none" stroke="black"/>
                <path d="M 248,240 L 416,240" fill="none" stroke="black"/>
                <path d="M 432,240 L 448,240" fill="none" stroke="black"/>
                <path d="M 8,288 L 120,288" fill="none" stroke="black"/>
                <path d="M 144,288 L 256,288" fill="none" stroke="black"/>
                <path d="M 328,288 L 440,288" fill="none" stroke="black"/>
                <path d="M 8,320 L 120,320" fill="none" stroke="black"/>
                <path d="M 144,320 L 256,320" fill="none" stroke="black"/>
                <path d="M 328,320 L 440,320" fill="none" stroke="black"/>
                <path d="M 464,208 C 472.83064,208 480,215.16936 480,224" fill="none" stroke="black"/>
                <path d="M 464,352 C 472.83064,352 480,344.83064 480,336" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="432,352 420,346.4 420,357.6" fill="black" transform="rotate(90,424,352)"/>
                <polygon class="arrowhead" points="432,280 420,274.4 420,285.6" fill="black" transform="rotate(90,424,280)"/>
                <polygon class="arrowhead" points="352,448 340,442.4 340,453.6" fill="black" transform="rotate(90,344,448)"/>
                <polygon class="arrowhead" points="352,352 340,346.4 340,357.6" fill="black" transform="rotate(90,344,352)"/>
                <polygon class="arrowhead" points="352,280 340,274.4 340,285.6" fill="black" transform="rotate(90,344,280)"/>
                <polygon class="arrowhead" points="352,200 340,194.4 340,205.6" fill="black" transform="rotate(90,344,200)"/>
                <polygon class="arrowhead" points="352,120 340,114.4 340,125.6" fill="black" transform="rotate(90,344,120)"/>
                <polygon class="arrowhead" points="248,352 236,346.4 236,357.6" fill="black" transform="rotate(90,240,352)"/>
                <polygon class="arrowhead" points="248,280 236,274.4 236,285.6" fill="black" transform="rotate(90,240,280)"/>
                <polygon class="arrowhead" points="168,448 156,442.4 156,453.6" fill="black" transform="rotate(90,160,448)"/>
                <polygon class="arrowhead" points="168,352 156,346.4 156,357.6" fill="black" transform="rotate(90,160,352)"/>
                <polygon class="arrowhead" points="168,280 156,274.4 156,285.6" fill="black" transform="rotate(90,160,280)"/>
                <polygon class="arrowhead" points="168,200 156,194.4 156,205.6" fill="black" transform="rotate(90,160,200)"/>
                <polygon class="arrowhead" points="168,120 156,114.4 156,125.6" fill="black" transform="rotate(90,160,120)"/>
                <polygon class="arrowhead" points="112,352 100,346.4 100,357.6" fill="black" transform="rotate(90,104,352)"/>
                <polygon class="arrowhead" points="112,280 100,274.4 100,285.6" fill="black" transform="rotate(90,104,280)"/>
                <polygon class="arrowhead" points="32,448 20,442.4 20,453.6" fill="black" transform="rotate(90,24,448)"/>
                <polygon class="arrowhead" points="32,352 20,346.4 20,357.6" fill="black" transform="rotate(90,24,352)"/>
                <polygon class="arrowhead" points="32,280 20,274.4 20,285.6" fill="black" transform="rotate(90,24,280)"/>
                <polygon class="arrowhead" points="32,200 20,194.4 20,205.6" fill="black" transform="rotate(90,24,200)"/>
                <polygon class="arrowhead" points="32,120 20,114.4 20,125.6" fill="black" transform="rotate(90,24,120)"/>
                <g class="text">
                  <text x="44" y="36">Aggregator</text>
                  <text x="96" y="36">0</text>
                  <text x="164" y="36">Aggregator</text>
                  <text x="216" y="36">1</text>
                  <text x="348" y="36">Aggregator</text>
                  <text x="428" y="36">SHARES-1</text>
                  <text x="56" y="84">input_share_0</text>
                  <text x="192" y="84">input_share_1</text>
                  <text x="404" y="84">input_share_[SHARES-1]</text>
                  <text x="312" y="100">...</text>
                  <text x="64" y="148">verify_init</text>
                  <text x="200" y="148">verify_init</text>
                  <text x="384" y="148">verify_init</text>
                  <text x="312" y="180">...</text>
                  <text x="260" y="228">verifier_shares_to_message</text>
                  <text x="512" y="244">R</text>
                  <text x="312" y="260">...</text>
                  <text x="512" y="260">O</text>
                  <text x="496" y="276">x</text>
                  <text x="512" y="276">U</text>
                  <text x="512" y="292">N</text>
                  <text x="64" y="308">verify_next</text>
                  <text x="200" y="308">verify_next</text>
                  <text x="384" y="308">verify_next</text>
                  <text x="512" y="308">D</text>
                  <text x="512" y="324">S</text>
                  <text x="312" y="340">...</text>
                  <text x="24" y="388">...</text>
                  <text x="144" y="388">...</text>
                  <text x="312" y="388">...</text>
                  <text x="312" y="420">...</text>
                  <text x="48" y="468">out_share_0</text>
                  <text x="184" y="468">out_share_1</text>
                  <text x="396" y="468">out_share_[SHARES-1]</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
    Aggregator 0   Aggregator 1           Aggregator SHARES-1
    ============   ============           ===================

    input_share_0    input_share_1         input_share_[SHARES-1]
      |                |                 ...  |
      v                v                      v
    +-------------+  +-------------+        +-------------+
    | verify_init |  | verify_init |        | verify_init |
    +-+---------+-+  +-+---------+-+        +-+---------+-+
      |         |      |         |       ...  |         |
      v         |      v         |            v         |
    +-----------|----------------|----------------------|--+ -.
    |           |      verifier_shares_to_message       |  |   |
    +-+---------|------+---------|------------+---------|--+   |   R
      |         |      |         |       ...  |         |      |   O
      v         v      v         v            v         v      | x U
    +-------------+  +-------------+        +-------------+    |   N
    | verify_next |  | verify_next |        | verify_next |    |   D
    +-+---------+-+  +-+---------+-+        +-+---------+-+    |   S
      |         |      |         |       ...  |         |      |
      v         v      v         v            v         v    -'

     ...            ...                  ...

      |                |                 ...  |
      |                |                      |
      v                v                      v
    out_share_0      out_share_1           out_share_[SHARES-1]
]]></artwork>
          </artset>
        </figure>
        <t>Verification 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 verification.
This is referred to as "verification state", usually written as <tt>verify_state</tt>
for short.</t>
        <t>During each round, each Aggregator broadcasts a message called a "verifier
share", usually written <tt>verifier_share</tt>. The verifier shares are then combined
into a single message called the "verifier message", or <tt>verifier_message</tt>. The
verifier message is computed from public information and therefore <bcp14>MAY</bcp14> be
computed by any one of the Aggregators.</t>
        <t>The verifier 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 verification state and the
previous verifier message. Its output in the last round is its output share and
its output in each of the preceding rounds is a verifier share.</t>
        <t>Just as for DAF preparation involves an aggregation parameter
(<xref target="sec-daf-prepare"/>), so does VDAF verification. The aggregation parameter is
consumed by each Aggregator before the first round of communication.</t>
        <t>In addition, VDAF verification 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>Verification is implemented by the following set of algorithms:</t>
        <ul spacing="normal">
          <li>
            <t><tt>vdaf.verify_init(verify_key: bytes, ctx: bytes, agg_id: int, agg_param:
AggParam, nonce: bytes, public_share: PublicShare, input_share: InputShare)
-&gt; tuple[VerifyState, VerifierShare]</tt> is the deterministic verification 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 verification state and outbound verifier
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.verifier_shares_to_message(ctx: bytes, agg_param: AggParam,
verifier_shares: list[VerifierShare]) -&gt; VerifierMessage</tt> is the
deterministic verifier message pre-processing algorithm. It combines the
verifier shares produced by the Aggregators in the previous round into the
verifier message consumed by each Aggregator to start the next round.</t>
          </li>
          <li>
            <t><tt>vdaf.verify_next(ctx: bytes, verify_state: VerifyState, verifier_message:
VerifierMessage) -&gt; tuple[VerifyState, VerifierShare] | OutShare</tt> is the
deterministic verification state update algorithm run by each Aggregator. It
updates the Aggregator's verification state (<tt>verify_state</tt>) and returns
either its next verification state and verifier 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 verification 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 verification
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>The following function describes the sequence of computations that are carried
out during VDAF execution:</t>
        <sourcecode type="python"><![CDATA[
def run_vdaf(
        vdaf: Vdaf[
            Measurement,
            AggParam,
            PublicShare,
            InputShare,
            OutShare,
            AggShare,
            AggResult,
            VerifyState,
            VerifierShare,
            VerifierMessage,
        ],
        verify_key: bytes,
        agg_param: AggParam,
        ctx: bytes,
        measurements: list[Measurement]) -> AggResult:
    """
    Execute the VDAF for the given measurements, aggregation
    parameter (`agg_param`), application context (`ctx`), and
    verification key (`verify_key`).
    """
    agg_shares = [vdaf.agg_init(agg_param)
                  for _ in range(vdaf.SHARES)]
    for measurement in measurements:
        # Sharding: The Client shards its measurement into a report
        # consisting of a public share and a sequence of input
        # shares.
        nonce = gen_rand(vdaf.NONCE_SIZE)
        rand = gen_rand(vdaf.RAND_SIZE)
        (public_share, input_shares) = \
            vdaf.shard(ctx, measurement, nonce, rand)

        # Initialize verification: Each Aggregator receives its
        # report share (the public share and its input share) from
        # the Client and initializes verification.
        verify_states = []
        outbound_verifier_shares = []
        for j in range(vdaf.SHARES):
            (state, share) = vdaf.verify_init(verify_key, ctx, j,
                                              agg_param,
                                              nonce,
                                              public_share,
                                              input_shares[j])
            verify_states.append(state)
            outbound_verifier_shares.append(share)

        # Complete verification: The Aggregators execute each round
        # of verification until each computes an output share. A
        # round begins by gathering the verifier shares and combining
        # them into the verifier message. The round ends when each
        # uses the verifier message to transition to the next state.
        for i in range(vdaf.ROUNDS - 1):
            verifier_message = vdaf.verifier_shares_to_message(
                ctx, agg_param, outbound_verifier_shares)

            outbound_verifier_shares = []
            for j in range(vdaf.SHARES):
                out = vdaf.verify_next(ctx,
                                       verify_states[j],
                                       verifier_message)
                assert isinstance(out, tuple)
                (verify_states[j], verifier_share) = out
                outbound_verifier_shares.append(verifier_share)

        verifier_message = vdaf.verifier_shares_to_message(
            ctx, agg_param, outbound_verifier_shares)

        # Aggregation: Each Aggregator updates its aggregate share
        # with its output share.
        for j in range(vdaf.SHARES):
            out_share = vdaf.verify_next(
                ctx, verify_states[j], verifier_message)
            assert not isinstance(out_share, tuple)
            agg_shares[j] = vdaf.agg_update(agg_param,
                                            agg_shares[j],
                                            out_share)

    # Unsharding: The Collector receives the aggregate shares from
    # the Aggregators and combines them into the aggregate result.
    num_measurements = len(measurements)
    agg_result = vdaf.unshard(agg_param, agg_shares,
                              num_measurements)
    return agg_result
]]></sourcecode>
        <t>Depending on the VDAF, verification, aggregation, and collection may be carried
out multiple times on the same sequence of reports.</t>
        <t>In practice, VDAF execution is distributed across Clients, Aggregators, and
Collectors that exchange messages (i.e., report shares, verifier shares, and
aggregate shares) over an insecure network. The application must therefore take
some additional steps in order to securely execute the VDAF in this
environment. See <xref target="security"/> for details.</t>
      </section>
      <section anchor="vdaf-verify-comm">
        <name>Communication Patterns for Verification</name>
        <t>The only stage of VDAF execution that requires interaction is verification
(<xref target="sec-vdaf-verify"/>). 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 verification, each Aggregator writes a verifier share to some
broadcast channel, which is then processed into the verifier message using the
public <tt>verifier_shares_to_message()</tt> algorithm and broadcast to the
Aggregators to start the next round. The goal of this section is to realize
this broadcast channel.</t>
        <t>The state machine of each Aggregator is shown below.</t>
        <figure anchor="vdaf-verification-state-machine">
          <name>State machine of VDAF verification.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="144" width="488" viewBox="0 0 488 144" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 16,32 L 16,64" fill="none" stroke="black"/>
                <path d="M 16,96 L 16,128" fill="none" stroke="black"/>
                <path d="M 152,32 L 152,64" fill="none" stroke="black"/>
                <path d="M 184,32 L 184,72" fill="none" stroke="black"/>
                <path d="M 304,32 L 304,64" fill="none" stroke="black"/>
                <path d="M 400,40 L 400,120" fill="none" stroke="black"/>
                <path d="M 16,32 L 40,32" fill="none" stroke="black"/>
                <path d="M 128,32 L 152,32" fill="none" stroke="black"/>
                <path d="M 184,32 L 304,32" fill="none" stroke="black"/>
                <path d="M 56,80 L 96,80" fill="none" stroke="black"/>
                <path d="M 16,128 L 144,128" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="408,120 396,114.4 396,125.6" fill="black" transform="rotate(90,400,120)"/>
                <polygon class="arrowhead" points="408,40 396,34.4 396,45.6" fill="black" transform="rotate(270,400,40)"/>
                <polygon class="arrowhead" points="312,64 300,58.4 300,69.6" fill="black" transform="rotate(90,304,64)"/>
                <polygon class="arrowhead" points="152,128 140,122.4 140,133.6" fill="black" transform="rotate(0,144,128)"/>
                <polygon class="arrowhead" points="136,32 124,26.4 124,37.6" fill="black" transform="rotate(180,128,32)"/>
                <polygon class="arrowhead" points="104,80 92,74.4 92,85.6" fill="black" transform="rotate(0,96,80)"/>
                <polygon class="arrowhead" points="48,32 36,26.4 36,37.6" fill="black" transform="rotate(0,40,32)"/>
                <g class="text">
                  <text x="84" y="36">Rejected</text>
                  <text x="408" y="36">Finished(out_share)</text>
                  <text x="24" y="84">Start</text>
                  <text x="200" y="84">Continued(verify_state,</text>
                  <text x="348" y="84">verify_round</text>
                  <text x="448" y="84">outbound)</text>
                  <text x="280" y="132">FinishedWithOutbound(out_share,</text>
                  <text x="448" y="132">outbound)</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
 +--> Rejected <--+   +--------------+   Finished(out_share)
 |                |   |              |           ^
 |                |   |              v           |
Start -----> Continued(verify_state, verify_round, outbound)
 |                                               |
 |                                               v
 +---------------> FinishedWithOutbound(out_share, outbound)
]]></artwork>
          </artset>
        </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; <tt>Finished(out_share)</tt>, indicating that the
Aggregator has recovered an output share <tt>out_share</tt>; and
<tt>FinishedWithOutbound(out_share, outbound)</tt>, indicating that the Aggregator has
recovered an output share, and has one more outbound message to send. For
completeness, these states are defined 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, verifier shares, verifier 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>In this section, the initiating Aggregator is called the Leader and the
responding Aggregator is called 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 verifier
share to the Helper, who computes the verifier message locally, computes its
output share, then sends the verifier message to the Leader. Verification
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 verifier share to the Helper, who replies with the first-round
verifier message and its second-round verifier share. In the next request,
the Leader computes its second-round verifier share locally, computes its
output share, and sends the second-round verifier message to the Helper.
Finally, the Helper computes its own output share.</t>
            </li>
            <li>
              <t>In general, each request includes the Leader's verifier share for the
previous round and/or the verifier message for the current round;
correspondingly, each response consists of the verifier message for the
current round and the Helper's verifier 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
verification is completed. All told there are <tt>ceil((vdaf.ROUNDS+1)/2)</tt>
requests sent.</t>
          <t>Protocol messages are specified 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 verifier_share<0..4294967295>;
    case continue:
      opaque verifier_message<0..4294967295>;
      opaque verifier_share<0..4294967295>;
    case finish:
      opaque verifier_message<0..4294967295>;
  };
} Message;

/* note that 4294967295 is 2 ** 32 - 1 */
]]></sourcecode>
          <t>These messages trigger all transitions in the state machine in
<xref target="vdaf-verification-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) -> Continued | Rejected:
    """Called by the Leader to initialize ping-ponging."""
    try:
        (verify_state, verifier_share) = self.verify_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_verifier_share = self.encode_verifier_share(
            verifier_share)
        return Continued(
            verify_state, 0,
            encode(0, encoded_verifier_share),  # initialize
        )
    except Exception:
        return Rejected()
]]></sourcecode>
          <t>The output is the <tt>State</tt> to which the Leader has transitioned. If the Leader's
state is <tt>Rejected</tt>, then processing halts. Otherwise, if the state is
<tt>Continued</tt>, then processing continues. In this case, the state also includes
the Leader's outbound message. 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,  # encoded ping pong Message
) -> Continued | FinishedWithOutbound | Rejected:
    """
    Called by the Helper in response to the Leader's initial
    message.
    """

    try:
        (verify_state, verifier_share) = self.verify_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()

        encoded_verifier_share = inbound_items[0]
        verifier_shares = [
            self.decode_verifier_share(
                verify_state, encoded_verifier_share),
            verifier_share,
        ]
        return self.ping_pong_transition(
            ctx, self.decode_agg_param(agg_param),
            verifier_shares, verify_state, 0)
    except Exception:
        return Rejected()
]]></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 verifier
shares, combines them into the verifier message, and computes the next
verification state of the caller:</t>
          <sourcecode type="python"><![CDATA[
def ping_pong_transition(
        self,
        ctx: bytes,
        agg_param: AggParam,
        verifier_shares: list[VerifierShare],
        verify_state: VerifyState,
        verify_round: int) -> Continued | FinishedWithOutbound:
    verifier_message = self.verifier_shares_to_message(
        ctx, agg_param, verifier_shares)
    encoded_verifier_message = self.encode_verifier_message(
        verifier_message)
    out = self.verify_next(ctx, verify_state, verifier_message)
    if verify_round+1 == self.ROUNDS:
        return FinishedWithOutbound(
            out, encode(2, encoded_verifier_message))  # finalize
    (verify_state, verifier_share) = cast(
        tuple[VerifyState, VerifierShare], out)
    encoded_verifier_share = self.encode_verifier_share(
        verifier_share)
    return Continued(
        verify_state, verify_round+1,
        encode(1, encoded_verifier_message,
               encoded_verifier_share))  # continue
]]></sourcecode>
          <t>The output is the <tt>State</tt> to which the Helper has transitioned. If the Helper's
state is <tt>Finished</tt> or <tt>Rejected</tt>, then processing halts. Otherwise, if the
state is <tt>Continued</tt> or <tt>FinishedWithOutbound</tt>, then the state include an
outbound message and 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: Continued,
    inbound: bytes,  # encoded ping pong Message
) -> State:
    """
    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: Continued,
    inbound: bytes,  # encoded ping pong Message
) -> State:
    try:
        verify_round = state.verify_round

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

        encoded_verifier_message = inbound_items[0]
        verifier_message = self.decode_verifier_message(
            state.verify_state,
            encoded_verifier_message,
        )
        out = self.verify_next(
            ctx, state.verify_state, verifier_message)
        if verify_round+1 < self.ROUNDS and \
                inbound_type == 1:  # continue
            (verify_state, verifier_share) = cast(
                tuple[VerifyState, VerifierShare], out)
            encoded_verifier_share = inbound_items[1]
            verifier_shares = [
                self.decode_verifier_share(
                    verify_state, encoded_verifier_share),
                verifier_share,
            ]
            if is_leader:
                verifier_shares.reverse()
            return self.ping_pong_transition(
                ctx, self.decode_agg_param(agg_param),
                verifier_shares, verify_state, verify_round+1)
        elif verify_round+1 == self.ROUNDS and \
                inbound_type == 2:  # finish
            return Finished(out)
        else:
            return Rejected()
    except Exception:
        return Rejected()
]]></sourcecode>
          <t>If the Leader's state is <tt>Finished</tt> or <tt>Rejected</tt>, then processing halts.
Otherwise, if the Leader's state is <tt>Continued</tt> or <tt>FinishedWithOutbound</tt>, 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: Continued,
    inbound: bytes,  # encoded ping pong Message
) -> State:
    """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 verification 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>Again, one Aggregator initiates the computation. This Aggregator is called the
Leader and all other Aggregators are called Helpers.</t>
          <t>At the start of each round, the Leader requests from each Helper its verifier
share. After gathering each of the verifier shares, the Leader computes the
next verifier message (via <tt>vdaf.verifier_shares_to_message()</tt>) and broadcasts
it to the Helpers. At this point, each Aggregator runs <tt>vdaf.verify_next()</tt>
locally to either recover an output share or, if more rounds of verification
are required, compute its updated state and verifier share. If another round is
required, then the Helper responds to the broadcast message with its next
verifier 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>Conversion of a field element to an <tt>int</tt> is denoted 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 called "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="RFC9861"/>. This XOF is <bcp14>RECOMMENDED</bcp14> for all use cases
for DAFs and VDAFs.</t>
          <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. This input is called 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. (These are specified 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 verification, each Aggregator performs some computation
on its measurement share and proof share locally, then broadcasts the result in
its verifier share. The validity decision is then made by the
<tt>verifier_shares_to_message()</tt> algorithm (<xref target="sec-vdaf-verify"/>).</t>
        <t>As usual, the interface implemented by a concrete FLP is described in terms of
an object <tt>flp</tt> of type <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>This 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 verifiability for the
VDAF that uses it. In particular, soundness of the FLP is necessary, but
insufficient for verifiability of Prio3 (<xref target="prio3"/>). See
<xref target="security-multiproof"/> for details.</t>
        <t>In addition, note that <xref target="BBCGGI19"/> defines a larger class of fully linear
proof systems than is considered 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>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,
verification, 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>VerifyState</tt></td>
              <td align="left">
                <tt>tuple[list[F], Optional[bytes]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>VerifierShare</tt></td>
              <td align="left">
                <tt>tuple[list[F], Optional[bytes]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>VerifierMessage</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"/>, the probability of an invalid measurement
being deemed valid can be decreased 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 causes the Aggregators
to accept an invalid measurement. 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-verification"/> 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-verification">
          <name>Verification</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). 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 verification state for Prio3 includes the output share
that will be released once verification 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 verify_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[
            Prio3VerifyState[F],
            Prio3VerifierShare[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 = list(joint_rand_parts)
        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,
        )

    verify_state = (out_share, corrected_joint_rand_seed)
    verifier_share = (verifiers_share, joint_rand_part)
    return (verify_state, verifier_share)

def verifier_shares_to_message(
    self,
    ctx: bytes,
    _agg_param: None,
    verifier_shares: list[Prio3VerifierShare[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 verifier_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 verify_next(
    self,
    _ctx: bytes,
    verify_state: Prio3VerifyState[F],
    verifier_message: Optional[bytes]
) -> tuple[Prio3VerifyState[F], Prio3VerifierShare[F]] | list[F]:
    joint_rand_seed = verifier_message
    (out_share, corrected_joint_rand_seed) = verify_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, let <tt>S</tt> be 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. Just as in <xref target="star-topo"/>, the former is called
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="verifier-share">
            <name>Verifier Share</name>
            <t>When joint randomness is not used, the verifier share is structured as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Field verifiers_share[F * V];
} Prio3VerifierShare;
]]></sourcecode>
            <t>where <tt>V = prio3.flp.VERIFIER_LEN * prio3.PROOFS</tt>. When joint randomness is
used, the verifier 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;
} Prio3VerifierhareWithJointRand;
]]></sourcecode>
          </section>
          <section anchor="verifier-message">
            <name>Verifier Message</name>
            <t>When joint randomness is not used, the verifier message is the empty string.
Otherwise the verifier message consists of the joint randomness seed computed
by the Aggregators:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Seed joint_rand;
} Prio3VerifierMessageWithJointRand;
]]></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><xref target="flp-bbcggi19-overview"/> provides 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>The proof system here 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 the 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, the FLP is slightly more general than this. One 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 one 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. This sub-circuit is called 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 the 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 the 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 polynomials 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, roots of unity for
the field are used. This allows constructing each 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 the 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, the FLP takes 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>
            <artset>
              <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="240" width="296" viewBox="0 0 296 240" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                  <path d="M 8,32 L 8,192" fill="none" stroke="black"/>
                  <path d="M 24,192 L 24,224" fill="none" stroke="black"/>
                  <path d="M 32,64 L 32,160" fill="none" stroke="black"/>
                  <path d="M 56,96 L 56,128" fill="none" stroke="black"/>
                  <path d="M 128,96 L 128,128" fill="none" stroke="black"/>
                  <path d="M 152,64 L 152,160" fill="none" stroke="black"/>
                  <path d="M 176,32 L 176,72" fill="none" stroke="black"/>
                  <path d="M 176,104 L 176,192" fill="none" stroke="black"/>
                  <path d="M 8,32 L 176,32" fill="none" stroke="black"/>
                  <path d="M 32,64 L 152,64" fill="none" stroke="black"/>
                  <path d="M 160,80 L 200,80" fill="none" stroke="black"/>
                  <path d="M 56,96 L 128,96" fill="none" stroke="black"/>
                  <path d="M 160,96 L 200,96" fill="none" stroke="black"/>
                  <path d="M 184,112 L 200,112" fill="none" stroke="black"/>
                  <path d="M 56,128 L 128,128" fill="none" stroke="black"/>
                  <path d="M 32,160 L 152,160" fill="none" stroke="black"/>
                  <path d="M 8,192 L 176,192" fill="none" stroke="black"/>
                  <polygon class="arrowhead" points="192,112 180,106.4 180,117.6" fill="black" transform="rotate(180,184,112)"/>
                  <polygon class="arrowhead" points="168,96 156,90.4 156,101.6" fill="black" transform="rotate(180,160,96)"/>
                  <polygon class="arrowhead" points="168,80 156,74.4 156,85.6" fill="black" transform="rotate(180,160,80)"/>
                  <polygon class="arrowhead" points="32,224 20,218.4 20,229.6" fill="black" transform="rotate(90,24,224)"/>
                  <g class="text">
                    <text x="48" y="52">prove()</text>
                    <text x="64" y="84">Valid</text>
                    <text x="228" y="84">meas</text>
                    <text x="232" y="100">joint</text>
                    <text x="276" y="100">rand</text>
                    <text x="92" y="116">Gadget</text>
                    <text x="232" y="116">prove</text>
                    <text x="276" y="116">rand</text>
                    <text x="56" y="228">proof</text>
                  </g>
                </svg>
              </artwork>
              <artwork type="ascii-art"><![CDATA[
+--------------------+
| prove()            |
|  +--------------+  |
|  | Valid        |<----- meas
|  |  +--------+  |<----- joint rand
|  |  | Gadget |  |  |<-- prove rand
|  |  +--------+  |  |
|  |              |  |
|  +--------------+  |
|                    |
+-+------------------+
  |
  v proof
]]></artwork>
            </artset>
          </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 prover records the values on input wires of
gadget instances during circuit evaluation, and constructs gadget polynomials
that the verifier will use to compute the outputs of each gadget. Additionally,
the prove randomness is used as a blinding factor when constructing gadget
polynomials.</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. This class is listed in <xref target="gadget-wrappers"/>. 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, the prover computes each of the "wire polynomials" for each gadget. For
each wire polynomial, take one prove randomness value and designate it the
"wire seed" for that polynomial. The <tt>j</tt>-th wire polynomial is the lowest
degree polynomial that evaluates to the "wire seed" at one point and
<tt>g.wires[j][k]</tt> at a sequence of other points. The gadget polynomial is
obtained 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>
            <artset>
              <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="272" width="312" viewBox="0 0 312 272" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                  <path d="M 8,64 L 8,224" fill="none" stroke="black"/>
                  <path d="M 24,224 L 24,256" fill="none" stroke="black"/>
                  <path d="M 32,96 L 32,192" fill="none" stroke="black"/>
                  <path d="M 56,128 L 56,160" fill="none" stroke="black"/>
                  <path d="M 96,48 L 96,128" fill="none" stroke="black"/>
                  <path d="M 128,128 L 128,160" fill="none" stroke="black"/>
                  <path d="M 152,96 L 152,192" fill="none" stroke="black"/>
                  <path d="M 176,64 L 176,104" fill="none" stroke="black"/>
                  <path d="M 176,136 L 176,224" fill="none" stroke="black"/>
                  <path d="M 8,64 L 88,64" fill="none" stroke="black"/>
                  <path d="M 104,64 L 176,64" fill="none" stroke="black"/>
                  <path d="M 32,96 L 88,96" fill="none" stroke="black"/>
                  <path d="M 104,96 L 152,96" fill="none" stroke="black"/>
                  <path d="M 160,112 L 200,112" fill="none" stroke="black"/>
                  <path d="M 56,128 L 88,128" fill="none" stroke="black"/>
                  <path d="M 104,128 L 128,128" fill="none" stroke="black"/>
                  <path d="M 160,128 L 200,128" fill="none" stroke="black"/>
                  <path d="M 184,144 L 200,144" fill="none" stroke="black"/>
                  <path d="M 56,160 L 128,160" fill="none" stroke="black"/>
                  <path d="M 32,192 L 152,192" fill="none" stroke="black"/>
                  <path d="M 8,224 L 176,224" fill="none" stroke="black"/>
                  <polygon class="arrowhead" points="192,144 180,138.4 180,149.6" fill="black" transform="rotate(180,184,144)"/>
                  <polygon class="arrowhead" points="168,128 156,122.4 156,133.6" fill="black" transform="rotate(180,160,128)"/>
                  <polygon class="arrowhead" points="168,112 156,106.4 156,117.6" fill="black" transform="rotate(180,160,112)"/>
                  <polygon class="arrowhead" points="104,128 92,122.4 92,133.6" fill="black" transform="rotate(90,96,128)"/>
                  <polygon class="arrowhead" points="32,256 20,250.4 20,261.6" fill="black" transform="rotate(90,24,256)"/>
                  <g class="text">
                    <text x="72" y="36">proof</text>
                    <text x="128" y="36">(share)</text>
                    <text x="48" y="84">query()</text>
                    <text x="64" y="116">Valid</text>
                    <text x="228" y="116">meas</text>
                    <text x="280" y="116">(share)</text>
                    <text x="232" y="132">joint</text>
                    <text x="276" y="132">rand</text>
                    <text x="92" y="148">Gadget</text>
                    <text x="232" y="148">query</text>
                    <text x="276" y="148">rand</text>
                    <text x="68" y="260">verifier</text>
                    <text x="136" y="260">(share)</text>
                  </g>
                </svg>
              </artwork>
              <artwork type="ascii-art"><![CDATA[
      proof (share)
           |
+----------|---------+
| query()  |         |
|  +-------|------+  |
|  | Valid |      |<----- meas (share)
|  |  +----v---+  |<----- joint rand
|  |  | Gadget |  |  |<-- query rand
|  |  +--------+  |  |
|  |              |  |
|  +--------------+  |
|                    |
+-+------------------+
  |
  v verifier (share)
]]></artwork>
            </artset>
          </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 used to evaluate it. This is
done by partially reconstructing the gadget polynomial and evaluating it at a
random point: when the gadget polynomial is evaluated at the same point, the
result should be the same.</t>
          <t>To start a gadget test, first construct the (shares of the) wire polynomials
just as the prover did. Then 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 compute the wire polynomials from the
recorded values.</t>
          <t>Next, 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>.
Note that the wire polynomials are in the value (Lagrange) representation
by construction. Faster polynomial evaluation in this representation is
possible by using the algorithm by <xref target="Faz25"/> without resorting to
polynomial interpolation.
The results are recorded in the verifier message passed to the decision
algorithm, where the test is finished.</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>
            <artset>
              <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="144" width="168" viewBox="0 0 168 144" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                  <path d="M 8,64 L 8,96" fill="none" stroke="black"/>
                  <path d="M 24,32 L 24,56" fill="none" stroke="black"/>
                  <path d="M 24,96 L 24,128" fill="none" stroke="black"/>
                  <path d="M 160,64 L 160,96" fill="none" stroke="black"/>
                  <path d="M 8,64 L 160,64" fill="none" stroke="black"/>
                  <path d="M 8,96 L 160,96" fill="none" stroke="black"/>
                  <polygon class="arrowhead" points="32,128 20,122.4 20,133.6" fill="black" transform="rotate(90,24,128)"/>
                  <polygon class="arrowhead" points="32,56 20,50.4 20,61.6" fill="black" transform="rotate(90,24,56)"/>
                  <g class="text">
                    <text x="68" y="36">verifier</text>
                    <text x="44" y="84">Decide</text>
                    <text x="68" y="132">is_valid</text>
                  </g>
                </svg>
              </artwork>
              <artwork type="ascii-art"><![CDATA[
  | verifier
  v
+------------------+
| Decide           |
+-+----------------+
  |
  v is_valid
]]></artwork>
            </artset>
          </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, 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>The 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>
          <sourcecode type="python"><![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()
]]></sourcecode>
        </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>. The latter is referred to 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 Poplar1 verification 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>While Poplar1 is intended to be used to compute heavy hitters in the above
protocol, it may be possible to use it for other applications as well. However,
care must be taken to ensure such usage is secure. See <xref target="agg-param-security"/>
and <xref target="idpf-extract"/> for details.</t>
      <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>. This
structure is called the "prefix tree" of 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. There are two types of fields: one for inner nodes (denoted
<tt>FieldInner</tt>), and one for leaf nodes (<tt>FieldLeaf</tt>). (The 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, <tt>Output</tt> is used 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, verification,
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>VerifyState</tt></td>
              <td align="left">
                <tt>tuple[bytes, int, FieldVec]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>VerifierShare</tt></td>
              <td align="left">
                <tt>FieldVec</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>VerifierMessage</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
verification.</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 verification. 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-verification">
          <name>Verification</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 verify_init(
        self,
        verify_key: bytes,
        ctx: bytes,
        agg_id: int,
        agg_param: Poplar1AggParam,
        nonce: bytes,
        public_share: Poplar1PublicShare,
        input_share: Poplar1InputShare) -> tuple[
            Poplar1VerifyState,
            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 = cast(
        list[Field],
        [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)

    verify_mem = [A_share, B_share, field(agg_id)] + out_share
    return (
        (
            b'evaluate sketch',
            level,
            cast(FieldVec, verify_mem),
        ),
        cast(FieldVec, sketch_share),
    )

def verify_next(
    self,
    _ctx: bytes,
    verify_state: Poplar1VerifyState,
    verifier_message: Optional[FieldVec]
) -> tuple[Poplar1VerifyState, FieldVec] | FieldVec:
    prev_sketch = cast(list[Field], verifier_message)
    (step, level, verify_mem) = verify_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, verify_mem[0])
        B_share = cast(Field, verify_mem[1])
        agg_id = cast(Field, verify_mem[2])
        verify_mem = verify_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[Poplar1VerifyState, FieldVec],
            (
                (
                    b'reveal sketch',
                    level,
                    verify_mem,
                ),
                sketch_share,
            )
        )

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

    raise ValueError('invalid verification state')

def verifier_shares_to_message(
        self,
        _ctx: bytes,
        agg_param: Poplar1AggParam,
        verifier_shares: list[FieldVec]) -> Optional[FieldVec]:
    if len(verifier_shares) != 2:
        raise ValueError('incorrect number of verifier shares')
    (level, _) = agg_param
    field = self.idpf.current_field(level)
    sketch = vec_add(
        cast(list[Field], verifier_shares[0]),
        cast(list[Field], verifier_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 verification 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 let <tt>Fi</tt> be 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="verifier-share-1">
            <name>Verifier Share</name>
            <t>Encoding of the verifier 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];
} Poplar1VerifierShareRoundOneInner;
]]></sourcecode>
            <t>For the first round and leaf field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldLeaf sketch_share[Fl * 3];
} Poplar1VerifierShareRoundOneLeaf;
]]></sourcecode>
            <t>For the second round and inner field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldInner sketch_share;
} Poplar1VerifierShareRoundTwoInner;
]]></sourcecode>
            <t>For the second round and leaf field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldLeaf sketch_share;
} Poplar1VerifierShareRoundTwoLeaf;
]]></sourcecode>
          </section>
          <section anchor="verifier-message-1">
            <name>Verifier Message</name>
            <t>Likewise, the structure of the verifier 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];
} Poplar1VerifierMessageRoundOneInner;
]]></sourcecode>
            <t>For the first round and leaf field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldLeaf sketch[Fl * 3];
} Poplar1VerifierMessageRoundOneLeaf;
]]></sourcecode>
            <t>Note that these messages have the same structures as the verifier shares for
the first round.</t>
            <t>The second-round verifier 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; successful verification is represented with the empty string,
otherwise the procedure returns 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 = []

last_byte_mask = 0
leftover_bits = (level + 1) % 8
if leftover_bits > 0:
    for bit_index in range(8 - leftover_bits, 8):
        last_byte_mask |= 1 << bit_index
    last_byte_mask ^= 255

bytes_per_prefix = ((level + 1) + 7) // 8
for chunk in itertools.batched(encoded_prefixes, bytes_per_prefix):
    if chunk[-1] & last_byte_mask > 0:
        raise ValueError('trailing bits in 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>This section specifies 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>The IDPF requires an XOF for deriving the output shares, as well as a variety
of other artifacts used internally. For performance reasons, this object is
instantiated 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 the 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 the length of the XOF expansion is set 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, viewing the seeds as XOR-shares of integers, 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>The following two sections 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
a subset of Aggregators learns nothing about the measurements of honest
Clients beyond what it can deduce from the aggregate result. It is assumed
that 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>Verifiability: 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. It is assumed that 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 verifiability (i.e., robustness) can be found
in <xref target="DPRS23"/>. A VDAF is the core cryptographic primitive of a protocol that
achieves the above privacy and verifiability 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>Verifiability 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 the computation is verifiably correct, 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 verification.</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 verification phases 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, one risks 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 DAF preparation or VDAF
verification 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 the 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. This is called 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 to verify the correctness of the
computation. 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 correctness of
the computation in 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 these 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, a
different AES key is used for every report, which in the ideal cipher model
leads to better concrete security <xref target="GKWWY20"/>.</t>
        <t>Note that for verifiability, the analysis of <xref target="BBCGGI21"/> still assumes a
random oracle to make the IDPF extractable. Thus XofTurboShake128 is used
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. And
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) verifiability.</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 verifiability 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, one should 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>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 the 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 verifiability. 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 verifiability 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="RFC9861">
          <front>
            <title>KangarooTwelve and TurboSHAKE</title>
            <author fullname="B. Viguier" initials="B." surname="Viguier"/>
            <author fullname="D. Wong" initials="D." role="editor" surname="Wong"/>
            <author fullname="G. Van Assche" initials="G." role="editor" surname="Van Assche"/>
            <author fullname="Q. Dang" initials="Q." role="editor" surname="Dang"/>
            <author fullname="J. Daemen" initials="J." role="editor" surname="Daemen"/>
            <date month="October" year="2025"/>
            <abstract>
              <t>This document defines four eXtendable-Output Functions (XOFs), hash functions with output of arbitrary length, named TurboSHAKE128, TurboSHAKE256, KT128, and KT256.</t>
              <t>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.</t>
              <t>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 NIST FIPS 202 and is meant to serve as a stable reference and an implementation guide.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9861"/>
          <seriesInfo name="DOI" value="10.17487/RFC9861"/>
        </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="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="Faz25">
          <front>
            <title>Rhizomes and the Roots of Efficiency—Improving Prio</title>
            <author fullname="Armando Faz-Hernandez" initials="A." surname="Faz-Hernandez">
              <organization/>
            </author>
            <date month="October" year="2025"/>
          </front>
          <seriesInfo name="Lecture Notes in Computer Science" value="pp. 425-449"/>
          <seriesInfo name="DOI" value="10.1007/978-3-032-06754-8_16"/>
          <seriesInfo name="ISBN" value="[&quot;9783032067531&quot;, &quot;9783032067548&quot;]"/>
          <refcontent>Springer Nature Switzerland</refcontent>
        </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="PANEL-FEEDBACK" target="https://mailarchive.ietf.org/arch/msg/cfrg/Omdhr4rO1pla_nlju2l7OJEGWPM/">
          <front>
            <title>Review of draft-irtf-cfrg-vdaf-15</title>
            <author initials="J." surname="Hesse" fullname="Julia Hesse">
              <organization/>
            </author>
            <date year="2025"/>
          </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="December"/>
          </front>
          <refcontent>commit hash 5b7df1d</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="2" month="September" year="2025"/>
            <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 on some server, 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 which
   can be used to collect aggregate data without revealing any
   individual contributor's data.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-ppm-dap-16"/>
        </reference>
        <reference anchor="I-D.draft-irtf-cfrg-cryptography-specification-02">
          <front>
            <title>Guidelines for Writing Cryptography Specifications</title>
            <author fullname="Nick Sullivan" initials="N." surname="Sullivan">
              <organization>Cryptography Consulting LLC</organization>
            </author>
            <author fullname="Christopher A. Wood" initials="C. A." surname="Wood">
              <organization>Cloudflare, Inc.</organization>
            </author>
            <date day="7" month="July" year="2025"/>
            <abstract>
              <t>   This document provides guidelines and best practices for writing
   technical specifications for cryptography protocols and primitives,
   targeting the needs of implementers, researchers, and protocol
   designers.  It highlights the importance of technical specifications
   and discusses strategies for creating high-quality specifications
   that cater to the needs of each community, including guidance on
   representing mathematical operations, security definitions, and
   threat models.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-cryptography-specification-02"/>
        </reference>
      </references>
    </references>
    <?line 6162?>

<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 Verification State</name>
      <t>This section lists the classes used to define each Aggregator's state during
VDAF verification (<xref target="vdaf-verify-comm"/>).</t>
      <sourcecode type="python"><![CDATA[
class State:
    pass

class Start(State):
    pass

class Continued(State, Generic[VerifyState]):
    def __init__(self,
                 verify_state: VerifyState,
                 verify_round: int,
                 outbound: bytes):
        self.verify_state = verify_state
        self.verify_round = verify_round
        self.outbound = outbound

    def __eq__(self, other: object) -> bool:
        return isinstance(other, Continued) and \
            self.verify_state == other.verify_state and \
            self.verify_round == other.verify_round and \
            self.outbound == other.outbound

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 FinishedWithOutbound(State, Generic[OutShare]):
    def __init__(self, out_share: OutShare, outbound: bytes):
        self.out_share = out_share
        self.outbound = outbound

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

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, verification, 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>reports</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>verifier_shares</tt>:</dt>
              <dd>
                <t>The expected list of verifier shares generated by each Aggregator at each
  round of verification, encoded in hexadecimal.</t>
              </dd>
              <dt><tt>verifier_messages</tt>:</dt>
              <dd>
                <t>The expected list of verifier messages for each round of
verification, 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>
          <dt><tt>operations</tt>:</dt>
          <dd>
            <t>This lists the VDAF operations that should be executed as part of known
answer tests, using messages from this test vector as input. Operations
should be executed in the order they appear, to ensure that verification state
values are computed before they are consumed. Verification state values are
not included in test vectors because this document does not specify their
representation or encoding.</t>
          </dd>
        </dl>
        <t>Each operation in the <tt>operations</tt> list has the following schema:</t>
        <dl>
          <dt><tt>operation</tt>:</dt>
          <dd>
            <t>The type of operation to be performed. This is one of "shard", "verify_init",
"verifier_shares_to_message", "verify_next", "aggregate", or "unshard".</t>
          </dd>
          <dt><tt>round</tt>:</dt>
          <dd>
            <t>For any verification operation, the round number of the operation to be
performed. This determines which verifier share, verification state, and/or
verifier message to use.</t>
          </dd>
          <dt><tt>aggregator_id</tt>:</dt>
          <dd>
            <t>The aggregator ID to use when performing this operation. This determines
which messages and which verification state to use, in addition to the
aggregator ID argument itself.</t>
          </dd>
          <dt><tt>report_index</tt>:</dt>
          <dd>
            <t>The index of the report on which to perform this operation. This is an index
into the <tt>reports</tt> array.</t>
          </dd>
          <dt><tt>success</tt>:</dt>
          <dd>
            <t>If this is <tt>True</tt>, the operation should succeed, and its output should match
the corresponding values in the test vector. If this is <tt>False</tt>, the operation
should fail, terminating verification of this report.</t>
          </dd>
        </dl>
        <t>The test vector 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 Julia Hesse who provided feedback on behalf of the Crypto Review
Panel.</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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
wbKzX5GNy9GhK4ZVj5WRVpFawtpZ5Ll0YGIt8sSkbQUHFFJo9vOCO0jaEn/R
imBSeDZx9WC5lpNtLZiG/acp/YVa8mFSpARTq9kXVfDAlUVR4GrMbG1p5xl4
aIlsYGl5tgurKtTXpKyeTQUZxgK57NUuQNGZspPQfeuKINp+QFR0gGAE19n2
P32KchAaamijs3SeT7DEM6WfnqflkAKBmm7TU6t80RELwZCrwFFEsVbmfLXq
fKGoLMw3oWRTS46GYhKfa6pDLq5icjppXxd6gfEoUmBZjlO3sO17Q92HCu5/
6p8S449X58zzsmEtwYyQnxcywzFTTrdSFwI7fAWKujq5/qEPMKFShWTf6cny
vGkn1KCobDQyCyXkLEs+fCA49XxvINv5bfEwkhl9nHNio+JSHB18AyeWnzaG
jJ9/6/00/9Sfb5s/LJ1eL8Poz82yjPtphrCwnOJLKO6nJZTFyShRvGwjfJZ/
wnBeXgLFjehyoj/dQr2PG4Lxvcafbr570Xz/mTC4PqhIf4q241FxDZGP20Zd
K7P5/aRRUGuJewzi/WJ5hfPG6sBjwA41TElNOOKu4pBMugmxxBL2afSqinLh
P6Ab1YXyYXHbeoZc5fdOQKQaZ758iMFG+ViSEvEP0tF3jSqCkZyYhErKrgnk
Q+9OYI1WlRMpi8cZRXyR0Y7nwcuVjgoFhTVdGNQ70s6/Arr3ZdUk0t2GP814
XgP28XlTqundyZdBpze/akRKdbAD10K7iEnyHB/EwApZTXOnE46kURHXeq29
hDC5TAPvILSuw/o444XXqMmBtW9Xtk78jaVe4cQ+m6F3AomE2fG1VrbkdW2r
MLfZnZS3aZ4h7MbFs8TnxNznrRdx5PsvrAm98piShif1qlGxyCoOUYtCHxbY
StKVBXNL9JwejBiVa0pH4d/95HttHc/X/pJD4DnC6TIvpmzj4XAA2ityehBB
RlmJUVF+kWkUCZO1kKzWo2/fvPFHQXsDyGbUsMypC+u79yAo1XHniEtendG3
nVY6os18zuy3msuqz2i5lmFRTF2+3+C0XCIWT/iOLNhqm0t+OSxXSnB4KJ5w
ccd4uoGQdO36CiQ0W9TZeA30sEZbmXNXTH5UStO1A8am4zv3HGVZZef5HIsu
JEHR7igCnG+KBJqRAKfRSl5RGMZlH38d0loMbBrhvFl+a8hHSdPQdq/5iYgQ
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

-->

</rfc>
