<?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.39 (Ruby 3.4.9) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-irtf-cfrg-vdaf-20" category="info" submissionType="IRTF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.34.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-20"/>
    <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="June" day="24"/>
    <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>20:</t>
        <ul spacing="normal">
          <li>
            <t>Take an editorial suggestion from Crypto Review Panel <xref target="PANEL-FEEDBACK"/>.</t>
          </li>
        </ul>
        <t>19:</t>
        <ul spacing="normal">
          <li>
            <t>Editorial changes only.</t>
          </li>
        </ul>
        <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 and 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">Multiplication</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 and division with floor</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. Here, we evaluate secret shares of the
        # gadget polynomial and secret shares of each of the wire
        # polynomials at the random point `t`. These secret shares
        # will be combined into polynomial evaluations at `t` when
        # verifier shares are combined into a verifier message.
        # Then, the `decide()` procedure will perform nonlinear
        # computations and the final consistency checks.
        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 evaluations of the wire
polynomials parsed from the verifier message: 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 evaluation of the gadget
polynomial in the verifier message; otherwise, the
output will not equal the gadget polynomial evaluation 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. Check if the evaluations of gadget
    # polynomials are consistent with evaluations of wire polynomials
    # by evaluating the gadgets on the evaluations of the wire
    # polynomials.
    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 is <bcp14>RECOMMENDED</bcp14> to set <tt>chunk_length</tt> to an integer near the square root of
<tt>length * bits</tt>, (see <xref target="parallel-sum-chunk-length"/>).</t>
          <t>The circuit is denoted <tt>SumVec</tt>. Each measurement is encoded as a vector of
field elements with a length of <tt>length * bits</tt>. The field elements in the
encoded vector represent 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. Assuming the
verification key is fixed ({the-verification-key}), this ensures any malicious
Aggregators trying to break privacy cannot control the randomness derived for
the verification process. Uniqueness of the nonce is not sufficient because the
verification key is controlled by the attacker <xref target="DPRS23"/>.</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="11" month="May" year="2026"/>
            <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-18"/>
        </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 6374?>

<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.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, Martin Thomson, Shan Wang, Xiao Wang, Bas Westerbaan, and
Christopher Wood for useful feedback on and contributions to the spec.</t>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA9S96XrbxpYo+h9PgVa+e0LZJDV4SCJvp1uWZUc7HnQtxdm7
3W4RJEEJMQkwACiJkd0Pcn7dZ7n3xe6aqmpVAdTg7O4+rS9fLJFADatWrXno
9XpRndXTdCdee5+W2SRLhtM0fp5VdZkNF3U6jndPT8v0NKmzIo9fLPIR/lKt
RclwWKbn+Nrz3Rdr0bgY5ckMhhmXyaTuZWU96Y0m5WnvfJxMetub0Sip09Oi
XO7EWT4poiiblztxXS6qentz84fN7Sgp02QnPnh3/CKqFsNZVlUwUb2cp/Lh
RVF+Oi2LxXwn3nvx7mX0KV3CR2P4Nq/TMk/r3nOcOoqqOsnHJ8m0yOHVZVpF
1Swp65PfF0WdVjtxXkTzbCf+UBejblwVZV2mkwp+W87wl49RlCzqs6LcieJe
FMMPb+tdNjpLynH8qh8/S2C2ir4rytMkz/4g4MCysmpU0OfpLMmmO3E5Hf5L
Nj/vV5f+YM+T82wc7xXFp5ZRDo5gc2qQcXaelqdpXo+T8/RfTvHD/qiY+SPu
nZVwZMX8LC3jw6Sui7xtfdNiMZ5MAdB6/BG+Oqd37mdpPVk1xeFZNp1m83l8
NDor5vNZkrfN8bIoTqfe+JV9/F9O6UsaOsqLcgbvnKc7ETy9u3+0Qy8ZZNwd
nyf5CNBvPx+Vyzlh3xEeLB5CBx5fX6Pn7WHRT0/W+rooYVPxX/vxc0SbLA++
358mWZ7iSX5Ky+C7v8L/q/hdP36Tjs7OkzqZtj7woqiz4ItXyUWZwqLjfUSS
qjpLZuG8/fhdMUxGn9qHhOWWyTL+a9mX72O4LICyf3VfxN/El7PpdjkZxXwD
M7hXVbyG46zFCfz2Vxqnjw8ziMbwxE4Mt2yLIZwANtU78Vldz6udjY2Li4t+
DsjTPy3ON+aL4TQb0VlWG4mcQS+1Z9Cr5Ax6CVyBCK+yd4wv//r2cHvLP8rD
MivuA/6U2XkyWsK/aZWW51l+aklLikdbwxqyURXDjuJnRTFNEzhxuHNpdd1J
Hy3KZRLvjsdJ/ik8j58BOnn8MimHaeP8M4D5ZBJ+/i6ZAM7Gb4H6FefVp2Xw
9W5eZ6dFnsWHxXQJ9wZ+TcbFwoPy9jb9CbRkBOQLri1A4CgdLcqsXsYAu3gP
QVmclsn8bBkD+ADPakTSKu4c7b0RtA4PKUv6o3IDRt/aePTdYwT1s2d7L18e
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
SHaOtgqUnlmEYo4BzIy5wGH2/wHa/SDBEjQEAA==

-->

</rfc>
