<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.29 (Ruby 3.4.4) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-irtf-cfrg-vdaf-15" category="info" submissionType="IRTF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.28.1 -->
  <?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-15"/>
    <author initials="R. L." surname="Barnes" fullname="Richard L. Barnes">
      <organization>Cisco</organization>
      <address>
        <email>rlb@ipv.sx</email>
      </address>
    </author>
    <author initials="D." surname="Cook" fullname="David Cook">
      <organization>ISRG</organization>
      <address>
        <email>divergentdave@gmail.com</email>
      </address>
    </author>
    <author initials="C." surname="Patton" fullname="Christopher Patton">
      <organization>Cloudflare</organization>
      <address>
        <email>chrispatton+ietf@gmail.com</email>
      </address>
    </author>
    <author initials="P." surname="Schoppmann" fullname="Phillipp Schoppmann">
      <organization>Google</organization>
      <address>
        <email>schoppmann@google.com</email>
      </address>
    </author>
    <date year="2025" month="June" day="17"/>
    <area>IRTF</area>
    <workgroup>CFRG</workgroup>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <?line 262?>

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

<section anchor="introduction">
      <name>Introduction</name>
      <t>(RFC EDITOR: remove this paragraph.) The source for this draft and the
reference implementation can be found at
https://github.com/cfrg/draft-irtf-cfrg-vdaf.</t>
      <t>The ubiquity of the Internet makes it an ideal platform for measurement of
large-scale phenomena, whether public health trends or the behavior of computer
systems at scale. There is substantial overlap, however, between information
that is valuable to measure and information that users consider private.</t>
      <t>For example, consider an application that provides health information to users.
The operator of an application might want to know which parts of their
application are used most often, as a way to guide future development of the
application. Specific users' patterns of usage, though, could reveal sensitive
things about them, such as which users are researching a given health
condition.</t>
      <t>In many situations, the measurement collector is only interested in aggregate
statistics, e.g., which portions of an application are most used or what
fraction of people have experienced a given disease. Thus systems that provide
aggregate statistics while protecting individual measurements can deliver the
value of the measurements while protecting users' privacy.</t>
      <t>This problem is often formulated in terms of differential privacy (DP)
<xref target="Dwo06"/>. Roughly speaking, a data aggregation system that is differentially
private ensures that the degree to which any individual measurement influences
the value of the aggregate result can be precisely controlled. For example, in
systems like RAPPOR <xref target="EPK14"/>, each user samples noise from a well-known
distribution and adds it to their measurement before submitting to the
aggregation server. The aggregation server then adds up the noisy measurements,
and because it knows the distribution from which the noise was sampled, it can
estimate the true sum with reasonable accuracy.</t>
      <t>Even when noise is added to the measurements, collecting them in the clear
still reveals a significant amount of information to the collector. On the one
hand, depending on the "amount" of noise a client adds to its measurement, it
may be possible for a curious collector to make a reasonable guess of the
measurement's true value. On the other hand, the more noise the clients add,
the less reliable will be the server's estimate of the aggregate. Thus systems
relying solely on a DP mechanism must strike a delicate balance between privacy
and utility.</t>
      <t>Another way of constructing a privacy-preserving measurement system is to use
multi-party computation (MPC). The goal of such a system is that no participant
in the protocol should learn anything about an individual measurement beyond
what it can deduce from the aggregate. MPC achieves this goal by distributing
the computation of the aggregate across multiple aggregation servers, one of
which is presumed to be honest, i.e., not under control of the attacker.
Moreover, MPC can be composed with various DP mechanisms to ensure the
aggregate itself does not leak too much information about any one of the
measurements <xref target="MPRV09"/>.</t>
      <t>This document describes two classes of MPC protocols, each aiming for a
different set of goals.</t>
      <t>In a Distributed Aggregation Function (DAF, <xref target="daf"/>), each client splits its
measurement into multiple secret shares, one for each aggregation
server. DAFs require two properties of the secret sharing scheme. First, we can
reconstruct the underlying measurement by simply adding up all of the shares.
(Typically the shares are vectors over some finite field.) Second, given all
but one of the shares, it is impossible to learn anything about the underlying
measurement. These properties give rise to a simple strategy for privately
aggregating the measurements: each aggregation server adds up its measurement
shares locally before revealing their sum to the data collector; then all
the data collector has to do is add up these sums to get the aggregate result.</t>
      <t>This strategy is compatible with any aggregation function that can be
represented as the sum of some encoding of the measurements. Examples include:
summary statistics such as sum, mean, and standard deviation; estimation of
quantiles, e.g., median; histograms; linear regression; or counting data
structures, e.g., Bloom filters. However, not all functions fit into this
rubric, as it is constrained to linear computations over the encoded
measurements.</t>
      <t>In fact, our framework admits DAFs with slightly more
functionality, computing aggregation functions of the form</t>
      <artwork><![CDATA[
F(agg_param, meas_1, ..., meas_M) =
    G(agg_param, meas_1) + ... + G(agg_param, meas_M)
]]></artwork>
      <t>where <tt>meas_1, ..., meas_M</tt> are the measurements, <tt>G</tt> is a possibly
non-linear function, and <tt>agg_param</tt> is a parameter of that function chosen by
the data collector. This paradigm, known as function secret sharing <xref target="BGI15"/>,
allows for more sophisticated data analysis tasks, such as grouping metrics by
private client attributes <xref target="MPDST25"/> or computing heavy hitters <xref target="BBCGGI21"/>.
(More on the latter task below.)</t>
      <t>The second class of protocols defined in this document are called Verifiable
Distributed Aggregation Functions (VDAFs, <xref target="vdaf"/>). In addition to being
private, VDAFs are verifiable in the following sense. By design, a secret
sharing of a valid measurement, e.g., a number between 1 and 10, is
indistinguishable from a secret sharing of an invalid measurement, e.g., a
number larger than 10. This means that DAFs are vulnerable to attacks from
malicious clients attempting to disrupt the computation by submitting invalid
measurements. VDAFs are designed to allow the servers to detect and remove
these measurements prior to aggregation. We refer to this property as
robustness.</t>
      <t>Achieving robustness without sacrificing privacy requires the servers to
interact with one another over a number of rounds of communication. DAFs on the
other hand are non-interactive, making them easier to deploy; but they do not
provide robustness on their own. This may be tolerable in some applications.
For instance, if the client's software is executed in a trusted execution
environment, it may be reasonable to assume that no client is malicious.</t>
      <t>The DAF and VDAF abstractions encompass a variety of MPC techniques in the
literature. These protocols vary in their operational and security
requirements, sometimes in subtle but consequential ways. This document
therefore has two important goals:</t>
      <ol spacing="normal" type="1"><li>
          <t>Provide higher-level protocols, like <xref target="DAP"/>, with
a simple, uniform interface for accessing privacy-preserving measurement
schemes, document relevant operational and security requirements, and
specify constraints for safe usage:  </t>
          <ol spacing="normal" type="1"><li>
              <t>General patterns of communications among the various actors involved in
the system (clients, aggregation servers, and the collector of the
aggregate result);</t>
            </li>
            <li>
              <t>Capabilities of a malicious coalition of parties attempting to divulge
information about client measurements; and</t>
            </li>
            <li>
              <t>Conditions that are necessary to ensure that malicious clients cannot
corrupt the computation.</t>
            </li>
          </ol>
        </li>
        <li>
          <t>Provide cryptographers with design criteria that provide a clear deployment
roadmap for new constructions of privacy-preserving measurement systems.</t>
        </li>
      </ol>
      <t>This document also specifies two concrete VDAF schemes, each based on a protocol
from the literature.</t>
      <ul spacing="normal">
        <li>
          <t>The Prio system <xref target="CGB17"/> allows for the privacy-preserving computation of a
variety of aggregate statistics, combining additive secret sharing as described
above with a mechanism for checking the validity of each measurement. In
<xref target="prio3"/> we specify Prio3, a VDAF that follows the same overall framework as
the original Prio protocol, but incorporates techniques introduced in
<xref target="BBCGGI19"/> that result in significant performance gains.</t>
        </li>
        <li>
          <t>The Poplar protocol <xref target="BBCGGI21"/> solves a problem known as private
heavy-hitters. In this problem, each client holds a bit-string, and the goal
of the aggregation servers is to compute the set of strings that occur at
least <tt>T</tt> times for some threshold <tt>T</tt>. The core primitive in their protocol
is a secret sharing of a point function <xref target="GI14"/> (denoted <tt>G</tt> above) that
allows the servers to privately count how many of the clients' strings begin
with a given prefix (<tt>agg_param</tt> in the notation above). In <xref target="poplar1"/> we
specify a VDAF called Poplar1 that implements this functionality.</t>
        </li>
      </ul>
      <t>The remainder of this document is organized as follows: <xref target="conventions"/> lists
definitions and conventions used in the remainder of the document; <xref target="overview"/>
gives a brief overview of DAFs and VDAFs, the parties involved in the
computation, and the requirements for non-collusion; <xref target="daf"/> defines the syntax
for DAFs; <xref target="vdaf"/> defines the syntax for VDAFs; <xref target="prelim"/> defines various
functionalities that are common to our constructions; <xref target="prio3"/> specifies
Prio3; <xref target="poplar1"/> specifies Poplar1; and <xref target="security"/> enumerates security
considerations for DAFs and VDAFs in general and our constructions in
particular.</t>
      <section anchor="change-log">
        <name>Change Log</name>
        <t>(RFC EDITOR: remove this section.)</t>
        <t>(*) Indicates a change that breaks wire compatibility with the previous draft.</t>
        <t>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>. We can also index from the end of the
list, e.g., <tt>x[-1]</tt> is the last element of <tt>x</tt>.</t>
      <t>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>Note that we overload these operators when defining finite fields; see
<xref target="field"/>.</t>
      <t>Exponentiation is denoted by <tt>x ** y</tt> in Python. We also sometimes use more
conventional notation for exponentiation, namely <tt>x^y</tt>.</t>
      <t>Type hints are used to define input and output types:</t>
      <ul spacing="normal">
        <li>
          <t>The type variable <tt>F</tt> is used in signatures to signify any type that is a
subclass of <tt>Field</tt> (<xref target="field"/>).</t>
        </li>
        <li>
          <t><tt>bytes</tt> is a byte string.</t>
        </li>
        <li>
          <t><tt>int</tt> is an integer.</t>
        </li>
        <li>
          <t><tt>Generic</tt> is used in class definitions to explicitly declare type variables
of generic classes.</t>
        </li>
        <li>
          <t><tt>Any</tt> is the universal supertype, which admits values of any type.</t>
        </li>
        <li>
          <t><tt>Optional[T]</tt> is shorthand for <tt>T | None</tt>. Its value may be <tt>None</tt> or have
type <tt>T</tt>.</t>
        </li>
        <li>
          <t><tt>Self</tt> represents the containing class of the method definition in which it
appears.</t>
        </li>
        <li>
          <t><tt>Sequence[T]</tt> is either a list or tuple of values of type <tt>T</tt>.</t>
        </li>
      </ul>
      <t>This document defines several byte-string constants. When comprised of printable
ASCII characters, they are written as Python 3 byte-string literals (e.g.,
<tt>b'some constant string'</tt>).</t>
      <t>A global constant <tt>VERSION</tt> of type <tt>int</tt> is defined, which algorithms are free
to use as desired. Its value <bcp14>SHALL</bcp14> be <tt>12</tt>.</t>
      <t>This document describes algorithms for multi-party computations in which the
parties typically communicate over a network. Wherever a quantity is defined
that must be transmitted from one party to another, this document prescribes
a particular encoding of that quantity as a byte string.</t>
      <t>Some common functionalities:</t>
      <ul spacing="normal">
        <li>
          <t><tt>additive_secret_share(x: list[F], num_shares: int, field: type[F]) -&gt;
list[list[F]]</tt> takes a vector <tt>x</tt> of field elements and returns <tt>num_shares</tt>
vectors of length <tt>len(x)</tt> such that they all add up to the input vector.
Note that this function is not used normatively in this document.</t>
        </li>
        <li>
          <t><tt>byte(x: int) -&gt; bytes</tt> returns the representation of the integer <tt>x</tt> in the
range <tt>[0, 256)</tt> as a single-byte byte string.</t>
        </li>
        <li>
          <t><tt>cast(typ: type[T], x: object) -&gt; T</tt> returns the input value unchanged.
This is only present to assist with static analysis of the Python code.
Type checkers will ignore the inferred type of the input value, and assume
the output value has the given type.</t>
        </li>
        <li>
          <t><tt>concat(parts: list[bytes]) -&gt; bytes</tt> returns the concatenation of the input
byte strings, i.e., <tt>parts[0] + ... + parts[len(parts)-1]</tt>.</t>
        </li>
        <li>
          <t><tt>from_be_bytes(encoded: bytes) -&gt; int</tt> decodes a big-endian byte string,
i.e., returns the integer <tt>x</tt> for which <tt>to_be_bytes(x, len(encoded)) ==
encoded</tt>.</t>
        </li>
        <li>
          <t><tt>from_le_bytes(encoded: bytes) -&gt; int</tt> decodes a little-endian byte string,
i.e., returns the integer <tt>x</tt> for which <tt>to_le_bytes(x, len(encoded)) ==
encoded</tt>.</t>
        </li>
        <li>
          <t><tt>front(len: int, x: list[Any]) -&gt; tuple[list[Any], list[Any]]</tt> splits <tt>x</tt>
into two vectors, where the first vector is made up of the first <tt>len</tt>
elements of <tt>x</tt> and the second is made up of the remaining elements. This
function is equivalent to <tt>(x[:len], x[len:])</tt>.</t>
        </li>
        <li>
          <t><tt>gen_rand(len: int) -&gt; bytes</tt> returns a byte array of the requested length
(<tt>len</tt>) generated by a cryptographically secure pseudorandom number generator
(CSPRNG).</t>
        </li>
        <li>
          <t><tt>next_power_of_2(x: int) -&gt; int</tt> returns the smallest integer
greater than or equal to <tt>x</tt> that is also a power of two.</t>
        </li>
        <li>
          <t><tt>range(stop: int)</tt> or <tt>range(start: int, stop: int[, step: int])</tt> is the range
function from the Python standard library. The one-argument form returns the
integers from zero (inclusive) to <tt>stop</tt> (exclusive). The two- and
three-argument forms allow overriding the start of the range and overriding
the step between successive output values.</t>
        </li>
        <li>
          <t><tt>to_be_bytes(x: int, len: int) -&gt; bytes</tt> converts an integer <tt>x</tt> whose value
is in the range <tt>[0, 2^(8*len))</tt> to a big-endian byte string of length <tt>len</tt>.</t>
        </li>
        <li>
          <t><tt>to_le_bytes(x: int, len: int) -&gt; bytes</tt> converts an integer <tt>x</tt> whose value
is in the range <tt>[0, 2^(8*len))</tt> to a little-endian byte string of length
<tt>len</tt>.</t>
        </li>
        <li>
          <t><tt>poly_eval(field: type[F], p: list[F], x: F) -&gt; F</tt> returns the result of
evaluating the polynomial, <tt>p(x)</tt>. The coefficients of polynomials are stored
in lists in ascending order of degree, starting with the constant
coefficient. The <tt>field</tt> parameter is the class object for <tt>F</tt> and is used by
the implementation to construct field elements. (See <xref target="field"/>.)</t>
        </li>
        <li>
          <t><tt>poly_interp(field: type[F], inputs: list[F], outputs: list[F]) -&gt; list[F]</tt>
returns the coefficients of the lowest degree polynomial <tt>p</tt> for which
<tt>p(inputs[k]) == outputs[k]</tt> for all <tt>k</tt>. Normally this will be computed
using the Number Theoretic Transform (NTT) <xref target="SML24"/>.</t>
        </li>
        <li>
          <t><tt>poly_mul(field: type[F], p: list[F], q: list[F]) -&gt; list[F]</tt> returns
the product of two polynomials.</t>
        </li>
        <li>
          <t><tt>poly_strip(field: type[F], p: list[F]) -&gt; list[F]</tt> strips the zeros from the
end of the input polynomial's list of coefficients. That is, it returns
<tt>p[:i]</tt> where <tt>i</tt> is the index of the highest-degree non-zero coefficient of
<tt>p</tt>.</t>
        </li>
        <li>
          <t><tt>xor(left: bytes, right: bytes) -&gt; bytes</tt> returns the bitwise XOR of <tt>left</tt>
and <tt>right</tt>. An exception is raised if the inputs are not the same length.</t>
        </li>
        <li>
          <t><tt>zeros(len: int) -&gt; bytes</tt> returns an array of bytes of the requested
length (<tt>len</tt>). Each element of the array is set to zero.</t>
        </li>
      </ul>
    </section>
    <section anchor="overview">
      <name>Overview</name>
      <figure anchor="overall-flow">
        <name>Overall data flow of a (V)DAF.</name>
        <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="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
+--------+-+                         +->+-----------+
           |            ...          |
           |                         |
           |             |           |
           |             V           |
           |    +----------------+   |
           +--->| Aggregator N-1 |---+
                +----------------+
]]></artwork>
        </artset>
      </figure>
      <t>In a DAF- or VDAF-based private measurement system, we distinguish between
three types of actors: Clients, Aggregators, and the Collector.  The overall
flow of the measurement process is as follows:</t>
      <ul spacing="normal">
        <li>
          <t>To submit an individual measurement, the Client shards the measurement into
"input shares" and sends one input share to each Aggregator. We sometimes
refer to this sequence of input shares collectively as the Client's "report".</t>
        </li>
        <li>
          <t>The Aggregators refine their input shares into "output shares":  </t>
          <ul spacing="normal">
            <li>
              <t>Output shares are in one-to-one correspondence with the input shares.</t>
            </li>
            <li>
              <t>Just as each Aggregator receives one input share of each measurement, if
this process succeeds, then each aggregator holds one output share.</t>
            </li>
            <li>
              <t>In VDAFs, Aggregators will need to exchange information among themselves
as part of the validation process.</t>
            </li>
          </ul>
        </li>
        <li>
          <t>As each Aggregator recovers output shares, it accumulates them into an
"aggregate share" for the batch of measurements.</t>
        </li>
        <li>
          <t>The Aggregators submit their aggregate shares to the Collector, who combines
them to obtain the aggregate result over the batch.</t>
        </li>
      </ul>
      <t>Aggregators are a new class of actor relative to traditional measurement systems
where Clients submit measurements to a single server.  They are critical for
both the privacy properties of the system and, in the case of VDAFs, the
validity of the aggregate results obtained.  The privacy properties of the
system are assured by non-collusion among Aggregators, and Aggregators are the
entities that perform validation of Client measurements.  Thus Clients trust
Aggregators not to collude (typically it is required that at least one
Aggregator is honest; see <xref target="num-aggregators"/>), and Collectors trust
Aggregators to correctly run the protocol.</t>
      <t>Within the bounds of the non-collusion requirements of a given (V)DAF instance,
it is possible for the same entity to play more than one role.  For example, the
Collector could also act as an Aggregator, effectively using the other
Aggregator(s) to augment a basic client-server protocol.</t>
      <t>In this document, we describe the computations performed by the actors in this
system. It is up to the higher-level protocol making use of the (V)DAF to
arrange for the required information to be delivered to the proper actors in the
proper sequence. In general, we assume that all communications are confidential
and mutually authenticated, with the exception that Clients submitting
measurements may be anonymous.</t>
    </section>
    <section anchor="daf">
      <name>Definition of DAFs</name>
      <t>By way of a gentle introduction to VDAFs, this section describes a simpler class
of schemes called Distributed Aggregation Functions (DAFs). Unlike VDAFs, DAFs
do not provide verifiability of the computation. Clients must therefore be
trusted to compute their input shares correctly. Because of this fact, the use
of a DAF is <bcp14>NOT RECOMMENDED</bcp14> for most applications. See <xref target="security"/> for
additional discussion.</t>
      <t>A DAF scheme is used to compute a particular "aggregation function" over a set
of measurements generated by Clients. Depending on the aggregation function, the
Collector might select an "aggregation parameter" and disseminate it to the
Aggregators. The semantics of this parameter is specific to the aggregation
function, but in general it is used to represent the set of "queries" that can
be made by the Collector on the batch of measurements. For example, the
aggregation parameter is used to represent the candidate prefixes in the
Poplar1 VDAF (<xref target="poplar1"/>).</t>
      <t>Execution of a DAF has four distinct stages:</t>
      <ul spacing="normal">
        <li>
          <t>Sharding: Each Client generates input shares from its measurement and
distributes them among the Aggregators. In addition to the input shares, the
client generates a "public share" during this step that is disseminated to
all of the Aggregators.</t>
        </li>
        <li>
          <t>Preparation: Each Aggregator converts each input share into an output share
compatible with the aggregation function. This computation involves the
aggregation parameter. In general, each aggregation parameter may result in a
different output share.</t>
        </li>
        <li>
          <t>Aggregation: Each Aggregator combines a sequence of output shares into its
aggregate share and sends the aggregate share to the Collector.</t>
        </li>
        <li>
          <t>Unsharding: The Collector combines the aggregate shares into the aggregate
result.</t>
        </li>
      </ul>
      <t>Sharding and preparation are done once per measurement. Aggregation and
unsharding are done over a batch of measurements (more precisely, over the
recovered output shares).</t>
      <t>A concrete DAF specifies the algorithm for the computation needed in each of
these stages. The interface, denoted <tt>Daf</tt>, is defined in the remainder of this
section. In addition, a concrete DAF defines the associated constants and types
enumerated in the following table.</t>
      <table anchor="daf-param">
        <name>Constants and types defined by each concrete DAF.</name>
        <thead>
          <tr>
            <th align="left">Parameter</th>
            <th align="left">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>ID: int</tt></td>
            <td align="left">Algorithm identifier for this DAF, in the range <tt>[0, 2^32)</tt>.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>SHARES: int</tt></td>
            <td align="left">Number of input shares into which each measurement is sharded.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>NONCE_SIZE: int</tt></td>
            <td align="left">Size of the nonce associated with the report.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>RAND_SIZE: int</tt></td>
            <td align="left">Size of the random byte string consumed by the sharding algorithm.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>Measurement</tt></td>
            <td align="left">Type of each measurement.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PublicShare</tt></td>
            <td align="left">Type of each public share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>InputShare</tt></td>
            <td align="left">Type of each input share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggParam</tt></td>
            <td align="left">Type of the aggregation parameter.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>OutShare</tt></td>
            <td align="left">Type of each output share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggShare</tt></td>
            <td align="left">Type of the aggregate share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggResult</tt></td>
            <td align="left">Type of the aggregate result.</td>
          </tr>
        </tbody>
      </table>
      <t>The types in this table define the inputs and outputs of DAF methods at various
stages of the computation. Some of these values need to be written to the
network in order to carry out the computation. In particular, it is <bcp14>RECOMMENDED</bcp14>
that concrete instantiations of the <tt>Daf</tt> interface specify a standard encoding
for the <tt>PublicShare</tt>, <tt>InputShare</tt>, <tt>AggParam</tt>, and <tt>AggShare</tt> types.</t>
      <section anchor="sec-daf-shard">
        <name>Sharding</name>
        <figure anchor="shard-flow">
          <name>Illustration of the sharding algorithm.</name>
          <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-prep-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="392" viewBox="0 0 392 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="344" y="340">out_share_M</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
                      +--+---------+
                         |
                         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 preparation is an interactive process
carried out by the Aggregators. If successful, this process results in each
Aggregator computing an output share. The process will fail if, for example,
the underlying measurement is invalid.</t>
      <t>Failure manifests as an exception raised by one of the algorithms defined in
this section. If an exception is raised during preparation, the Aggregators
<bcp14>MUST</bcp14> remove the report from the batch and not attempt to aggregate it.
Otherwise, a malicious Client can cause the Collector to compute a malformed
aggregate result.</t>
      <t>The remainder of this section defines the VDAF interface, which we denote by
<tt>Vdaf</tt>. The attributes listed in <xref target="vdaf-param"/> are defined by each concrete
VDAF.</t>
      <table anchor="vdaf-param">
        <name>Constants and types defined by each concrete VDAF.</name>
        <thead>
          <tr>
            <th align="left">Parameter</th>
            <th align="left">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>ID: int</tt></td>
            <td align="left">Algorithm identifier for this VDAF, in the range <tt>[0, 2^32)</tt>.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>SHARES: int</tt></td>
            <td align="left">Number of input shares into which each measurement is sharded.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>ROUNDS: int</tt></td>
            <td align="left">Number of rounds of communication during preparation.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>NONCE_SIZE: int</tt></td>
            <td align="left">Size of the report nonce.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>RAND_SIZE: int</tt></td>
            <td align="left">Size of the random byte string consumed during sharding.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>VERIFY_KEY_SIZE: int</tt></td>
            <td align="left">Size of the verification key used during preparation.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>Measurement</tt></td>
            <td align="left">Type of each measurement.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PublicShare</tt></td>
            <td align="left">Type of each public share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>InputShare</tt></td>
            <td align="left">Type of each input share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggParam</tt></td>
            <td align="left">Type of the aggregation parameter.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>OutShare</tt></td>
            <td align="left">Type of each output share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggShare</tt></td>
            <td align="left">Type of the aggregate share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggResult</tt></td>
            <td align="left">Type of the aggregate result.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PrepState</tt></td>
            <td align="left">Type of the prep state.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PrepShare</tt></td>
            <td align="left">Type of each prep share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PrepMessage</tt></td>
            <td align="left">Type of each prep message.</td>
          </tr>
        </tbody>
      </table>
      <t>Some of the types in the table above need to be written to the network in
order to carry out the computation. It is <bcp14>RECOMMENDED</bcp14> that concrete
instantiations of the <tt>Vdaf</tt> interface specify a method of encoding the
<tt>PublicShare</tt>, <tt>InputShare</tt>, <tt>AggParam</tt>, <tt>AggShare</tt>, <tt>PrepShare</tt>, and
<tt>PrepMessage</tt> types.</t>
      <t>Each VDAF is identified by a unique 32-bit integer, denoted <tt>ID</tt>. Identifiers
for each VDAF specified in this document are defined in <xref target="codepoints"/>. The
following method is used by both Prio3 and Poplar1:</t>
      <sourcecode type="python"><![CDATA[
def domain_separation_tag(self, usage: int, ctx: bytes) -> bytes:
    """
    Format domain separation tag for this VDAF with the given
    application context and usage.

    Pre-conditions:

        - `usage` in the range `[0, 2^16)`
    """
    return format_dst(0, self.ID, usage) + ctx
]]></sourcecode>
      <t>The output, called the "domain separation tag", is used in our constructions
for domain separation. Function <tt>format_dst()</tt> is defined in <xref target="dst-binder"/>.</t>
      <section anchor="sec-vdaf-shard">
        <name>Sharding</name>
        <t>Sharding is as described for DAFs in <xref target="sec-daf-shard"/>. The public share and
input shares encode additional information used during preparation to validate
the output shares before they are aggregated (e.g., the "proof shares" in
<xref target="prio3"/>).</t>
        <t>Like DAFs, sharding is bound to the application context via the application
context string. Again, this is intended to ensure that aggregation succeeds
only if the Clients and Aggregators agree on the application context. Unlike
DAFs, however, disagreement on the context should manifest as a preparation
failure, causing the report to be rejected without garbling the aggregate
result. The application context also provides some defense-in-depth against
cross protocol attacks; see <xref target="deep"/>.</t>
      </section>
      <section anchor="sec-vdaf-prepare">
        <name>Preparation</name>
        <figure anchor="prep-flow">
          <name>Illustration of interactive VDAF preparation.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="496" width="528" viewBox="0 0 528 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 88,160 L 88,280" fill="none" stroke="black"/>
                <path d="M 88,320 L 88,352" fill="none" stroke="black"/>
                <path d="M 104,128 L 104,160" fill="none" stroke="black"/>
                <path d="M 104,288 L 104,320" fill="none" stroke="black"/>
                <path d="M 128,128 L 128,160" fill="none" stroke="black"/>
                <path d="M 128,288 L 128,320" fill="none" stroke="black"/>
                <path d="M 144,96 L 144,120" fill="none" stroke="black"/>
                <path d="M 144,160 L 144,200" fill="none" stroke="black"/>
                <path d="M 144,240 L 144,280" fill="none" stroke="black"/>
                <path d="M 144,320 L 144,352" fill="none" stroke="black"/>
                <path d="M 144,416 L 144,448" fill="none" stroke="black"/>
                <path d="M 208,160 L 208,280" fill="none" stroke="black"/>
                <path d="M 208,320 L 208,352" fill="none" stroke="black"/>
                <path d="M 224,128 L 224,160" fill="none" stroke="black"/>
                <path d="M 224,288 L 224,320" fill="none" stroke="black"/>
                <path d="M 312,128 L 312,160" fill="none" stroke="black"/>
                <path d="M 312,288 L 312,320" fill="none" stroke="black"/>
                <path d="M 328,96 L 328,120" fill="none" stroke="black"/>
                <path d="M 328,160 L 328,200" fill="none" stroke="black"/>
                <path d="M 328,240 L 328,280" fill="none" stroke="black"/>
                <path d="M 328,320 L 328,352" fill="none" stroke="black"/>
                <path d="M 328,416 L 328,448" fill="none" stroke="black"/>
                <path d="M 392,160 L 392,280" fill="none" stroke="black"/>
                <path d="M 392,320 L 392,352" fill="none" stroke="black"/>
                <path d="M 408,128 L 408,160" fill="none" stroke="black"/>
                <path d="M 408,288 L 408,320" fill="none" stroke="black"/>
                <path d="M 416,208 L 416,240" fill="none" stroke="black"/>
                <path d="M 448,224 L 448,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 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"/>
                <path d="M 8,208 L 80,208" fill="none" stroke="black"/>
                <path d="M 96,208 L 200,208" fill="none" stroke="black"/>
                <path d="M 216,208 L 384,208" fill="none" stroke="black"/>
                <path d="M 400,208 L 416,208" fill="none" stroke="black"/>
                <path d="M 8,240 L 80,240" fill="none" stroke="black"/>
                <path d="M 96,240 L 200,240" fill="none" stroke="black"/>
                <path d="M 216,240 L 384,240" fill="none" stroke="black"/>
                <path d="M 400,240 L 416,240" fill="none" stroke="black"/>
                <path d="M 8,288 L 104,288" fill="none" stroke="black"/>
                <path d="M 128,288 L 224,288" fill="none" stroke="black"/>
                <path d="M 312,288 L 408,288" fill="none" stroke="black"/>
                <path d="M 8,320 L 104,320" fill="none" stroke="black"/>
                <path d="M 128,320 L 224,320" fill="none" stroke="black"/>
                <path d="M 312,320 L 408,320" fill="none" stroke="black"/>
                <path d="M 432,208 C 440.83064,208 448,215.16936 448,224" fill="none" stroke="black"/>
                <path d="M 432,352 C 440.83064,352 448,344.83064 448,336" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="400,352 388,346.4 388,357.6" fill="black" transform="rotate(90,392,352)"/>
                <polygon class="arrowhead" points="400,280 388,274.4 388,285.6" fill="black" transform="rotate(90,392,280)"/>
                <polygon class="arrowhead" points="336,448 324,442.4 324,453.6" fill="black" transform="rotate(90,328,448)"/>
                <polygon class="arrowhead" points="336,352 324,346.4 324,357.6" fill="black" transform="rotate(90,328,352)"/>
                <polygon class="arrowhead" points="336,280 324,274.4 324,285.6" fill="black" transform="rotate(90,328,280)"/>
                <polygon class="arrowhead" points="336,200 324,194.4 324,205.6" fill="black" transform="rotate(90,328,200)"/>
                <polygon class="arrowhead" points="336,120 324,114.4 324,125.6" fill="black" transform="rotate(90,328,120)"/>
                <polygon class="arrowhead" points="216,352 204,346.4 204,357.6" fill="black" transform="rotate(90,208,352)"/>
                <polygon class="arrowhead" points="216,280 204,274.4 204,285.6" fill="black" transform="rotate(90,208,280)"/>
                <polygon class="arrowhead" points="152,448 140,442.4 140,453.6" fill="black" transform="rotate(90,144,448)"/>
                <polygon class="arrowhead" points="152,352 140,346.4 140,357.6" fill="black" transform="rotate(90,144,352)"/>
                <polygon class="arrowhead" points="152,280 140,274.4 140,285.6" fill="black" transform="rotate(90,144,280)"/>
                <polygon class="arrowhead" points="152,200 140,194.4 140,205.6" fill="black" transform="rotate(90,144,200)"/>
                <polygon class="arrowhead" points="152,120 140,114.4 140,125.6" fill="black" transform="rotate(90,144,120)"/>
                <polygon class="arrowhead" points="96,352 84,346.4 84,357.6" fill="black" transform="rotate(90,88,352)"/>
                <polygon class="arrowhead" points="96,280 84,274.4 84,285.6" fill="black" transform="rotate(90,88,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="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="56" y="148">prep_init</text>
                  <text x="176" y="148">prep_init</text>
                  <text x="360" y="148">prep_init</text>
                  <text x="296" y="180">...</text>
                  <text x="304" y="228">prep_shares_to_prep</text>
                  <text x="296" y="260">...</text>
                  <text x="464" y="276">x</text>
                  <text x="500" y="276">ROUNDS</text>
                  <text x="56" y="308">prep_next</text>
                  <text x="176" y="308">prep_next</text>
                  <text x="360" y="308">prep_next</text>
                  <text x="296" y="340">...</text>
                  <text x="24" y="388">...</text>
                  <text x="144" y="388">...</text>
                  <text x="328" y="388">...</text>
                  <text x="296" y="420">...</text>
                  <text x="48" y="468">out_share_0</text>
                  <text x="168" y="468">out_share_1</text>
                  <text x="364" 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
    +-----------+  +-----------+          +-----------+
    | prep_init |  | prep_init |          | prep_init |
    +-+-------+-+  +-+-------+-+          +-+-------+-+
      |       |      |       |         ...  |       |
      v       |      v       |              v       |
    +---------|--------------|----------------------|--+ -.
    |         |              |  prep_shares_to_prep |  |   |
    +-+-------|------+-------|--------------+-------|--+   |
      |       |      |       |         ...  |       |      |
      v       v      v       v              v       v      | x ROUNDS
    +-----------+  +-----------+          +-----------+    |
    | prep_next |  | prep_next |          | prep_next |    |
    +-+-------+-+  +-+-------+-+          +-+-------+-+    |
      |       |      |       |         ...  |       |      |
      v       v      v       v              v       v    -'

     ...            ...                    ...

      |              |                 ...  |
      |              |                      |
      v              v                      v
    out_share_0    out_share_1         out_share_[SHARES-1]
]]></artwork>
          </artset>
        </figure>
        <t>Preparation is organized into a number of rounds. The number of rounds depends
on the VDAF: Prio3 (<xref target="prio3"/>) has one round and Poplar1 (<xref target="poplar1"/>) has two.</t>
        <t>Aggregators retain some local state between successive rounds of preparation.
This is referred to as "preparation state" or "prep state" for short.</t>
        <t>During each round, each Aggregator broadcasts a message called a
"preparation share", or "prep share" for short. The prep shares are then
combined into a single message called the "preparation message", or "prep
message". The prep message <bcp14>MAY</bcp14> be computed by any one of the Aggregators.</t>
        <t>The prep message is disseminated to each of the Aggregators to begin the next
round. An Aggregator begins the first round with its input share and it begins
each subsequent round with the current prep state and the previous prep
message. Its output in the last round is its output share and its output in
each of the preceding rounds is a prep share.</t>
        <t>Just as for DAFs (<xref target="sec-daf-prepare"/>), preparation involves an aggregation
parameter. The aggregation parameter is consumed by each Aggregator before the
first round of communication.</t>
        <t>Unlike DAFs, VDAF preparation involves a secret "verification key" held by each
of the Aggregators. This key is used to verify validity of the output shares
they compute. It is up to the high level protocol in which the VDAF is used to
arrange for the distribution of the verification key prior to generating and
processing reports. See <xref target="security"/> for details.</t>
        <t>Preparation is implemented by the following set of algorithms:</t>
        <ul spacing="normal">
          <li>
            <t><tt>vdaf.prep_init(verify_key: bytes, ctx: bytes, agg_id: int, agg_param:
AggParam, nonce: bytes, public_share: PublicShare, input_share: InputShare)
-&gt; tuple[PrepState, PrepShare]</tt> is the deterministic preparation state
initialization algorithm run by each Aggregator. It consumes the shared
verification key, the application context, the Aggregator's unique
identifier, the aggregation parameter chosen by the Collector, the report
nonce, the public share, and one of the input shares generated by the Client.
It produces the Aggregator's initial prep state and prep share.  </t>
            <t>
Protocols <bcp14>MUST</bcp14> ensure that public share consumed by each of the Aggregators is
identical. This is security critical for VDAFs such as Poplar1.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>verify_key</tt> <bcp14>MUST</bcp14> have length <tt>vdaf.VERIFY_KEY_SIZE</tt>.</t>
              </li>
              <li>
                <t><tt>agg_id</tt> <bcp14>MUST</bcp14> be the integer in the range <tt>[0, vdaf.SHARES)</tt> that matches the
index of <tt>input_share</tt> in the sequence of input shares output by the
Client.</t>
              </li>
              <li>
                <t><tt>nonce</tt> <bcp14>MUST</bcp14> have length <tt>vdaf.NONCE_SIZE</tt>.</t>
              </li>
            </ul>
          </li>
          <li>
            <t><tt>vdaf.prep_shares_to_prep(ctx: bytes, agg_param: AggParam, prep_shares:
list[PrepShare]) -&gt; PrepMessage</tt> is the deterministic preparation message
pre-processing algorithm. It combines the prep shares produced by the
Aggregators in the previous round into the prep message consumed by each
Aggregator to start the next round.</t>
          </li>
          <li>
            <t><tt>vdaf.prep_next(ctx: bytes, prep_state: PrepState, prep_msg: PrepMessage) -&gt;
tuple[PrepState, PrepShare] | OutShare</tt> is the deterministic
preparation state update algorithm run by each Aggregator. It updates the
Aggregator's prep state (<tt>prep_state</tt>) and returns either its next prep state
and prep share for the next round or, if this is the last round, its output
share.</t>
          </li>
        </ul>
        <t>An exception may be raised by one of these algorithms, in which case the report
<bcp14>MUST</bcp14> be deemed invalid and not processed any further.</t>
        <t>Implementation note: The preparation process accomplishes two tasks: recovery
of output shares from the input shares and ensuring that the recovered output
shares are valid. The abstraction boundary is drawn so that an Aggregator only
recovers an output share if the underlying data is deemed valid (at least,
based on the Aggregator's view of the protocol). Another way to draw this
boundary would be to have the Aggregators recover output shares first, then
verify that they are valid. However, this would allow the possibility of
misusing the API by, say, aggregating an invalid output share. Moreover, in
protocols like Prio+ <xref target="AGJOP21"/> based on oblivious transfer, it is necessary
for the Aggregators to interact in order to recover aggregatable output shares
at all.</t>
      </section>
      <section anchor="sec-vdaf-validity-scopes">
        <name>Validity of Aggregation Parameters</name>
        <t>Aggregation parameter validation is as described for DAFs in
<xref target="sec-daf-validity-scopes"/>. Again, each Aggregator <bcp14>MUST</bcp14> validate each
aggregation parameter received from the Collector before beginning preparation
with that parameter.</t>
      </section>
      <section anchor="sec-vdaf-aggregate">
        <name>Aggregation</name>
        <t>Aggregation is identical to DAF aggregation as described in
<xref target="sec-daf-aggregate"/>. As with DAFs, computation of the VDAF aggregate is not
usually sensitive to the order in which output shares are aggregated. See
<xref target="agg-order"/>.</t>
      </section>
      <section anchor="sec-vdaf-unshard">
        <name>Unsharding</name>
        <t>Unsharding is identical to DAF unsharding as described in <xref target="sec-daf-unshard"/>.</t>
      </section>
      <section anchor="vdaf-execution">
        <name>Execution of a VDAF</name>
        <t>Secure execution of a VDAF involves simulating the following procedure over an
insecure network.</t>
        <sourcecode type="python"><![CDATA[
def run_vdaf(
        vdaf: Vdaf[
            Measurement,
            AggParam,
            PublicShare,
            InputShare,
            OutShare,
            AggShare,
            AggResult,
            PrepState,
            PrepShare,
            PrepMessage,
        ],
        verify_key: bytes,
        agg_param: AggParam,
        ctx: bytes,
        measurements: list[Measurement]) -> AggResult:
    """
    Pre-conditions:

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

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

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

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

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

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

    # Unsharding
    num_measurements = len(measurements)
    agg_result = vdaf.unshard(agg_param, agg_shares,
                              num_measurements)
    return agg_result
]]></sourcecode>
        <t>The inputs to this algorithm are the verification key, application context,
aggregation parameter, and a list of measurements. As explained in
<xref target="daf-execution"/>, the secure execution of a VDAF requires the application to
instantiate secure channels between each of the protocol participants.</t>
      </section>
      <section anchor="vdaf-prep-comm">
        <name>Communication Patterns for Preparation</name>
        <t>The only stage of VDAF execution that requires interaction is preparation
(<xref target="sec-vdaf-prepare"/>). There are a number of ways to coordinate this
interaction; the best strategy depends largely on the number of Aggregators
(i.e., <tt>vdaf.SHARES</tt>). This section describes two strategies, one specialized
for two Aggregators and another that is suitable for any number of Aggregators.</t>
        <t>In each round of preparation, each Aggregator writes a prep share to some
broadcast channel, which is then processed into the prep message using the
public <tt>prep_shares_to_prep()</tt> algorithm and broadcast to the Aggregators to
start the next round. Our goal in this section is to realize this broadcast
channel.</t>
        <t>The state machine of each Aggregator is shown below.</t>
        <figure anchor="vdaf-prep-state-machine">
          <name>State machine of VDAF preparation.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="144" width="504" viewBox="0 0 504 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,64" fill="none" stroke="black"/>
                <path d="M 320,32 L 320,64" fill="none" stroke="black"/>
                <path d="M 416,40 L 416,64" fill="none" stroke="black"/>
                <path d="M 416,96 L 416,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 320,32" fill="none" stroke="black"/>
                <path d="M 56,80 L 88,80" fill="none" stroke="black"/>
                <path d="M 16,128 L 160,128" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="424,120 412,114.4 412,125.6" fill="black" transform="rotate(90,416,120)"/>
                <polygon class="arrowhead" points="424,40 412,34.4 412,45.6" fill="black" transform="rotate(270,416,40)"/>
                <polygon class="arrowhead" points="328,64 316,58.4 316,69.6" fill="black" transform="rotate(90,320,64)"/>
                <polygon class="arrowhead" points="168,128 156,122.4 156,133.6" fill="black" transform="rotate(0,160,128)"/>
                <polygon class="arrowhead" points="136,32 124,26.4 124,37.6" fill="black" transform="rotate(180,128,32)"/>
                <polygon class="arrowhead" points="96,80 84,74.4 84,85.6" fill="black" transform="rotate(0,88,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="424" y="36">Finished(out_share)</text>
                  <text x="24" y="84">Start</text>
                  <text x="184" y="84">Continued(prep_state,</text>
                  <text x="320" y="84">prep_round,</text>
                  <text x="408" y="84">outbound)</text>
                  <text x="296" y="132">FinishedWithOutbound(out_share,</text>
                  <text x="464" y="132">outbound)</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
 +--> Rejected <--+   +----------------+   Finished(out_share)
 |                |   |                |           ^
 |                |   |                v           |
Start ----> Continued(prep_state, prep_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, we define these states in <xref target="topo-states"/>.</t>
        <t>The methods described in this section are defined in terms of opaque byte
strings. A compatible <tt>Vdaf</tt> <bcp14>MUST</bcp14> specify methods for encoding public shares,
input shares, prep shares, prep messages, and aggregation parameters.</t>
        <t>Implementations of Prio3 and Poplar1 <bcp14>MUST</bcp14> use the encoding schemes specified in
<xref target="prio3-encode"/> and <xref target="poplar1-encode"/> respectively.</t>
        <section anchor="ping-pong-topo">
          <name>The Ping-Pong Topology (Only Two Aggregators)</name>
          <t>For VDAFs with precisely two Aggregators (i.e., <tt>vdaf.SHARES == 2</tt>), the
following "ping pong" communication pattern can be used. It is compatible with
any request/response transport protocol, such as HTTP.</t>
          <t>Let us call the initiating Aggregator the "Leader" and the responding
Aggregator the "Helper". The high-level idea is that the Leader and Helper will
take turns running the computation locally until input from their peer is
required:</t>
          <ul spacing="normal">
            <li>
              <t>For a 1-round VDAF (e.g., Prio3 in <xref target="prio3"/>), the Leader sends its prep share
to the Helper, who computes the prep message locally, computes its output
share, then sends the prep message to the Leader. Preparation requires just
one round trip between the Leader and the Helper.</t>
            </li>
            <li>
              <t>For a 2-round VDAF (e.g., Poplar1 in <xref target="poplar1"/>), the Leader sends its
first-round prep share to the Helper, who replies with the first-round prep
message and its second-round prep share. In the next request, the Leader
computes its second-round prep share locally, computes its output share, and
sends the second-round prep message to the Helper. Finally, the Helper
computes its own output share.</t>
            </li>
            <li>
              <t>In general, each request includes the Leader's prep share for the previous
round and/or the prep message for the current round; correspondingly, each
response consists of the prep message for the current round and the Helper's
prep share for the next round.</t>
            </li>
          </ul>
          <t>The Aggregators proceed in this ping-ponging fashion until a step of the
computation fails (indicating the report is invalid and should be rejected) or
preparation is completed. All told there are <tt>ceil((vdaf.ROUNDS+1)/2)</tt>
requests sent.</t>
          <t>We specify protocol messages in the presentation language of TLS; see <xref section="3" sectionFormat="of" target="RFC8446"/>. Each message is structured as follows:</t>
          <sourcecode type="tls-presentation"><![CDATA[
enum {
  initialize(0),
  continue(1),
  finish(2),
  (255)
} MessageType;

struct {
  MessageType type;
  select (Message.type) {
    case initialize:
      opaque prep_share<0..2^32-1>;
    case continue:
      opaque prep_msg<0..2^32-1>;
      opaque prep_share<0..2^32-1>;
    case finish:
      opaque prep_msg<0..2^32-1>;
  };
} Message;
]]></sourcecode>
          <t>These messages trigger all transitions in the state machine in
<xref target="vdaf-prep-state-machine"/>, except for the Leader's initial transition. The
Leader's state is initialized using its local inputs with the following method
on class <tt>Vdaf</tt>:</t>
          <sourcecode type="python"><![CDATA[
def ping_pong_leader_init(
        self,
        vdaf_verify_key: bytes,
        ctx: bytes,
        agg_param: bytes,
        nonce: bytes,
        public_share: bytes,
        input_share: bytes) -> Continued | Rejected:
    """Called by the Leader to initialize ping-ponging."""
    try:
        (prep_state, prep_share) = self.prep_init(
            vdaf_verify_key,
            ctx,
            0,
            self.decode_agg_param(agg_param),
            nonce,
            self.decode_public_share(public_share),
            self.decode_input_share(0, input_share),
        )

        encoded_prep_share = self.encode_prep_share(prep_share)
        return Continued(
            prep_state, 0,
            encode(0, encoded_prep_share),  # initialize
        )
    except 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:
        (prep_state, prep_share) = self.prep_init(
            vdaf_verify_key,
            ctx,
            1,
            self.decode_agg_param(agg_param),
            nonce,
            self.decode_public_share(public_share),
            self.decode_input_share(1, input_share),
        )

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

        encoded_prep_share = inbound_items[0]
        prep_shares = [
            self.decode_prep_share(prep_state, encoded_prep_share),
            prep_share,
        ]
        return self.ping_pong_transition(
            ctx,
            self.decode_agg_param(agg_param),
            prep_shares,
            prep_state,
            0,
        )
    except 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 prep shares,
combines them into the prep message, and computes the next prep state of the
caller:</t>
          <sourcecode type="python"><![CDATA[
def ping_pong_transition(
        self,
        ctx: bytes,
        agg_param: AggParam,
        prep_shares: list[PrepShare],
        prep_state: PrepState,
        prep_round: int) -> Continued | FinishedWithOutbound:
    prep_msg = self.prep_shares_to_prep(ctx,
                                        agg_param,
                                        prep_shares)
    encoded_prep_msg = self.encode_prep_msg(prep_msg)
    out = self.prep_next(ctx, prep_state, prep_msg)
    if prep_round+1 == self.ROUNDS:
        return FinishedWithOutbound(
            out,
            encode(2, encoded_prep_msg),  # finalize
        )
    (prep_state, prep_share) = cast(
        tuple[PrepState, PrepShare], out)
    encoded_prep_share = self.encode_prep_share(prep_share)
    return Continued(
        prep_state, prep_round+1,
        encode(1, encoded_prep_msg, encoded_prep_share)  # continue
    )
]]></sourcecode>
          <t>The output is the <tt>State</tt> to which the Helper has transitioned. 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:
        prep_round = state.prep_round

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

        encoded_prep_msg = inbound_items[0]
        prep_msg = self.decode_prep_msg(
            state.prep_state,
            encoded_prep_msg,
        )
        out = self.prep_next(ctx, state.prep_state, prep_msg)
        if prep_round+1 < self.ROUNDS and \
                inbound_type == 1:  # continue
            (prep_state, prep_share) = cast(
                tuple[PrepState, PrepShare], out)
            encoded_prep_share = inbound_items[1]
            prep_shares = [
                self.decode_prep_share(
                    prep_state,
                    encoded_prep_share,
                ),
                prep_share,
            ]
            if is_leader:
                prep_shares.reverse()
            return self.ping_pong_transition(
                ctx,
                self.decode_agg_param(agg_param),
                prep_shares,
                prep_state,
                prep_round+1,
            )
        elif prep_round+1 == self.ROUNDS and \
                inbound_type == 2:  # finish
            return Finished(out)
        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 preparation that are required, when one party reaches the
<tt>Finished</tt> state, there may be one more message to send before the peer can
also finish processing (i.e., the outbound message is not <tt>None</tt>).</t>
        </section>
        <section anchor="star-topo">
          <name>The Star Topology (Any Number of Aggregators)</name>
          <t>The ping-pong topology of the previous section is only suitable for applications
of VDAFs involving exactly two Aggregators. In applications with more than two
Aggregators, the star topology described in this section can
be used instead.</t>
          <t>We again designate an Aggregator to initiate the computation. We refer to this
Aggregator as the Leader and to all other Aggregators as Helpers.</t>
          <t>At the start of each round, the Leader requests from each Helper its prep
share. After gathering each of the prep shares, the Leader computes the next
prep message (via <tt>vdaf.prep_shares_to_prep()</tt>) and broadcasts it to the
Helpers. At this point, each Aggregator runs <tt>vdaf.prep_next()</tt> locally to
either recover an output share or, if more rounds of preparation are required,
compute its updated state and prep share. If another round is required, then
the Helper responds to the broadcast message with its next prep share.</t>
          <t>The Aggregators proceed in this way until each recovers an output share or some
step of the computation fails.</t>
        </section>
      </section>
    </section>
    <section anchor="prelim">
      <name>Preliminaries</name>
      <t>This section describes the primitives that are common to the VDAFs specified in
this document.</t>
      <section anchor="field">
        <name>Finite Fields</name>
        <t>Both Prio3 and Poplar1 use finite fields of prime order. Finite field
elements are represented by a class <tt>Field</tt> with the following associated
parameters:</t>
        <ul spacing="normal">
          <li>
            <t><tt>MODULUS: int</tt> is the prime modulus that defines the field.</t>
          </li>
          <li>
            <t><tt>ENCODED_SIZE: int</tt> is the number of bytes used to encode a field element
as a byte string.</t>
          </li>
        </ul>
        <t>Concrete fields, i.e., subclasses of <tt>Field</tt>, implement the following class
methods:</t>
        <ul spacing="normal">
          <li>
            <t><tt>Field.zeros(length: int) -&gt; list[Self]</tt> returns a vector of zeros of the
requested length.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>length</tt> <bcp14>MUST</bcp14> be greater than or equal <tt>0</tt>.</t>
              </li>
            </ul>
            <t>
Post-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t>The length of the output <bcp14>MUST</bcp14> be <tt>length</tt>.</t>
              </li>
            </ul>
          </li>
          <li>
            <t><tt>Field.rand_vec(length: int) -&gt; list[Self]</tt> returns a vector of random field
elements and has the same pre- and post-conditions as for <tt>Field.zeros()</tt>.
Note that this function is not used normatively in the specification of
either Prio3 or Poplar1.</t>
          </li>
        </ul>
        <t>A field element is an instance of a concrete <tt>Field</tt>. Addition,
subtraction, multiplication, division, negation, and inversion are denoted,
respectively, <tt>x + y</tt>, <tt>x - y</tt>, <tt>x * y</tt>, <tt>x / y</tt>, <tt>-x</tt>, and <tt>x.inv()</tt>.</t>
        <t>We sometimes need to convert a field element to an <tt>int</tt>, which we denote by
<tt>x.int()</tt>. Likewise, each concrete <tt>Field</tt> implements a constructor for
converting an integer into a field element:</t>
        <ul spacing="normal">
          <li>
            <t><tt>Field(integer: int)</tt> returns <tt>integer</tt> represented as a field element. The
value of <tt>integer</tt> <bcp14>MUST</bcp14> be in the range <tt>(-Field.MODULUS, Field.MODULUS)</tt>;
negative values are treated as negations.</t>
          </li>
        </ul>
        <section anchor="auxiliary-functions">
          <name>Auxiliary Functions</name>
          <t>The following class methods on <tt>Field</tt> are used to encode and decode vectors of
field elements as byte strings:</t>
          <sourcecode type="python"><![CDATA[
def encode_vec(cls, vec: list[Self]) -> bytes:
    """
    Encode a vector of field elements `vec` as a byte string.
    """
    encoded = bytes()
    for x in vec:
        encoded += to_le_bytes(x.int(), cls.ENCODED_SIZE)
    return encoded

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

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

    Pre-conditions:

        - `val >= 0`
        - `bits >= 0`
    """
    if val >= 2 ** bits:
        # Sanity check we are able to represent `val` with `bits`
        # number of bits.
        raise ValueError("Number of bits is not enough to represent "
                         "the input integer.")
    encoded = []
    for l in range(bits):
        encoded.append(cls((val >> l) & 1))
    return encoded

def decode_from_bit_vec(cls, vec: list[Self]) -> Self:
    """
    Decode the field element from the bit representation, expressed
    as a vector of field elements `vec`.

    This may also be used with secret shares of a bit representation,
    since it is linear.
    """
    bits = len(vec)
    if cls.MODULUS >> bits == 0:
        raise ValueError("Number of bits is too large to be "
                         "represented by field modulus.")
    decoded = cls(0)
    for (l, bit) in enumerate(vec):
        decoded += cls(1 << l) * bit
    return decoded
]]></sourcecode>
          <t>Finally, the following functions define arithmetic on vectors over a finite
field. Note that an exception is raised by each function if the operands are
not the same length.</t>
          <sourcecode type="python"><![CDATA[
def vec_sub(left: list[F], right: list[F]) -> list[F]:
    """
    Subtract the right operand from the left and return the result.
    """
    if len(left) != len(right):
        raise ValueError("mismatched vector sizes")
    return list(map(lambda x: x[0] - x[1], zip(left, right)))

def vec_add(left: list[F], right: list[F]) -> list[F]:
    """Add the right operand to the left and return the result."""
    if len(left) != len(right):
        raise ValueError("mismatched vector sizes")
    return list(map(lambda x: x[0] + x[1], zip(left, right)))

def vec_neg(vec: list[F]) -> list[F]:
    """Negate the input vector."""
    return list(map(lambda x: -x, vec))
]]></sourcecode>
        </section>
        <section anchor="field-ntt-friendly">
          <name>NTT-Friendly Fields</name>
          <t>Some VDAFs, including Prio3, require fields that are suitable for efficient
computation of the number theoretic transform (NTT) <xref target="SML24"/>, as this allows
for fast polynomial interpolation. Specifically, a field is said to be
"NTT-friendly" if, in addition to the interface described in <xref target="field"/>, it
provides the following interface:</t>
          <ul spacing="normal">
            <li>
              <t><tt>Field.gen() -&gt; Self</tt> is a class method that returns the generator of a large
subgroup of the multiplicative group. To be NTT-friendly, the order of this
subgroup <bcp14>MUST</bcp14> be a power of 2.</t>
            </li>
            <li>
              <t><tt>GEN_ORDER: int</tt> is the order of the multiplicative subgroup generated by
<tt>Field.gen()</tt>. This is the smallest positive integer for which
<tt>Field.gen()**Field.GEN_ORDER == Field(1)</tt>.</t>
            </li>
          </ul>
          <t>The size of the subgroup dictates how large interpolated polynomials can be. It
is <bcp14>RECOMMENDED</bcp14> that a generator is chosen with order at least <tt>2^20</tt>.</t>
        </section>
        <section anchor="parameters">
          <name>Parameters</name>
          <t><xref target="fields"/> defines finite fields used in the remainder of this document.</t>
          <table anchor="fields">
            <name>Parameters for the finite fields used in this document.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Field64</th>
                <th align="left">Field128</th>
                <th align="left">Field255</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">MODULUS</td>
                <td align="left">2^32 * 4294967295 + 1</td>
                <td align="left">2^66 * 4611686018427387897 + 1</td>
                <td align="left">2^255 - 19</td>
              </tr>
              <tr>
                <td align="left">ENCODED_SIZE</td>
                <td align="left">8</td>
                <td align="left">16</td>
                <td align="left">32</td>
              </tr>
              <tr>
                <td align="left">Generator</td>
                <td align="left">7^4294967295</td>
                <td align="left">7^4611686018427387897</td>
                <td align="left">n/a</td>
              </tr>
              <tr>
                <td align="left">GEN_ORDER</td>
                <td align="left">2^32</td>
                <td align="left">2^66</td>
                <td align="left">n/a</td>
              </tr>
            </tbody>
          </table>
        </section>
      </section>
      <section anchor="xof">
        <name>Extendable Output Functions (XOFs)</name>
        <t>VDAFs in this specification use eXtendable Output Functions (XOFs) for two
purposes:</t>
        <ol spacing="normal" type="1"><li>
            <t>Extracting short, pseudorandom strings we call "seeds" from high entropy
inputs</t>
          </li>
          <li>
            <t>Expanding seeds into long, pseudorandom outputs</t>
          </li>
        </ol>
        <t>Concrete XOFs implement a class <tt>Xof</tt> providing the following interface:</t>
        <ul spacing="normal">
          <li>
            <t><tt>SEED_SIZE: int</tt> is the size (in bytes) of a seed.</t>
          </li>
          <li>
            <t><tt>Xof(seed: bytes, dst: bytes, binder: bytes)</tt> constructs an instance of the
XOF from the given seed and a domain separation tag and binder string as
defined in <xref target="dst-binder"/>. The length of the seed will typically be
<tt>SEED_SIZE</tt>, but some XOFs may support multiple seed sizes. The seed <bcp14>MUST</bcp14> be
generated securely, i.e., it is either the output of a CSPRNG or a
previous invocation of the XOF.</t>
          </li>
          <li>
            <t><tt>xof.next(length: int)</tt> returns the next chunk of the output of the
initialized XOF as a byte string. The length of the chunk <bcp14>MUST</bcp14> be <tt>length</tt>.</t>
          </li>
        </ul>
        <t>The following methods are provided for all concrete XOFs. The first is a class
method used to derive a fresh seed from an existing one. The second is an
instance method used to compute a sequence of field elements. The third is a
class method that provides a one-shot interface for expanding a seed into a
field vector.</t>
        <sourcecode type="python"><![CDATA[
def derive_seed(cls,
                seed: bytes,
                dst: bytes,
                binder: bytes) -> bytes:
    """
    Derive a new seed.

    Pre-conditions:

        - `len(seed) == cls.SEED_SIZE`
    """
    xof = cls(seed, dst, binder)
    return xof.next(cls.SEED_SIZE)

def next_vec(self, field: type[F], length: int) -> list[F]:
    """
    Output the next `length` field elements.

    Pre-conditions:

        - `field` is sub-class of `Field`
        - `length > 0`
    """
    m = next_power_of_2(field.MODULUS) - 1
    vec: list[F] = []
    while len(vec) < length:
        x = from_le_bytes(self.next(field.ENCODED_SIZE))
        x &= m
        if x < field.MODULUS:
            vec.append(field(x))
    return vec

def expand_into_vec(cls,
                    field: type[F],
                    seed: bytes,
                    dst: bytes,
                    binder: bytes,
                    length: int) -> list[F]:
    """
    Expand the input `seed` into a vector of `length` field elements.

    Pre-conditions:

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

    # Associated parameters
    SEED_SIZE = 32

    def __init__(self, seed: bytes, dst: bytes, binder: bytes):
        self.l = 0
        self.m = \
            to_le_bytes(len(dst), 2) + dst \
            to_le_bytes(len(seed), 1) + seed + \
            binder

    def next(self, length: int) -> bytes:
        self.l += length

        # Function `TurboSHAKE128(M, D, L)` is as defined in
        # Section 2.2 of [TurboSHAKE].
        #
        # Implementation note: rather than re-generate the output
        # stream each time `next()` is invoked, most implementations
        # of TurboSHAKE128 will expose an "absorb-then-squeeze" API
        # that allows stateful handling of the stream.
        stream = TurboSHAKE128(self.m, 1, self.l)
        return stream[-length:]
]]></sourcecode>
        </section>
        <section anchor="xof-fixed-key-aes128">
          <name>XofFixedKeyAes128</name>
          <t>The XOF in the previous section can be used safely wherever a XOF is needed in
this document. However, there are some situations where TurboSHAKE128 creates a
performance bottleneck and a more efficient XOF can be used safely instead.</t>
          <t>This section describes XofFixedKeyAes128, which is used to implement the IDPF
of Poplar1 (<xref target="idpf-bbcggi21"/>). It is <bcp14>NOT RECOMMENDED</bcp14> to use this XOF for any
other purpose. See <xref target="xof-vs-ro"/> for a more detailed discussion.</t>
          <t>XofFixedKeyAes128 uses the AES-128 blockcipher <xref target="AES"/> for most of the
computation, thereby taking advantage of the hardware implementations of this
blockcipher that are widely available. AES-128 is used in a fixed-key mode of
operation; the key is derived during initialization using TurboSHAKE128.</t>
          <t>Pre-conditions:</t>
          <ul spacing="normal">
            <li>
              <t>The length of the seed <bcp14>MUST</bcp14> be <tt>16</tt>.</t>
            </li>
            <li>
              <t>The length of the domain separation string <tt>dst</tt> passed to XofFixedKeyAes128
<bcp14>MUST NOT</bcp14> exceed 65535 bytes. Otherwise initialization will raise an
exception.</t>
            </li>
          </ul>
          <sourcecode type="python"><![CDATA[
class XofFixedKeyAes128(Xof):
    """
    XOF based on a circular collision-resistant hash function from
    fixed-key AES.
    """

    # Associated parameters
    SEED_SIZE = 16

    def __init__(self, seed: bytes, dst: bytes, binder: bytes):
        if len(seed) != self.SEED_SIZE:
            raise ValueError("incorrect seed size")

        self.length_consumed = 0

        # Use TurboSHAKE128 to derive a key from the binder string
        # and domain separation tag. Note that the AES key does not
        # need to be kept secret from any party. However, when used
        # with an IDPF, we require the binder to be a random nonce.
        #
        # Implementation note: this step can be cached across XOF
        # evaluations with many different seeds.
        dst_length = to_le_bytes(len(dst), 2)
        self.fixed_key = TurboSHAKE128(
            dst_length + dst + binder,
            2,
            16,
        )
        self.seed = seed

    def next(self, length: int) -> bytes:
        offset = self.length_consumed % 16
        new_length = self.length_consumed + length
        block_range = range(
            self.length_consumed // 16,
            new_length // 16 + 1
        )
        self.length_consumed = new_length

        hashed_blocks = [
            self.hash_block(xor(self.seed, to_le_bytes(i, 16)))
            for i in block_range
        ]
        return concat(hashed_blocks)[offset:offset+length]

    def hash_block(self, block: bytes) -> bytes:
        """
        The multi-instance tweakable circular correlation-robust hash
        function of [GKWWY20] (Section 4.2). The tweak here is the
        key that stays constant for all XOF evaluations of the same
        Client, but differs between Clients.

        Function `AES128(key, block)` is the AES-128 blockcipher.
        """
        lo, hi = block[:8], block[8:]
        sigma_block = concat([hi, xor(hi, lo)])
        return xor(AES128(self.fixed_key, sigma_block), sigma_block)
]]></sourcecode>
        </section>
        <section anchor="dst-binder">
          <name>The Domain Separation Tag and Binder String</name>
          <t>XOFs are used to map a seed to a finite domain, e.g., a fresh seed or a vector
of field elements. To ensure domain separation, derivation is bound to some
distinguished domain separation tag. The domain separation tag encodes the
following values:</t>
          <ol spacing="normal" type="1"><li>
              <t>The document version (i.e.,<tt>VERSION</tt>);</t>
            </li>
            <li>
              <t>The "class" of the algorithm using the output (e.g., DAF, VDAF, or IDPF as
defined in <xref target="idpf"/>);</t>
            </li>
            <li>
              <t>A unique identifier for the algorithm (e.g., <tt>VDAF.ID</tt>); and</t>
            </li>
            <li>
              <t>Some indication of how the output is used (e.g., for deriving the measurement
shares in Prio3 <xref target="prio3"/>).</t>
            </li>
          </ol>
          <t>The following algorithm is used in the remainder of this document in order to
format the domain separation tag:</t>
          <sourcecode type="python"><![CDATA[
def format_dst(algo_class: int,
               algo: int,
               usage: int) -> bytes:
    """
    Format XOF domain separation tag.

    Pre-conditions:

        - `algo_class` in the range `[0, 2^8)`
        - `algo` in the range `[0, 2^32)`
        - `usage` in the range `[0, 2^16)`
    """
    return concat([
        to_be_bytes(VERSION, 1),
        to_be_bytes(algo_class, 1),
        to_be_bytes(algo, 4),
        to_be_bytes(usage, 2),
    ])
]]></sourcecode>
          <t>It is also sometimes necessary to bind the output to some ephemeral value that
multiple parties need to agree on. We call this input the "binder string".</t>
        </section>
      </section>
    </section>
    <section anchor="prio3">
      <name>Prio3</name>
      <t>This section describes Prio3, a VDAF for general-purpose aggregation. Prio3 is
suitable for a wide variety of aggregation functions, including (but not
limited to) sum, mean, standard deviation, histograms, and linear regression.
It is compatible with any aggregation function that has the following
structure:</t>
      <ul spacing="normal">
        <li>
          <t>Each measurement is encoded as a vector over some finite field.</t>
        </li>
        <li>
          <t>Measurement validity is determined by an "arithmetic circuit" evaluated over
the encoded measurement. An arithmetic circuit is a function comprised of
arithmetic operations in the field. (We specify these in full detail in
<xref target="flp-bbcggi19-valid"/>.)</t>
        </li>
        <li>
          <t>The aggregate result is obtained by summing up the encoded measurements and
computing some function of the sum.</t>
        </li>
      </ul>
      <t>Clients protect the privacy of their measurements by secret sharing them and
distributing the shares among the Aggregators. To ensure each measurement is
valid, the Aggregators run a multi-party computation on their shares, the
result of which is the output of the arithmetic circuit. This involves
verification of a "Fully Linear Proof (FLP)" (<xref target="flp"/>) generated by the Client.
FLPs are the core component of Prio3, as they specify the types of
measurements and how they are encoded, verified, and aggregated. In fact Prio3
can be thought of as a transformation of an FLP into a VDAF.</t>
      <t>Prio3 does not have an aggregation parameter. Instead, each output share is
derived from each input share by applying a fixed map. See <xref target="poplar1"/> for an
example of a VDAF that makes meaningful use of the aggregation parameter.</t>
      <t>The remainder of this section is structured as follows. The interface of FLPs is
described in <xref target="flp"/>. The generic transformation of an FLP into Prio3 is
specified in <xref target="prio3-construction"/>. Next, a concrete FLP suitable for any
validity circuit is specified in <xref target="flp-bbcggi19"/>. Finally, variants of Prio3
for various types of aggregation tasks are specified in
<xref target="prio3-instantiations"/>. Test vectors for each variant can be found in
<xref target="test-vectors"/>.</t>
      <section anchor="flp">
        <name>Fully Linear Proofs (FLPs)</name>
        <t>Conceptually, an FLP is a two-party protocol executed by a prover and a
verifier. The verifier is restricted to only access the messages it receives
from the prover via linear queries. In actual use in Prio3, however, the
prover's computation is carried out by the Client, and the verifier's
computation is distributed among the Aggregators. The Client generates a
"proof" of its measurement's validity and distributes shares of the proof to
the Aggregators. During preparation, each Aggregator performs some computation
on its measurement share and proof share locally, then broadcasts the result in
its prep share. The validity decision is then made by the
<tt>prep_shares_to_prep()</tt> algorithm (<xref target="sec-vdaf-prepare"/>).</t>
        <t>As usual, we describe the interface implemented by a concrete FLP in terms of
an 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>Our application requires that the FLP is "fully linear" in the sense defined in
<xref target="BBCGGI19"/>. As a practical matter, what this property implies is that, when
run on a share of the measurement and proof, the query algorithm outputs a
share of the verifier message (hereafter the "verifier share"). Furthermore,
the privacy property of the FLP system ensures that the verifier message
reveals nothing about the measurement other than the fact that it is valid.
Therefore, to decide if a measurement is valid, the Aggregators will run the
query algorithm locally, exchange verifier shares, combine them to recover the
verifier message, and run the decision algorithm.</t>
        <t>The query algorithm includes a parameter <tt>num_shares</tt> that specifies the number
of shares of the measurement and proof that were generated. If these data are
not secret shared, then <tt>num_shares == 1</tt>. This parameter is useful for
normalizing constants in arithmetic circuits so that each Aggregator properly
computes a secret share of the circuit's output. See <xref target="flp-bbcggi19"/> for
details.</t>
        <t>An FLP is executed by the prover and verifier as follows:</t>
        <sourcecode type="python"><![CDATA[
def run_flp(
        flp: Flp[Measurement, AggResult, F],
        meas: list[F],
        num_shares: int) -> bool:
    """Run the FLP on an encoded measurement."""

    joint_rand = flp.field.rand_vec(flp.JOINT_RAND_LEN)
    prove_rand = flp.field.rand_vec(flp.PROVE_RAND_LEN)
    query_rand = flp.field.rand_vec(flp.QUERY_RAND_LEN)

    # Prover generates the proof.
    proof = flp.prove(meas, prove_rand, joint_rand)

    # Shard the measurement and the proof.
    meas_shares = additive_secret_share(
        meas,
        num_shares,
        flp.field,
    )
    proof_shares = additive_secret_share(
        proof,
        num_shares,
        flp.field,
    )

    # Verifier queries the meas shares and proof shares.
    verifier_shares = [
        flp.query(
            meas_share,
            proof_share,
            query_rand,
            joint_rand,
            num_shares,
        )
        for meas_share, proof_share in zip(meas_shares, proof_shares)
    ]

    # Combine the verifier shares into the verifier.
    verifier = flp.field.zeros(len(verifier_shares[0]))
    for verifier_share in verifier_shares:
        verifier = vec_add(verifier, verifier_share)

    # Verifier decides if the measurement is valid.
    return flp.decide(verifier)
]]></sourcecode>
        <t>The proof system is designed so that, if <tt>meas</tt> is valid, then <tt>run_flp(flp,
meas, num_shares)</tt> always returns <tt>True</tt>. On the other hand, if <tt>meas</tt> is
invalid, then as long as <tt>joint_rand</tt> and <tt>query_rand</tt> are generated uniform
randomly, the output is <tt>False</tt> with high probability. False positives are
possible: there is a small probability that a verifier accepts an invalid input
as valid. An FLP is said to be "sound" if this probability is sufficiently
small. The soundness of the FLP depends on a variety of parameters, like the
length of the input and the size of the field. See <xref target="flp-bbcggi19"/> for
details.</t>
        <t>Note that soundness of an FLP system is not the same as robustness for the VDAF
that uses it. In particular, soundness of the FLP is necessary, but
insufficient for robustness of Prio3 (<xref target="prio3"/>). See <xref target="security-multiproof"/>
for details.</t>
        <t>We remark that <xref target="BBCGGI19"/> defines a larger class of fully linear proof
systems than we consider here. In particular, what is called an "FLP" here is
called a 1.5-round, public-coin, interactive oracle proof system in their
paper.</t>
        <table anchor="flp-param">
          <name>FLP parameters.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>PROVE_RAND_LEN: int</tt></td>
              <td align="left">Length of the prover randomness, the number of random field elements consumed by the prover when generating a proof.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>QUERY_RAND_LEN: int</tt></td>
              <td align="left">Length of the query randomness, the number of random field elements consumed by the verifier.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>JOINT_RAND_LEN: int</tt></td>
              <td align="left">Length of the joint randomness, the number of random field elements shared by the prover and verifier.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>MEAS_LEN: int</tt></td>
              <td align="left">Length of the encoded measurement (<xref target="flp-encode"/>).</td>
            </tr>
            <tr>
              <td align="left">
                <tt>OUTPUT_LEN: int</tt></td>
              <td align="left">Length of the aggregatable output (<xref target="flp-encode"/>).</td>
            </tr>
            <tr>
              <td align="left">
                <tt>PROOF_LEN: int</tt></td>
              <td align="left">Length of the proof.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VERIFIER_LEN: int</tt></td>
              <td align="left">Length of the verifier message generated by querying the measurement and proof.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">Type of the measurement.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">Type of the aggregate result.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>field: type[F]</tt></td>
              <td align="left">Class object for the field (<xref target="field"/>).</td>
            </tr>
          </tbody>
        </table>
        <section anchor="flp-encode">
          <name>Encoding the Input</name>
          <t>The type of measurement being aggregated is defined by the FLP. Hence, the FLP
also specifies a method of encoding raw measurements as a vector of field
elements:</t>
          <ul spacing="normal">
            <li>
              <t><tt>flp.encode(measurement: Measurement) -&gt; list[F]</tt> encodes a raw measurement
as a vector of field elements.  </t>
              <t>
Post-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The encoded measurement <bcp14>MUST</bcp14> have length <tt>flp.MEAS_LEN</tt>.</t>
                </li>
              </ul>
            </li>
          </ul>
          <t>For some FLPs, the encoded measurement also includes redundant field elements
that are useful for checking the proof, but which are not needed after the
proof has been checked. An example is the <tt>Sum</tt> type defined in <xref target="prio3sum"/>
for which each measurement is an integer in the range <tt>[0, max_measurement]</tt>.
The range check requires encoding the measurement with several field elements,
though just one is needed for aggregation. Thus the FLP defines an algorithm
for truncating the encoded measurement to the length of the aggregatable output:</t>
          <ul spacing="normal">
            <li>
              <t><tt>flp.truncate(meas: list[F]) -&gt; list[F]</tt> maps an encoded measurement (e.g.,
the bit-encoding of the measurement) to an aggregatable output (e.g., the
singleton vector containing the measurement).  </t>
              <t>
Pre-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The length of the input <bcp14>MUST</bcp14> be <tt>flp.MEAS_LEN</tt></t>
                </li>
              </ul>
              <t>
Post-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The length of the output <bcp14>MUST</bcp14> be <tt>flp.OUTPUT_LEN</tt>.</t>
                </li>
              </ul>
            </li>
          </ul>
          <t>Once the aggregate shares have been transmitted to the Collector, their sum can
be converted into the aggregate result. This could be a projection from the
FLP's field to the integers, or it could include additional post-processing.
Either way, this functionality is implemented by the following method:</t>
          <ul spacing="normal">
            <li>
              <t><tt>flp.decode(output: list[F], num_measurements: int) -&gt; AggResult</tt> maps a sum
of aggregate shares to an aggregate result.  </t>
              <t>
Pre-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The length of the output <bcp14>MUST</bcp14> be <tt>OUTPUT_LEN</tt>.</t>
                </li>
                <li>
                  <t><tt>num_measurements</tt> <bcp14>MUST</bcp14> equal the number of measurements that were
aggregated.</t>
                </li>
              </ul>
            </li>
          </ul>
          <t>We remark that, taken together, these three functionalities correspond to the
notion of "Affine-aggregatable encodings (AFEs)" from <xref target="CGB17"/>.</t>
        </section>
        <section anchor="multiproofs">
          <name>Multiple Proofs</name>
          <t>It is sometimes desirable to generate and verify multiple independent proofs
for the same input. First, this improves the soundness of the proof system
without having to change any of its parameters. Second, it allows a smaller
field to be used (e.g., replace Field128 with Field64)
without sacrificing soundness. This is useful because it reduces the overall
communication of the protocol. (This is a trade-off, of course, since
generating and verifying more proofs requires more time.) Given these benefits,
this feature is implemented by Prio3 (<xref target="prio3"/>).</t>
          <t>To generate these proofs for a specific measurement, the prover calls
<tt>flp.prove()</tt> multiple times, each time using fresh prover and joint
randomness. The verifier checks each proof independently, each time with fresh
query randomness. It accepts the measurement only if the decision algorithm
accepts on each proof.</t>
          <t>See <xref target="security-multiproof"/> for guidance on choosing the field size and number
of proofs.</t>
        </section>
      </section>
      <section anchor="prio3-construction">
        <name>Specification</name>
        <t>This section specifies <tt>Prio3</tt>, an implementation of the <tt>Vdaf</tt> interface
defined in <xref target="vdaf"/>. The parameters and types required by the <tt>Vdaf</tt> interface
are defined in <xref target="prio3-param"/>. The methods required for sharding, preparation,
aggregation, and unsharding are described in the remaining subsections. These
methods refer to constants enumerated in <xref target="prio3-const"/>.</t>
        <table anchor="prio3-param">
          <name>Parameters for Prio3.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>flp</tt></td>
              <td align="left">An instance of <tt>Flp</tt> (<xref target="flp"/>).</td>
            </tr>
            <tr>
              <td align="left">
                <tt>xof</tt></td>
              <td align="left">
                <tt>XofTurboShake128</tt> (<xref target="xof-turboshake128"/>)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>PROOFS</tt></td>
              <td align="left">Any <tt>int</tt> in the range <tt>[1, 256)</tt>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VERIFY_KEY_SIZE</tt></td>
              <td align="left">
                <tt>xof.SEED_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>RAND_SIZE</tt></td>
              <td align="left">
                <tt>xof.SEED_SIZE * SHARES if flp.JOINT_RAND_LEN == 0 else 2 * xof.SEED_SIZE * SHARES</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>NONCE_SIZE</tt></td>
              <td align="left">
                <tt>16</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>ROUNDS</tt></td>
              <td align="left">
                <tt>1</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>SHARES</tt></td>
              <td align="left">Any <tt>int</tt> in the range <tt>[2, 256)</tt>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">As defined by <tt>flp</tt>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggParam</tt></td>
              <td align="left">
                <tt>None</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PublicShare</tt></td>
              <td align="left">
                <tt>Optional[list[bytes]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>InputShare</tt></td>
              <td align="left">
                <tt>tuple[list[F], list[F], Optional[bytes]] | tuple[bytes, Optional[bytes]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>OutShare</tt></td>
              <td align="left">
                <tt>list[F]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggShare</tt></td>
              <td align="left">
                <tt>list[F]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">As defined by <tt>flp</tt>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepState</tt></td>
              <td align="left">
                <tt>tuple[list[F], Optional[bytes]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepShare</tt></td>
              <td align="left">
                <tt>tuple[list[F], Optional[bytes]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepMessage</tt></td>
              <td align="left">
                <tt>Optional[bytes]</tt></td>
            </tr>
          </tbody>
        </table>
        <table anchor="prio3-const">
          <name>Constants used by Prio3.</name>
          <thead>
            <tr>
              <th align="left">Variable</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>USAGE_MEAS_SHARE: int</tt></td>
              <td align="left">1</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_PROOF_SHARE: int</tt></td>
              <td align="left">2</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_JOINT_RANDOMNESS: int</tt></td>
              <td align="left">3</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_PROVE_RANDOMNESS: int</tt></td>
              <td align="left">4</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_QUERY_RANDOMNESS: int</tt></td>
              <td align="left">5</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_JOINT_RAND_SEED: int</tt></td>
              <td align="left">6</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_JOINT_RAND_PART: int</tt></td>
              <td align="left">7</td>
            </tr>
          </tbody>
        </table>
        <section anchor="sharding">
          <name>Sharding</name>
          <t>Recall from <xref target="flp"/> that the FLP syntax calls for "joint randomness" shared by
the prover (i.e., the Client) and the verifier (i.e., the Aggregators). VDAFs
have no such notion. Instead, the Client derives the joint randomness from its
measurement in a way that allows the Aggregators to reconstruct it from their
shares. (This idea is based on the Fiat-Shamir heuristic and is described in
Section 6.2.3 of <xref target="BBCGGI19"/>.)</t>
          <t>The sharding algorithm involves the following steps:</t>
          <ol spacing="normal" type="1"><li>
              <t>Encode the Client's measurement as specified by the FLP</t>
            </li>
            <li>
              <t>Shard the measurement into a sequence of measurement shares</t>
            </li>
            <li>
              <t>Derive the joint randomness from the measurement shares and nonce</t>
            </li>
            <li>
              <t>Generate the proof using the derived joint randomness</t>
            </li>
            <li>
              <t>Shard the proof into a sequence of proof shares</t>
            </li>
          </ol>
          <t>As described in <xref target="multiproofs"/>, robustness of Prio3 can be amplified by
generating and verifying multiple proofs. To support this:</t>
          <ul spacing="normal">
            <li>
              <t>In step 3, derive as much joint randomness as required by <tt>PROOFS</tt> proofs</t>
            </li>
            <li>
              <t>Repeat step 4 <tt>PROOFS</tt> times, each time with a unique joint randomness</t>
            </li>
          </ul>
          <t>Depending on the FLP, joint randomness may not be required. In particular, when
<tt>flp.JOINT_RAND_LEN == 0</tt>, the Client does not derive the joint randomness
(Step 3).</t>
          <t>The sharding algorithm is specified below:</t>
          <sourcecode type="python"><![CDATA[
def shard(
        self,
        ctx: bytes,
        measurement: Measurement,
        nonce: bytes,
        rand: bytes) -> tuple[
            Optional[list[bytes]],
            list[Prio3InputShare]]:
    if len(nonce) != self.NONCE_SIZE:
        raise ValueError("incorrect nonce size")
    if len(rand) != self.RAND_SIZE:
        raise ValueError("incorrect size of random bytes argument")

    l = self.xof.SEED_SIZE
    seeds = [rand[i:i + l] for i in range(0, self.RAND_SIZE, l)]

    meas = self.flp.encode(measurement)
    if self.flp.JOINT_RAND_LEN > 0:
        return self.shard_with_joint_rand(ctx, meas, nonce, seeds)
    else:
        return self.shard_without_joint_rand(ctx, meas, seeds)
]]></sourcecode>
          <t>It starts by splitting the randomness into seeds. It then encodes the
measurement as prescribed by the FLP and calls one of two methods, depending on
whether joint randomness is required by the FLP. The methods are defined in the
subsections below.</t>
          <section anchor="prio3-shard-without-joint-rand">
            <name>FLPs Without Joint Randomness</name>
            <t>The following method is used for FLPs that do not require joint randomness,
i.e., when <tt>flp.JOINT_RAND_LEN == 0</tt>. It consists of the following steps:</t>
            <ol spacing="normal" type="1"><li>
                <t>Shard the encoded measurement into shares</t>
              </li>
              <li>
                <t>Generate proofs and shard each into shares</t>
              </li>
              <li>
                <t>Encode each measurement share and shares of each proof into an input share</t>
              </li>
            </ol>
            <t>Only one pair of measurement and proof(s) share (called the "Leader" shares)
are vectors of field elements. The other shares (called the "Helper"
shares) are represented instead by an XOF seed, which is expanded into vectors
of field elements. The methods on <tt>Prio3</tt> for deriving the prover randomness,
measurement shares, and proof shares are defined in <xref target="prio3-auxiliary"/>.</t>
            <sourcecode type="python"><![CDATA[
def shard_without_joint_rand(
        self,
        ctx: bytes,
        meas: list[F],
        seeds: list[bytes]) -> tuple[
            Optional[list[bytes]],
            list[Prio3InputShare[F]]]:
    helper_shares, seeds = front(self.SHARES - 1, seeds)
    (prove_seed,), seeds = front(1, seeds)

    # Shard the encoded measurement into shares.
    leader_meas_share = meas
    for j in range(self.SHARES - 1):
        leader_meas_share = vec_sub(
            leader_meas_share,
            self.helper_meas_share(ctx, j + 1, helper_shares[j]),
        )

    # Generate and shard each proof into shares.
    prove_rands = self.prove_rands(ctx, prove_seed)
    leader_proofs_share = []
    for _ in range(self.PROOFS):
        prove_rand, prove_rands = front(
            self.flp.PROVE_RAND_LEN, prove_rands)
        leader_proofs_share += self.flp.prove(meas, prove_rand, [])
    for j in range(self.SHARES - 1):
        leader_proofs_share = vec_sub(
            leader_proofs_share,
            self.helper_proofs_share(
                ctx,
                j + 1,
                helper_shares[j],
            ),
        )

    # Each Aggregator's input share contains its measurement share
    # and its share of the proof(s).
    input_shares: list[Prio3InputShare[F]] = []
    input_shares.append((
        leader_meas_share,
        leader_proofs_share,
        None,
    ))
    for j in range(self.SHARES - 1):
        input_shares.append((
            helper_shares[j],
            None,
        ))
    return (None, input_shares)
]]></sourcecode>
          </section>
          <section anchor="flps-with-joint-randomness">
            <name>FLPs With Joint Randomness</name>
            <t>The following method is used for FLPs that require joint randomness, i.e., for
which <tt>flp.JOINT_RAND_LEN &gt; 0</tt>. Joint randomness derivation involves an
additional XOF seed for each Aggregator called the "blind". The computation
involves the following steps:</t>
            <ol spacing="normal" type="1"><li>
                <t>Compute a "joint randomness part" from each measurement share and blind</t>
              </li>
              <li>
                <t>Compute a "joint randomness seed" from the joint randomness parts</t>
              </li>
              <li>
                <t>Compute the joint randomness for each proof evaluation from the joint
randomness seed</t>
              </li>
            </ol>
            <t>This three-step process is designed to ensure that the joint randomness does
not leak the measurement to the Aggregators while preventing a malicious Client
from tampering with the joint randomness in a way that allows it to break
robustness. To save a round of communication between the Aggregators later, the
Client encodes the joint randomness parts in the public share. (See
<xref target="prio3-preparation"/> for details.)</t>
            <t>All functions used in the following listing are defined in <xref target="prio3-auxiliary"/>:</t>
            <sourcecode type="python"><![CDATA[
def shard_with_joint_rand(
        self,
        ctx: bytes,
        meas: list[F],
        nonce: bytes,
        seeds: list[bytes]) -> tuple[
            Optional[list[bytes]],
            list[Prio3InputShare[F]]]:
    helper_seeds, seeds = front((self.SHARES - 1) * 2, seeds)
    helper_shares = [
        helper_seeds[i]
        for i in range(0, (self.SHARES - 1) * 2, 2)
    ]
    helper_blinds = [
        helper_seeds[i]
        for i in range(1, (self.SHARES - 1) * 2, 2)
    ]
    (leader_blind, prove_seed), seeds = front(2, seeds)

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

    # Generate each proof and shard it into proof shares.
    prove_rands = self.prove_rands(ctx, prove_seed)
    joint_rands = self.joint_rands(
        ctx, self.joint_rand_seed(ctx, joint_rand_parts))
    leader_proofs_share = []
    for _ in range(self.PROOFS):
        prove_rand, prove_rands = front(
            self.flp.PROVE_RAND_LEN, prove_rands)
        joint_rand, joint_rands = front(
            self.flp.JOINT_RAND_LEN, joint_rands)
        leader_proofs_share += self.flp.prove(
            meas,
            prove_rand,
            joint_rand,
        )
    for j in range(self.SHARES - 1):
        leader_proofs_share = vec_sub(
            leader_proofs_share,
            self.helper_proofs_share(
                ctx,
                j + 1,
                helper_shares[j],
            ),
        )

    # Each Aggregator's input share contains its measurement share,
    # share of proof(s), and blind. The public share contains the
    # Aggregators' joint randomness parts.
    input_shares: list[Prio3InputShare[F]] = []
    input_shares.append((
        leader_meas_share,
        leader_proofs_share,
        leader_blind,
    ))
    for j in range(self.SHARES - 1):
        input_shares.append((
            helper_shares[j],
            helper_blinds[j],
        ))
    return (joint_rand_parts, input_shares)
]]></sourcecode>
          </section>
        </section>
        <section anchor="prio3-preparation">
          <name>Preparation</name>
          <t>This section describes the process of recovering output shares from the input
shares. The high-level idea is that each Aggregator first queries its
measurement share and proof(s) share(s) locally, then broadcasts its verifier
share(s) in its prep share. The shares of verifier(s) are then combined into
the verifier message(s) used to decide whether to accept.</t>
          <t>In addition, the Aggregators must recompute the same joint randomness used by
the Client to generate the proof(s). In order to avoid an extra round of
communication, the Client includes the joint randomness parts in the public
share. This leaves open the possibility that the Client cheated by, say,
forcing the Aggregators to use joint randomness that biases the proof check
procedure some way in its favor. To mitigate this, the Aggregators also check
that they have all computed the same joint randomness seed before accepting
their output shares. To do so, they exchange their parts of the joint
randomness along with their shares of verifier(s).</t>
          <t>Implementation note: the prep state for Prio3 includes the output share that
will be released once preparation is complete. In some situations, it may be
necessary for the Aggregator to encode this state as bytes and store it for
retrieval later on. For all but the first Aggregator, it is possible to save
storage by storing the measurement share rather than output share itself. It is
relatively inexpensive to expand this seed into the measurement share, then
truncate the measurement share to get the output share.</t>
          <t>All functions used in the following listing are defined in <xref target="prio3-auxiliary"/>:</t>
          <sourcecode type="python"><![CDATA[
def prep_init(
        self,
        verify_key: bytes,
        ctx: bytes,
        agg_id: int,
        _agg_param: None,
        nonce: bytes,
        public_share: Optional[list[bytes]],
        input_share: Prio3InputShare[F]) -> tuple[
            Prio3PrepState[F],
            Prio3PrepShare[F]]:
    joint_rand_parts = public_share
    (meas_share, proofs_share, blind) = \
        self.expand_input_share(ctx, agg_id, input_share)
    out_share = self.flp.truncate(meas_share)

    # Compute the joint randomness.
    joint_rand: list[F] = []
    corrected_joint_rand_seed, joint_rand_part = None, None
    if self.flp.JOINT_RAND_LEN > 0:
        assert blind is not None
        assert joint_rand_parts is not None
        joint_rand_part = self.joint_rand_part(
            ctx, agg_id, blind, meas_share, nonce)
        joint_rand_parts = 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,
        )

    prep_state = (out_share, corrected_joint_rand_seed)
    prep_share = (verifiers_share, joint_rand_part)
    return (prep_state, prep_share)

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

    # Verify that each proof is well-formed and input is valid.
    for _ in range(self.PROOFS):
        verifier, verifiers = front(self.flp.VERIFIER_LEN, verifiers)
        if not self.flp.decide(verifier):
            raise ValueError('proof verifier check failed')

    # Combine the joint randomness parts computed by the
    # Aggregators into the true joint randomness seed. This is
    # used in the last step.
    joint_rand_seed = None
    if self.flp.JOINT_RAND_LEN > 0:
        joint_rand_seed = self.joint_rand_seed(ctx, joint_rand_parts)
    return joint_rand_seed

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

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

    return out_share
]]></sourcecode>
        </section>
        <section anchor="validity-of-aggregation-parameters">
          <name>Validity of Aggregation Parameters</name>
          <t><tt>Prio3</tt> only permits a report to be aggregated once.</t>
          <sourcecode type="python"><![CDATA[
def is_valid(
        self,
        _agg_param: None,
        previous_agg_params: list[None]) -> bool:
    return len(previous_agg_params) == 0
]]></sourcecode>
        </section>
        <section anchor="aggregation">
          <name>Aggregation</name>
          <t>Aggregating a set of output shares is simply a matter of adding up the vectors
element-wise.</t>
          <sourcecode type="python"><![CDATA[
def agg_init(self, _agg_param: None) -> list[F]:
    return self.flp.field.zeros(self.flp.OUTPUT_LEN)

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

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

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

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

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

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

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

def joint_rand_seed(self,
                    ctx: bytes,
                    joint_rand_parts: list[bytes]) -> bytes:
    """Derive the joint randomness seed from its parts."""
    return self.xof.derive_seed(
        zeros(self.xof.SEED_SIZE),
        self.domain_separation_tag(USAGE_JOINT_RAND_SEED, ctx),
        concat(joint_rand_parts),
    )

def joint_rands(self,
                ctx: bytes,
                joint_rand_seed: bytes) -> list[F]:
    """Derive the joint randomness from its seed."""
    return self.xof.expand_into_vec(
        self.flp.field,
        joint_rand_seed,
        self.domain_separation_tag(USAGE_JOINT_RANDOMNESS, ctx),
        byte(self.PROOFS),
        self.flp.JOINT_RAND_LEN * self.PROOFS,
    )
]]></sourcecode>
        </section>
        <section anchor="prio3-encode">
          <name>Message Serialization</name>
          <t>This section defines serialization formats for messages exchanged over the
network while executing Prio3. Messages are defined in the presentation
language of TLS as defined in <xref section="3" sectionFormat="of" target="RFC8446"/>.</t>
          <t>Let <tt>prio3</tt> denote an instance of <tt>Prio3</tt>. In the remainder we use <tt>S</tt> as an
alias for <tt>prio3.xof.SEED_SIZE</tt> and <tt>F</tt> as an alias for
<tt>prio3.field.ENCODED_SIZE</tt>. XOF seeds are represented as follows:</t>
          <sourcecode type="tls-presentation"><![CDATA[
opaque Prio3Seed[S];
]]></sourcecode>
          <t>Field elements are encoded in little-endian byte order (as defined in
<xref target="field"/>) and represented as follows:</t>
          <sourcecode type="tls-presentation"><![CDATA[
opaque Prio3Field[F];
]]></sourcecode>
          <section anchor="public-share">
            <name>Public Share</name>
            <t>The contents of the public share depend on whether joint randomness is
required for the underlying FLP (i.e., <tt>prio3.flp.JOINT_RAND_LEN &gt; 0</tt>). If
joint randomness is not used, then the public share is the empty string.
Otherwise, if joint randomness is used, then the public share encodes the joint
randomness parts as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Seed joint_rand_parts[S * prio3.SHARES];
} Prio3PublicShareWithJointRand;
]]></sourcecode>
          </section>
          <section anchor="input-share">
            <name>Input Share</name>
            <t>Just as for the public share, the content of the input shares depends on
whether joint randomness is used. If so, then each input share includes the
Aggregator's blind for generating its joint randomness part.</t>
            <t>In addition, the encoding of the input shares depends on which aggregator is
receiving the message. If the aggregator ID is <tt>0</tt>, then the input share
includes the full measurement share and proofs(s) share(s). Otherwise, if the
aggregator ID is greater than <tt>0</tt>, then the measurement and shares of proof(s)
are represented by an XOF seed. We shall call the former the "Leader" and the
latter the "Helpers".</t>
            <t>In total there are four variants of the input share. When joint randomness is
not used, the Leader's share is structured as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Field meas_share[F * prio3.flp.MEAS_LEN];
    Prio3Field proofs_share[F * prio3.flp.PROOF_LEN * prio3.PROOFS];
} Prio3LeaderShare;
]]></sourcecode>
            <t>When joint randomness is not used, the Helpers' shares are structured
as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Seed share;
} Prio3HelperShare;
]]></sourcecode>
            <t>When joint randomness is used, the Leader's input share is structured as
follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3LeaderShare inner;
    Prio3Seed blind;
} Prio3LeaderShareWithJointRand;
]]></sourcecode>
            <t>Finally, when joint randomness is used, the Helpers' shares are structured as
follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3HelperShare inner;
    Prio3Seed blind;
} Prio3HelperShareWithJointRand;
]]></sourcecode>
          </section>
          <section anchor="prep-share">
            <name>Prep Share</name>
            <t>When joint randomness is not used, the prep share is structured as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Field verifiers_share[F * V];
} Prio3PrepShare;
]]></sourcecode>
            <t>where <tt>V = prio3.flp.VERIFIER_LEN * prio3.PROOFS</tt>. When joint randomness is
used, the prep share includes the Aggregator's joint randomness part and is
structured as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Field verifiers_share[F * V];
    Prio3Seed joint_rand_part;
} Prio3PrepShareWithJointRand;
]]></sourcecode>
          </section>
          <section anchor="prep-message">
            <name>Prep Message</name>
            <t>When joint randomness is not used, the prep message is the empty string.
Otherwise the prep message consists of the joint randomness seed computed by
the Aggregators:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Seed joint_rand;
} Prio3PrepMessageWithJointRand;
]]></sourcecode>
          </section>
          <section anchor="aggregation-1">
            <name>Aggregation</name>
            <t>Aggregate shares are structured as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Field agg_share[F * prio3.flp.OUTPUT_LEN];
} Prio3AggShare;
]]></sourcecode>
          </section>
        </section>
      </section>
      <section anchor="flp-bbcggi19">
        <name>FLP Specification</name>
        <t>This section specifies an implementation of the <tt>Flp</tt> interface (<xref target="flp"/>) based
on the construction from <xref target="BBCGGI19"/>, Section 4.2. The types and parameters
required by this interface are listed in the table below.</t>
        <t>We begin in <xref target="flp-bbcggi19-overview"/> with an overview of the proof system and
some extensions to it. <xref target="flp-bbcggi19-valid"/> defines validity circuits, the
core component of the proof system that determines measurement validity and how
measurements are aggregated. The proof-generation algorithm, query algorithm,
and decision algorithm are defined in <xref target="flp-bbcggi19-construction-prove"/>,
<xref target="flp-bbcggi19-construction-query"/>, and <xref target="flp-bbcggi19-construction-decide"/>
respectively.</t>
        <table anchor="flp-bbcggi19-param">
          <name>FLP parameters for a validity circuit.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>valid</tt></td>
              <td align="left">An instance of <tt>Valid</tt> (<xref target="flp-bbcggi19-valid"/>).</td>
            </tr>
            <tr>
              <td align="left">
                <tt>field</tt></td>
              <td align="left">
                <tt>valid.field</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PROVE_RAND_LEN</tt></td>
              <td align="left">
                <tt>valid.prove_rand_len()</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>QUERY_RAND_LEN</tt></td>
              <td align="left">
                <tt>valid.query_rand_len()</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>JOINT_RAND_LEN</tt></td>
              <td align="left">
                <tt>valid.JOINT_RAND_LEN</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>MEAS_LEN</tt></td>
              <td align="left">
                <tt>valid.MEAS_LEN</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>OUTPUT_LEN</tt></td>
              <td align="left">
                <tt>valid.OUTPUT_LEN</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PROOF_LEN</tt></td>
              <td align="left">
                <tt>valid.proof_len()</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>VERIFIER_LEN</tt></td>
              <td align="left">
                <tt>valid.verifier_len()</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">As defined by <tt>valid</tt>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">As defined by <tt>valid</tt>.</td>
            </tr>
          </tbody>
        </table>
        <section anchor="flp-bbcggi19-overview">
          <name>Overview</name>
          <t>An FLP is a type of "zero-knowledge proof". A conventional zero-knowledge proof
system involves two parties:</t>
          <ul spacing="normal">
            <li>
              <t>The prover, who holds a measurement and generates a proof of the
measurement's validity</t>
            </li>
            <li>
              <t>The verifier who holds an encryption of, or commitment to, the measurement
and checks the proof</t>
            </li>
          </ul>
          <t>Our proof system is much the same, except the verifier is split across multiple
Aggregators, each of which has a secret share of the measurement rather than a
commitment to it.</t>
          <t>Validity is defined in terms of an arithmetic circuit evaluated over the
measurement. The inputs to this circuit are elements of a finite field that
comprise the encoded measurement; the gates of the circuit are multiplication,
addition, and subtraction operations; and the output of the circuit is a single
field element. If the value is zero, then the measurement is deemed valid;
otherwise, if the output is non-zero, then the measurement is deemed invalid.</t>
          <t>For example, the simplest circuit specified in this document is the following
(<xref target="prio3count"/>):</t>
          <artwork><![CDATA[
C(x) = x * (x-1)
]]></artwork>
          <t>This circuit contains one subtraction gate (<tt>x-1</tt>) and one multiplication gate
(<tt>x * (x-1)</tt>). Observe that <tt>C(x) = 0</tt> if and only if <tt>x</tt> is in the range
<tt>[0, 2)</tt>.</t>
          <t>The goal of the proof system is to allow each Aggregator to privately and
correctly compute a share of <tt>C(x)</tt> from its share of <tt>x</tt>. Then all they need
to do to determine validity is to broadcast their shares of <tt>C(x)</tt>.</t>
          <t>Suppose for a moment that <tt>C</tt> is an affine arithmetic circuit, meaning its only
operations are addition, subtraction, and multiplication-by-constant. (The
circuit above is non-affine because it contains a multiplication gate with two
non-constant inputs.) Then each Aggregator can compute its share locally, since</t>
          <artwork><![CDATA[
C(x_shares[0] + ... + x_shares[SHARES-1]) =
    C(x_shares[0]) + ... + C(x_shares[SHARES-1])
]]></artwork>
          <t>(Note that, for this equality to hold, it is necessary to scale any addition of
a constant in the circuit by <tt>1/SHARES</tt>.) However, this is not the case if <tt>C</tt>
contains multiplication gates with two non-constant inputs. Thus our goal is to
transform these multiplication gates into computations on secret shared data
that each Aggregator can perform locally.</t>
          <t>The key idea is to have the prover construct a polynomial <tt>p</tt> such that <tt>p(j)</tt>
is equal to the output of the <tt>j</tt>-th multiplication gate. Polynomial evaluation
is fully linear, which means the coefficients of the polynomial can be secret
shared in a way that allows each Aggregator to compute a share of <tt>p(j)</tt> for
any <tt>j</tt>. These intermediate results can then be combined with the affine
arithmetic operations of the validity circuit to produce the final output.</t>
          <t>Applying this idea to the example circuit <tt>C</tt> above:</t>
          <ol spacing="normal" type="1"><li>
              <t>The Client, given its measurement <tt>x</tt>, constructs the lowest degree
polynomial <tt>p</tt> for which <tt>p(0) = s</tt> and <tt>p(1) = x * (x-1)</tt>, where <tt>s</tt> is a
random blinding value generated by the Client. (The blinding value is to
protect the privacy of the measurement.) It then sends shares of <tt>x</tt> and
shares of the coefficients of <tt>p</tt> to each of the Aggregators.</t>
            </li>
            <li>
              <t>Each Aggregator locally computes and broadcasts its share of <tt>p(1)</tt>, which
is equal to its share of <tt>C(x)</tt>.</t>
            </li>
          </ol>
          <t>In fact, our FLP is slightly more general than this. We can replace the
multiplication gate with any non-affine sub-circuit and apply the same idea.
For example, in <xref target="prio3sum"/>, the validity circuit uses the following
sub-circuit multiple times:</t>
          <artwork><![CDATA[
Range2(x) = x * (x-1) = x^2 - x
]]></artwork>
          <t>(This is the same functionality computed by the example circuit <tt>C</tt> above.)
Here again we can interpolate the lowest degree polynomial <tt>p</tt> for which <tt>p(j)</tt>
is the value of the <tt>j</tt>-th call to <tt>Range2</tt> in the validity circuit. Each
validity circuit defines a sub-circuit that encapsulates its non-affine
arithmetic operations. We refer to this sub-circuit as the "gadget".</t>
          <t>Finally, the proof system has one more important component. It is possible for
a malicious Client to produce a gadget polynomial <tt>p</tt> that would result in
<tt>C(x)</tt> being computed incorrectly, potentially resulting in an invalid
measurement being accepted. To prevent this, the Aggregators perform a
probabilistic test to check that the gadget polynomial was constructed
properly. This "gadget test", and the procedure for constructing the
polynomial, are described in detail in <xref target="flp-bbcggi19-construction-prove"/>.</t>
          <section anchor="flp-bbcggi19-overview-extensions">
            <name>Extensions</name>
            <t>The FLP described in <xref target="flp-bbcggi19"/> extends the proof system of
<xref target="BBCGGI19"/>, Section 4.2 in a few ways.</t>
            <t>First, the validity circuit in our construction includes an additional, random
input (this is the "joint randomness" derived from the measurement shares in
Prio3; see <xref target="prio3-construction"/>). This allows for circuit optimizations that
trade a small soundness error for a shorter proof. For example, consider a
circuit that recognizes the set of length-<tt>N</tt> vectors for which each element is
either one or zero. A deterministic circuit could be constructed for this
language, but it would involve a large number of multiplications that would
result in a large proof. (See the discussion in <xref target="BBCGGI19"/>, Section 5.2 for
details). A much shorter proof can be constructed for the following randomized
circuit:</t>
            <artwork><![CDATA[
C(x, r) = r * Range2(x[0]) + ... + r^N * Range2(x[N-1])
]]></artwork>
            <t>(Note that this is a special case of <xref target="BBCGGI19"/>, Theorem 5.2.) Here <tt>x</tt> is
the length-<tt>N</tt> input and <tt>r</tt> is a random field element. The gadget circuit
<tt>Range2</tt> is the "range-check" polynomial described above, i.e., <tt>Range2(x) =
x^2 - x</tt>. The idea is that, if <tt>x</tt> is valid, i.e., each <tt>x[j]</tt> is in
the range <tt>[0, 2)</tt>, then the circuit will evaluate to zero regardless of the
value of <tt>r</tt>; but if some <tt>x[j]</tt> is not in the range <tt>[0, 2)</tt>, then the output
will be non-zero with high probability.</t>
            <t>The second extension implemented by our FLP allows the validity circuit to
contain multiple gadget types. (This generalization was suggested in
<xref target="BBCGGI19"/>, Remark 4.5.) This provides additional flexibility for designing
circuits by allowing multiple, non-affine sub-circuits. For example, the
following circuit is allowed:</t>
            <artwork><![CDATA[
C(x, r) = r * Range2(x[0]) + ... + r^L * Range2(x[L-1]) + \
            r^(L+1) * Range3(x[L]) + ... + r^N * Range3(x[N-1])
]]></artwork>
            <t>where <tt>Range3(x) = x^3 - 3x^2 + 2x</tt>. This circuit checks that the first <tt>L</tt>
inputs are in the range <tt>[0, 2)</tt> and the last <tt>N-L</tt> inputs are in the range
<tt>[0, 3)</tt>. The same circuit can be expressed using a simpler gadget, namely
multiplication, but the resulting proof would be longer.</t>
            <t>Third, rather than interpolate the gadget polynomial at inputs <tt>1</tt>, <tt>2</tt>, ...,
<tt>j</tt>, ..., where <tt>j</tt> is the <tt>j</tt>-th invocation of the gadget, we use roots of
unity for the field. This allows us to construct each gadget polynomial via the
number theoretic transform <xref target="SML24"/>, which is far more efficient than generic
formulas. Note that the roots of unity are powers of the generator for the
NTT-friendly field (see <xref target="field-ntt-friendly"/>).</t>
            <t>Finally, the validity circuit in our FLP may have any number of outputs (at
least one). The input is said to be valid if each of the outputs is zero. To
save bandwidth, we take a random linear combination of the outputs. If each of
the outputs is zero, then the reduced output will be zero; but if one of the
outputs is non-zero, then the reduced output will be non-zero with high
probability.</t>
          </section>
        </section>
        <section anchor="flp-bbcggi19-valid">
          <name>Validity Circuits</name>
          <t>An instance of the proof system is defined in terms of a validity circuit that
implements the <tt>Valid</tt> interface specified in this section. The parameters are
listed in the table below.</t>
          <table>
            <name>Validity circuit parameters.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Description</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS: list[Gadget]</tt></td>
                <td align="left">A list of gadgets.</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS: list[int]</tt></td>
                <td align="left">Number of times each gadget is called.</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>MEAS_LEN: int</tt></td>
                <td align="left">Length of the measurement.</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN: int</tt></td>
                <td align="left">Length of the joint randomness.</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>EVAL_OUTPUT_LEN: int</tt></td>
                <td align="left">Length of the circuit output.</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN: int</tt></td>
                <td align="left">Length of the aggregatable output.</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">Type of the measurement.</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">Type of the aggregate result.</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>field: type[F]</tt></td>
                <td align="left">Class object for the field (<xref target="field-ntt-friendly"/>)</td>
              </tr>
            </tbody>
          </table>
          <t>The circuit is invoked with the following method:</t>
          <ul spacing="normal">
            <li>
              <t><tt>valid.eval(meas: list[F], joint_rand: list[F], num_shares: int) -&gt; list[F]</tt>
evaluates the arithmetic circuit on a measurement and joint randomness. The
output is a list of field elements: if every element is equal to
<tt>valid.field(0)</tt>, then the circuit is said to "accept" the measurement;
otherwise, if any element is not equal to <tt>valid.field(0)</tt>, then the circuit
is said to "reject" the measurement.  </t>
              <t>
This method can also be called on a secret share of the measurement, in which
case it produces a secret share of the output.  </t>
              <t>
The circuit must be composed of affine gates and gadget calls, so that the
verifier may check the prover's proof and circuit evaluation using linear
queries. This means that all non-affine multiplications in the circuit must
be encapsulated in gadget calls. Additions of constants must be rescaled by
the inverse of <tt>num_shares</tt>.  </t>
              <t>
Pre-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The length of <tt>meas</tt> <bcp14>MUST</bcp14> be <tt>valid.MEAS_LEN</tt>.</t>
                </li>
                <li>
                  <t>The length of <tt>joint_rand</tt> <bcp14>MUST</bcp14> be <tt>valid.JOINT_RAND_LEN</tt>.</t>
                </li>
                <li>
                  <t><tt>num_shares</tt> <bcp14>MUST</bcp14> be the number of secret shares of <tt>meas</tt>, or <tt>1</tt> if
<tt>meas</tt> is not secret shared.</t>
                </li>
              </ul>
              <t>
Post-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The length of the output <bcp14>MUST</bcp14> be <tt>valid.EVAL_OUTPUT_LEN</tt>.</t>
                </li>
              </ul>
            </li>
          </ul>
          <t>Each circuit has a list of gadgets, denoted <tt>GADGETS</tt>, that are invoked by
<tt>valid.eval()</tt>. The circuit evaluated by the gadget should be non-affine, and <bcp14>MUST</bcp14>
be arithmetic, i.e., composed only of multiplication, addition, and subtraction
gates. An instance of class <tt>Gadget</tt> has the following interface:</t>
          <ul spacing="normal">
            <li>
              <t><tt>ARITY: int</tt> is the number of input wires. For example, the multiplication
gadget <tt>Mul(x,y) = x*y</tt> has arity of 2.</t>
            </li>
            <li>
              <t><tt>DEGREE: int</tt> is the arithmetic degree of the gadget circuit. This is defined
to be the degree of the polynomial that computes it. This exists
because the circuit is arithmetic. For example, <tt>Mul</tt> has degree 2.</t>
            </li>
            <li>
              <t><tt>gadget.eval(field: type[F], inp: list[F]) -&gt; F</tt> evaluates the gadget over
the given inputs and field.</t>
            </li>
            <li>
              <t><tt>gadget.eval_poly(field: type[F], inp_poly: list[list[F]]) -&gt; list[F]</tt> is the
same as <tt>gadget.eval()</tt> except it evaluates the circuit over the polynomial
ring of the field. This is well defined because the circuit is arithmetic.</t>
            </li>
          </ul>
          <t>In addition to the list of gadgets, the validity circuit specifies how many
times each gadget is called (<tt>GADGET_CALLS</tt>). The circuit needs to define an
ordering of the calls it makes to each gadget, so that all parties agree on how
to identify recorded wire values. It also specifies the length of the circuit's
input (<tt>MEAS_LEN</tt>), the length of the joint randomness (<tt>JOINT_RAND_LEN</tt>), and
the length of the circuit's output (<tt>EVAL_OUTPUT_LEN</tt>).</t>
          <t>A validity circuit also specifies parameters and methods needed for Prio3
aggregation. These are used to implement the interface in <xref target="flp-encode"/>:</t>
          <ul spacing="normal">
            <li>
              <t><tt>valid.encode(measurement: Measurement) -&gt; list[F]</tt> returns a vector of
length <tt>MEAS_LEN</tt> representing a measurement of type <tt>Measurement</tt>.</t>
            </li>
            <li>
              <t><tt>valid.truncate(meas: list[F]) -&gt; list[F]</tt> returns a vector of length
<tt>OUTPUT_LEN</tt> representing (a share of) an aggregatable output.</t>
            </li>
            <li>
              <t><tt>valid.decode(agg: list[F], num_measurements: int) -&gt; AggResult</tt> returns an
aggregate result of type <tt>AggResult</tt>. This computation may depend on the
number of outputs aggregated.</t>
            </li>
          </ul>
          <t>Finally, the following are helper methods used to instantiate parameters of the
<tt>Flp</tt> interface (<xref target="flp"/>):</t>
          <sourcecode type="python"><![CDATA[
def prove_rand_len(self) -> int:
    """Length of the prover randomness."""
    return sum(g.ARITY for g in self.GADGETS)

def query_rand_len(self) -> int:
    """Length of the query randomness."""
    query_rand_len = len(self.GADGETS)
    if self.EVAL_OUTPUT_LEN > 1:
        query_rand_len += self.EVAL_OUTPUT_LEN
    return query_rand_len

def proof_len(self) -> int:
    """Length of the proof."""
    length = 0
    for (g, g_calls) in zip(self.GADGETS, self.GADGET_CALLS):
        p = next_power_of_2(1 + g_calls)
        length += g.ARITY + g.DEGREE * (p - 1) + 1
    return length

def verifier_len(self) -> int:
    """Length of the verifier message."""
    length = 1
    for g in self.GADGETS:
        length += g.ARITY + 1
    return length
]]></sourcecode>
        </section>
        <section anchor="flp-bbcggi19-construction-prove">
          <name>Generating the Proof</name>
          <figure>
            <name>Components of the proof generation algorithm.</name>
            <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 prove randomness is used to construct the
gadget polynomials that the verifier will use to compute the outputs of each
gadget.</t>
          <t>To generate the gadget polynomials, the prover evaluates the validity circuit,
and records the values on each input wire of each call to each gadget. This is
accomplished by "wrapping" each gadget in a class <tt>ProveGadget</tt> that records
the wire inputs. We list this class in <xref target="gadget-wrappers"/>. We denote the value
of the <tt>j</tt>-th wire for the <tt>k</tt>-th invocation of gadget <tt>g</tt> as <tt>g.wires[j][k]</tt>.</t>
          <t>Next, we compute each of the "wire polynomials" for each gadget. The <tt>j</tt>-th
wire polynomial is the lowest degree polynomial that evaluates to
<tt>g.wire[j][k]</tt> at a sequence of fixed points. We obtain the gadget polynomial by
evaluating the gadget on the wire polynomials.</t>
          <sourcecode type="python"><![CDATA[
def prove(self,
          meas: list[F],
          prove_rand: list[F],
          joint_rand: list[F]) -> list[F]:
    # Evaluate the validity circuit, recording the value of each
    # input wire for each evaluation of each gadget.
    valid = ProveGadget.wrap(self.valid, prove_rand)
    valid.eval(meas, joint_rand, 1)

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

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

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

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

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

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

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

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

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

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

        verifier += wire_checks
        verifier.append(gadget_check)

    return verifier
]]></sourcecode>
        </section>
        <section anchor="flp-bbcggi19-construction-decide">
          <name>Deciding Validity</name>
          <figure>
            <name>Components of the decision algorithm.</name>
            <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, we evaluate the gadget on the wire checks: if the
encoded measurement and joint randomness used to generate the proof are the
same as the measurement (share) and joint randomness used to verify the proof,
then the output of the gadget will be equal to the gadget check; otherwise, the
output will not equal the gadget check with high probability.</t>
          <sourcecode type="python"><![CDATA[
def decide(self, verifier: list[F]) -> bool:
    # Check the output of the validity circuit.
    ([v], verifier) = front(1, verifier)
    if v != self.field(0):
        return False

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def decode(self, output: list[F], _num_measurements: int) -> int:
        return output[0].int()
]]></sourcecode>
        </section>
        <section anchor="prio3sumvec">
          <name>Prio3SumVec</name>
          <table>
            <name>Parameters for Prio3SumVec.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Valid</tt></td>
                <td align="left">
                  <tt>SumVec(field, length, bits, chunk_length)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
            </tbody>
          </table>
          <t>This instance of Prio3 supports summing vectors of integers. It has three
parameters: <tt>length</tt>, <tt>bits</tt>, and <tt>chunk_length</tt>. Each measurement is a vector
of positive integers with length equal to the <tt>length</tt> parameter. Each element
of the measurement is an integer in the range <tt>[0, 2^bits)</tt>. It is <bcp14>RECOMMENDED</bcp14>
to set <tt>chunk_length</tt> to an integer near the square root of <tt>length * bits</tt>
(see <xref target="parallel-sum-chunk-length"/>).</t>
          <t>The circuit is denoted <tt>SumVec</tt>. Each measurement is encoded as a vector of
field elements with a length of <tt>length * bits</tt>. The field elements in the
encoded vector represent all the bits of the measurement vector's elements,
consecutively, in LSB to MSB order.</t>
          <t>The validity circuit uses the <tt>ParallelSum</tt> gadget in <xref target="gadget-parallel-sum"/>.
This gadget applies an arithmetic subcircuit to multiple inputs in parallel,
then sums the results. Along with the subcircuit, the
parallel-sum gadget is parameterized by an integer, denoted <tt>count</tt>, specifying
how many times to call the subcircuit. It takes in a list of inputs and passes
them through to instances of the subcircuit in the same order. It returns the
sum of the subcircuit outputs.</t>
          <t>Note that only the <tt>ParallelSum</tt> gadget itself, and not its subcircuit,
participates in the FLP's wire recording during evaluation, gadget consistency
proofs, and proof validation, even though the subcircuit is provided to
<tt>ParallelSum</tt> gadget as an implementation of the <tt>Gadget</tt> interface.</t>
          <t>The <tt>SumVec</tt> validity circuit checks that the encoded measurement consists of
ones and zeros. Rather than use the <tt>PolyEval</tt> gadget on each element, as in
the <tt>Sum</tt> validity circuit, it instead uses <tt>Mul</tt> subcircuits (<xref target="gadget-mul"/>)
and "free" constant multiplication and addition gates to simultaneously
evaluate the same range check polynomial on each element, and multiply by a
constant. One of the two <tt>Mul</tt> subcircuit inputs is equal to a measurement
element multiplied by a power of one of the elements of the joint randomness
vector, and the other is equal to the same measurement element minus one. These
<tt>Mul</tt> subcircuits are evaluated by a <tt>ParallelSum</tt> gadget, and the results are
added up both within the <tt>ParallelSum</tt> gadget and after it.</t>
          <t>The complete circuit is specified below:</t>
          <sourcecode type="python"><![CDATA[
class SumVec(Valid[list[int], list[int], F]):
    EVAL_OUTPUT_LEN = 1
    length: int
    bits: int
    chunk_length: int
    field: type[F]

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

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

    def eval(
            self,
            meas: list[F],
            joint_rand: list[F],
            num_shares: int) -> list[F]:
        out = self.field(0)
        shares_inv = self.field(num_shares).inv()
        for i in range(self.GADGET_CALLS[0]):
            r = joint_rand[i]
            r_power = r
            inputs: list[Optional[F]]
            inputs = [None] * (2 * self.chunk_length)
            for j in range(self.chunk_length):
                index = i * self.chunk_length + j
                if index < len(meas):
                    meas_elem = meas[index]
                else:
                    meas_elem = self.field(0)

                inputs[j * 2] = r_power * meas_elem
                inputs[j * 2 + 1] = meas_elem - shares_inv

                r_power *= r

            out += self.GADGETS[0].eval(
                self.field,
                cast(list[F], inputs),
            )

        return [out]

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

    def decode(
            self,
            output: list[F],
            _num_measurements: int) -> list[int]:
        return [x.int() for x in output]
]]></sourcecode>
          <section anchor="parallel-sum-chunk-length">
            <name>Selection of <tt>ParallelSum</tt> Chunk Length</name>
            <t>The <tt>chunk_length</tt> parameter provides a trade-off between the arity of the
<tt>ParallelSum</tt> gadget (<xref target="gadget-parallel-sum"/>) and the number of times the
gadget is called. The proof length is asymptotically minimized when the chunk
length is near the square root of the length of the encoded measurement.
However, the relationship between VDAF parameters and proof length is
complicated, involving two forms of rounding:</t>
            <ul spacing="normal">
              <li>
                <t>The circuit pads the inputs to its last <tt>ParallelSum</tt> gadget call, up to
the chunk length.</t>
              </li>
              <li>
                <t>The proof system rounds the degree of wire polynomials, determined by the
number of times a gadget is called, up to the next power of two.</t>
              </li>
            </ul>
            <t>Therefore, the optimal choice of <tt>chunk_length</tt> for a concrete measurement size
will vary, and must be found through trial and error. Setting <tt>chunk_length</tt>
equal to the square root of the appropriate measurement length will result in
proofs up to 50% larger than the optimal proof size.</t>
          </section>
        </section>
        <section anchor="prio3histogram">
          <name>Prio3Histogram</name>
          <table>
            <name>Parameters for Prio3Histogram.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Valid</tt></td>
                <td align="left">
                  <tt>Histogram(field, length, chunk_length)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
            </tbody>
          </table>
          <t>This variant of Prio3 allows for estimating the distribution of some quantity
by computing a simple histogram. Each measurement increments one histogram
bucket, out of a set of fixed buckets. (Bucket indexing begins at <tt>0</tt>.) For
example, the buckets might quantize the real numbers, and each measurement
would report the bucket that the corresponding client's real-numbered value
falls into. The aggregate result counts the number of measurements in each
bucket.</t>
          <t>The validity circuit is denoted <tt>Histogram</tt>. It has two parameters: <tt>length</tt>,
the number of histogram buckets; and <tt>chunk_length</tt>, which is used by a
circuit optimization described below. It is <bcp14>RECOMMENDED</bcp14> to set <tt>chunk_length</tt>
to an integer near the square root of <tt>length</tt> (see
<xref target="parallel-sum-chunk-length"/>).</t>
          <t>The measurement is encoded as a one-hot vector representing the bucket into
which the measurement falls. The circuit checks for one-hotness in two steps,
by checking that the encoded measurement consists of ones and zeros, and by
checking that the sum of all elements in the encoded measurement is equal to
one. The individual checks constitute the output of the circuit.</t>
          <t>As in the <tt>SumVec</tt> validity circuit (<xref target="prio3sumvec"/>), the first part of the
validity circuit uses the <tt>ParallelSum</tt> (<xref target="gadget-parallel-sum"/>) gadget to
perform range checks while achieving a smaller proof size. The <tt>ParallelSum</tt>
gadget uses <tt>Mul</tt> subcircuits (<xref target="gadget-mul"/>) to evaluate a range check
polynomial on each element, and includes an additional constant multiplication.
One of the two <tt>Mul</tt> subcircuit inputs is equal to a measurement element
multiplied by a power of an element of the joint randomness vector, and the
other is equal to the same measurement element minus one. The results are added
up both within the <tt>ParallelSum</tt> gadget and after it.</t>
          <sourcecode type="python"><![CDATA[
class Histogram(Valid[int, list[int], F]):
    EVAL_OUTPUT_LEN = 2
    field: type[F]
    length: int
    chunk_length: int

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

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

    def eval(
            self,
            meas: list[F],
            joint_rand: list[F],
            num_shares: int) -> list[F]:
        # Check that each bucket is one or zero.
        range_check = self.field(0)
        shares_inv = self.field(num_shares).inv()
        for i in range(self.GADGET_CALLS[0]):
            r = joint_rand[i]
            r_power = r
            inputs: list[Optional[F]]
            inputs = [None] * (2 * self.chunk_length)
            for j in range(self.chunk_length):
                index = i * self.chunk_length + j
                if index < len(meas):
                    meas_elem = meas[index]
                else:
                    meas_elem = self.field(0)

                inputs[j * 2] = r_power * meas_elem
                inputs[j * 2 + 1] = meas_elem - shares_inv

                r_power *= r

            range_check += self.GADGETS[0].eval(
                self.field,
                cast(list[F], inputs),
            )

        # Check that the buckets sum to 1.
        sum_check = -shares_inv
        for b in meas:
            sum_check += b

        return [range_check, sum_check]

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

    def decode(
            self,
            output: list[F],
            _num_measurements: int) -> list[int]:
        return [bucket_count.int()
                for bucket_count in output]
]]></sourcecode>
        </section>
        <section anchor="prio3multihotcountvec">
          <name>Prio3MultihotCountVec</name>
          <table>
            <name>Parameters for Prio3MultihotCountVec.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Valid</tt></td>
                <td align="left">
                  <tt>MultihotCountVec(field, length, max_weight, chunk_length)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
            </tbody>
          </table>
          <t>For this instance of Prio3, each measurement is a vector of Boolean
values, where the number of <tt>True</tt> values is bounded. This provides a
functionality similar to Prio3Histogram except that more than one entry (or none
at all) may be non-zero. This allows Prio3MultihotCountVec to be composed with a
randomized response mechanism, like <xref target="EPK14"/>, for providing differential
privacy. (For example, each Client would set each entry with some small
probability.)</t>
          <t>The validity circuit is denoted <tt>MultihotCountVec</tt> and has three parameters:
<tt>length</tt>, the number of entries in the count vector; <tt>max_weight</tt>, the maximum
number of <tt>True</tt> entries (i.e., the weight must be at most <tt>max_weight</tt>); and
<tt>chunk_length</tt>, used the same way as in <xref target="prio3sumvec"/> and <xref target="prio3histogram"/>.</t>
          <t>Validation works as follows. Let</t>
          <ul spacing="normal">
            <li>
              <t><tt>bits_for_weight = max_weight.bit_length()</tt></t>
            </li>
            <li>
              <t><tt>offset = 2^bits_for_weight - 1 - max_weight</tt></t>
            </li>
          </ul>
          <t>The Client reports the weight of the count vector by adding <tt>offset</tt> to it and
bit-encoding the result. Observe that only a weight of at most <tt>max_weight</tt> can
be encoded with <tt>bits_for_weight</tt> bits.</t>
          <t>The verifier checks that each entry of the encoded measurement is a bit (i.e.,
either one or zero). It then decodes the reported weight and subtracts it from
<tt>offset + sum(count_vec)</tt>, where <tt>count_vec</tt> is the count vector. The result is
zero if and only if the reported weight is equal to the true weight. The two
checks constitute the output of the circuit. The complete circuit is defined
below.</t>
          <sourcecode type="python"><![CDATA[
class MultihotCountVec(Valid[list[bool], list[int], F]):
    EVAL_OUTPUT_LEN = 2
    field: type[F]

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

        Pre-conditions:

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

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

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

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

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

        # The first part is the vector of counters.
        count_vec = [self.field(int(x)) for x in measurement]

        # The second part is the reported weight.
        weight_reported = sum(count_vec, self.field(0))

        encoded = []
        encoded += count_vec
        encoded += self.field.encode_into_bit_vec(
            (self.offset + weight_reported).int(),
            self.bits_for_weight)
        return encoded

    def eval(
            self,
            meas: list[F],
            joint_rand: list[F],
            num_shares: int) -> list[F]:
        # Check that each entry in the input vector is one or zero.
        range_check = self.field(0)
        shares_inv = self.field(num_shares).inv()
        for i in range(self.GADGET_CALLS[0]):
            r = joint_rand[i]
            r_power = r
            inputs: list[Optional[F]]
            inputs = [None] * (2 * self.chunk_length)
            for j in range(self.chunk_length):
                index = i * self.chunk_length + j
                if index < len(meas):
                    meas_elem = meas[index]
                else:
                    meas_elem = self.field(0)

                inputs[j * 2] = r_power * meas_elem
                inputs[j * 2 + 1] = meas_elem - shares_inv

                r_power *= r

            range_check += self.GADGETS[0].eval(
                self.field,
                cast(list[F], inputs),
            )

        # Check that the weight `offset` plus the sum of the counters
        # is equal to the value claimed by the Client.
        count_vec = meas[:self.length]
        weight = sum(count_vec, self.field(0))
        weight_reported = \
            self.field.decode_from_bit_vec(meas[self.length:])
        weight_check = self.offset*shares_inv + weight - \
            weight_reported

        return [range_check, weight_check]

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

    def decode(
            self,
            output: list[F],
            _num_measurements: int) -> list[int]:
        return [bucket_count.int() for
                bucket_count in output]
]]></sourcecode>
        </section>
      </section>
    </section>
    <section anchor="poplar1">
      <name>Poplar1</name>
      <t>This section specifies Poplar1, a VDAF for the following task. Each Client
holds a bit-string of length <tt>BITS</tt> and the Collector chooses a sequence of
<tt>L</tt>-bit strings, where <tt>L &lt;= BITS</tt>. We will refer to the latter as the
"candidate prefixes". The goal is to count how many of the Clients' inputs
begin with each candidate prefix.</t>
      <t>This functionality is the core component of the heavy hitters protocol of
<xref target="BBCGGI21"/>. The goal of this protocol is to compute the subset of inputs held
by at least <tt>T</tt> Clients for some threshold <tt>T</tt>. It invokes Poplar1 as follows:</t>
      <ol spacing="normal" type="1"><li>
          <t>Each Client shards its string into secret shares and uploads one share to
each of the Aggregators.</t>
        </li>
        <li>
          <t>The Collector picks an initial set of candidate prefixes, say <tt>0</tt> and <tt>1</tt>,
and sends them to the Aggregators.</t>
        </li>
        <li>
          <t>The Aggregators run VDAF preparation and aggregation on each of the reports
and send their aggregate shares to the Collector.</t>
        </li>
        <li>
          <t>The Collector unshards the aggregate result, which consists of the hit count
for each candidate prefix. For each prefix <tt>p</tt> with hit count at least <tt>T</tt>,
the Collector adds <tt>p || 0</tt> and <tt>p || 1</tt> to the next generation of
candidate prefixes and repeats Step 2.</t>
        </li>
      </ol>
      <t>Poplar1 is constructed from an "Incremental Distributed Point Function (IDPF)",
a primitive described by <xref target="BBCGGI21"/> that generalizes the notion of a
Distributed Point Function (DPF) <xref target="GI14"/>. Briefly, a DPF is used to distribute
the computation of a "point function", a function that evaluates to zero on
every input except at a programmable "point". The computation is distributed in
such a way that no one party knows either the point or what it evaluates to.</t>
      <t>An IDPF generalizes this "point" to a path on a full binary tree from the root
to one of the leaves. It is evaluated on an "index" representing a unique node
of the tree. If the node is on the programmed path, then the function evaluates
to a non-zero value; otherwise it evaluates to zero. This structure allows an
IDPF to provide the functionality required for the above protocol: to compute
the hit count for an index, just evaluate each set of IDPF shares at that index
and add up the results.</t>
      <t>Consider the sub-tree constructed from a set of input strings and a target
threshold <tt>T</tt> by including all indices with hit count at least <tt>T</tt>. We shall
refer to this structure as the "prefix tree" for the batch of measurements and
target threshold. To compute the <tt>T</tt>-heavy-hitters for the batch, the
Aggregators and Collector first compute the prefix tree, then extract the heavy
hitters from the leaves of this tree. Note that the prefix tree leaks more
information about the set than the heavy hitters themselves; see
<xref target="agg-param-security"/> for more discussion.</t>
      <t>Poplar1 composes an IDPF with the arithmetic sketch of <xref target="BBCGGI21"/>, Section
4.2. (The paper calls this a "secure sketch", but the underlying technique was
later generalized in <xref target="BBCGGI23"/>, where it is called "arithmetic sketching".)
The sketch ensures that evaluating a set of input shares on a set of unique
candidate prefixes results in shares of a zero vector or a "one-hot" vector,
i.e., a vector that is zero everywhere except for in at most one position.
Moreover, the value at that position should be one.</t>
      <t>The remainder of this section is structured as follows. The syntax of IDPFs is
defined in <xref target="idpf"/>. The Poplar1 VDAF is defined in <xref target="poplar1-construction"/> in
terms of a generic IDPF. A specification of the IDPF of <xref target="BBCGGI21"/> is given in
<xref target="idpf-bbcggi21"/>. Test vectors for Poplar1 can be found in <xref target="test-vectors"/>.</t>
      <section anchor="idpf">
        <name>Incremental Distributed Point Functions (IDPFs)</name>
        <t>An IDPF is defined over a domain of size <tt>2^BITS</tt>, where <tt>BITS</tt> is a constant.
Indices into the IDPF tree are bit strings. (In Poplar1, each Client's bit
string is an index; see <xref target="poplar1-idpf-index-encoding"/> for details.) The Client
specifies an index <tt>alpha</tt> and a vector of values <tt>beta</tt>, one for each "level"
<tt>L</tt> in the range <tt>[0, BITS)</tt>. The key generation algorithm generates one IDPF
"key" for each Aggregator. When evaluated at level <tt>L</tt> and index <tt>prefix</tt>, each
IDPF key returns an additive share of <tt>beta[L]</tt> if <tt>prefix</tt> is the <tt>L</tt>-bit
prefix of <tt>alpha</tt> and shares of zero otherwise.</t>
        <t>Each of the programmed points <tt>beta</tt> is a vector of elements of some finite
field. We distinguish two types of fields: one for inner nodes (denoted
<tt>FieldInner</tt>), and one for leaf nodes (<tt>FieldLeaf</tt>). (Our instantiation of
Poplar1 (<xref target="poplar1-construction"/>) will use a much larger field for leaf nodes
than for inner nodes. This is to ensure the IDPF is "extractable" as defined in
<xref target="BBCGGI21"/>, Definition 1. See <xref target="idpf-extract"/> for details.)</t>
        <t>A concrete IDPF defines the types and parameters enumerated in <xref target="idpf-param"/>.
In the remainder we write <tt>Output</tt> as shorthand for the type
<tt>list[list[FieldInner]] | list[list[FieldLeaf]]</tt>. (This type denotes either a
vector of inner node field elements or leaf node field elements.) The scheme is
comprised of the following algorithms:</t>
        <ul spacing="normal">
          <li>
            <t><tt>idpf.gen(alpha: tuple[bool, ...], beta_inner: list[list[FieldInner]], beta_leaf:
list[FieldLeaf], ctx: bytes, nonce: bytes, rand: bytes) -&gt; tuple[PublicShare,
list[bytes]]</tt> is the IDPF-key generation algorithm. Its inputs are the index
<tt>alpha</tt>, the values <tt>beta</tt>, the application context, and the report nonce.  </t>
            <t>
The output is a public part (of type <tt>PublicShare</tt>) that is sent to each
Aggregator and a vector of private IDPF keys, one for each Aggregator. The
nonce and application context are used to derive the fixed AES key for
XofFixedKeyAes128 (<xref target="xof-fixed-key-aes128"/>). Looking ahead, this key is used
for extending a node's seed into the seeds for the child nodes at each level
of the tree; see <xref target="idpf-bbcggi21"/>.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>alpha</tt> <bcp14>MUST</bcp14> have length <tt>BITS</tt>.</t>
              </li>
              <li>
                <t><tt>beta_inner</tt> <bcp14>MUST</bcp14> have length <tt>BITS - 1</tt>.</t>
              </li>
              <li>
                <t><tt>beta_inner[level]</tt> <bcp14>MUST</bcp14> have length <tt>VALUE_LEN</tt> for each <tt>level</tt> in
 the range <tt>[0, BITS - 1)</tt>.</t>
              </li>
              <li>
                <t><tt>beta_leaf</tt> <bcp14>MUST</bcp14> have length <tt>VALUE_LEN</tt>.</t>
              </li>
              <li>
                <t><tt>rand</tt> <bcp14>MUST</bcp14> be generated by a CSPRNG and have length <tt>RAND_SIZE</tt>.</t>
              </li>
              <li>
                <t><tt>nonce</tt> <bcp14>MUST</bcp14> be generated by a CSPRNG (see <xref target="nonce-requirements"/> for
details) and have length <tt>idpf.NONCE_SIZE</tt>.</t>
              </li>
            </ul>
            <t>
Post-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t>The number of IDPF keys <bcp14>MUST</bcp14> be <tt>idpf.SHARES</tt>.</t>
              </li>
            </ul>
          </li>
          <li>
            <t><tt>idpf.eval(agg_id: int, public_share: PublicShare, key: bytes, level: int,
prefixes: Sequence[tuple[bool, ...]], ctx: bytes, nonce: bytes) -&gt; Output</tt> is
the IDPF-key evaluation algorithm run by each Aggregator. Its inputs are the
Aggregator's unique identifier, the public share distributed to all of the
Aggregators, the Aggregator's IDPF key, the "level" at which to evaluate the
IDPF, the sequence of candidate prefixes, the application context, and the
report nonce. It returns the share of the value corresponding to each
candidate prefix.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>agg_id</tt> <bcp14>MUST</bcp14> be in the range <tt>[0, idpf.SHARES)</tt> and match the index of
<tt>key</tt> in the sequence of IDPF keys output by the Client.</t>
              </li>
              <li>
                <t><tt>level</tt> <bcp14>MUST</bcp14> be in the range <tt>[0, BITS)</tt>.</t>
              </li>
              <li>
                <t>Each prefix <bcp14>MUST</bcp14> be distinct and have length <tt>level + 1</tt>.</t>
              </li>
              <li>
                <t>The length of the nonce <bcp14>MUST</bcp14> be <tt>idpf.NONCE_SIZE</tt>.</t>
              </li>
            </ul>
            <t>
Post-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t>The length of the output <bcp14>MUST</bcp14> be <tt>len(prefixes)</tt></t>
              </li>
              <li>
                <t>The length of each element of the output <bcp14>MUST</bcp14> be <tt>idpf.VALUE_LEN</tt></t>
              </li>
              <li>
                <t>If <tt>level == idpf.BITS - 1</tt>, then the output field <bcp14>MUST</bcp14> be <tt>FieldLeaf</tt> and
 <tt>FieldInner</tt> otherwise</t>
              </li>
            </ul>
          </li>
        </ul>
        <t>In addition, the IDPF provides the following method:</t>
        <sourcecode type="python"><![CDATA[
def current_field(
        self,
        level: int) -> type[FieldInner] | type[FieldLeaf]:
    if level < self.BITS - 1:
        return self.field_inner
    return self.field_leaf
]]></sourcecode>
        <t>Finally, an implementation note. The interface for IDPFs specified here is
stateless, in the sense that there is no state carried between IDPF evaluations.
This is to align the IDPF syntax with the VDAF abstraction boundary, which does
not include shared state across VDAF evaluations. In practice, of course, it
will often be beneficial to expose a stateful API for IDPFs and carry the state
across evaluations. See <xref target="idpf-bbcggi21"/> for details.</t>
        <table anchor="idpf-param">
          <name>Constants and types defined by a concrete IDPF.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>SHARES: int</tt></td>
              <td align="left">Number of IDPF keys output by IDPF-key generator.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>BITS: int</tt></td>
              <td align="left">Length in bits of each input string.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VALUE_LEN: int</tt></td>
              <td align="left">Number of field elements of each output value.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>RAND_SIZE: int</tt></td>
              <td align="left">Size of the random string consumed by the IDPF-key generator.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>NONCE_SIZE: int</tt></td>
              <td align="left">Size of the random nonce generated by the Client.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>KEY_SIZE: int</tt></td>
              <td align="left">Size in bytes of each IDPF key.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>FieldInner</tt></td>
              <td align="left">Implementation of <tt>Field</tt> (<xref target="field"/>) used for values of inner nodes.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>FieldLeaf</tt></td>
              <td align="left">Implementation of <tt>Field</tt> used for values of leaf nodes.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>PublicShare</tt></td>
              <td align="left">Type of public share for this IDPF.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>Output</tt></td>
              <td align="left">Alias of <tt>list[list[FieldInner]] | list[list[FieldLeaf]]</tt>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>FieldVec</tt></td>
              <td align="left">Alias of <tt>list[FieldInner] | list[FieldLeaf].</tt></td>
            </tr>
          </tbody>
        </table>
        <section anchor="poplar1-idpf-index-encoding">
          <name>Encoding Inputs as Indices</name>
          <t>How data are represented as IDPF indices is up to the application. When the
inputs are fixed-length byte strings, the most natural choice of representation
is as a bit string formed from all the bits of the byte string, first ordered by
byte position, then ordered from most significant bit to least significant bit
within each byte. This ensures that, when a byte string is a prefix of another,
so too is its corresponding index. (Index prefixes are defined in <xref target="idpf"/>.) For
example,</t>
          <artwork><![CDATA[
Byte string: 01 02
Bit string: 00000001 00000010
]]></artwork>
          <t>is a prefix of</t>
          <artwork><![CDATA[
Byte string: 01 02 03
Bit string: 00000001 00000010 00000011
]]></artwork>
          <t>Additionally, lexicographic ordering is preserved by this mapping from a byte
string to a bit string.</t>
          <t>When the inputs are variable length, it is necessary to pad each input to some
fixed length. Further, the padding scheme must be non-ambiguous. For example,
each input could be padded with <tt>b"\x01"</tt> followed by as many <tt>b"\x00"</tt> bytes
as needed.</t>
        </section>
      </section>
      <section anchor="poplar1-construction">
        <name>Specification</name>
        <t>This section specifies <tt>Poplar1</tt>, an implementation of the <tt>Vdaf</tt> interface
(<xref target="vdaf"/>). It is defined in terms of the <tt>Idpf</tt> implementation of
<xref target="idpf-bbcggi21"/> with <tt>SHARES == 2</tt> and <tt>VALUE_LEN == 2</tt> and
<tt>XofTurboShake128</tt> as specified in <xref target="xof-turboshake128"/>. The associated
constants and types required by the <tt>Vdaf</tt> interface are defined in
<xref target="poplar1-param"/>. The methods required for sharding, preparation, aggregation,
and unsharding are described in the remaining subsections. These methods make
use of constants defined in <xref target="poplar1-const"/>.</t>
        <table anchor="poplar1-param">
          <name>VDAF parameters for Poplar1.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>idpf</tt></td>
              <td align="left">As specified in <xref target="idpf-bbcggi21"/>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>xof</tt></td>
              <td align="left">
                <tt>XofTurboShake128</tt> (<xref target="xof-turboshake128"/>)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VERIFY_KEY_SIZE</tt></td>
              <td align="left">
                <tt>xof.SEED_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>RAND_SIZE</tt></td>
              <td align="left">
                <tt>xof.SEED_SIZE * 3 + idpf.RAND_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>NONCE_SIZE</tt></td>
              <td align="left">
                <tt>16</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>ROUNDS</tt></td>
              <td align="left">
                <tt>2</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>SHARES</tt></td>
              <td align="left">
                <tt>2</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">
                <tt>tuple[bool, ...]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggParam</tt></td>
              <td align="left">
                <tt>tuple[int, Sequence[tuple[bool, ...]]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PublicShare</tt></td>
              <td align="left">As defined by <tt>idpf</tt>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>InputShare</tt></td>
              <td align="left">
                <tt>tuple[bytes, bytes, list[FieldInner], list[FieldLeaf]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>OutShare</tt></td>
              <td align="left">
                <tt>FieldVec</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggShare</tt></td>
              <td align="left">
                <tt>FieldVec</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">
                <tt>list[int]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepState</tt></td>
              <td align="left">
                <tt>tuple[bytes, int, FieldVec]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepShare</tt></td>
              <td align="left">
                <tt>FieldVec</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepMessage</tt></td>
              <td align="left">
                <tt>Optional[FieldVec]</tt></td>
            </tr>
          </tbody>
        </table>
        <table anchor="poplar1-const">
          <name>Constants used by Poplar1.</name>
          <thead>
            <tr>
              <th align="left">Variable</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">USAGE_SHARD_RAND: int</td>
              <td align="left">1</td>
            </tr>
            <tr>
              <td align="left">USAGE_CORR_INNER: int</td>
              <td align="left">2</td>
            </tr>
            <tr>
              <td align="left">USAGE_CORR_LEAF: int</td>
              <td align="left">3</td>
            </tr>
            <tr>
              <td align="left">USAGE_VERIFY_RAND: int</td>
              <td align="left">4</td>
            </tr>
          </tbody>
        </table>
        <section anchor="sharding-1">
          <name>Sharding</name>
          <t>The Client's measurement is an IDPF index, denoted <tt>alpha</tt>, whose type is a
sequence of bits <tt>tuple[bool, ...]</tt> (See <xref target="poplar1-idpf-index-encoding"/> for
guidelines on index encoding.)</t>
          <t>The programmed IDPF values are pairs of field elements <tt>(1, k)</tt> where each <tt>k</tt> is
chosen at random. This random value is used as part of the arithmetic sketching
protocol of <xref target="BBCGGI21"/>, Appendix C.4. After evaluating their IDPF key shares
on a given sequence of candidate prefixes, the Aggregators use the sketching
protocol to verify that they hold shares of a zero vector or a one-hot vector at
a given level of the IDPF tree.</t>
          <t>In addition to programming <tt>k</tt> into the IDPF output, for each level of the
tree, the Client generates random elements <tt>a</tt>, <tt>b</tt>, and <tt>c</tt> and computes</t>
          <artwork><![CDATA[
    A = -2*a + k
    B = a^2 + b - k*a + c
]]></artwork>
          <t>and sends additive shares of <tt>a</tt>, <tt>b</tt>, <tt>c</tt>, <tt>A</tt> and <tt>B</tt> to each of the
Aggregators. These help the Aggregators evaluate the sketch during preparation.</t>
          <t>Putting everything together, the sharding algorithm is defined as
follows.</t>
          <sourcecode type="python"><![CDATA[
def shard(
    self,
    ctx: bytes,
    measurement: tuple[bool, ...],
    nonce: bytes,
    rand: bytes,
) -> tuple[Poplar1PublicShare, list[Poplar1InputShare]]:
    if len(nonce) != self.NONCE_SIZE:
        raise ValueError("incorrect nonce size")
    if len(rand) != self.RAND_SIZE:
        raise ValueError("incorrect size of random bytes argument")

    l = self.xof.SEED_SIZE

    # Split the random input into the random input for IDPF key
    # generation, correlated randomness, and sharding.
    if len(rand) != self.RAND_SIZE:
        raise ValueError('incorrect rand size')
    idpf_rand, rand = front(self.idpf.RAND_SIZE, rand)
    seeds = [rand[i:i + l] for i in range(0, 3 * l, l)]
    corr_seed, seeds = front(2, seeds)
    (shard_seed,), seeds = front(1, seeds)

    xof = self.xof(
        shard_seed,
        self.domain_separation_tag(USAGE_SHARD_RAND, ctx),
        nonce,
    )

    # Construct the IDPF values for each level of the IDPF tree.
    # Each "data" value is 1; in addition, the Client generates
    # a random "authenticator" value used by the Aggregators to
    # evaluate the sketch during preparation. This sketch is used
    # to verify the one-hotness of their output shares.
    beta_inner = [
        [self.idpf.field_inner(1), k]
        for k in xof.next_vec(self.idpf.field_inner,
                              self.idpf.BITS - 1)
    ]
    beta_leaf = [self.idpf.field_leaf(1)] + \
        xof.next_vec(self.idpf.field_leaf, 1)

    # Generate the IDPF keys.
    (public_share, keys) = self.idpf.gen(
        measurement,
        beta_inner,
        beta_leaf,
        ctx,
        nonce,
        idpf_rand,
    )

    # Generate correlated randomness used by the Aggregators to
    # evaluate the sketch over their output shares. Seeds are used
    # to encode shares of the `(a, b, c)` triples. (See [BBCGGI21,
    # Appendix C.4].)
    corr_offsets: list[Field] = vec_add(
        self.xof.expand_into_vec(
            self.idpf.field_inner,
            corr_seed[0],
            self.domain_separation_tag(USAGE_CORR_INNER, ctx),
            byte(0) + nonce,
            3 * (self.idpf.BITS - 1),
        ),
        self.xof.expand_into_vec(
            self.idpf.field_inner,
            corr_seed[1],
            self.domain_separation_tag(USAGE_CORR_INNER, ctx),
            byte(1) + nonce,
            3 * (self.idpf.BITS - 1),
        ),
    )
    corr_offsets += vec_add(
        self.xof.expand_into_vec(
            self.idpf.field_leaf,
            corr_seed[0],
            self.domain_separation_tag(USAGE_CORR_LEAF, ctx),
            byte(0) + nonce,
            3,
        ),
        self.xof.expand_into_vec(
            self.idpf.field_leaf,
            corr_seed[1],
            self.domain_separation_tag(USAGE_CORR_LEAF, ctx),
            byte(1) + nonce,
            3,
        ),
    )

    # For each level of the IDPF tree, shares of the `(A, B)`
    # pairs are computed from the corresponding `(a, b, c)`
    # triple and authenticator value `k`.
    corr_inner: list[list[Field64]] = [[], []]
    for level in range(self.idpf.BITS):
        field = cast(type[Field], self.idpf.current_field(level))
        k = beta_inner[level][1] if level < self.idpf.BITS - 1 \
            else beta_leaf[1]
        (a, b, c), corr_offsets = corr_offsets[:3], corr_offsets[3:]
        A = -field(2) * a + k
        B = a ** 2 + b - a * k + c
        corr1 = xof.next_vec(field, 2)
        corr0 = vec_sub([A, B], corr1)
        if level < self.idpf.BITS - 1:
            corr_inner[0] += cast(list[Field64], corr0)
            corr_inner[1] += cast(list[Field64], corr1)
        else:
            corr_leaf = [
                cast(list[Field255], corr0),
                cast(list[Field255], corr1),
            ]

    # Each input share consists of the Aggregator's IDPF key
    # and a share of the correlated randomness.
    input_shares = list(zip(keys, corr_seed, corr_inner, corr_leaf))
    return (public_share, input_shares)
]]></sourcecode>
        </section>
        <section anchor="poplar1-prep">
          <name>Preparation</name>
          <t>The aggregation parameter encodes a sequence of candidate prefixes. When an
Aggregator receives an input share from the Client, it begins by evaluating its
IDPF share on each candidate prefix, recovering a <tt>data_share</tt> and <tt>auth_share</tt>
for each. The Aggregators use these and the correlation shares provided by the
Client to verify that the sequence of <tt>data_share</tt> values are additive shares of
a zero vector or a one-hot vector.</t>
          <t>Aggregators <bcp14>MUST</bcp14> ensure the candidate prefixes are all unique and appear in
lexicographic order. (This is enforced in the definition of <tt>is_valid()</tt>
below.) Uniqueness is necessary to ensure the refined measurement (i.e., the sum
of the output shares) is in fact a one-hot vector. Otherwise, sketch
verification might fail, causing the Aggregators to erroneously reject a report
that is actually valid. Note that enforcing the order is not strictly necessary,
but this does allow uniqueness to be determined more efficiently.</t>
          <sourcecode type="python"><![CDATA[
def prep_init(
        self,
        verify_key: bytes,
        ctx: bytes,
        agg_id: int,
        agg_param: Poplar1AggParam,
        nonce: bytes,
        public_share: Poplar1PublicShare,
        input_share: Poplar1InputShare) -> tuple[
            Poplar1PrepState,
            FieldVec]:
    (level, prefixes) = agg_param
    (key, corr_seed, corr_inner, corr_leaf) = input_share
    field = self.idpf.current_field(level)

    # Evaluate the IDPF key at the given set of prefixes.
    value = self.idpf.eval(
        agg_id, public_share, key, level, prefixes, ctx, nonce)

    # Get shares of the correlated randomness for evaluating the
    # Aggregator's share of the sketch.
    if level < self.idpf.BITS - 1:
        corr_xof = self.xof(
            corr_seed,
            self.domain_separation_tag(USAGE_CORR_INNER, ctx),
            byte(agg_id) + nonce,
        )
        # Fast-forward the XOF state to the current level.
        corr_xof.next_vec(field, 3 * level)
    else:
        corr_xof = self.xof(
            corr_seed,
            self.domain_separation_tag(USAGE_CORR_LEAF, ctx),
            byte(agg_id) + nonce,
        )
    (a_share, b_share, c_share) = corr_xof.next_vec(field, 3)
    if level < self.idpf.BITS - 1:
        (A_share, B_share) = cast(
            list[Field],
            corr_inner[2 * level:2 * (level + 1)],
        )
    else:
        (A_share, B_share) = cast(list[Field], corr_leaf)

    # Evaluate the Aggregator's share of the sketch. These are
    # called the "masked input values" [BBCGGI21, Appendix C.4].
    verify_rand_xof = self.xof(
        verify_key,
        self.domain_separation_tag(USAGE_VERIFY_RAND, ctx),
        nonce + to_be_bytes(level, 2),
    )
    verify_rand = cast(
        list[Field],
        verify_rand_xof.next_vec(field, len(prefixes)),
    )
    sketch_share = 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)

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

def prep_next(
    self,
    _ctx: bytes,
    prep_state: Poplar1PrepState,
    prep_msg: Optional[FieldVec]
) -> tuple[Poplar1PrepState, FieldVec] | FieldVec:
    prev_sketch = cast(list[Field], prep_msg)
    (step, level, prep_mem) = prep_state

    if step == b'evaluate sketch':
        if prev_sketch is None:
            raise ValueError('expected value, got none')
        elif len(prev_sketch) != 3:
            raise ValueError('incorrect sketch length')
        A_share = cast(Field, prep_mem[0])
        B_share = cast(Field, prep_mem[1])
        agg_id = cast(Field, prep_mem[2])
        prep_mem = prep_mem[3:]
        sketch_share = [
            agg_id * (prev_sketch[0] ** 2
                      - prev_sketch[1]
                      - prev_sketch[2])
            + A_share * prev_sketch[0]
            + B_share
        ]
        return cast(
            tuple[Poplar1PrepState, FieldVec],
            (
                (
                    b'reveal sketch',
                    level,
                    prep_mem,
                ),
                sketch_share,
            )
        )

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

    raise ValueError('invalid prep state')

def prep_shares_to_prep(
        self,
        _ctx: bytes,
        agg_param: Poplar1AggParam,
        prep_shares: list[FieldVec]) -> Optional[FieldVec]:
    if len(prep_shares) != 2:
        raise ValueError('incorrect number of prep shares')
    (level, _) = agg_param
    field = self.idpf.current_field(level)
    sketch = vec_add(
        cast(list[Field], prep_shares[0]),
        cast(list[Field], prep_shares[1]),
    )
    if len(sketch) == 3:
        return cast(FieldVec, sketch)
    elif len(sketch) == 1:
        if sketch == field.zeros(1):
            # In order to reduce communication overhead, let `None`
            # denote a successful sketch verification.
            return None
        else:
            raise ValueError('sketch verification failed')
    else:
        raise ValueError('incorrect sketch length')
]]></sourcecode>
        </section>
        <section anchor="validity-of-aggregation-parameters-1">
          <name>Validity of Aggregation Parameters</name>
          <t>Aggregation parameters are valid for a given input share if no aggregation
parameter with the same level has been used with the same input share before.
The whole preparation phase <bcp14>MUST NOT</bcp14> be run more than once for a given
combination of input share and level. This function checks that candidate
prefixes are unique and lexicographically sorted, checks that levels are
increasing between calls, and also enforces that the prefixes at each level are
suffixes of the previous level's prefixes.</t>
          <sourcecode type="python"><![CDATA[
def is_valid(
        self,
        agg_param: Poplar1AggParam,
        previous_agg_params: list[Poplar1AggParam]) -> bool:
    """
    Checks that candidate prefixes are unique and lexicographically
    sorted, checks that levels are increasing between calls, and also
    enforces that the prefixes at each level are suffixes of the
    previous level's prefixes.
    """
    (level, prefixes) = agg_param

    # Ensure that candidate prefixes are all unique and appear in
    # lexicographic order.
    for i in range(1, len(prefixes)):
        if prefixes[i - 1] >= prefixes[i]:
            return False

    if len(previous_agg_params) < 1:
        return True

    (last_level, last_prefixes) = previous_agg_params[-1]
    last_prefixes_set = set(last_prefixes)

    # Check that level increased.
    if level <= last_level:
        return False

    # Check that prefixes are suffixes of the last level's prefixes.
    for prefix in prefixes:
        last_prefix = get_ancestor(prefix, last_level)
        if last_prefix not in last_prefixes_set:
            # Current prefix not a suffix of last level's prefixes.
            return False
    return True

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

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

def merge(self,
          agg_param: Poplar1AggParam,
          agg_shares: list[FieldVec]) -> FieldVec:
    (level, prefixes) = agg_param
    field = self.idpf.current_field(level)
    agg = cast(list[Field], field.zeros(len(prefixes)))
    for agg_share in agg_shares:
        agg = vec_add(agg, cast(list[Field], agg_share))
    return cast(FieldVec, agg)
]]></sourcecode>
        </section>
        <section anchor="unsharding-1">
          <name>Unsharding</name>
          <t>Finally, the Collector unshards the aggregate result by adding up the aggregate
shares.</t>
          <sourcecode type="python"><![CDATA[
def unshard(
        self,
        agg_param: Poplar1AggParam,
        agg_shares: list[FieldVec],
        _num_measurements: int) -> list[int]:
    agg = self.merge(agg_param, agg_shares)
    return [x.int() for x in agg]
]]></sourcecode>
        </section>
        <section anchor="poplar1-encode">
          <name>Message Serialization</name>
          <t>This section defines serialization formats for messages exchanged over the
network while executing <tt>Poplar1</tt>. Messages are defined in the presentation
language of TLS as defined in <xref section="3" sectionFormat="of" target="RFC8446"/>.</t>
          <t>Let <tt>poplar1</tt> be an instance of <tt>Poplar1</tt>. In the remainder we use <tt>Fi</tt> as an
alias for <tt>poplar1.idpf.field_inner.ENCODED_SIZE</tt>, <tt>Fl</tt> as an alias for
<tt>poplar1.idpf.field_leaf.ENCODED_SIZE</tt>, and <tt>B</tt> as an alias for
<tt>poplar1.idpf.BITS</tt>.</t>
          <t>Elements of the inner field are encoded in little-endian byte order (as defined
in <xref target="field"/>) and are represented as follows:</t>
          <sourcecode type="tls-presentation"><![CDATA[
opaque Poplar1FieldInner[Fi];
]]></sourcecode>
          <t>Likewise, elements of the leaf field are encoded in little-endian byte order
(as defined in <xref target="field"/>) and are represented as follows:</t>
          <sourcecode type="tls-presentation"><![CDATA[
opaque Poplar1FieldLeaf[Fl];
]]></sourcecode>
          <section anchor="public-share-1">
            <name>Public Share</name>
            <t>The public share of the IDPF scheme in <xref target="idpf-bbcggi21"/> consists of a sequence
of "correction words". A correction word has three components:</t>
            <ol spacing="normal" type="1"><li>
                <t>the XOF seed of type <tt>bytes</tt>;</t>
              </li>
              <li>
                <t>the control bits of type <tt>tuple[bool, bool]</tt>; and</t>
              </li>
              <li>
                <t>the payload of type <tt>list[Field64]</tt> for the first <tt>BITS-1</tt> words and
<tt>list[Field255]</tt> for the last word.</t>
              </li>
            </ol>
            <t>The encoding is a straightforward structure of arrays, except that the control
bits are packed as tightly as possible. The encoded public share is structured
as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    opaque packed_control_bits[packed_len];
    opaque seed[poplar1.idpf.KEY_SIZE*B];
    Poplar1FieldInner payload_inner[Fi*poplar1.idpf.VALUE_LEN*(B-1)];
    Poplar1FieldLeaf payload_leaf[Fl*poplar1.idpf.VALUE_LEN];
} Poplar1PublicShare;
]]></sourcecode>
            <t>Here <tt>packed_len = (2*B + 7) // 8</tt> is the length of the packed control bits.
Field <tt>packed_control_bits</tt> is encoded with the following function:</t>
            <sourcecode type="python"><![CDATA[
packed_control_buf = [int(0)] * packed_len
for i, bit in enumerate(control_bits):
    packed_control_buf[i // 8] |= bit << (i % 8)
packed_control_bits = bytes(packed_control_buf)
]]></sourcecode>
            <t>It encodes each group of eight bits into a byte, in LSB to MSB order, padding the most
significant bits of the last byte with zeros as necessary, and returns the byte
array. Decoding performs the reverse operation: it takes in a byte array
and a number of bits, and returns a list of bits, extracting eight bits from
each byte in turn, in LSB to MSB order, and stopping after the requested number
of bits. If the byte array has an incorrect length, or if unused bits in the
last bytes are not zero, it throws an error:</t>
            <sourcecode type="python"><![CDATA[
control_bits = []
for i in range(length):
    control_bits.append(bool(
        (packed_control_bits[i // 8] >> (i % 8)) & 1
    ))
leftover_bits = packed_control_bits[-1] >> (
    (length + 7) % 8 + 1
)
if (length + 7) // 8 != len(packed_control_bits) or \
        leftover_bits != 0:
    raise ValueError('trailing bits')
]]></sourcecode>
          </section>
          <section anchor="input-share-1">
            <name>Input Share</name>
            <t>Each input share is structured as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    opaque idpf_key[poplar1.idpf.KEY_SIZE];
    opaque corr_seed[poplar1.xof.SEED_SIZE];
    Poplar1FieldInner corr_inner[Fi * 2 * (B- 1)];
    Poplar1FieldLeaf corr_leaf[Fl * 2];
} Poplar1InputShare;
]]></sourcecode>
          </section>
          <section anchor="prep-share-1">
            <name>Prep Share</name>
            <t>Encoding of the prep share depends on the round of sketching: if the first
round, then each sketch share has three field elements; if the second round,
then each sketch share has one field element. The field that is used depends on
the level of the IDPF tree specified by the aggregation parameter, either the
inner field or the leaf field.</t>
            <t>For the first round and inner field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldInner sketch_share[Fi * 3];
} Poplar1PrepShareRoundOneInner;
]]></sourcecode>
            <t>For the first round and leaf field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldLeaf sketch_share[Fl * 3];
} Poplar1PrepShareRoundOneLeaf;
]]></sourcecode>
            <t>For the second round and inner field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldInner sketch_share;
} Poplar1PrepShareRoundTwoInner;
]]></sourcecode>
            <t>For the second round and leaf field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldLeaf sketch_share;
} Poplar1PrepShareRoundTwoLeaf;
]]></sourcecode>
          </section>
          <section anchor="prep-message-1">
            <name>Prep Message</name>
            <t>Likewise, the structure of the prep message for Poplar1 depends on the
sketching round and field. For the first round and inner field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldInner[Fi * 3];
} Poplar1PrepMessageRoundOneInner;
]]></sourcecode>
            <t>For the first round and leaf field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldLeaf sketch[Fl * 3];
} Poplar1PrepMessageRoundOneLeaf;
]]></sourcecode>
            <t>Note that these messages have the same structures as the prep shares for the
first round.</t>
            <t>The second-round prep message is the empty string. This is because the sketch
shares are expected to sum to a particular value if the output shares are
valid; we represent a successful preparation with the empty string and
otherwise return an error.</t>
          </section>
          <section anchor="aggregate-share">
            <name>Aggregate Share</name>
            <t>The encoding of the aggregate share depends on whether the inner or leaf field
is used, and the number of candidate prefixes. Both of these are determined by
 the aggregation parameter.</t>
            <t>Let <tt>prefix_count</tt> denote the number of candidate prefixes. For the inner field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldInner agg_share[Fi * prefix_count];
} Poplar1AggShareInner;
]]></sourcecode>
            <t>For the leaf field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Poplar1FieldLeaf agg_share[Fl * prefix_count];
} Poplar1AggShareLeaf;
]]></sourcecode>
          </section>
          <section anchor="aggregation-parameter">
            <name>Aggregation Parameter</name>
            <t>The aggregation parameter is encoded as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    uint16_t level;
    uint32_t num_prefixes;
    opaque encoded_prefixes[prefixes_len];
} Poplar1AggParam;
]]></sourcecode>
            <t>The fields in this struct are: <tt>level</tt>, the level of the IDPF tree of each
prefixes; <tt>num_prefixes</tt>, the number of prefixes to evaluate; and
<tt>encoded_prefixes</tt>, the sequence of prefixes encoded into a byte string of
length <tt>prefixes_len</tt>. Each prefix is packed into a byte string, with the bits
assigned in MSB-to-LSB order, and then the byte strings for each prefix are
concatenated together. The prefixes are encoded with the following procedure:</t>
            <sourcecode type="python"><![CDATA[
prefixes_len = ((level + 1) + 7) // 8 * len(prefixes)
encoded_prefixes = bytearray()
for prefix in prefixes:
    for chunk in itertools.batched(prefix, 8):
        byte_out = 0
        for (bit_position, bit) in enumerate(chunk):
            byte_out |= bit << (7 - bit_position)
        encoded_prefixes.append(byte_out)
]]></sourcecode>
            <t>Decoding involves the following procedure:</t>
            <sourcecode type="python"><![CDATA[
prefixes = []

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>In this section we specify a concrete IDPF suitable for instantiating Poplar1.
The constant and type definitions required by the <tt>Idpf</tt> interface are given in
<xref target="idpf-bbcggi21-param"/>.</t>
        <t>Our IDPF requires an XOF for deriving the output shares, as well as a variety
of other artifacts used internally. For performance reasons, we instantiate
this object using XofFixedKeyAes128 (<xref target="xof-fixed-key-aes128"/>) wherever
possible. See <xref target="xof-vs-ro"/> for security considerations.</t>
        <table anchor="idpf-bbcggi21-param">
          <name>Constants and type definitions for our concrete IDPF.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>xof</tt></td>
              <td align="left">
                <tt>XofFixedKeyAes128</tt> (<xref target="xof-fixed-key-aes128"/>)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>SHARES</tt></td>
              <td align="left">
                <tt>2</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>BITS</tt></td>
              <td align="left">Any positive integer.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VALUE_LEN</tt></td>
              <td align="left">Any positive integer.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>KEY_SIZE</tt></td>
              <td align="left">
                <tt>xof.SEED_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>FieldInner</tt></td>
              <td align="left">
                <tt>Field64</tt> (<xref target="fields"/>)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>FieldLeaf</tt></td>
              <td align="left">
                <tt>Field255</tt> (<xref target="fields"/>)</td>
            </tr>
          </tbody>
        </table>
        <section anchor="overview-1">
          <name>Overview</name>
          <t>At a high level, the IDPF maps a key generator's input <tt>(alpha, beta_1, ...,
beta_BITS)</tt> onto a binary tree with <tt>BITS+1</tt> levels, where each edge going from
a parent node to a left child is labeled <tt>0</tt>, and each right edge is labeled
<tt>1</tt>. Then each leaf node corresponds to a bit string of length <tt>BITS</tt>, where the
labels on the path from the root to <tt>x</tt> contain the individual bits.  Finally,
all nodes in the tree have an assigned value, with the nodes on the path
from the root to <tt>alpha</tt> having values <tt>beta_1, ..., beta_BITS</tt>, and all other
nodes having value <tt>0</tt>.</t>
          <t>The IDPF construction now boils down to secret-sharing the values at each node
of that tree in an efficient way. Note that explicitly representing the tree
requires <tt>O(2^BITS)</tt> space, so the generator cannot just compute additive shares
of it and send them to the two evaluators. Instead, the evaluators will
re-generate shares of values at selected nodes of the tree using a XOF
(<xref target="xof"/>).</t>
          <t>The basic observation is that if both evaluators have the same seed <tt>s</tt> of
length <tt>KEY_SIZE</tt>, then expanding <tt>s</tt> using a XOF will also result in the same
expansion. If we set the length of the XOF expansion to <tt>2*KEY_SIZE</tt>, it can
then be split again into two seeds <tt>s_l</tt>, <tt>s_r</tt>, that can again serve as XOF
seeds. Now if we view seeds as XOR-shares of integers, and if evaluators have
the same seed at the root of the tree, then their expanded trees will form a
secret-shared tree of zeros. The actual construction will additionally use a
<tt>convert()</tt> function before each expansion, which maps seeds into the
appropriate output domain (see <xref target="idpf-bbcggi21-helper-functions"/>), generating
a new seed for the next level in the process.</t>
          <t>The open task now is to ensure that evaluators have different seeds at nodes
that lie on the path to <tt>alpha</tt>, while having the same seeds on all other nodes.
This is done using so-called "correction words" included in the public share.
The correction words are conditionally added to the XOF output by both
evaluators.  The condition here is a secret-shared bit, called a "control bit",
which indicates whether the current node is on the path to <tt>alpha</tt> or not. On
the path, the control bits add up to <tt>1</tt>, meaning only one evaluator will add
the correction word to its XOF output. Off the path, either none or both
evaluators add the correction word, and so the seeds at the next level stay the
same.</t>
          <t>What remains is to turn the (now pseudorandom) values on the path to <tt>alpha</tt>
into the desired <tt>beta</tt> values. This is done by including "value correction
words" in the public share, which are chosen such that when added with the
pseudorandom shares at the <tt>i</tt>th node on the path to <tt>alpha</tt>, they add up to
shares of <tt>beta_i</tt>.</t>
          <t>In the following two sections we describe the algorithms for key generation in
full detail.</t>
        </section>
        <section anchor="key-generation">
          <name>Key Generation</name>
          <t>The description of the IDPF-key generation algorithm makes use of auxiliary
functions <tt>extend()</tt> and <tt>convert()</tt> defined in
<xref target="idpf-bbcggi21-helper-functions"/>.</t>
          <sourcecode type="python"><![CDATA[
def gen(
        self,
        alpha: tuple[bool, ...],
        beta_inner: list[list[Field64]],
        beta_leaf: list[Field255],
        ctx: bytes,
        nonce: bytes,
        rand: bytes) -> tuple[list[CorrectionWord], list[bytes]]:
    if len(alpha) != self.BITS:
        raise ValueError("incorrect alpha length")
    if len(beta_inner) != self.BITS - 1:
        raise ValueError("incorrect beta_inner length")
    if len(rand) != self.RAND_SIZE:
        raise ValueError("incorrect rand size")
    if len(nonce) != self.NONCE_SIZE:
        raise ValueError("incorrect nonce size")

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

    seed = key.copy()
    ctrl = [False, True]
    public_share = []
    for level in range(self.BITS):
        bit = alpha[level]
        keep = int(bit)
        lose = 1 - keep

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

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

        if level < self.BITS - 1:
            b = cast(list[Field], beta_inner[level])
        else:
            b = cast(list[Field], beta_leaf)
        if len(b) != self.VALUE_LEN:
            raise ValueError(
                "length of beta must match the value length"
            )

        w_cw = vec_add(vec_sub(b, w0), w1)
        # Implementation note: this conditional negation should be
        # replaced with a constant time select or a constant time
        # multiplication in practice in order to reduce leakage via
        # timing side channels.
        if ctrl[1]:
            for i in range(len(w_cw)):
                w_cw[i] = -w_cw[i]

        public_share.append((seed_cw, ctrl_cw, w_cw))
    return (public_share, key)
]]></sourcecode>
        </section>
        <section anchor="key-evaluation">
          <name>Key Evaluation</name>
          <t>The description of the IDPF-evaluation algorithm makes use of auxiliary
functions <tt>extend()</tt> and <tt>convert()</tt> defined in
<xref target="idpf-bbcggi21-helper-functions"/>.</t>
          <sourcecode type="python"><![CDATA[
def eval(
        self,
        agg_id: int,
        public_share: list[CorrectionWord],
        key: bytes,
        level: int,
        prefixes: Sequence[tuple[bool, ...]],
        ctx: bytes,
        nonce: bytes) -> list[list[Field64]] | list[list[Field255]]:
    if agg_id not in range(self.SHARES):
        raise ValueError('aggregator id out of range')
    if level not in range(self.BITS):
        raise ValueError('level out of range')
    if len(set(prefixes)) != len(prefixes):
        raise ValueError('prefixes must be unique')

    out_share = []
    for prefix in prefixes:
        if len(prefix) != level + 1:
            raise ValueError('incorrect prefix length')

        # The Aggregator's output share is the value of a node of
        # the IDPF tree at the given `level`. The node's value is
        # computed by traversing the path defined by the candidate
        # `prefix`. Each node in the tree is represented by a seed
        # (`seed`) and a control bit (`ctrl`).
        seed = key
        ctrl = bool(agg_id)
        y: FieldVec
        for current_level in range(level + 1):
            bit = int(prefix[current_level])

            # Implementation note: typically the current round of
            # candidate prefixes would have been derived from
            # aggregate results computed during previous rounds.
            # For example, when using the IDPF to compute heavy
            # hitters, a string whose hit count exceeded the
            # given threshold in the last round would be the
            # prefix of each `prefix` in the current round. (See
            # [BBCGGI21, Section 5.1].) In this case, part of the
            # path would have already been traversed.
            #
            # Re-computing nodes along previously traversed paths is
            # wasteful. Implementations can eliminate this added
            # complexity by caching nodes (i.e., `(seed, ctrl)`
            # pairs) output by previous calls to `eval_next()`.
            (seed, ctrl, y) = self.eval_next(
                seed,
                ctrl,
                public_share[current_level],
                current_level,
                bit,
                ctx,
                nonce,
            )
        if agg_id == 0:
            out_share.append(cast(list[Field], y))
        else:
            out_share.append(vec_neg(cast(list[Field], y)))
    return cast(
        list[list[Field64]] | list[list[Field255]],
        out_share,
    )

def eval_next(
        self,
        prev_seed: bytes,
        prev_ctrl: bool,
        correction_word: CorrectionWord,
        level: int,
        bit: int,
        ctx: bytes,
        nonce: bytes) -> tuple[bytes, bool, FieldVec]:
    """
    Compute the next node in the IDPF tree along the path determined
    by a candidate prefix. The next node is determined by `bit`, the
    bit of the prefix corresponding to the next level of the tree.
    """

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

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

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

    return (next_seed, next_ctrl, cast(FieldVec, y))
]]></sourcecode>
        </section>
        <section anchor="idpf-bbcggi21-helper-functions">
          <name>Auxiliary Functions</name>
          <sourcecode type="python"><![CDATA[
def extend(
        self,
        level: int,
        seed: bytes,
        ctx: bytes,
        nonce: bytes) -> tuple[list[bytes], list[bool]]:
    xof = self.current_xof(
        level,
        seed,
        format_dst(1, 0, 0) + ctx,
        nonce,
    )
    s = [
        bytearray(xof.next(self.KEY_SIZE)),
        bytearray(xof.next(self.KEY_SIZE)),
    ]
    # Use the least significant bits as the control bit correction,
    # and then zero it out. This gives effectively 127 bits of
    # security, but reduces the number of AES calls needed by 1/3.
    t = [bool(s[0][0] & 1), bool(s[1][0] & 1)]
    s[0][0] &= 0xFE
    s[1][0] &= 0xFE
    return ([bytes(s[0]), bytes(s[1])], t)

def convert(
        self,
        level: int,
        seed: bytes,
        ctx: bytes,
        nonce: bytes) -> tuple[bytes, FieldVec]:
    xof = self.current_xof(
        level,
        seed,
        format_dst(1, 0, 1) + ctx,
        nonce,
    )
    next_seed = xof.next(self.KEY_SIZE)
    field = self.current_field(level)
    w = xof.next_vec(field, self.VALUE_LEN)
    return (next_seed, cast(FieldVec, w))

def current_xof(self,
                level: int,
                seed: bytes,
                dst: bytes,
                nonce: bytes) -> Xof:
    if level < self.BITS-1:
        return XofFixedKeyAes128(seed, dst, nonce)
    return XofTurboShake128(seed, dst, nonce)
]]></sourcecode>
        </section>
      </section>
    </section>
    <section anchor="security">
      <name>Security Considerations</name>
      <t>VDAFs (<xref target="vdaf"/>) have two essential security goals:</t>
      <ol spacing="normal" type="1"><li>
          <t>Privacy: an attacker that controls the Collector and a subset of Clients and
Aggregators learns nothing about the measurements of honest Clients beyond
what it can deduce from the aggregate result. We assume the attacker
controls the entire network except for channels between honest Clients and
honest Aggregators. In particular, it cannot forge or prevent transmission
of messages on these channels.</t>
        </li>
        <li>
          <t>Robustness: an attacker that controls a subset of Clients cannot cause the
Collector to compute anything other than the aggregate of the measurements
of honest Clients, plus valid measurements from some of the
attacker-controlled Clients. We assume the attacker eavesdrops on the
network but does not control transmission of messages between honest
parties.</t>
        </li>
      </ol>
      <t>Formal definitions of privacy and robustness can be found in <xref target="DPRS23"/>. A VDAF
is the core cryptographic primitive of a protocol that achieves the above
privacy and robustness goals. It is not sufficient on its own, however. The
application will need to assure a few security properties, for example:</t>
      <ul spacing="normal">
        <li>
          <t>Securely distributing the long-lived parameters, in particular the
verification key.</t>
        </li>
        <li>
          <t>Establishing secure channels:  </t>
          <ul spacing="normal">
            <li>
              <t>Confidential and authentic channels among Aggregators, and between the
Aggregators and the Collector; and</t>
            </li>
            <li>
              <t>Confidential and Aggregator-authenticated channels between Clients and
Aggregators.</t>
            </li>
          </ul>
        </li>
        <li>
          <t>Enforcing the non-collusion properties required of the specific VDAF in use.</t>
        </li>
      </ul>
      <t>In such an environment, a VDAF provides the high-level privacy property
described above: the Collector learns only the aggregate result, and nothing
about individual measurements aside from what can be inferred from the
aggregate result.  The Aggregators learn neither individual measurements nor
the aggregate result.  The Collector is assured that the aggregate statistic
accurately reflects the inputs as long as the Aggregators correctly executed
their role in the VDAF.</t>
      <t>On their own, VDAFs do not provide:</t>
      <ol spacing="normal" type="1"><li>
          <t>Mitigation of Sybil attacks <xref target="Dou02"/>. In this attack, the adversary
observes a subset of input shares transmitted by a Client it is interested
in. It allows the input shares to be processed, but corrupts and picks bogus
measurements for the remaining Clients.  Applications can guard against
these risks by adding additional controls on report submission, such as
Client authentication and rate limits.</t>
        </li>
        <li>
          <t>Differential privacy <xref target="Dwo06"/>. Depending on the distribution of the
measurements, the aggregate result itself can still leak a significant
amount of information about an individual measurement or the person that
generated it.</t>
        </li>
        <li>
          <t>Robustness in the presence of a malicious Aggregator. An Aggregator can,
without detection, manipulate the aggregate result by modifying its own
aggregate share.</t>
        </li>
        <li>
          <t>Guaranteed output delivery <xref target="GSZ20"/>. An attacker that controls transmission
of messages between honest parties can prevent computation of the aggregate
result by dropping messages.</t>
        </li>
      </ol>
      <section anchor="the-verification-key">
        <name>The Verification Key</name>
        <t>The Aggregators are responsible for exchanging the verification key in advance
of executing the VDAF. Any procedure is acceptable as long as the following
conditions are met:</t>
        <ol spacing="normal" type="1"><li>
            <t>To ensure robustness of the computation, the Aggregators <bcp14>MUST NOT</bcp14> reveal the
verification key to the Clients. Otherwise, a malicious Client might be able
to exploit knowledge of this key to craft an invalid report that would be
accepted by the Aggregators.</t>
          </li>
          <li>
            <t>To ensure privacy of the measurements, the Aggregators <bcp14>MUST</bcp14> commit to the
verification key prior to processing reports generated by Clients.
Otherwise, the attacker may be able to craft a verification key that, for a
given report, causes an honest Aggregator to leak information about the
measurement during preparation.</t>
          </li>
        </ol>
        <t>Meeting these requirements is relatively straightforward. For example, the
Aggregators may designate one of their peers to generate the verification key
and distribute it to the others. To assure Clients of key commitment, the
Clients and (honest) Aggregators <bcp14>SHOULD</bcp14> bind the verification key to the
application context. For instance, the "task ID" of DAP <xref target="DAP"/> could be set to
the hash of the verification key; then as long as honest Aggregators only
consume reports for the task indicated by the Client, forging a new key after
the fact would reduce to finding collisions in the underlying hash function.
(Keeping the key secret from the Clients would require the hash function to be
one-way.) However, since rotating the key implies rotating the task ID, this
scheme would not allow key rotation over the lifetime of a task.</t>
      </section>
      <section anchor="nonce-requirements">
        <name>The Nonce</name>
        <t>The sharding and preparation steps of VDAF execution depend on a nonce
associated with the Client's report. To ensure privacy of the underlying
measurement, the Client <bcp14>MUST</bcp14> generate this nonce using a CSPRNG. This is
required in order to leverage security analysis for the privacy definition of
<xref target="DPRS23"/>, which assumes the nonce is chosen at random prior to generating the
report. Uniqueness of the nonce is not sufficient because the verification key
is controlled by the attacker.</t>
        <t>Applications will need to protect against replay attacks to prevent disallowed
re-use of reports (see <xref target="agg-param-security"/>). Furthermore, in applications
that aim to achieve differential privacy, it is necessary to limit how much
each party contributes to a single batch or multiple batches. It is <bcp14>RECOMMENDED</bcp14>
that the nonce generated by the Client be used by the Aggregators for replay
protection.</t>
      </section>
      <section anchor="the-public-share">
        <name>The Public Share</name>
        <t>The Aggregators <bcp14>MUST</bcp14> ensure they have both received the same public share from
the Client. It is sufficient, for example, to exchange a hash of the public
share over a secure channel.</t>
      </section>
      <section anchor="agg-param-security">
        <name>The Aggregation Parameter</name>
        <t>As described in <xref target="sec-daf-validity-scopes"/> and <xref target="sec-vdaf-validity-scopes"/>
respectively, DAFs and VDAFs may impose restrictions on the re-use of reports.
For Prio3, reports should only be aggregated once; for Poplar1, reports may be
aggregated multiple times, but never twice at the same level of the tree.
Otherwise, we risk re-using correlated randomness, which might compromise
confidentiality of the Client's measurement.</t>
        <t>Higher level applications that use DAFs or VDAFs <bcp14>MUST</bcp14> enforce aggregation
parameter validity. In particular, prior to beginning preparation with an
aggregation parameter provided by the Collector, they <bcp14>MUST</bcp14> invoke <tt>is_valid()</tt>
to decide if the parameter is valid given the sequence of previously accepted
parameters.</t>
        <t>Note that aggregating a batch of reports multiple times, even with a valid
sequence of aggregation parameters, can result in information leakage beyond
what is used by the application.</t>
        <t>For example, when Poplar1 is used for heavy hitters, the Aggregators learn not
only the heavy hitters themselves, but also the prefix tree (as defined in
<xref target="poplar1"/>) computed along the way. Indeed, this leakage is inherent to any
construction that uses an IDPF (<xref target="idpf"/>) in the same way. Depending on the
distribution of the measurements, the prefix tree can leak a significant amount
of information about unpopular inputs. For instance, it is possible (though
perhaps unlikely) for a large set of non-heavy-hitter values to share a common
prefix, which would be leaked by a prefix tree with a sufficiently small
threshold.</t>
        <t>A malicious adversary controlling the Collector and one of the Aggregators can
further turn arbitrary non-heavy prefixes into heavy ones by tampering with the
IDPF output at any position. While our construction ensures that the nodes
evaluated at one level are children of the nodes evaluated at the previous
level, this still may allow an adversary to discover individual non-heavy
strings. We call this a "steering attack".</t>
        <t>The only practical, general-purpose defense against steering attacks is to
compose Poplar1 with some mechanism for differential privacy. It is therefore
<bcp14>RECOMMENDED</bcp14> to use differential privacy for any heavy-hitter type application.</t>
      </section>
      <section anchor="idpf-extract">
        <name>Safe Usage of IDPF Outputs</name>
        <t>The arithmetic sketch described in <xref target="poplar1"/> is used by the Aggregators to check
that the shares of the vector obtained by evaluating a Client's IDPF at a
sequence of candidate prefixes has at most one non-zero value, and that the
non-zero value is <tt>1</tt>. Depending on how the values are used, the arithmetic sketch
on its own may not be sufficient for robustness of the application. In
particular, a malicious Client may attempt to influence the computation by
choosing an IDPF that evaluates to <tt>1</tt> at more than one node at a given
level of the tree.</t>
        <t>This issue can be mitigated by using an IDPF that is extractable as defined
in Appendix D of <xref target="BBCGGI21"/>. Extractability ensures that, for a particular
level of the tree, it is infeasible for an attacker to control values of the
IDPF such that it takes on chosen non-zero values at more than one node. (It
can practically only achieve the zero function, a point function, or a
pseudorandom function.)</t>
        <t>The IDPF specified in <xref target="idpf"/> only guarantees extractability at the last level
of the tree. (This is by virtue of using a larger field for the leaves than for
inner nodes and using an XOF to derive leaves that is safe to model as a random
oracle. See <xref target="xof-vs-ro"/>.) For intermediate levels, it is feasible for a
client to produce IDPF shares with two controlled non-zero nodes.</t>
        <t>This is not an issue for running heavy hitters, since (1) each node in the
prefix tree is a child of a previously traversed node, (2) the arithmetic sketch
would detect double voting at every level of the prefix tree, and (3) the IDPF
is extractable at the last level of the tree. However, the lack of
extractability at intermediate levels may result in attacks on the robustness
of certain applications.</t>
        <t>Thus applications <bcp14>SHOULD NOT</bcp14> use prefix counts for intermediate levels for any
purpose beyond computing the prefix tree for heavy hitters.</t>
      </section>
      <section anchor="xof-vs-ro">
        <name>Safe Usage of XOFs</name>
        <t>In the security analyses of our protocols, XOFs (<xref target="xof"/>) are usually modeled
as random oracles. XofTurboShake128 is designed to be indifferentiable from a
random oracle <xref target="MRH04"/>, making it a suitable choice for most situations.</t>
        <t>The one exception is the IDPF of <xref target="idpf-bbcggi21"/>. Here, a random oracle is not
needed to prove privacy, since the analysis of <xref target="BBCGGI21"/>, Proposition 1, only
requires a Pseudorandom Generator (PRG). As observed in <xref target="GKWY20"/>, a PRG can be
instantiated from a correlation-robust hash function <tt>H</tt>. Informally,
correlation robustness requires that for a random <tt>r</tt>, <tt>H(xor(r, x))</tt> is
computationally indistinguishable from a random function of <tt>x</tt>. A PRG can
therefore be constructed as</t>
        <artwork><![CDATA[
PRG(r) = H(xor(r, 1)) || H(xor(r, 2)) || ...
]]></artwork>
        <t>since each individual hash function evaluation is indistinguishable from a random
function.</t>
        <t>XofFixedKeyAes128 in <xref target="xof-fixed-key-aes128"/> implements a correlation-robust
hash function using fixed-key AES. For security, it assumes that AES with a
fixed key can be modeled as a random permutation <xref target="GKWY20"/>. Additionally, we
use a different AES key for every client, which in the ideal cipher model leads
to better concrete security <xref target="GKWWY20"/>.</t>
        <t>We note that for robustness, the analysis of <xref target="BBCGGI21"/> still assumes a
random oracle to make the IDPF extractable. We therefore use XofTurboShake128
instead for the last level of the tree. It is important that XofTurboShake128
supports many seed lengths, in particular 16 bytes, as this is the seed size
for the inner levels.</t>
        <t>While XofFixedKeyAes128 has been shown to be differentiable from a random
oracle <xref target="GKWWY20"/>, there are no known attacks exploiting this difference. We
also stress that even if the IDPF is not extractable, Poplar1 guarantees that
every client can contribute to at most one prefix among the ones being
evaluated by the helpers.</t>
      </section>
      <section anchor="security-multiproof">
        <name>Choosing FLP Parameters</name>
        <t>Prio3 and other systems built from the FLP of <xref target="flp-bbcggi19"/> may benefit from
choosing a field size that is as small as possible. Generally speaking, a
smaller field results in lower communication and storage costs. Care must be
taken, however, since a smaller field also results in degraded (or even
vacuous) robustness.</t>
        <t>Different variants of Prio3 (<xref target="prio3"/>) use different field sizes: Prio3Count
and Prio3Sum use Field64; but Prio3SumVec, Prio3Histogram, and
Prio3MultihotCountVec all use Field128, a field that is twice as large as
Field64. This is due to the use of joint randomness (<xref target="flp"/>) in the latter
variants. Joint randomness allows for more flexible circuit design (see
<xref target="flp-bbcggi19-overview-extensions"/>), but opens up Prio3 to offline attacks in
which the attacker searches for input shares for an invalid measurement that
derive joint randomness that causes the circuit to accept. Choosing a large
enough field ensures this computation is too expensive to be feasible. (See
<xref target="DPRS23"/>, Theorem 1.) Note that privacy is not susceptible to such attacks.</t>
        <t>Another way to mitigate this issue (or improve robustness in general) is to
generate and verify multiple, independent proofs. (See <xref target="multiproofs"/>.) For
Prio3, the <tt>PROOFS</tt> parameter controls the number of proofs (at least one) that
are generated and verified. In general the soundness error of the FLP is given
by the following formula:</t>
        <artwork><![CDATA[
(circuit_soundness + flp_soundness)^PROOFS
]]></artwork>
        <t>where:</t>
        <ul spacing="normal">
          <li>
            <t><tt>circuit_soundness</tt> is the soundness of the validity circuit
(<xref target="flp-bbcggi19-valid"/>)</t>
          </li>
          <li>
            <t><tt>flp_soundness</tt> is the base soundness of the proof system (<xref target="BBCGGI19"/>,
Theorem 4.3)</t>
          </li>
        </ul>
        <t>For circuits involving joint randomness, we aim for the soundness error to be
close to <tt>2^-128</tt> in order to mitigate offline attacks. Such circuits <bcp14>MUST</bcp14> use
Field128 with at least one proof or Field64 with at least three proofs.
Depending on the circuit, Field64 with two proofs might have significantly
lower soundness than Field128 with one proof.</t>
        <t>We stress that weak parameters (too small a field, too few proofs, or both) can
be exploited to attack any aggregation task using those parameters. To
mitigate offline attacks, it is necessary to disable all tasks that use the
weak parameters.</t>
      </section>
      <section anchor="num-aggregators">
        <name>Choosing the Number of Aggregators</name>
        <t>Two Aggregators are required for privacy in our threat model, but some (V)DAFs,
including Prio3 (<xref target="prio3"/>), allow for any number of Aggregators, only one of
which needs to be trusted in order for the computation to be private. To hedge
against corruptions that happen during the course of the attack, deployments
may consider involving more than two Aggregators as described for example in
<xref target="star-topo"/>. Note however that some schemes are not compatible with this mode
of operation, such as Poplar1.</t>
      </section>
      <section anchor="deep">
        <name>Defense-in-Depth Measures</name>
        <t>Prio3 and Poplar1 are designed to resist some attacks that fall outside the
main threat model for VDAFs.</t>
        <t>Broadly speaking, domain separation is used to prevent cross protocol attacks,
in which data from evaluation of one VDAF translates to an attack against another.
For example:</t>
        <ol spacing="normal" type="1"><li>
            <t>Weak entropy sources: the VDAF algorithm ID is bound to each XOF invocation,
thereby ensuring the outputs are different between VDAF invocations, even if
the underlying randomness is the same. For example, two different instances
of Prio3 would compute different measurement shares.</t>
          </li>
          <li>
            <t>Weak parameters: Prio3 variants that require joint randomness are subject to
offline attacks against robustness. These attacks are feasible if the field
size or number of proofs is sufficiently small. (See
<xref target="security-multiproof"/>.) The joint randomness derivation is bound to both
the field (via the algorithm ID) and the number of proofs, thereby ensuring
that joint randomness derived for weak parameters is not reused for stronger
parameters. In addition, the joint randomness is bound to the application
context, meaning any work the attacker does to attack some application is
not useful for other applications that use the same parameters.</t>
          </li>
        </ol>
        <t>There are also some important limitations to be aware of. For example, Prio3
provides domain separation between families of circuits, but does not provide
domain separation between instances of a circuit. Concretely, it is possible
for Aggregators to accept a report for Prio3SumVec from a Client who disagrees
with them on the value of <tt>bits</tt> and <tt>length</tt> (so long as the encoded
measurement is the same size). This is because there is no
binding of the circuit parameters to the computation.</t>
      </section>
      <section anchor="side-channel-resistance">
        <name>Side-Channel Resistance</name>
        <t>Implementations of VDAFs should incorporate defenses against side-channel
attacks. For side-channel attacks against the privacy security goal, the
relevant threat model includes an attacker that may control the Collector, a
subset of Clients, and a subset of Aggregators, and monitor side-channel
signals from the honest Clients and Aggregators. Side-channel attacks by third
parties may indirectly target robustness by trying to leak the Aggregators'
verification key. Thus, implementations of Clients and Aggregators should treat
measurements, input shares, output shares, and the verification key as secret,
and avoid leaking those secret values or any intermediate computations that
depend on them.</t>
        <t>For example, the following routines should all be implemented in a side-channel
resistant manner.</t>
        <ul spacing="normal">
          <li>
            <t>Finite field arithmetic</t>
          </li>
          <li>
            <t>XOFs</t>
          </li>
          <li>
            <t>IDPF generation and evaluation, including handling of control bits</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>IANA is requested to make one new registry:</t>
      <ul spacing="normal">
        <li>
          <t>DAF and VDAF Identifiers</t>
        </li>
      </ul>
      <t>This registry should be created under the heading "Verifiable Distributed
Aggregation Functions (VDAF)", and administered under the Specification Required
policy <xref target="RFC8126"/>.</t>
      <t>The "VDAF Identifiers" registry lists identifiers for Distributed Aggregation
Functions (DAFs) and Verifiable Distributed Aggregation Functions (VDAFs). These
identifiers are four-byte values, so the minimum possible value is <tt>0x00000000</tt>
and the maximum possible value is <tt>0xffffffff</tt>.</t>
      <t>Template:</t>
      <ul spacing="normal">
        <li>
          <t>Value: The four-byte identifier for the DAF or VDAF</t>
        </li>
        <li>
          <t>Scheme: The name of the DAF or VDAF</t>
        </li>
        <li>
          <t>Type: Either "DAF" for a Distributed Aggregation Function or "VDAF" for a
Verifiable Distributed Aggregation Function</t>
        </li>
        <li>
          <t>Reference: Where the algorithm is defined</t>
        </li>
      </ul>
      <t>The initial contents of the registry are as follows:</t>
      <table anchor="codepoints">
        <name>Verifiable Distributed Aggregation Function Identifiers Registry</name>
        <thead>
          <tr>
            <th align="left">Value</th>
            <th align="left">Scheme</th>
            <th align="left">Type</th>
            <th align="left">Reference</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>0x00000000</tt></td>
            <td align="left">Reserved</td>
            <td align="left">n/a</td>
            <td align="left">RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000001</tt></td>
            <td align="left">Prio3Count</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3count"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000002</tt></td>
            <td align="left">Prio3Sum</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3sum"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000003</tt></td>
            <td align="left">Prio3SumVec</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3sumvec"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000004</tt></td>
            <td align="left">Prio3Histogram</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3histogram"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000005</tt></td>
            <td align="left">Prio3MultihotCountVec</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3multihotcountvec"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000006</tt></td>
            <td align="left">Poplar1</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="poplar1-construction"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0xFFFF0000</tt> to <tt>0xFFFFFFFF</tt></td>
            <td align="left">Reserved for Private Use</td>
            <td align="left">n/a</td>
            <td align="left">n/a</td>
          </tr>
        </tbody>
      </table>
      <t>(RFC EDITOR: Please replace "RFC XXXX" above with the RFC number assigned to
this document.)</t>
      <t>VDAF identifiers are used for domain separation, as described in
<xref target="dst-binder"/>. Domain separation guards against cross protocol attacks and
certain failures of entropy sources. See <xref target="deep"/>.</t>
      <t>The benefits of domain separation are undermined if different VDAFs are used
with the same VDAF Identifier.  The "Reserved for Private Use" code points
should thus be used judiciously, because they provide no defense against such
collisions.  Applications <bcp14>SHOULD</bcp14> prefer the use of registered code points.</t>
    </section>
  </middle>
  <back>
    <references anchor="sec-combined-references">
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="AES" target="https://www.nist.gov/publications/advanced-encryption-standard-aes">
          <front>
            <title>Advanced Encryption Standard (AES)</title>
            <author initials="M. J." surname="Dworkin" fullname="Morris J. Dworkin">
              <organization/>
            </author>
            <author initials="E." surname="Barker" fullname="Elaine Barker">
              <organization/>
            </author>
            <author initials="J. R." surname="Nechvatal" fullname="James R. Nechvatal">
              <organization/>
            </author>
            <author initials="J." surname="Foti" fullname="James Foti">
              <organization/>
            </author>
            <author initials="L. E." surname="Bassham" fullname="Lawrence E. Bassham">
              <organization/>
            </author>
            <author initials="E." surname="Roback" fullname="E. Roback">
              <organization/>
            </author>
            <author initials="J." surname="Dray Jr" fullname="James F. Dray Jr.">
              <organization/>
            </author>
            <date year="2001"/>
          </front>
        </reference>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
            <abstract>
              <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        <reference anchor="RFC8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
        <reference anchor="RFC8446">
          <front>
            <title>The Transport Layer Security (TLS) Protocol Version 1.3</title>
            <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
            <date month="August" year="2018"/>
            <abstract>
              <t>This document specifies version 1.3 of the Transport Layer Security (TLS) protocol. TLS allows client/server applications to communicate over the Internet in a way that is designed to prevent eavesdropping, tampering, and message forgery.</t>
              <t>This document updates RFCs 5705 and 6066, and obsoletes RFCs 5077, 5246, and 6961. This document also specifies new requirements for TLS 1.2 implementations.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8446"/>
          <seriesInfo name="DOI" value="10.17487/RFC8446"/>
        </reference>
        <reference anchor="TurboSHAKE">
          <front>
            <title>KangarooTwelve and TurboSHAKE</title>
            <author fullname="Benoît Viguier" initials="B." surname="Viguier">
              <organization>ABN AMRO Bank</organization>
            </author>
            <author fullname="David Wong" initials="D." surname="Wong">
              <organization>zkSecurity</organization>
            </author>
            <author fullname="Gilles Van Assche" initials="G." surname="Van Assche">
              <organization>STMicroelectronics</organization>
            </author>
            <author fullname="Quynh Dang" initials="Q." surname="Dang">
              <organization>National Institute of Standards and Technology</organization>
            </author>
            <author fullname="Joan Daemen" initials="J." surname="Daemen">
              <organization>Radboud University</organization>
            </author>
            <date day="21" month="February" year="2025"/>
            <abstract>
              <t>   This document defines four eXtendable Output Functions (XOF), hash
   functions with output of arbitrary length, named TurboSHAKE128,
   TurboSHAKE256, KT128 and KT256.

   All four functions provide efficient and secure hashing primitives,
   and the last two are able to exploit the parallelism of the
   implementation in a scalable way.

   This document is a product of the Crypto Forum Research Group.  It
   builds up on the definitions of the permutations and of the sponge
   construction in [FIPS 202], and is meant to serve as a stable
   reference and an implementation guide.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-kangarootwelve-17"/>
        </reference>
        <reference anchor="RFC8126">
          <front>
            <title>Guidelines for Writing an IANA Considerations Section in RFCs</title>
            <author fullname="M. Cotton" initials="M." surname="Cotton"/>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <author fullname="T. Narten" initials="T." surname="Narten"/>
            <date month="June" year="2017"/>
            <abstract>
              <t>Many protocols make use of points of extensibility that use constants to identify various protocol parameters. To ensure that the values in these fields do not have conflicting uses and to promote interoperability, their allocations are often coordinated by a central record keeper. For IETF protocols, that role is filled by the Internet Assigned Numbers Authority (IANA).</t>
              <t>To make assignments in a given registry prudently, guidance describing the conditions under which new values should be assigned, as well as when and how modifications to existing values can be made, is needed. This document defines a framework for the documentation of these guidelines by specification authors, in order to assure that the provided guidance for the IANA Considerations is clear and addresses the various issues that are likely in the operation of a registry.</t>
              <t>This is the third edition of this document; it obsoletes RFC 5226.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="26"/>
          <seriesInfo name="RFC" value="8126"/>
          <seriesInfo name="DOI" value="10.17487/RFC8126"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="AGJOP21" target="https://ia.cr/2021/576">
          <front>
            <title>Prio+: Privacy Preserving Aggregate Statistics via Boolean Shares</title>
            <author initials="S." surname="Addanki" fullname="Surya Addanki">
              <organization/>
            </author>
            <author initials="K." surname="Garbe" fullname="Kevin Garbe">
              <organization/>
            </author>
            <author initials="E." surname="Jaffe" fullname="Eli Jaffe">
              <organization/>
            </author>
            <author initials="R." surname="Ostrovsky" fullname="Rafail Ostrovsky">
              <organization/>
            </author>
            <author initials="A." surname="Polychroniadou" fullname="Antigoni Polychroniadou">
              <organization/>
            </author>
            <date year="2022"/>
          </front>
          <refcontent>Security and Cryptography for Networks (SCN)</refcontent>
        </reference>
        <reference anchor="BBCGGI19" target="https://ia.cr/2019/188">
          <front>
            <title>Zero-Knowledge Proofs on Secret-Shared Data via Fully Linear PCPs</title>
            <author initials="D." surname="Boneh" fullname="Dan Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle" fullname="Elette Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs" fullname="Henry Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa" fullname="Niv Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai" fullname="Yuval Ishai">
              <organization/>
            </author>
            <date year="2019"/>
          </front>
          <refcontent>Crypto</refcontent>
        </reference>
        <reference anchor="BBCGGI21" target="https://ia.cr/2021/017">
          <front>
            <title>Lightweight Techniques for Private Heavy Hitters</title>
            <author initials="D." surname="Boneh" fullname="Dan Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle" fullname="Elette Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs" fullname="Henry Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa" fullname="Niv Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai" fullname="Yuval Ishai">
              <organization/>
            </author>
            <date year="2021"/>
          </front>
          <refcontent>IEEE Security &amp; Privacy (S&amp;P)</refcontent>
        </reference>
        <reference anchor="BBCGGI23" target="https://ia.cr/2023/1012">
          <front>
            <title>Arithmetic Sketching</title>
            <author initials="D." surname="Boneh" fullname="Dan Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle" fullname="Elette Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs" fullname="Henry Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa" fullname="Niv Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai" fullname="Yuval Ishai">
              <organization/>
            </author>
            <date year="2023"/>
          </front>
          <refcontent>Crypto</refcontent>
        </reference>
        <reference anchor="BGI15" target="https://www.iacr.org/archive/eurocrypt2015/90560300/90560300.pdf">
          <front>
            <title>Function Secret Sharing</title>
            <author initials="E." surname="Boyle" fullname="Elette Boyle">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa" fullname="Niv Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai" fullname="Yuval Ishai">
              <organization/>
            </author>
            <date year="2015"/>
          </front>
          <refcontent>Eurocrypt</refcontent>
        </reference>
        <reference anchor="CGB17" target="https://dl.acm.org/doi/10.5555/3154630.3154652">
          <front>
            <title>Prio: Private, Robust, and Scalable Computation of Aggregate Statistics</title>
            <author initials="D." surname="Boneh" fullname="Dan Boneh">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs" fullname="Henry Corrigan-Gibbs">
              <organization/>
            </author>
            <date year="2017"/>
          </front>
          <refcontent>USENIX Symposium on Networked Systems Design and Implementation (NSDI)</refcontent>
        </reference>
        <reference anchor="Dou02" target="https://doi.org/10.1007/3-540-45748-8_24">
          <front>
            <title>The Sybil Attack</title>
            <author initials="J. R." surname="Douceur" fullname="John R. Douceur">
              <organization/>
            </author>
            <date year="2002"/>
          </front>
          <refcontent>International Workshop on Peer-to-Peer Systems (IPTPS)</refcontent>
        </reference>
        <reference anchor="DPRS23" target="https://ia.cr/2023/130">
          <front>
            <title>Verifiable Distributed Aggregation Functions</title>
            <author initials="" surname="Hannah Davis">
              <organization/>
            </author>
            <author initials="" surname="Christopher Patton">
              <organization/>
            </author>
            <author initials="" surname="Mike Rosulek">
              <organization/>
            </author>
            <author initials="" surname="Phillipp Schoppmann">
              <organization/>
            </author>
            <date year="2023"/>
          </front>
          <refcontent>Privacy Enhancing Technologies Symposium (PETS)</refcontent>
        </reference>
        <reference anchor="Dwo06" target="https://link.springer.com/chapter/10.1007/11787006_1">
          <front>
            <title>Differential Privacy</title>
            <author initials="" surname="Cynthia Dwork">
              <organization/>
            </author>
            <date year="2006"/>
          </front>
          <refcontent>International Colloquium on Automata, Languages, and Programming (ICALP)</refcontent>
        </reference>
        <reference anchor="EPK14" target="https://dl.acm.org/doi/10.1145/2660267.2660348">
          <front>
            <title>RAPPOR: Randomized Aggregatable Privacy-Preserving Ordinal Response</title>
            <author initials="Ú." surname="Erlingsson" fullname="Úlfar Erlingsson">
              <organization/>
            </author>
            <author initials="V." surname="Pihur" fullname="Vasyl Pihur">
              <organization/>
            </author>
            <author initials="A." surname="Korolova" fullname="Aleksandra Korolova">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <refcontent>ACM Conference on Computer and Communications Security (CCS)</refcontent>
        </reference>
        <reference anchor="ENPA" target="https://covid19-static.cdn-apple.com/applications/covid19/current/static/contact-tracing/pdf/ENPA_White_Paper.pdf">
          <front>
            <title>Exposure Notification Privacy-preserving Analytics (ENPA) White Paper</title>
            <author>
              <organization/>
            </author>
            <date year="2021"/>
          </front>
        </reference>
        <reference anchor="GI14" target="https://link.springer.com/chapter/10.1007/978-3-642-55220-5_35">
          <front>
            <title>Distributed Point Functions and Their Applications</title>
            <author initials="N." surname="Gilboa" fullname="Niv Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai" fullname="Yuval Ishai">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <refcontent>Eurocrypt</refcontent>
        </reference>
        <reference anchor="GSZ20" target="https://link.springer.com/chapter/10.1007/978-3-030-56880-1_22">
          <front>
            <title>Guaranteed Output Delivery Comes Free in Honest Majority MPC</title>
            <author initials="V." surname="Goyal" fullname="Vipul Goyal">
              <organization/>
            </author>
            <author initials="Y." surname="Song" fullname="Yifan Song">
              <organization/>
            </author>
            <author initials="C." surname="Zhu" fullname="Chenzhi Zhu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <refcontent>Crypto</refcontent>
        </reference>
        <reference anchor="GKWWY20" target="https://link.springer.com/chapter/10.1007/978-3-030-56880-1_28">
          <front>
            <title>Better concrete security for half-gates garbling (in the multi-instance setting)</title>
            <author initials="C." surname="Guo" fullname="Chun Guo">
              <organization/>
            </author>
            <author initials="J." surname="Katz" fullname="Jonathan Katz">
              <organization/>
            </author>
            <author initials="X." surname="Wang" fullname="Xiao Wang">
              <organization/>
            </author>
            <author initials="C." surname="Weng" fullname="Chenkai Weng">
              <organization/>
            </author>
            <author initials="Y." surname="Yu" fullname="Yu Yu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <refcontent>Crypto</refcontent>
        </reference>
        <reference anchor="GKWY20" target="https://eprint.iacr.org/2019/074">
          <front>
            <title>Efficient and Secure Multiparty Computation from Fixed-Key Block Ciphers</title>
            <author initials="C." surname="Guo" fullname="Chun Guo">
              <organization/>
            </author>
            <author initials="J." surname="Katz" fullname="Jonathan Katz">
              <organization/>
            </author>
            <author initials="X." surname="Wang" fullname="Xiao Wang">
              <organization/>
            </author>
            <author initials="Y." surname="Yu" fullname="Yu Yu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <refcontent>IEEE Security &amp; Privacy (S&amp;P)</refcontent>
        </reference>
        <reference anchor="MPDST25" target="https://eprint.iacr.org/2024/221">
          <front>
            <title>Mastic: Private Weighted Heavy-Hitters and Attribute-Based Metrics</title>
            <author initials="D." surname="Mouris" fullname="Dimitris Mouris">
              <organization/>
            </author>
            <author initials="C." surname="Patton" fullname="Christopher Patton">
              <organization/>
            </author>
            <author initials="H." surname="Davis" fullname="Hannah Davis">
              <organization/>
            </author>
            <author initials="P." surname="Sarkar" fullname="Pratik Sarkar">
              <organization/>
            </author>
            <author initials="N. G." surname="Tsoutsos" fullname="Nektarios Georgios Tsoutsos">
              <organization/>
            </author>
            <date year="2025"/>
          </front>
          <refcontent>Privacy Enhancing Technologies Symposium (PETS)</refcontent>
        </reference>
        <reference anchor="MPRV09" target="https://link.springer.com/chapter/10.1007/978-3-642-03356-8_8">
          <front>
            <title>Computational Differential Privacy</title>
            <author initials="I." surname="Mironov" fullname="Ilya Mironov">
              <organization/>
            </author>
            <author initials="O." surname="Pandey" fullname="Omkant Pandey">
              <organization/>
            </author>
            <author initials="O." surname="Reingold" fullname="Omer Reingold">
              <organization/>
            </author>
            <author initials="S." surname="Vadhan" fullname="Salil Vadhan">
              <organization/>
            </author>
            <date year="2009"/>
          </front>
          <refcontent>Crypto</refcontent>
        </reference>
        <reference anchor="MRH04" target="https://doi.org/10.1007/978-3-540-24638-1_2">
          <front>
            <title>Indifferentiability, impossibility results on reductions, and applications to the random oracle methodology</title>
            <author initials="U." surname="Maurer" fullname="Ueli Maurer">
              <organization/>
            </author>
            <author initials="R." surname="Renner" fullname="Renato Renner">
              <organization/>
            </author>
            <author initials="C." surname="Holenstein" fullname="Clemens Holenstein">
              <organization/>
            </author>
            <date year="2004"/>
          </front>
          <refcontent>Theory of Cryptography (TCC)</refcontent>
        </reference>
        <reference anchor="OriginTelemetry" target="https://web.archive.org/web/20221025174046/https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/collection/origin.html">
          <front>
            <title>Origin Telemetry</title>
            <author>
              <organization/>
            </author>
            <date year="2020"/>
          </front>
        </reference>
        <reference anchor="SML24" target="https://eprint.iacr.org/2024/585">
          <front>
            <title>A Complete Beginner Guide to the Number Theoretic Transform (NTT)</title>
            <author initials="A." surname="Satriawan" fullname="Ardianto Satriawan">
              <organization/>
            </author>
            <author initials="R." surname="Mareta" fullname="Rella Mareta">
              <organization/>
            </author>
            <author initials="H." surname="Lee" fullname="Hanho Lee">
              <organization/>
            </author>
            <date year="2024"/>
          </front>
          <refcontent>IEEE Access, vol. 11</refcontent>
        </reference>
        <reference anchor="TestVectors" target="https://github.com/cfrg/draft-irtf-cfrg-vdaf">
          <front>
            <title>Test vectors for Prio3 and Poplar1</title>
            <author>
              <organization/>
            </author>
            <date year="2024" month="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="29" month="April" year="2025"/>
            <abstract>
              <t>   There are many situations in which it is desirable to take
   measurements of data which people consider sensitive.  In these
   cases, the entity taking the measurement is usually not interested in
   people's individual responses but rather in aggregated data.
   Conventional methods require collecting individual responses and then
   aggregating them on some server, thus representing a threat to user
   privacy and rendering many such measurements difficult and
   impractical.  This document describes a multi-party distributed
   aggregation protocol (DAP) for privacy preserving measurement which
   can be used to collect aggregate data without revealing any
   individual contributor's data.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-ppm-dap-15"/>
        </reference>
      </references>
    </references>
    <?line 6067?>

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

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

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

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

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

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

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

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

    def eval(self, field: type[F], inp: list[F]) -> F:
        out = field(0)
        for i in range(self.count):
            start_index = i * self.subcircuit.ARITY
            end_index = (i + 1) * self.subcircuit.ARITY
            out += self.subcircuit.eval(
                field,
                inp[start_index:end_index],
            )
        return out

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

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

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

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

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

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

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

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

    @classmethod
    def wrap(cls,
             valid: Valid[Measurement, AggResult, F],
             proof: list[F]) -> Valid[Measurement, AggResult, F]:
        wrapped_gadgets: list[Gadget[F]] = []
        for (g, g_calls) in zip(valid.GADGETS, valid.GADGET_CALLS):
            p = next_power_of_2(1 + g_calls)
            gadget_poly_len = g.DEGREE * (p - 1) + 1
            (wire_seeds, proof) = front(g.ARITY, proof)
            (gadget_poly, proof) = front(gadget_poly_len, proof)
            wrapped = cls(valid.field,
                          wire_seeds,
                          gadget_poly,
                          g,
                          g_calls)
            wrapped_gadgets.append(wrapped)
        wrapped_valid = deepcopy(valid)
        wrapped_valid.GADGETS = wrapped_gadgets
        return wrapped_valid
]]></sourcecode>
      </section>
    </section>
    <section anchor="topo-states">
      <name>VDAF Preparation State</name>
      <t>This section lists the classes used to define each Aggregator's state during
VDAF preparation (<xref target="vdaf-prep-comm"/>).</t>
      <sourcecode type="python"><![CDATA[
class State:
    pass

class Start(State):
    pass

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

    def __eq__(self, other: object) -> bool:
        return isinstance(other, Continued) and \
            self.prep_state == other.prep_state and \
            self.prep_round == other.prep_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, preparation, aggregation,
and unsharding of a batch of several measurements. The test vector schema is
defined below.</t>
      <section anchor="schema">
        <name>Schema</name>
        <dl>
          <dt><tt>ctx</tt>:</dt>
          <dd>
            <t>The application context string encoded in hexadecimal.</t>
          </dd>
          <dt><tt>verify_key</tt>:</dt>
          <dd>
            <t>The verification key encoded in hexadecimal.</t>
          </dd>
          <dt><tt>agg_param</tt>:</dt>
          <dd>
            <t>The aggregation parameter encoded in hexadecimal.</t>
          </dd>
          <dt><tt>prep</tt>:</dt>
          <dd>
            <t>A list of objects with the following schema:
</t>
            <dl>
              <dt><tt>measurement</tt>:</dt>
              <dd>
                <t>The measurement of type <tt>Measurement</tt> defined by the VDAF.</t>
              </dd>
              <dt><tt>nonce</tt>:</dt>
              <dd>
                <t>The nonce encoded in hexadecimal.</t>
              </dd>
              <dt><tt>rand</tt>:</dt>
              <dd>
                <t>The sharding randomness encoded in hexadecimal.</t>
              </dd>
              <dt><tt>public_share</tt>:</dt>
              <dd>
                <t>The expected public share encoded in hexadecimal.</t>
              </dd>
              <dt><tt>input_shares</tt>:</dt>
              <dd>
                <t>The expected list of input shares, each encoded in hexadecimal.</t>
              </dd>
              <dt><tt>prep_shares</tt>:</dt>
              <dd>
                <t>The expected list of prep shares generated by each Aggregator at each
round of preparation, encoded in hexadecimal.</t>
              </dd>
              <dt><tt>prep_messages</tt>:</dt>
              <dd>
                <t>The expected list of prep messages for each round of preparation, encoded
in hexadecimal.</t>
              </dd>
              <dt><tt>out_shares</tt>:</dt>
              <dd>
                <t>The expected list of output shares, encoded in hexadecimal.</t>
              </dd>
            </dl>
          </dd>
          <dt><tt>agg_shares</tt>:</dt>
          <dd>
            <t>The expected aggregate shares encoded in hexadecimal.</t>
          </dd>
          <dt><tt>agg_result</tt>:</dt>
          <dd>
            <t>The expected aggregate result of type <tt>AggResult</tt> defined by the VDAF.</t>
          </dd>
          <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 prepare state
values are computed before they are consumed. Prepare 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", "prep_init",
"prep_shares_to_prep", "prep_next", "aggregate", or "unshard".</t>
          </dd>
          <dt><tt>round</tt>:</dt>
          <dd>
            <t>For any preparation operation, the round number of the operation to be
performed. This determines which prepare share, prepare state, and/or prepare
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 prepare 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>prep</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 preparation of this report.</t>
          </dd>
        </dl>
        <t>The test vector schema also includes whatever parameters are required to
instantiate the VDAF. These are listed in the subsections below.</t>
        <section anchor="prio3count-1">
          <name>Prio3Count</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3sum-1">
          <name>Prio3Sum</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>max_measurement</tt>:</dt>
            <dd>
              <t>The largest valid measurement, an integer. Each measurement is in the range
  <tt>[0, max_measurement]</tt>.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3sumvec-1">
          <name>Prio3SumVec</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>length</tt>:</dt>
            <dd>
              <t>The length of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>a parameter of the ParallelSum gadget, an integer.</t>
            </dd>
            <dt><tt>bits</tt>:</dt>
            <dd>
              <t>the bit length of each element of the vector, an integer. Each element is in
the range <tt>[0, 2^bits)</tt>.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3histogram-1">
          <name>Prio3Histogram</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>length</tt>:</dt>
            <dd>
              <t>The length of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>a parameter of the ParallelSum gadget, an integer.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3multihotcountvec-1">
          <name>Prio3MultihotCountVec</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>length</tt>:</dt>
            <dd>
              <t>The length of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>a parameter of the ParallelSum gadget, an integer.</t>
            </dd>
            <dt><tt>max_weight</tt>:</dt>
            <dd>
              <t>The largest vector weight, an integer. The sum of the elements of the
measurement must be in the range <tt>[0, max_weight]</tt>.</t>
            </dd>
          </dl>
        </section>
        <section anchor="poplar1-test-vec-param">
          <name>Poplar1</name>
          <dl>
            <dt><tt>bits</tt>:</dt>
            <dd>
              <t>The length of each input in bits, an integer.</t>
            </dd>
          </dl>
        </section>
      </section>
    </section>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The impetus of this work is the success of recent deployments of predecessors
of Prio3. These include the Mozilla Origin Telemetry project
<xref target="OriginTelemetry"/> and the Exposure Notification Private Analytics system
<xref target="ENPA"/> developed jointly by ISRG, Google, Apple, and others. Together these
systems have aggregated data from hundreds of millions of users.</t>
      <t>As the name implies, Prio3 is a descendant of the original Prio construction
<xref target="CGB17"/>. A second iteration was deployed in the <xref target="ENPA"/> system, and like the
VDAF described here, the ENPA system was built from techniques introduced in
<xref target="BBCGGI19"/> that significantly improve communication cost. That system was
specialized for a particular aggregation function; the goal of Prio3 is to
provide the same level of generality as the original construction.</t>
      <t>The security considerations in <xref target="security"/> are based largely on the security
analysis of <xref target="DPRS23"/>. Thanks to Hannah Davis and Mike Rosulek, who lent their
time to developing definitions and security proofs.</t>
      <t>Thanks to Junye Chen, Henry Corrigan-Gibbs, Armando Faz-Hernández, Simon
Friedberger, Tim Geoghegan, Albert Liu, Brandon Pitman, Mariana Raykova,
Michael Rosenberg, Jacob Rothstein, Shan Wang, Xiao Wang, Bas Westerbaan, and
Christopher Wood for useful feedback on and contributions to the spec.</t>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA+y923bbVpYo+o6vWK2M3aFikpbkSxy5nG5FlhxVYlvHUpyq
9naJIAmSKJMACwAlMbb7Q/ZTf0ufHzvzui4AKMuuVPfuMY5GRiyRwLrMNde8
X3q9XlSl1TzZN1uvkyKdpPFwnpinaVkV6XBVJWNzMJ0WyTSu0jwzx6tshL+U
W1E8HBbJJb729OB4KxrnoyxewDDjIp5UvbSoJr3RpJj2LsfxpLf7IBrFVTLN
i/W+SbNJHkXpstg3VbEqq72dne929qK4SOJ9c/Lq/DgqV8NFWpYwUbVeJvLh
VV68mxb5arlvDo9fPYveJWv4aAzfZlVSZEnVe4pTR1FZxdn4Ip7nGby6Tsqo
XMRFdfG3VV4l5b7J8miZ7ps3VT7qmjIvqiKZlPDbeoG/vI2ieFXN8mI/Mr3I
wA9v61U6msXF2PzcNz/EMFtJ3+XFNM7S3wg4sKy0HOX0ebKI0/m+KebDf02X
l/3yOhzsaXyZjs1hnr9rGeXkDDbnDTJOL5NimmTVOL5M/nWKH/ZH+SIc8XBW
wJHly1lSmNO4qvKsbX3zfDWezAHQ/vgjfHVJ79xJk2qyaYrTWTqfp8ulORvN
8uVyEWdtczzL8+k8GL+0j//rlL6koaMsLxbwzmWyH8HTB0dn+/SSIuPB+DLO
RoB+R9moWC8J+87wYPEQOvD49hY9bw+Lfnqy1ud5AZsyf+ybp4g2aVb7/mge
p1mCJ/kuKWrf/RH+X5pXffMiGc0u4yqetz5wnFdp7Yuf46sigUWbI0SSspzF
i/q8ffMqH8ajd+1DwnKLeG3+WPTlewOXBVD2j+4L85W5Xsz3isnI8A1M4V6V
ZgvH2TIx/PZHGqePDzOIxvDEvoFbtssQjgGbqn0zq6pluX/37tXVVT8D5OlP
88u7y9Vwno7oLMu7sZxBL7Fn0CvlDHoxXIEIr3JwjM/++PJ0bzc8ytMize8A
/hTpZTxaw79JmRSXaTa1pCXBo61gDemoNLAj80Oez5MYThzuXFLedNJnq2Id
m4PxOM7e1c/jJ4BOZp7FxTBpnH8KMJ9M6p+/iieAs+YlUL/8sny3rn19kFXp
NM9Sc5rP13Bv4Nd4nK8CKO/t0Z9AS0ZAvuDaAgTOktGqSKu1AdiZQwRlPi3i
5WxtAHyAZxUiaWk6Z4cvBK3rh5TG/VFxF0bfvfvg24cI6h9+OHz27GT3uxDW
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

-->

</rfc>
