<?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.30 (Ruby 3.4.8) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-irtf-cfrg-vdaf-18" category="info" submissionType="IRTF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.31.0 -->
  <?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-18"/>
    <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="2026" month="January" day="30"/>
    <area>IRTF</area>
    <workgroup>CFRG</workgroup>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <?line 273?>

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

<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>18:</t>
        <ul spacing="normal">
          <li>
            <t>FLP: Represent the gadget polynomials in the Lagrange basis instead of the
monomial basis. This allows us to take advantage of additional algorithmic
improvements described in <xref target="Faz25"/>. (*)</t>
          </li>
          <li>
            <t>Prio3Sum, Prio3SumVec, Prio3MultihotCountVec: Unify the bit decomposition
used in range proofs. The new technique allows for arbitrary ranges with only
<tt>ceil(log2(max_measurement))</tt> field elements. The previous technique required
twice as many. (*)</t>
          </li>
        </ul>
        <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>18</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>assert_power_of_2(x: int) -&gt; int</tt> returns <tt>math.ceil(math.log2(n))</tt> if <tt>x</tt>
is a positive power of two and raises an exception otherwise.</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>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>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="Pol71"/>, as this allows
for fast conversion between polynomial representations. Refer to <xref target="SML24"/>
for an overview regarding NTT.
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 two.</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>
            <li>
              <t><tt>Field.nth_root(n: int) -&gt; F</tt> returns the principal <tt>n</tt>-th root of
unity that is uniquely determined as <tt>Wn = Field.gen() ** (GEN_ORDER // n)</tt>
to ensure interoperability.
Note that <tt>n</tt> must be a power of two such that <tt>1 &lt;= n &lt;= GEN_ORDER</tt>.</t>
            </li>
            <li>
              <t><tt>Field.nth_root_powers(n: int) -&gt; list[F]</tt> returns a list <tt>v</tt> with
the first <tt>n</tt> powers of the principal <tt>n</tt>-th root of unity.
It sets <tt>v[i] = Wn ** i</tt>, such that <tt>Wn = Field.nth_root(n)</tt>.</t>
            </li>
            <li>
              <t><tt>Field.ntt(p: list[F], n: int, set_s: bool = False) -&gt; list[F]</tt> returns
a list <tt>v</tt> with the evaluations of a polynomial <tt>p</tt>
(given its coefficients) at <tt>n</tt> points.
When <tt>set_s=False</tt>, it sets <tt>v[i] = p(Wn ** i)</tt> (this is the Lagrange
representation of the polynomial, see <xref target="poly-repr"/>);
otherwise, it sets <tt>v[i] = p(s * (Wn ** i))</tt>,
such that <tt>Wn = Field.nth_root(n)</tt>, and <tt>s = Field.nth_root(2 * n)</tt>.</t>
            </li>
            <li>
              <t><tt>Field.inv_ntt(v: list[F], n: int) -&gt; list[F]</tt> returns the coefficients of
a polynomial <tt>p</tt> such that <tt>v</tt> are the evaluations of <tt>p</tt> at the first <tt>n</tt>
powers of the principal <tt>n</tt>-th root of unity. (This is the monomial
representation of the polynomial, see <xref target="poly-repr"/>.)</t>
            </li>
          </ul>
          <t>The size of the subgroup dictates how large the 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="poly-repr">
          <name>Polynomial Representation</name>
          <t>Two standard representations of polynomials are described.
While it is possible to convert between representations
(using the NTT algorithm), polynomials are maintained in the most
efficient representation according to the target operation.</t>
          <section anchor="monomial-basis">
            <name>Monomial Basis</name>
            <t>The monomial basis is the standard way of representing a polynomial,
where each element of the list corresponds to one of their coefficients
stored in ascending degree order,
that is, starting with the coefficient of the constant term.</t>
            <t>The following function denotes polynomial evaluation in the
coefficient representation.</t>
            <ul spacing="normal">
              <li>
                <t><tt>poly_eval(field: type[F], p: list[F], x: F) -&gt; F</tt> returns the
evaluation of the polynomial <tt>p</tt> (in the monomial basis) at <tt>x</tt>.
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>
            </ul>
          </section>
          <section anchor="lagrange-basis">
            <name>Lagrange Basis</name>
            <t>In the Lagrange basis, polynomials are represented as a list of
evaluations over a set of points.
This set is fixed to the first <tt>n</tt> powers of the
principal <tt>n</tt>-th root of unity.
So any polynomial <tt>p</tt> of degree lesser than <tt>n</tt> is represented as a
list <tt>v</tt> of <tt>n</tt> values such that <tt>v[i] = p(Wn ** i)</tt>,
where <tt>Wn = Field.nth_root(n)</tt>.</t>
            <t>The <tt>Lagrange</tt> class defines operations over polynomials in the
Lagrange basis. It implements the following methods:</t>
            <ul spacing="normal">
              <li>
                <t><tt>poly_mul(self, p: list[F], q: list[F]) -&gt; list[F]</tt> multiplies two
polynomials, where the input and output polynomials are in the Lagrange basis.
The inputs must have lengths that are equal and a power of two.</t>
              </li>
              <li>
                <t><tt>poly_eval(self, p: list[F], x: F) -&gt; F</tt> evaluates a polynomial
<tt>p</tt> (in the Lagrange basis) at <tt>x</tt> in linear time.
It avoids conversion to the monomial basis as shown below.</t>
              </li>
              <li>
                <t><tt>poly_eval_batched(self, polys: list[list[F]], x: F) -&gt; list[F]</tt> evaluates
every polynomial in the input list at <tt>x</tt>.
This function runs faster than invoking <tt>poly_eval</tt> multiple times
because some intermediate calculations are shared.</t>
              </li>
              <li>
                <t><tt>extend_values_to_power_of_2(self, p: list[F], n: int)</tt> appends evaluations
to the polynomial <tt>p</tt> (in-place) until the number of evaluations is <tt>n</tt>.
The output length <tt>n</tt> must be a power of two.</t>
              </li>
              <li>
                <t><tt>double_evaluations(self, p: list[F]) -&gt; list[F]</tt> returns a list of
<tt>2*n</tt> evaluations of a polynomial <tt>p</tt> given <tt>n=len(p)</tt> evaluations.
The length of the input must be a power of two.</t>
              </li>
            </ul>
            <t>An instance of the <tt>Lagrange</tt> class is initialized with an NTT-friendly field.
For algorithm derivations, refer to <xref target="Faz25"/>.
In the following, <tt>prod</tt> computes the product of its inputs.</t>
            <sourcecode type="python"><![CDATA[
class Lagrange[F: NttField]():
    def __init__(self, field: type[F]) -> None:
        self.field = field

    def poly_mul(self, p: list[F], q: list[F]) -> list[F]:
        """Multiply two polynomials in the Lagrange basis."""
        n = len(p)
        assert_power_of_2(n)
        assert len(p) == len(q)
        p_2n = self.double_evaluations(p)
        q_2n = self.double_evaluations(q)
        return [pi*qi for pi, qi in zip(p_2n, q_2n)]

    def poly_eval(self, p: list[F], x: F) -> F:
        """Evaluate a polynomial p in the Lagrange basis at x."""
        return self.poly_eval_batched([p], x).pop()

    def poly_eval_batched(self, polys: list[list[F]], x: F) -> list[F]:
        """Evaluate each polynomial in the Lagrange basis at x."""
        assert len({len(p) for p in polys}) == 1
        n = len(polys[0])
        assert_power_of_2(n)

        nodes = self.field.nth_root_powers(n)
        k = self.field(1)
        u = [p[0] for p in polys]
        d = nodes[0] - x
        for i in range(1, n):
            k *= d
            d = nodes[i] - x
            t = k * nodes[i]
            for j, p in enumerate(polys):
                u[j] *= d
                if i < len(p):
                    u[j] += t * p[i]

        factor = self.field(-1)**(n-1) * self.field(n).inv()
        for i in range(len(u)):
            u[i] *= factor
        return u

    def extend_values_to_power_of_2(self, p: list[F], n: int) -> None:
        """
        Appends evaluations to the polynomial p (in-place) until the
        number of evaluations is n, and n must be a power of two.
        """
        assert_power_of_2(n)
        assert len(p) <= n
        x = self.field.nth_root_powers(n)

        w = [self.field(0)]*n
        for i in range(len(p)):
            diff = (x[i] - x[j] for j in range(len(p)) if i != j)
            w[i] = prod(diff, start=self.field(1))

        for k in range(len(p), n):
            for i in range(k):
                w[i] *= x[i] - x[k]

            y_num, y_den = self.field(0), self.field(1)
            for i, v in enumerate(p):
                y_num = y_num * w[i] + y_den * v
                y_den *= w[i]

            diff = (x[k] - x[j] for j in range(k))
            w[k] = prod(diff, start=self.field(1))
            p.append(-w[k] * y_num * y_den.inv())

    def double_evaluations(self, p: list[F]) -> list[F]:
        """
        Returns 2n evaluations of a polynomial from n Lagrange-basis
        evaluations, such that n=len(p) is a power of two.
        """
        n = len(p)
        assert_power_of_2(n)
        even = p
        odd = self.field.ntt(self.field.inv_ntt(even, n), n, True)
        return [i for pair in zip(even, odd) for i in pair]
]]></sourcecode>
          </section>
        </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.1 of [RFC9861].
        #
        # 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 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 <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 defining 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, the roots of unity for
the field are used. This allows using the NTT algorithm for efficiency.
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 = wire_poly_len(g_calls)
        length += g.ARITY + gadget_poly_len(g.DEGREE, p)
    return length

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

def wire_poly_len(gadget_calls: int) -> int:
    """
    Calculates the number of coordinates in each wire polynomial for
    a gadget.
    """
    return next_power_of_2(1 + gadget_calls)

def gadget_poly_len(gadget_degree: int,
                    wire_polynomial_len: int) -> int:
    """
    Calculates the number of coordinates in a gadget polynomial.
    """
    return gadget_degree * (wire_polynomial_len - 1) + 1
]]></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, g_calls in zip(valid.GADGETS, valid.GADGET_CALLS):
        g = cast(ProveGadget[F], g)

        # Define the wire polynomial length `p` as the smallest power
        # of two accommodating all gadget calls plus one constant
        # term for the seed.
        p = wire_poly_len(g_calls)

        # The validity circuit evaluation defines one polynomial for
        # each input wire of each gadget.
        # For each wire `j`, the vector `g.wires[j]` of length `p`
        # is built as follows:
        # - `g.wires[j][0]` is set to the seed for wire `j` (from
        #   the prover's randomness).
        # - The subsequent entries are the assigned values from each
        #   gadget call.
        # - Pad the vector with zeros to reach length `p`.
        # The wire polynomial is then defined by its evaluations:
        #   `wire_poly(alpha**k) = g.wires[j][k]`
        # for all `k`, where `alpha` is a `p`-th root of unity.
        wire_polys = [g.wires[j] for j in range(g.ARITY)]
        wire_seeds = [g.wires[j][0] for j in range(g.ARITY)]
        proof += wire_seeds

        # 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)
        proof += gadget_poly[:gadget_poly_len(g.DEGREE, p)]

    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.
Note that these polynomials are in the Lagrange basis representation
by construction, and the gadget polynomials parsed from the proof share
are similarly transmitted in the Lagrange basis representation.
Generating additive secret shares of a polynomial works equally both in
the monomial and the Lagrange basis (<xref target="poly-repr"/>).</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>.
Polynomial evaluation in the Lagrange basis is
faster 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
define 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.
    lag = Lagrange(self.field)
    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 = lag.poly_eval_batched(g.wires[:g.ARITY], t)
        gadget_check = lag.poly_eval(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 vector of field
elements with value zero or one, such that a weighted sum of these values can only
be in the range <tt>[0, max_measurement]</tt>.</t>
          <t>All but the last of the weights are successive powers of two, as in
the binary bit decomposition, and the last weight is chosen such that the sum of
all weights is equal to <tt>max_measurement</tt>. With these weights, valid
measurements have either one or two possible representations as vectors of
field elements with value zero or one, and invalid measurements cannot be
represented.</t>
          <t>The validity circuit checks that each entry of the bit vector has a value of
zero or one. It 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 the constant weights. Thus, 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]):
    JOINT_RAND_LEN = 0
    OUTPUT_LEN = 1
    field: type[F]

    def __init__(self, field: type[F], max_measurement: int):
        self.field = field
        bits = max_measurement.bit_length()
        self.bits = bits
        self.max_measurement = max_measurement
        self.GADGET_CALLS = [self.bits]
        self.GADGETS = [PolyEval([0, -1, 1], self.bits)]
        self.MEAS_LEN = self.bits
        self.EVAL_OUTPUT_LEN = self.bits

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

    def eval(
            self,
            meas: list[F],
            joint_rand: list[F],
            _num_shares: int) -> list[F]:
        out = []
        for b in meas:
            out.append(self.GADGETS[0].eval(self.field, [b]))

        return out

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

    def decode(self, output: list[F], _num_measurements: int) -> int:
        return output[0].int()


def encode_range_checked_int(
        field: type[F],
        value: int,
        max_measurement: int) -> list[F]:
    """
    Encode an integer into multiple field elements, representing a
    weighted sum of zeros and ones, to allow for efficient range
    proofs.

    Pre-conditions:

        - `value >= 0`
        - `max_measurement > 0`
        - `value <= max_measurement`
        - `value < field.MODULUS`
        - `max_measurement < field.MODULUS`
    """
    if value > max_measurement:
        raise ValueError("measurement is too large")

    bits = max_measurement.bit_length()
    rest_all_ones_value = 2 ** (bits - 1) - 1
    last_weight = max_measurement - rest_all_ones_value

    # Implementation note: this conditional should be replaced with
    # constant time operations in order to reduce leakage via timing
    # side channels.
    if value <= rest_all_ones_value:
        rest = value
        last_elem = field(0)
    else:
        rest = value - last_weight
        last_elem = field(1)

    encoded = []
    for l in range(bits - 1):
        encoded.append(field((rest >> l) & 1))
    encoded.append(last_elem)
    return encoded


def decode_range_checked_int(
        field: type[F],
        encoded: list[F],
        max_measurement: int) -> F:
    """
    Decode a field element from a vector of field elements produced
    by `encode_range_checked_int()`.

    This may also be applied to secret shares of an encoded integer,
    since it is a linear function.
    """
    bits = max_measurement.bit_length()
    rest_all_ones_value = 2 ** (bits - 1) - 1
    last_weight = max_measurement - rest_all_ones_value

    decoded = field(0)
    for (l, bit) in enumerate(encoded[:bits - 1]):
        decoded += field(1 << l) * bit
    decoded += field(last_weight) * encoded[bits - 1]
    return decoded
]]></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, max_measurement, 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>max_measurement</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, max_measurement]</tt>.</t>
          <t>Let <tt>bits = max_measurement.bit_length()</tt>, the number of bits needed to encode
the largest valid measurement.</t>
          <t>It s <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 modified bit decompositions of each of the measurement
vector's elements, following the <tt>Sum</tt> circuit's encoding procedure
(<xref target="prio3sum"/>), concatenated together.</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
    max_measurement: int
    chunk_length: int
    field: type[F]

    def __init__(self,
                 field: type[F],
                 length: int,
                 max_measurement: int,
                 chunk_length: int):
        """
        Instantiate the `SumVec` circuit for measurements with
        `length` elements, each in the range `[0, max_measurement]`.
        """
        self.field = field
        self.length = length
        bits = max_measurement.bit_length()
        self.bits = bits
        self.max_measurement = max_measurement
        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 += encode_range_checked_int(
                self.field,
                val,
                self.max_measurement,
            )
        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(
                decode_range_checked_int(
                    self.field,
                    meas[i * self.bits:(i + 1) * self.bits],
                    self.max_measurement,
                )
            )
        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>The Client's encoded measurement includes both the count vector and the
weight of the count vector. The weight is encoded as multiple field
elements, using the same modified bit decomposition as in the <tt>Sum</tt>
circuit's encoding procedure (<xref target="prio3sum"/>).</t>
          <t>The verifier checks that each entry of the encoded measurement is a bit (i.e.,
either one or zero), including both the count vector and the encoding of the
reported weight. It then decodes the reported weight and subtracts it from
<tt>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()

        # Make sure `length` and `max_weight` don't overflow the
        # field modulus. Otherwise we may not correctly compute the
        # sum of measurement vector entries during circuit evaluation.
        if self.field.MODULUS <= length:
            raise ValueError('length is too large for the '
                             'current field size')
        if self.field.MODULUS <= max_weight:
            raise ValueError('max_weight is 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(measurement)

        encoded = []
        encoded += count_vec
        encoded += encode_range_checked_int(
            self.field,
            weight_reported,
            self.max_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 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 = decode_range_checked_int(
            self.field,
            meas[self.length:],
            self.max_weight,
        )
        weight_check = 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>
        <li>
          <t>Security against protocol-confusion attacks. Privacy or verifiability may be
compromised if the attacker coerces an honest party into using either an
incorrect (V)DAF or incorrect parameters for the correct (V)DAF.</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>max_measurement</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="Pol71">
          <front>
            <title>The fast Fourier transform in a finite field</title>
            <author fullname="J. M. Pollard" initials="J." surname="Pollard">
              <organization/>
            </author>
            <date year="1971"/>
          </front>
          <seriesInfo name="Mathematics of Computation" value="vol. 25, no. 114, pp. 365-374"/>
          <seriesInfo name="DOI" value="10.1090/s0025-5718-1971-0301966-0"/>
          <refcontent>American Mathematical Society (AMS)</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 6356?>

<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]:
        lag = Lagrange(field)
        return lag.poly_mul(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], num_calls: 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
        wire_poly_length = wire_poly_len(num_calls)
        gadget_poly_length = gadget_poly_len(
            self.DEGREE,
            wire_poly_length,
        )
        self.n = next_power_of_2(gadget_poly_length)

    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]:
        inp_poly_len = len(inp_poly[0])
        assert_power_of_2(inp_poly_len)

        # Convert the input polynomial from Lagrange to monomial basis.
        inp_mon = field.inv_ntt(inp_poly[0], inp_poly_len)
        # Obtain n evaluations of the input polynomial I.
        inp_lag = field.ntt(inp_mon, self.n)
        # Returns the polynomial composition (P*I)
        p_mon = [field(coeff) for coeff in self.p]
        return [poly_eval(field, p_mon, x) for x in inp_lag]
]]></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 = next_power_of_2(gadget_poly_len(
            self.DEGREE,
            len(inp_poly[0]),
        ))
        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 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 = wire_poly_len(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 = wire_poly_len(g_calls)
        self.alpha = field.gen() ** (field.GEN_ORDER // p)
        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)

        # Recover all the values of the gadget_poly.
        lag = Lagrange(field)
        n = next_power_of_2(len(gadget_poly))
        gadget_poly = list(gadget_poly)
        lag.extend_values_to_power_of_2(gadget_poly, n)

        # Calculate 'size' evaluations of the gadget_poly.
        size = next_power_of_2(gadget_poly_len(g.DEGREE, p))
        while len(gadget_poly) < size:
            gadget_poly = lag.double_evaluations(gadget_poly)
        self.poly = gadget_poly

        # Get the step size used to index the gadget evaluations.
        log_size = assert_power_of_2(size)
        log_p = assert_power_of_2(p)
        self.step = 1 << (log_size-log_p)

    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.poly[self.k*self.step]

    @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 = wire_poly_len(g_calls)
            g_poly_len = gadget_poly_len(g.DEGREE, p)
            (wire_seeds, proof) = front(g.ARITY, proof)
            (gadget_poly, proof) = front(g_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>max_measurement</tt>:</dt>
            <dd>
              <t>The largest allowable value of each element of the vector, an integer. Each
element is in the range <tt>[0, max_measurement]</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>Special thanks to Armando Faz-Hernandez who discovered a number of algorithmic
improvements for FLPs <xref target="Faz25"/> that significantly improved the runtime of
Prio3 and other applications. Also, thanks to Ian Goldberg for pointing out the
bit decomposition technique used in the range proofs of the Prio3 variants.</t>
      <t>Thanks to Junye Chen, Henry Corrigan-Gibbs, 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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
a7KZiHe3pjNJRx6EZu66UUa3zmVyl6IXIgMFckXNUzT5TpT+/V7KXlhuKUX0
JZrswU5/lNmy9iqF+NVz7FVkWWwVmdQDHtFkMU9sNpvXVU7lHV9duba1UgYz
Cj11trYCLE05g5QDaLdh4eMmtyeuye1JnZx2qnQ27XE/cIkMdIYzV5KbLSkb
Gxv07wuqMtPSNRcG9EULF4FNkTtsM2hqwdKRFy8LWyRaDbf404+HSz60Vpll
+3F36C1VrAdcF+dkUtUdeBD3PHj1XLbdje/jnp1ZgYlxz7rCMdulda8bPd1o
S8K9gc1zOQrGgMaLA1sbJh6qZXWHQfr51RV83B+RiEyVLZrZeOc6HU9nUHBn
JdFCp1IBkgf1s/ikymoYlxl54hz38NAdgXWhoXViB9INE+QU1Wehq00apNam
/Jhye0gzRII7tyLld1AFjJy7E0DyE6YhsKO3OmtJIFljdInPsyT8LjLfST8e
UKvg3KQyUFZ5WSQ3JW9Ea5I3/DpkNyZvcMWgiPdn3aE6icK8btd+RkWyjF7K
uQr6UCLpMNkjBc54DkQCZnZgi9nh1UWST9kYjabAkeH4x2tgzE0f2eBQsa2l
0aw9QRhXdcRhE9ZewW2vbZ/ASSqFOzG6U2OYugWsvt/ojG3zxcb/VdkF6/IL
7pJecNfg+jukGDSSDFTYf/Cx+GgZ6Bwm+KnlA7Ng7+NmqkEj2UDP633cgMmn
NR/o5FD6uAGdT2s+aHzcgNOnhvq9RitH+PUHUTi4mVmkENU6WQRG99wntYAw
2bf5QcvH92W+d18OOffP2wYQz9d8sObjT/Fl/POfwTuzkjc+AmKChYeA5gMz
beNj/N/zP4OJZpCjPw3YPwfU/tciG3nF8ht/2g+jLyQrt3ieP/4iMhRk+azL
81mX5sNhGLfI8dHGZhJPPTsJKk8ef8GmeOUpMNM/TMnpRHn52SwVhp+KsWpC
teZQErBmzN2WiC3MKOLylyixrI3f4j551ApLixBlSkkCxFtnBdrmSU1u67Dk
bGjeliOTYmRSIrlJYNBvnUbd6NlW06q56FCuFj0yJImXOrnCSp+zTMh2MJy+
GQk/Kotkgk0PK1L8mPqZKvBmEWnJ8WotCxj6RHTIh+Er9y3lwyM/5DCYmOTO
UImHybHBl51PPuYZo/Dp2FY3M91ARcLWgrM45KSG4+u9v2MdR+2GpBBA5z5Q
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
AA==

-->

</rfc>
