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

<t>This document describes Verifiable Distributed Aggregation Functions (VDAFs), a
family of multi-party protocols for computing aggregate statistics over user
measurements. These protocols are designed to ensure that, as long as at least
one aggregation server executes the protocol honestly, individual measurements
are never seen by any server in the clear. At the same time, VDAFs allow the
servers to detect if a malicious or misconfigured client submitted an invalid
measurement. Two concrete VDAFs are specified, one for general-purpose
aggregation (Prio3) and another for heavy hitters (Poplar1).</t>
    </abstract>
    <note removeInRFC="true">
      <name>Discussion Venues</name>
      <t>Discussion of this document takes place on the
    Crypto Forum Research Group mailing list (cfrg@ietf.org),
    which is archived at <eref target="https://mailarchive.ietf.org/arch/search/?email_list=cfrg"/>.</t>
      <t>Source for this draft and an issue tracker can be found at
    <eref target="https://github.com/cfrg/draft-irtf-cfrg-vdaf"/>.</t>
    </note>
  </front>
  <middle>
    <?line 269?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>(RFC EDITOR: remove this paragraph.) The source for this draft and the
reference implementation can be found at
https://github.com/cfrg/draft-irtf-cfrg-vdaf.</t>
      <t>The ubiquity of the Internet makes it an ideal platform for measurement of
large-scale phenomena, whether public health trends or the behavior of computer
systems at scale. There is substantial overlap, however, between information
that is valuable to measure and information that users consider private.</t>
      <t>For example, consider an application that provides health information to users.
The operator of an application might want to know which parts of their
application are used most often, as a way to guide future development of the
application. Specific users' patterns of usage, though, could reveal sensitive
things about them, such as which users are researching a given health
condition.</t>
      <t>In many situations, the measurement collector is only interested in aggregate
statistics, e.g., which portions of an application are most used or what
fraction of people have experienced a given disease. Thus systems that provide
aggregate statistics while protecting individual measurements can deliver the
value of the measurements while protecting users' privacy.</t>
      <t>This problem is often formulated in terms of differential privacy (DP)
<xref target="Dwo06"/>. Roughly speaking, a data aggregation system that is differentially
private ensures that the degree to which any individual measurement influences
the value of the aggregate result can be precisely controlled. For example, in
systems like RAPPOR <xref target="EPK14"/>, each user samples noise from a well-known
distribution and adds it to their measurement before submitting to the
aggregation server. The aggregation server then adds up the noisy measurements,
and because it knows the distribution from which the noise was sampled, it can
estimate the true sum with reasonable accuracy.</t>
      <t>Even when noise is added to the measurements, collecting them in the clear
still reveals a significant amount of information to the collector. On the one
hand, depending on the "amount" of noise a client adds to its measurement, it
may be possible for a curious collector to make a reasonable guess of the
measurement's true value. On the other hand, the more noise the clients add,
the less reliable will be the server's estimate of the aggregate. Thus systems
relying solely on a DP mechanism must strike a delicate balance between privacy
and utility.</t>
      <t>Another way of constructing a privacy-preserving measurement system is to use
multi-party computation (MPC). The goal of such a system is that no participant
in the protocol should learn anything about an individual measurement beyond
what it can deduce from the aggregate. MPC achieves this goal by distributing
the computation of the aggregate across multiple aggregation servers, one of
which is presumed to be honest, i.e., not under control of the attacker.
Moreover, MPC can be composed with various DP mechanisms to ensure the
aggregate itself does not leak too much information about any one of the
measurements <xref target="MPRV09"/>.</t>
      <t>This document describes two classes of MPC protocols, each aiming for a
different set of goals.</t>
      <t>In a Distributed Aggregation Function (DAF, <xref target="daf"/>), each client splits its
measurement into multiple secret shares, one for each aggregation
server. DAFs require two properties of the secret sharing scheme. First, we can
reconstruct the underlying measurement by simply adding up all of the shares.
(Typically the shares are vectors over some finite field.) Second, given all
but one of the shares, it is impossible to learn anything about the underlying
measurement. These properties give rise to a simple strategy for privately
aggregating the measurements: each aggregation server adds up its measurement
shares locally before revealing their sum to the data collector; then all
the data collector has to do is add up these sums to get the aggregate result.</t>
      <t>This strategy is compatible with any aggregation function that can be
represented as the sum of some encoding of the measurements. Examples include:
summary statistics such as sum, mean, and standard deviation; estimation of
quantiles, e.g., median; histograms; linear regression; or counting data
structures, e.g., Bloom filters. However, not all functions fit into this
rubric, as it is constrained to linear computations over the encoded
measurements.</t>
      <t>In fact, our framework admits DAFs with slightly more
functionality, computing aggregation functions of the form</t>
      <artwork><![CDATA[
F(agg_param, meas_1, ..., meas_M) =
    G(agg_param, meas_1) + ... + G(agg_param, meas_M)
]]></artwork>
      <t>where <tt>meas_1, ..., meas_M</tt> are the measurements, <tt>G</tt> is a possibly
non-linear function, and <tt>agg_param</tt> is a parameter of that function chosen by
the data collector. This paradigm, known as function secret sharing <xref target="BGI15"/>,
allows for more sophisticated data analysis tasks, such as grouping metrics by
private client attributes <xref target="MPDST25"/> or computing heavy hitters <xref target="BBCGGI21"/>.
(More on the latter task below.)</t>
      <t>The second class of protocols defined in this document are called Verifiable
Distributed Aggregation Functions (VDAFs, <xref target="vdaf"/>). In addition to being
private, VDAFs are verifiable in the following sense. By design, a secret
sharing of a valid measurement, e.g., a number between 1 and 10, is
indistinguishable from a secret sharing of an invalid measurement, e.g., a
number larger than 10. This means that DAFs are vulnerable to attacks from
malicious clients attempting to disrupt the computation by submitting invalid
measurements. VDAFs are designed to allow the servers to detect and remove
these measurements prior to aggregation. We refer to this property as
robustness.</t>
      <t>Achieving robustness without sacrificing privacy requires the servers to
interact with one another over a number of rounds of communication. DAFs on the
other hand are non-interactive, making them easier to deploy; but they do not
provide robustness on their own. This may be tolerable in some applications.
For instance, if the client's software is executed in a trusted execution
environment, it may be reasonable to assume that no client is malicious.</t>
      <t>The DAF and VDAF abstractions encompass a variety of MPC techniques in the
literature. These protocols vary in their operational and security
requirements, sometimes in subtle but consequential ways. This document
therefore has two important goals:</t>
      <ol spacing="normal" type="1"><li>
          <t>Provide higher-level protocols, like <xref target="DAP"/>, with
a simple, uniform interface for accessing privacy-preserving measurement
schemes, document relevant operational and security requirements, and
specify constraints for safe usage:  </t>
          <ol spacing="normal" type="1"><li>
              <t>General patterns of communications among the various actors involved in
the system (clients, aggregation servers, and the collector of the
aggregate result);</t>
            </li>
            <li>
              <t>Capabilities of a malicious coalition of parties attempting to divulge
information about client measurements; and</t>
            </li>
            <li>
              <t>Conditions that are necessary to ensure that malicious clients cannot
corrupt the computation.</t>
            </li>
          </ol>
        </li>
        <li>
          <t>Provide cryptographers with design criteria that provide a clear deployment
roadmap for new constructions of privacy-preserving measurement systems.</t>
        </li>
      </ol>
      <t>This document also specifies two concrete VDAF schemes, each based on a protocol
from the literature.</t>
      <ul spacing="normal">
        <li>
          <t>The Prio system <xref target="CGB17"/> allows for the privacy-preserving computation of a
variety of aggregate statistics, combining additive secret sharing as described
above with a mechanism for checking the validity of each measurement. In
<xref target="prio3"/> we specify Prio3, a VDAF that follows the same overall framework as
the original Prio protocol, but incorporates techniques introduced in
<xref target="BBCGGI19"/> that result in significant performance gains.</t>
        </li>
        <li>
          <t>The Poplar protocol <xref target="BBCGGI21"/> solves a problem known as private
heavy-hitters. In this problem, each client holds a bit-string, and the goal
of the aggregation servers is to compute the set of strings that occur at
least <tt>T</tt> times for some threshold <tt>T</tt>. The core primitive in their protocol
is a secret sharing of a point function <xref target="GI14"/> (denoted <tt>G</tt> above) that
allows the servers to privately count how many of the clients' strings begin
with a given prefix (<tt>agg_param</tt> in the notation above). In <xref target="poplar1"/> we
specify a VDAF called Poplar1 that implements this functionality.</t>
        </li>
      </ul>
      <t>The remainder of this document is organized as follows: <xref target="conventions"/> lists
definitions and conventions used in the remainder of the document; <xref target="overview"/>
gives a brief overview of DAFs and VDAFs, the parties involved in the
computation, and the requirements for non-collusion; <xref target="daf"/> defines the syntax
for DAFs; <xref target="vdaf"/> defines the syntax for VDAFs; <xref target="prelim"/> defines various
functionalities that are common to our constructions; <xref target="prio3"/> specifies
Prio3; <xref target="poplar1"/> specifies Poplar1; and <xref target="security"/> enumerates security
considerations for DAFs and VDAFs in general and our constructions in
particular.</t>
      <section anchor="change-log">
        <name>Change Log</name>
        <t>(RFC EDITOR: remove this section.)</t>
        <t>(*) Indicates a change that breaks wire compatibility with the previous draft.</t>
        <t>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>Exponentiation is denoted by <tt>x ** y</tt> in Python. We also sometimes use more
conventional notation for exponentiation, namely <tt>x^y</tt>.</t>
      <t>Division of <tt>x</tt> by <tt>y</tt> is denoted by <tt>x / y</tt>. Python includes a similar
operator, <tt>x // y</tt>, which is short for <tt>floor(x / y)</tt>.</t>
      <t>Type hints are used to define input and output types:</t>
      <ul spacing="normal">
        <li>
          <t>The type variable <tt>F</tt> is used in signatures to signify any type that is a
subclass of <tt>Field</tt> (<xref target="field"/>).</t>
        </li>
        <li>
          <t><tt>bytes</tt> is a byte string.</t>
        </li>
        <li>
          <t><tt>int</tt> is an integer.</t>
        </li>
        <li>
          <t><tt>Generic</tt> is used in class definitions to explicitly declare type variables
of generic classes.</t>
        </li>
        <li>
          <t><tt>Any</tt> is the universal supertype, which admits values of any type.</t>
        </li>
        <li>
          <t><tt>Optional[T]</tt> is shorthand for <tt>T | None</tt>. Its value may be <tt>None</tt> or have
type <tt>T</tt>.</t>
        </li>
        <li>
          <t><tt>Self</tt> represents the containing class of the method definition in which it
appears.</t>
        </li>
        <li>
          <t><tt>Sequence[T]</tt> is either a list or tuple of values of type <tt>T</tt>.</t>
        </li>
      </ul>
      <t>This document defines several byte-string constants. When comprised of printable
ASCII characters, they are written as Python 3 byte-string literals (e.g.,
<tt>b'some constant string'</tt>).</t>
      <t>A global constant <tt>VERSION</tt> of type <tt>int</tt> is defined, which algorithms are free
to use as desired. Its value <bcp14>SHALL</bcp14> be <tt>12</tt>.</t>
      <t>This document describes algorithms for multi-party computations in which the
parties typically communicate over a network. Wherever a quantity is defined
that must be transmitted from one party to another, this document prescribes
a particular encoding of that quantity as a byte string.</t>
      <t>Some common functionalities:</t>
      <ul spacing="normal">
        <li>
          <t><tt>additive_secret_share(x: list[F], num_shares: int, field: type[F]) -&gt;
list[list[F]]</tt> takes a vector <tt>x</tt> of field elements and returns <tt>num_shares</tt>
vectors of length <tt>len(x)</tt> such that they all add up to the input vector.
Note that this function is not used normatively in this document.</t>
        </li>
        <li>
          <t><tt>byte(x: int) -&gt; bytes</tt> returns the representation of the integer <tt>x</tt> in the
range <tt>[0, 256)</tt> as a single-byte byte string.</t>
        </li>
        <li>
          <t><tt>cast(typ: type[T], x: object) -&gt; T</tt> returns the input value unchanged.
This is only present to assist with static analysis of the Python code.
Type checkers will ignore the inferred type of the input value, and assume
the output value has the given type.</t>
        </li>
        <li>
          <t><tt>concat(parts: list[bytes]) -&gt; bytes</tt> returns the concatenation of the input
byte strings, i.e., <tt>parts[0] + ... + parts[len(parts)-1]</tt>.</t>
        </li>
        <li>
          <t><tt>from_be_bytes(encoded: bytes) -&gt; int</tt> decodes a big-endian byte string,
i.e., returns the integer <tt>x</tt> for which <tt>to_be_bytes(x, len(encoded)) ==
encoded</tt>.</t>
        </li>
        <li>
          <t><tt>from_le_bytes(encoded: bytes) -&gt; int</tt> decodes a little-endian byte string,
i.e., returns the integer <tt>x</tt> for which <tt>to_le_bytes(x, len(encoded)) ==
encoded</tt>.</t>
        </li>
        <li>
          <t><tt>front(len: int, x: list[Any]) -&gt; tuple[list[Any], list[Any]]</tt> splits <tt>x</tt>
into two vectors, where the first vector is made up of the first <tt>len</tt>
elements of <tt>x</tt> and the second is made up of the remaining elements. This
function is equivalent to <tt>(x[:len], x[len:])</tt>.</t>
        </li>
        <li>
          <t><tt>gen_rand(len: int) -&gt; bytes</tt> returns a byte array of the requested length
(<tt>len</tt>) generated by a cryptographically secure pseudorandom number generator
(CSPRNG).</t>
        </li>
        <li>
          <t><tt>next_power_of_2(x: int) -&gt; int</tt> returns the smallest integer
greater than or equal to <tt>x</tt> that is also a power of two.</t>
        </li>
        <li>
          <t><tt>range(stop: int)</tt> or <tt>range(start: int, stop: int[, step: int])</tt> is the range
function from the Python standard library. The one-argument form returns the
integers from zero (inclusive) to <tt>stop</tt> (exclusive). The two- and
three-argument forms allow overriding the start of the range and overriding
the step between successive output values.</t>
        </li>
        <li>
          <t><tt>to_be_bytes(x: int, len: int) -&gt; bytes</tt> converts an integer <tt>x</tt> whose value
is in the range <tt>[0, 2^(8*len))</tt> to a big-endian byte string of length <tt>len</tt>.</t>
        </li>
        <li>
          <t><tt>to_le_bytes(x: int, len: int) -&gt; bytes</tt> converts an integer <tt>x</tt> whose value
is in the range <tt>[0, 2^(8*len))</tt> to a little-endian byte string of length
<tt>len</tt>.</t>
        </li>
        <li>
          <t><tt>poly_eval(field: type[F], p: list[F], x: F) -&gt; F</tt> returns the result of
evaluating the polynomial, <tt>p(x)</tt>. The coefficients of polynomials are stored
in lists in ascending order of degree, starting with the constant
coefficient. The <tt>field</tt> parameter is the class object for <tt>F</tt> and is used by
the implementation to construct field elements. (See <xref target="field"/>.)</t>
        </li>
        <li>
          <t><tt>poly_interp(field: type[F], inputs: list[F], outputs: list[F]) -&gt; list[F]</tt>
returns the coefficients of the lowest degree polynomial <tt>p</tt> for which
<tt>p(inputs[k]) == outputs[k]</tt> for all <tt>k</tt>. Normally this will be computed
using the Number Theoretic Transform (NTT) <xref target="SML24"/>.</t>
        </li>
        <li>
          <t><tt>poly_mul(field: type[F], p: list[F], q: list[F]) -&gt; list[F]</tt> returns
the product of two polynomials.</t>
        </li>
        <li>
          <t><tt>poly_strip(field: type[F], p: list[F]) -&gt; list[F]</tt> strips the zeros from the
end of the input polynomial's list of coefficients. That is, it returns
<tt>p[:i]</tt> where <tt>i</tt> is the index of the highest-degree non-zero coefficient of
<tt>p</tt>.</t>
        </li>
        <li>
          <t><tt>xor(left: bytes, right: bytes) -&gt; bytes</tt> returns the bitwise XOR of <tt>left</tt>
and <tt>right</tt>. An exception is raised if the inputs are not the same length.</t>
        </li>
        <li>
          <t><tt>zeros(len: int) -&gt; bytes</tt> returns an array of bytes of the requested
length (<tt>len</tt>). Each element of the array is set to zero.</t>
        </li>
      </ul>
    </section>
    <section anchor="overview">
      <name>Overview</name>
      <figure anchor="overall-flow">
        <name>Overall data flow of a (V)DAF.</name>
        <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,
            list[F],  # OutShare
            AggShare,
            AggResult,
            PrepState,
            PrepShare,
            PrepMessage,
        ],
        verify_key: bytes,
        agg_param: AggParam,
        ctx: bytes,
        measurements: list[Measurement]) -> AggResult:
    """
    Pre-conditions:

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

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

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

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

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

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

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

struct {
  MessageType type;
  select (Message.type) {
    case initialize:
      opaque prep_share<0..2^32-1>;
    case continue:
      opaque prep_msg<0..2^32-1>;
      opaque prep_share<0..2^32-1>;
    case finish:
      opaque prep_msg<0..2^32-1>;
  };
} Message;
]]></sourcecode>
          <t>These messages trigger all transitions in the state machine in
<xref target="vdaf-prep-state-machine"/>, except for the Leader's initial transition. The
Leader's state is initialized using its local inputs with the following method
on class <tt>Vdaf</tt>:</t>
          <sourcecode type="python"><![CDATA[
def ping_pong_leader_init(
        self,
        vdaf_verify_key: bytes,
        ctx: bytes,
        agg_param: bytes,
        nonce: bytes,
        public_share: bytes,
        input_share: bytes) -> tuple[State, Optional[bytes]]:
    """Called by the Leader to initialize ping-ponging."""
    try:
        (prep_state, prep_share) = self.prep_init(
            vdaf_verify_key,
            ctx,
            0,
            self.decode_agg_param(agg_param),
            nonce,
            self.decode_public_share(public_share),
            self.decode_input_share(0, input_share),
        )
        encoded_prep_share = self.encode_prep_share(prep_share)
        return (
            Continued(prep_state, 0),
            encode(0, encoded_prep_share),  # initialize
        )
    except:
        return (Rejected(), None)
]]></sourcecode>
          <t>The output is the <tt>State</tt> to which the Leader has transitioned and an encoded
<tt>Message</tt>. If the Leader's state is <tt>Rejected</tt>, then processing halts.
Otherwise, if the state is <tt>Continued</tt>, then processing continues. The function
<tt>encode</tt>  is used to encode the outbound message, which has the message type of
<tt>initialize</tt> (identified by the number <tt>0</tt>).</t>
          <t>To continue processing the report, the Leader sends the outbound message to the
Helper. The Helper's initial transition is computed using the following
procedure:</t>
          <sourcecode type="python"><![CDATA[
def ping_pong_helper_init(
        self,
        vdaf_verify_key: bytes,
        ctx: bytes,
        agg_param: bytes,
        nonce: bytes,
        public_share: bytes,
        input_share: bytes,
        inbound: bytes) -> tuple[State, Optional[bytes]]:
    """
    Called by the Helper in response to the Leader's initial
    message.
    """
    try:
        (prep_state, prep_share) = self.prep_init(
            vdaf_verify_key,
            ctx,
            1,
            self.decode_agg_param(agg_param),
            nonce,
            self.decode_public_share(public_share),
            self.decode_input_share(1, input_share),
        )

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

        encoded_prep_share = inbound_items[0]
        prep_shares = [
            self.decode_prep_share(prep_state, encoded_prep_share),
            prep_share,
        ]
        return self.ping_pong_transition(
            ctx,
            self.decode_agg_param(agg_param),
            prep_shares,
            prep_state,
            0,
        )
    except:
        return (Rejected(), None)
]]></sourcecode>
          <t>The procedure <tt>decode()</tt> decodes the inbound message and returns the
MessageType variant (<tt>initialize</tt>, <tt>continue</tt>, or <tt>finish</tt>) and the fields of
the message. The procedure <tt>ping_pong_transition()</tt> takes in the prep shares,
combines them into the prep message, and computes the next prep state of the
caller:</t>
          <sourcecode type="python"><![CDATA[
def ping_pong_transition(
        self,
        ctx: bytes,
        agg_param: AggParam,
        prep_shares: list[PrepShare],
        prep_state: PrepState,
        prep_round: int) -> tuple[State, bytes]:
    prep_msg = self.prep_shares_to_prep(ctx,
                                        agg_param,
                                        prep_shares)
    encoded_prep_msg = self.encode_prep_msg(prep_msg)
    out = self.prep_next(ctx, prep_state, prep_msg)
    if prep_round+1 == self.ROUNDS:
        return (
            Finished(out),
            encode(2, encoded_prep_msg),  # finalize
        )
    (prep_state, prep_share) = cast(
        tuple[PrepState, PrepShare], out)
    encoded_prep_share = self.encode_prep_share(prep_share)
    return (
        Continued(prep_state, prep_round+1),
        encode(1, encoded_prep_msg, encoded_prep_share)  # continue
    )
]]></sourcecode>
          <t>The output is the <tt>State</tt> to which the Helper has transitioned and an encoded
<tt>Message</tt>. If the Helper's state is <tt>Finished</tt> or <tt>Rejected</tt>, then processing
halts. Otherwise, if the state is <tt>Continued</tt>, then processing continues.</t>
          <t>To continue processing, the Helper sends the outbound message to the Leader.
The Leader computes its next state transition using the following method on
class <tt>Vdaf</tt>:</t>
          <sourcecode type="python"><![CDATA[
def ping_pong_leader_continued(
    self,
    ctx: bytes,
    agg_param: bytes,
    state: State,
    inbound: bytes,
) -> tuple[State, Optional[bytes]]:
    """
    Called by the Leader to start the next step of ping-ponging.
    """
    return self.ping_pong_continued(
        True, ctx, agg_param, state, inbound)

def ping_pong_continued(
    self,
    is_leader: bool,
    ctx: bytes,
    agg_param: bytes,
    state: State,
    inbound: bytes,
) -> tuple[State, Optional[bytes]]:
    try:
        if not isinstance(state, Continued):
            return (Rejected(), None)
        prep_round = state.prep_round

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

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

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

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

    Pre-conditions:

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

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

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

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

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

    Pre-conditions:

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

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

    Pre-conditions:

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

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

    Pre-conditions:

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

    # Associated parameters
    SEED_SIZE = 32

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

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

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

    # Associated parameters
    SEED_SIZE = 16

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

        self.length_consumed = 0

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

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

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

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

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

    Pre-conditions:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    # Query the measurement and proof(s) share(s).
    query_rands = self.query_rands(verify_key, ctx, nonce)
    verifiers_share = []
    for _ in range(self.PROOFS):
        proof_share, proofs_share = front(
            self.flp.PROOF_LEN, proofs_share)
        query_rand, query_rands = front(
            self.flp.QUERY_RAND_LEN, query_rands)
        if self.flp.JOINT_RAND_LEN > 0:
            joint_rand, joint_rands = front(
                self.flp.JOINT_RAND_LEN, joint_rands)
        verifiers_share += self.flp.query(
            meas_share,
            proof_share,
            query_rand,
            joint_rand,
            self.SHARES,
        )

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

def verifier_len(self) -> int:
    """Length of the verifier message."""
    length = 1
    for g in self.GADGETS:
        length += g.ARITY + 1
    return length
]]></sourcecode>
        </section>
        <section anchor="flp-bbcggi19-construction-prove">
          <name>Generating the Proof</name>
          <figure>
            <name>Components of the proof generation algorithm.</name>
            <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 = [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="December" year="2024"/>
            <abstract>
              <t>   This document defines four eXtendable Output Functions (XOF), hash
   functions with output of arbitrary length, named TurboSHAKE128,
   TurboSHAKE256, KT128 and KT256.

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

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

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-kangarootwelve-16"/>
        </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 c0e76dc</refcontent>
        </reference>
        <reference anchor="DAP">
          <front>
            <title>Distributed Aggregation Protocol for Privacy Preserving Measurement</title>
            <author fullname="Tim Geoghegan" initials="T." surname="Geoghegan">
              <organization>ISRG</organization>
            </author>
            <author fullname="Christopher Patton" initials="C." surname="Patton">
              <organization>Cloudflare</organization>
            </author>
            <author fullname="Brandon Pitman" initials="B." surname="Pitman">
              <organization>ISRG</organization>
            </author>
            <author fullname="Eric Rescorla" initials="E." surname="Rescorla">
              <organization>Independent</organization>
            </author>
            <author fullname="Christopher A. Wood" initials="C. A." surname="Wood">
              <organization>Cloudflare</organization>
            </author>
            <date day="2" month="November" year="2024"/>
            <abstract>
              <t>   There are many situations in which it is desirable to take
   measurements of data which people consider sensitive.  In these
   cases, the entity taking the measurement is usually not interested in
   people's individual responses but rather in aggregated data.
   Conventional methods require collecting individual responses and then
   aggregating them, thus representing a threat to user privacy and
   rendering many such measurements difficult and impractical.  This
   document describes a multi-party distributed aggregation protocol
   (DAP) for privacy preserving measurement (PPM) which can be used to
   collect aggregate data without revealing any individual user's data.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

class Start(State):
    pass

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

    def __eq__(self, other: object) -> bool:
        return isinstance(other, Continued) and \
            self.prep_state == other.prep_state and \
            self.prep_round == other.prep_round

class Finished(State, Generic[OutShare]):
    def __init__(self, out_share: OutShare):
        self.out_share = out_share

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

class Rejected(State):
    pass
]]></sourcecode>
    </section>
    <section anchor="test-vectors">
      <name>Test Vectors</name>
      <t>Test vectors for Prio3 (<xref target="prio3"/>) and Poplar1 (<xref target="poplar1"/>) are available at
<xref target="TestVectors"/>. The test vector directory, <tt>test_vec/vdaf</tt>, contains a set of
JSON files. Each file contains a test vector for an instance of class <tt>Vdaf</tt> as
defined in <xref target="vdaf"/>. A test vector covers sharding, preparation, aggregation,
and unsharding of a batch of several measurements. The test vector schema is
defined below.</t>
      <section anchor="schema">
        <name>Schema</name>
        <dl>
          <dt><tt>ctx</tt>:</dt>
          <dd>
            <t>The application context string encoded in hexadecimal.</t>
          </dd>
          <dt><tt>verify_key</tt>:</dt>
          <dd>
            <t>The verification key encoded in hexadecimal.</t>
          </dd>
          <dt><tt>agg_param</tt>:</dt>
          <dd>
            <t>The aggregation parameter encoded in hexadecimal.</t>
          </dd>
          <dt><tt>prep</tt>:</dt>
          <dd>
            <t>A list of objects with the following schema:
</t>
            <dl>
              <dt><tt>measurement</tt>:</dt>
              <dd>
                <t>The measurement of type <tt>Measurement</tt> defined by the VDAF.</t>
              </dd>
              <dt><tt>nonce</tt>:</dt>
              <dd>
                <t>The nonce encoded in hexadecimal.</t>
              </dd>
              <dt><tt>rand</tt>:</dt>
              <dd>
                <t>The sharding randomness encoded in hexadecimal.</t>
              </dd>
              <dt><tt>public_share</tt>:</dt>
              <dd>
                <t>The expected public share encoded in hexadecimal.</t>
              </dd>
              <dt><tt>input_shares</tt>:</dt>
              <dd>
                <t>The expected list of input shares, each encoded in hexadecimal.</t>
              </dd>
              <dt><tt>prep_shares</tt>:</dt>
              <dd>
                <t>The expected list of prep shares generated by each Aggregator at each
round of preparation, encoded in hexadecimal.</t>
              </dd>
              <dt><tt>prep_messages</tt>:</dt>
              <dd>
                <t>The expected list of prep messages for each round of preparation, encoded
in hexadecimal.</t>
              </dd>
              <dt><tt>out_shares</tt>:</dt>
              <dd>
                <t>The expected list of output shares, encoded in hexadecimal.</t>
              </dd>
            </dl>
          </dd>
          <dt><tt>agg_shares</tt>:</dt>
          <dd>
            <t>The expected aggregate shares encoded in hexadecimal.</t>
          </dd>
          <dt><tt>agg_result</tt>:</dt>
          <dd>
            <t>The expected aggregate result of type <tt>AggResult</tt> defined by the VDAF.</t>
          </dd>
        </dl>
        <t>The schema also includes whatever parameters are required to instantiate the
VDAF. These are listed in the subsections below.</t>
        <section anchor="prio3count-1">
          <name>Prio3Count</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3sum-1">
          <name>Prio3Sum</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>max_measurement</tt>:</dt>
            <dd>
              <t>The largest valid measurement, an integer. Each measurement is in the range
  <tt>[0, max_measurement]</tt>.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3sumvec-1">
          <name>Prio3SumVec</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>length</tt>:</dt>
            <dd>
              <t>The length of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>a parameter of the ParallelSum gadget, an integer.</t>
            </dd>
            <dt><tt>bits</tt>:</dt>
            <dd>
              <t>the bit length of each element of the vector, an integer. Each element is in
the range <tt>[0, 2^bits)</tt>.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3histogram-1">
          <name>Prio3Histogram</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>length</tt>:</dt>
            <dd>
              <t>The length of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>a parameter of the ParallelSum gadget, an integer.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3multihotcountvec-1">
          <name>Prio3MultihotCountVec</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>length</tt>:</dt>
            <dd>
              <t>The length of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>a parameter of the ParallelSum gadget, an integer.</t>
            </dd>
            <dt><tt>max_weight</tt>:</dt>
            <dd>
              <t>The largest vector weight, an integer. The sum of the elements of the
measurement must be in the range <tt>[0, max_weight]</tt>.</t>
            </dd>
          </dl>
        </section>
        <section anchor="poplar1-test-vec-param">
          <name>Poplar1</name>
          <dl>
            <dt><tt>bits</tt>:</dt>
            <dd>
              <t>The length of each input in bits, an integer.</t>
            </dd>
          </dl>
        </section>
      </section>
    </section>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The impetus of this work is the success of recent deployments of predecessors
of Prio3. These include the Mozilla Origin Telemetry project
<xref target="OriginTelemetry"/> and the Exposure Notification Private Analytics system
<xref target="ENPA"/> developed jointly by ISRG, Google, Apple, and others. Together these
systems have aggregated data from hundreds of millions of users.</t>
      <t>As the name implies, Prio3 is a descendant of the original Prio construction
<xref target="CGB17"/>. A second iteration was deployed in the <xref target="ENPA"/> system, and like the
VDAF described here, the ENPA system was built from techniques introduced in
<xref target="BBCGGI19"/> that significantly improve communication cost. That system was
specialized for a particular aggregation function; the goal of Prio3 is to
provide the same level of generality as the original construction.</t>
      <t>The security considerations in <xref target="security"/> are based largely on the security
analysis of <xref target="DPRS23"/>. Thanks to Hannah Davis and Mike Rosulek, who lent their
time to developing definitions and security proofs.</t>
      <t>Thanks to Junye Chen, Henry Corrigan-Gibbs, Armando Faz-Hernández, Simon
Friedberger, Tim Geoghegan, Albert Liu, Brandon Pitman, Mariana Raykova,
Michael Rosenberg, Jacob Rothstein, Shan Wang, Xiao Wang, Bas Westerbaan, and
Christopher Wood for useful feedback on and contributions to the spec.</t>
    </section>
  </back>
  <!-- ##markdown-source:
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
eQrU+zheJHmofWw3ax/DDFThre9Qr4BhesPRvBsvFqwk3sd/WW1EnrwPO0eU
v89v3EcQxsOyW+Yx3rX7wI/u41LOaCVntBJlUsCkH1ZvkKM3x1k6Lx2lIbgD
6U1zs+ut4yaUuTuTbsCEzzDpz1+c77590n3Qffxwu/vo0fb2ZvfR2YNHtPuT
f9/eDLf/YhnnMUwMu3+9LAHdgL1N0d6AzJNU0jxJgHiYH4DJFqV5Gf81I7x7
ebx3EyDepovl1LzIVjXl+dd0jHpdNp9Uftg7T+a/nafm388r+tTm3YSz28IH
hJfuo8dPnmx2t862ifO++PGXX36tQug5SmS5gblRiEtMoTcP1YLzeDruTkgB
n4CWOSWqB9AqgWHPltMy7QLdLVGHhvfKEn6+0Wqxd74EdXWZ1Vg6UGFgJebH
uPyt8tuf0zgzv8SN0PwQp+aXpPbTr0v43z8fxE8ExDUIH4yBwKQwK0uGCN/E
vEToLeK8XAUi4jjPZuYwvUpG3R+TlXk+zYYfzF6KjP3Gi/k7QvZ24PsCJStB
gJZOACeFdfNbkppeHu+fnG5XFIyXMcrHVsKGs0bVFa4yaald0VIJqiA3MpXr
Po8LeOJlAp8/I1qns7REI9rLDDZR1bFukKhEAm8SxsSQmMNhfjAncf4hrrLO
V8kHgEuaFeZFAkDAf5wW2bIsslB+327Qbn4Xuat+CtsP729vb/EpvHm7WTG4
eNgJFP72Ahlv92i6ikH6zLN5dlH56fXsA1BmAO58lFTtUK9nAPY3CWwxm44q
v53EU1AU3sYjAEIo493RbHIXRrP54MGjxyDj0yV/+eaHzQqbPZqPHGRAkYFL
0TEpnkeR8kdYF4jfJdmq8mS0ZB7MQqUvBpgyI/Kak9BnMuD6IOrNEoDuCE/6
RnD/DMwNeBgQmCrevUmAEmT4n3nttz1S8grggVP4T5mkFbg28HAQGzLgoaDR
Bta+1une3i11J4Yt6k/boCE+QQqKsH0NCm06P01wSWW+CqHMPxr7a0UA22xW
+pNBT3R9WgB8RqTf3oI7tvXtw82Hj+/ro+MUNplddeFC5sOkO8qGRW+W/QYa
Ukyvllk2/ZCWIJLByc4BEsX9UtcCX06nCZ3q/YzW2TsvZ1Pc08nLn7Yr+LJL
VH+KDPd5As/CoQD5TkeJHv+r5WwA3xGcyd50CghRoDEa1PDT0xvZ7C4oAXC1
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
iD5711ICA4CdSAcbmk1GvBePeE9GvLd5xHvY9N7dRwydSAcbmjWHQo7MjT9U
ckPy0Xj/oO9AyZm52et9dy+DUsik2lCOHv5Os7lsCZr0OojiNU0QvlswIncV
eY7ui3MHLSZMPc5pLHe8sg0dUe3Sa3CoeVOMXFPBy4ZAN8RGJNlOEKNPcaWQ
5Ju5QdsFzGAqXiQ95KaJ4LiTN4L8CuaYE7xt8Itp4Xo1WbZaxXgDR7B8wLSx
HUeIz1ca6TwA8g0jd7OQ9aiFs7DL//Qkt7eceOoGfFBHcg5HJTVt0/DSYhsm
txGkXAYP3CjlNvrcfw8JN4QmTRMkE5jZECw2K1iayz/Fs/UZ4gFqBQUtrKk5
ub0w7DMvI5D8pIg5CNle8mVILs7CN9IO+VWG67zbtcfYdk1AwAMVj7rUIkrC
DdPmI2EqbZx9vz2NTgcAp+CzfTWMXr75/9r71iU3riPN//UUNVTEGpCAFpvy
eHbbw4hp8+4RRW43bXmGSzeqgUJ3iQAKRgHdhCg9zDzLvtjml5dz8lQVWtTY
Ye1EDMMRVqOqzjVP3k7ml3c1HWIirPiyIFjYrfwBdMW7oBAixgRuvmUwenf/
6ZBv2kFA0XH8A4crAef015EW/Sj8l1PtxEieew6UREcleL6GK8C94Etq34ou
JQqS1nnAneumQJaLObbYDnf1T9nhEWBrYhMa+GQhT+LncVcUKGPo0hm5kD0Y
lWtiMMEPE81/9C4fegReNhkeuZNt5kCiySKWCEkhCvAYnu1jsn4SBGRZ6S2j
oC88A//EMIDyL9N9m3z/zm2sTKlfyu3XiuXjPWOWX9BqoQecRW/54cFkzCO+
zNYiHa2v21nnTdzqWPNKIg+4/xasxmdJsXJx6kRMc6G5OtyGXJfFzb71/XW1
3YpT3C7LpGTndcUFz1dbTnosZwI02/pYaBhZEw0XhFR64oQjWa5bU/27H0es
DamwqfRpjSTLLuWSWg04eFtL2v7Ho+N3R8PcYiJISStHvgpnewg4O263isWm
LGZ72TU9ZwYEE75qtXFWjmV9sXZy3VMsardxi31sints/NmWRm5pxcr5bnHU
IsiGbz7KBVQYAQquGvHatamwxncfEExAJ9fiaWQ4iqk/GSh4OZ3CYRv9jEvK
DJ0DOpAdIyWxow+SWyBNh5N0TVzLo3wfzeHwQUdn6uJR4x830PnVKwCt89zT
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

-->

</rfc>
