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

<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
measurement that would result in an invalid aggregate result.</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/cjpatton/vdaf"/>.</t>
    </note>
  </front>
  <middle>
    <?line 261?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>(RFC EDITOR: remove this paragraph.) The source for this draft and 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>The ideal goal for a privacy-preserving measurement system is that of secure
multi-party computation (MPC): 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 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.</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_N) =
    g(agg_param, meas_1) + ... + g(agg_param, meas_N)
]]></artwork>
      <t>where <tt>meas_1, ..., meas_N</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. Thus 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, and are therefore 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>Providing higher-level protocols like <xref target="DAP"/> (RFC
EDITOR: remove this reference if not published before the current document)
with a simple, uniform interface for accessing privacy-preserving measurement
schemes, documenting relevant operational and security requirements, and
specifying 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 servers 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>Providing cryptographers with design criteria that provide a clear
deployment roadmap for new constructions.</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 the heavy-hitters problem in a
privacy-preserving manner. Here 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"/> (<tt>g</tt> in the notation 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 for specification; <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"/> describes the Prio3 construction;
<xref target="poplar1"/> describes the Poplar1 construction; and <xref target="security"/> enumerates the
security considerations for DAFs and VDAFs.</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>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 end 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 mutliple 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 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 and Definitions</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 3. Type hints are used to
define input and output types. The type variable <tt>F</tt> is used in signatures to
signify any type that is a subclass of <tt>Field</tt>. 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>A variable with type <tt>bytes</tt> is a byte string. 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 be transmitted from one party to another, this document prescribes
a particular encoding of that quantity as a byte string.</t>
      <ul empty="true">
        <li>
          <t>OPEN ISSUE It might be better to not be prescriptive about how quantities are
encoded on the wire. See issue #58.</t>
        </li>
      </ul>
      <t>Some common functionalities:</t>
      <ul spacing="normal">
        <li>
          <t><tt>zeros(len: int) -&gt; bytes</tt> returns an array of zero bytes. The length of
<tt>output</tt> <bcp14>MUST</bcp14> be <tt>len</tt>.</t>
        </li>
        <li>
          <t><tt>gen_rand(len: int) -&gt; bytes</tt> returns an array of random bytes generated by a
cryptographically secure pseudorandom number generator (CSPRNG). The length
of <tt>output</tt> <bcp14>MUST</bcp14> be <tt>len</tt>.</t>
        </li>
        <li>
          <t><tt>byte(int: int) -&gt; bytes</tt> returns the representation of <tt>int</tt> as a byte
string. The value of <tt>int</tt> <bcp14>MUST</bcp14> be in <tt>[0,256)</tt>.</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>front(length: int, vec: list[Any]) -&gt; (list[Any], list[Any])</tt> splits <tt>vec</tt>
into two vectors, where the first vector is made up of the first <tt>length</tt>
elements of the input. I.e., <tt>(vec[:length], vec[length:])</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>to_be_bytes(val: int, length: int) -&gt; bytes</tt> converts <tt>val</tt> to big-endian
bytes; its value <bcp14>MUST</bcp14> be at least <tt>0</tt> but less than <tt>2**(8*length)</tt>. Function
<tt>from_be_bytes(encoded: bytes) -&gt; int</tt> computes the inverse.</t>
        </li>
        <li>
          <t><tt>to_le_bytes(val: int, length: int) -&gt; bytes</tt> converts <tt>val</tt> to little-endian
bytes; its value <bcp14>MUST</bcp14> be at least <tt>0</tt> but less than <tt>2**(8*length)</tt>. Function
<tt>from_le_bytes(encoded: bytes) -&gt; int</tt> computes the inverse.</t>
        </li>
        <li>
          <t><tt>next_power_of_2(n: int) -&gt; int</tt> returns the smallest integer
greater than or equal to <tt>n</tt> that is also a power of two.</t>
        </li>
        <li>
          <t><tt>additive_secret_share(vec: list[Field], num_shares: int, field: type)
-&gt; list[list[Field]]</tt> takes a vector of field elements and returns multiple
vectors of the same length, such that they all add up to the input vector,
and each proper subset of the vectors are indistinguishable from random.</t>
        </li>
        <li>
          <t><tt>cast(typ: type, val: object) -&gt; object</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>range(stop)</tt> or <tt>range(start, stop[, step])</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>
      </ul>
    </section>
    <section anchor="overview">
      <name>Overview</name>
      <figure anchor="overall-flow">
        <name>Overall data flow of a (V)DAF</name>
        <artwork><![CDATA[
                 +--------------+
           +---->| Aggregator 0 |----+
           |     +--------------+    |
           |             ^           |
           |             |           |
           |             V           |
           |     +--------------+    |
           | +-->| Aggregator 1 |--+ |
           | |   +--------------+  | |
+--------+-+ |           ^         | +->+-----------+
| Client |---+           |         +--->| Collector |--> Aggregate
+--------+-+                         +->+-----------+
           |            ...          |
           |                         |
           |             |           |
           |             V           |
           |    +----------------+   |
           +--->| Aggregator N-1 |---+
                +----------------+

      Input shares           Aggregate shares
]]></artwork>
      </figure>
      <t>In a DAF- or VDAF-based private measurement system, we distinguish three types
of actors: Clients, Aggregators, and Collectors.  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>Each Aggregator combines the output shares in the batch to compute the
"aggregate share" for that batch, i.e., its share of the desired aggregate
result.</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
correctness of the measurements 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 disseminates 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 on the measurement set. For example, the aggregation parameter is used
to represent the candidate prefixes in Poplar1 <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.</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 an 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 an algorithm for the computation needed in each of
these stages. The interface of each algorithm 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 <tt>range(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 passed by the application.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>RAND_SIZE: int</tt></td>
            <td align="left">Size of the random byte string passed to 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 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>These types 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 method of encoding the
<tt>PublicShare</tt>, <tt>InputShare</tt>, and <tt>AggShare</tt>.</t>
      <t>Each DAF is identified by a unique, 32-bit integer <tt>ID</tt>. Identifiers for each
(V)DAF specified in this document are defined in <xref target="codepoints"/>.</t>
      <section anchor="sec-daf-shard">
        <name>Sharding</name>
        <t>In order to protect the privacy of its measurements, a DAF Client shards its
measurements into a sequence of input shares. The <tt>shard</tt> method is used for
this purpose.</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.shard(ctx: bytes, measurement: Measurement, nonce: bytes, rand: bytes)
-&gt; tuple[PublicShare, list[InputShare]]</tt> is the randomized sharding algorithm
run by each Client that consumes the application context, a measurement, and
a nonce and produces a "public share" distributed to each of the Aggregate
and a corresponding sequence of 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>NONCE_SIZE</tt> and <bcp14>MUST</bcp14> be generated using
a 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>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>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. This is intended 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>
        <figure anchor="shard-flow">
          <name>The Client divides its measurement into input shares and distributes them to the Aggregators. The public share is broadcast to all Aggregators.</name>
          <artwork><![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>
        </figure>
      </section>
      <section anchor="sec-daf-prepare">
        <name>Preparation</name>
        <t>Once an Aggregator has received the public share and one of the input shares,
the next step is to prepare the input share for aggregation. This is
accomplished using the following 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> is the
deterministic preparation algorithm. It takes as input the public share and
one of the input shares generated by a Client, the application context, the
Aggregator's unique identifier, the aggregation parameter selected by the
Collector, and a 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 <tt>range(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>NONCE_SIZE</tt>.</t>
              </li>
            </ul>
          </li>
        </ul>
      </section>
      <section anchor="sec-daf-validity-scopes">
        <name>Validity of Aggregation Parameters</name>
        <t>Concrete DAFs implementations <bcp14>MAY</bcp14> impose certain restrictions for input shares
and aggregation parameters. Protocols using a DAF <bcp14>MUST</bcp14> ensure that for each
input share and aggregation parameter <tt>agg_param</tt>, <tt>daf.prep</tt> is only called if
<tt>daf.is_valid(agg_param, previous_agg_params)</tt> returns True, where
<tt>previous_agg_params</tt> contains all aggregation parameters that have previously
been used with the same input share.</t>
        <t>DAFs <bcp14>MUST</bcp14> implement the following function:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.is_valid(agg_param: AggParam, previous_agg_params: list[AggParam]) -&gt;
bool</tt>: checks if the <tt>agg_param</tt> is compatible with all elements of
<tt>previous_agg_params</tt>.</t>
          </li>
        </ul>
      </section>
      <section anchor="sec-daf-aggregate">
        <name>Aggregation</name>
        <t>Once an Aggregator holds output shares for a batch of measurements (where
batches are defined by the application), it combines them into a share of the
desired aggregate result:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.aggregate(agg_param: AggParam, out_shares: list[OutShare]) -&gt; AggShare</tt>
is the deterministic aggregation algorithm. It is run by each Aggregator a
set of recovered output shares.</t>
          </li>
        </ul>
        <figure anchor="aggregate-flow">
          <name>Aggregation of output shares. `B` indicates the number of measurements in the batch.</name>
          <artwork><![CDATA[
    Aggregator 0    Aggregator 1        Aggregator SHARES-1
    ============    ============        ===================

    out_share_0_0   out_share_1_0       out_share_[SHARES-1]_0
    out_share_0_1   out_share_1_1       out_share_[SHARES-1]_1
    out_share_0_2   out_share_1_2       out_share_[SHARES-1]_2
         ...             ...                     ...
    out_share_0_B   out_share_1_B       out_share_[SHARES-1]_B
      |               |                   |
      V               V                   V
    +-----------+   +-----------+       +-----------+
    | aggregate |   | aggregate |   ... | aggregate |
    +-----------+   +-----------+       +-----------+
      |               |                   |
      V               V                   V
    agg_share_0     agg_share_1         agg_share_[SHARES-1]
]]></artwork>
        </figure>
        <t>For simplicity, we have written this algorithm in a "one-shot" form, where all
output shares for a batch are provided at the same time. Many DAFs may also
support a "streaming" form, where shares are processed one at a time.</t>
        <t>Implementation note: for most natural DAFs (and VDAFs) it is not necessary for
an Aggregator to store all output shares individually before aggregating.
Typically it is possible to merge output shares into aggregate shares as they
arrive, merge these into other aggregate shares, and so on. In particular, this
is the case when the output shares are vectors over some finite field and
aggregating them involves merely adding up the vectors element-wise. Such is the
case for Prio3 <xref target="prio3"/> and Poplar1 <xref target="poplar1"/>.</t>
      </section>
      <section anchor="sec-daf-unshard">
        <name>Unsharding</name>
        <t>After the Aggregators have aggregated a sufficient number of output shares, each
sends its aggregate share to the Collector, who runs the following algorithm to
recover the following output:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.unshard(agg_param: AggParam, agg_shares: list[AggShare],
num_measurements: int) -&gt; AggResult</tt> is run by the Collector in order to
compute the aggregate result from the Aggregators' shares. The length of
<tt>agg_shares</tt> <bcp14>MUST</bcp14> be <tt>SHARES</tt>. <tt>num_measurements</tt> is the number of
measurements that contributed to each of the aggregate shares. This algorithm
is deterministic.</t>
          </li>
        </ul>
        <figure anchor="unshard-flow">
          <name>Computation of the final aggregate result from aggregate shares.</name>
          <artwork><![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>
        </figure>
      </section>
      <section anchor="daf-execution">
        <name>Execution of a DAF</name>
        <t>Securely executing a DAF involves emulating the following procedure.</t>
        <figure anchor="run-daf">
          <name>Execution of a DAF.</name>
          <sourcecode type="python"><![CDATA[
def run_daf(
        daf: Daf[
            Measurement,
            AggParam,
            PublicShare,
            InputShare,
            OutShare,
            AggShare,
            AggResult,
        ],
        ctx: bytes,
        agg_param: AggParam,
        measurements: list[Measurement],
        nonces: list[bytes]) -> AggResult:
    """
    Run a DAF on a list of measurements.

    Pre-conditions:

        - `type(agg_param) == daf.AggParam`
        - `type(measurement) == daf.Measurement` for each
          `measurement` in `measurements`
        - `len(nonce) == daf.NONCE_SIZE` for each `nonce` in `nonces`
        - `len(nonces) == len(measurements)`
    """
    if any(len(nonce) != daf.NONCE_SIZE for nonce in nonces):
        raise ValueError("incorrect nonce size")
    if len(nonces) != len(measurements):
        raise ValueError(
            "measurements and nonces lists have different lengths"
        )

    out_shares: list[list[OutShare]]
    out_shares = [[] for j in range(daf.SHARES)]
    for (measurement, nonce) in zip(measurements, nonces):
        # Each Client shards its measurement into input shares and
        # distributes them among the Aggregators.
        rand = gen_rand(daf.RAND_SIZE)
        (public_share, input_shares) = \
            daf.shard(ctx, measurement, nonce, rand)

        # Each Aggregator prepares its input share for aggregation.
        for j in range(daf.SHARES):
            out_shares[j].append(
                daf.prep(ctx, j, agg_param, nonce,
                         public_share, input_shares[j]))

    # Each Aggregator aggregates its output shares into an aggregate
    # share and sends it to the Collector.
    agg_shares = []
    for j in range(daf.SHARES):
        agg_share_j = daf.aggregate(agg_param,
                                    out_shares[j])
        agg_shares.append(agg_share_j)

    # Collector unshards the aggregate result.
    num_measurements = len(measurements)
    agg_result = daf.unshard(agg_param, agg_shares,
                             num_measurements)
    return agg_result
]]></sourcecode>
        </figure>
        <t>The inputs to this procedure are the same as the aggregation function computed by
the DAF: an aggregation parameter and a sequence of measurements. 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>Like DAFs described in the previous section, a VDAF scheme is used to compute a
particular aggregation function over a set of Client-generated measurements.
Evaluation of a VDAF involves the same four stages as for DAFs: Sharding,
Preparation, Aggregation, and Unsharding. However, the Preparation stage will
require interaction among the Aggregators in order to facilitate verifiability
of the computation's correctness. Accommodating this interaction will require
syntactic changes.</t>
      <t>Overall execution of a VDAF comprises the following stages:</t>
      <ul spacing="normal">
        <li>
          <t>Sharding - Computing input shares from an individual measurement</t>
        </li>
        <li>
          <t>Preparation - Conversion and verification of input shares to output shares
compatible with the aggregation function being computed</t>
        </li>
        <li>
          <t>Aggregation - Combining a sequence of output shares into an aggregate share</t>
        </li>
        <li>
          <t>Unsharding - Combining a sequence of aggregate shares into an aggregate
result</t>
        </li>
      </ul>
      <t>In contrast to DAFs, the Preparation stage for VDAFs now performs an additional
task: verification of the validity of the recovered output shares. This process
ensures that aggregating the output shares will not lead to a garbled aggregate
result.</t>
      <t>The remainder of this section defines the VDAF interface. The attributes are
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</tt></td>
            <td align="left">Algorithm identifier for this VDAF.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>VERIFY_KEY_SIZE</tt></td>
            <td align="left">Size (in bytes) of the verification key (<xref target="sec-vdaf-prepare"/>).</td>
          </tr>
          <tr>
            <td align="left">
              <tt>RAND_SIZE</tt></td>
            <td align="left">Size of the random byte string passed to sharding algorithm.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>NONCE_SIZE</tt></td>
            <td align="left">Size (in bytes) of the nonce.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>ROUNDS</tt></td>
            <td align="left">Number of rounds of communication during the Preparation stage (<xref target="sec-vdaf-prepare"/>).</td>
          </tr>
          <tr>
            <td align="left">
              <tt>SHARES</tt></td>
            <td align="left">Number of input shares into which each measurement is sharded (<xref target="sec-vdaf-shard"/>).</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 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">Aggregator's state during preparation.</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 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>Vdaf</tt> interface specify a method of encoding the <tt>PublicShare</tt>,
<tt>InputShare</tt>, <tt>AggShare</tt>, <tt>PrepShare</tt>, and <tt>PrepMessage</tt>.</t>
      <t>Each VDAF is identified by a unique, 32-bit integer <tt>ID</tt>. Identifiers for each
(V)DAF specified in this document are defined in <xref target="codepoints"/>. The following
method is defined for each VDAF specified in this document:</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 `range(2**16)`
    """
    return format_dst(0, self.ID, usage) + ctx
]]></sourcecode>
      <t>It is used to construct a domain separation tag for an instance of <tt>Xof</tt> used by
the VDAF. (See <xref target="xof"/>.)</t>
      <section anchor="sec-vdaf-shard">
        <name>Sharding</name>
        <t>Sharding transforms a measurement and nonce into a public share and input shares
as it does in DAFs (cf. <xref target="sec-daf-shard"/>):</t>
        <ul spacing="normal">
          <li>
            <t><tt>vdaf.shard(ctx: bytes, measurement: Measurement, nonce: bytes, rand: bytes)
-&gt; tuple[PublicShare, list[InputShare]]</tt> is the randomized sharding algorithm
run by each Client that consumes the application context, a measurement, and
a nonce and produces a public share distributed to each of the Aggregate and
a corresponding sequence of input shares, one for each Aggregator. Depending
on the VDAF, the input shares may encode additional information used to
verify the recovered output shares (e.g., the "proof shares" in Prio3
<xref target="prio3"/>)  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>nonce</tt> <bcp14>MUST</bcp14> have length equal to <tt>NONCE_SIZE</tt> and <bcp14>MUST</bcp14> be generated using
a CSPRNG. (See <xref target="security"/> for details.)</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>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>SHARES</tt>.</t>
              </li>
            </ul>
          </li>
        </ul>
        <t>Like DAFs, sharding is bound to the application context via the <tt>ctx</tt> 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 failure to validate the
report, 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>
        <t>To recover and verify output shares, the Aggregators interact with one another
over <tt>ROUNDS</tt> rounds. Prior to each round, each Aggregator constructs an
outbound message. Next, the sequence of outbound messages is combined into a
single message, called a "preparation message", or "prep message" for short.
(Each of the outbound messages are called "preparation-message shares", or
"prep shares" for short.) Finally, the preparation message is distributed to
the Aggregators to begin the next round.</t>
        <t>An Aggregator begins the first round with its input share and it begins each
subsequent round with 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>This process involves a value called the "aggregation parameter" used to map the
input shares to output shares. The Aggregators need to agree on this parameter
before they can begin preparing the measurement shares for aggregation.</t>
        <figure anchor="prep-flow">
          <name>VDAF preparation process on the input shares for a single measurement. At the end of the computation, each Aggregator holds an output share or an error.</name>
          <artwork><![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       |     | x ROUNDS
    +-----------+  +-----------+          +-----------+   |
    | prep_next |  | prep_next |          | prep_next |   |
    +-----------+  +-----------+          +-----------+   |
      |       |      |                 ...  |       |     |
      V       V      V                      V       V     /
     ...            ...                    ...
      |              |                 ...  |
      V              V                      V
    out_share_0    out_share_1         out_share_[SHARES-1]
]]></artwork>
        </figure>
        <t>To facilitate the preparation process, a concrete VDAF implements the following
methods:</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 to begin processing its input
share into an output share. Its inputs are the shared verification key
(<tt>verify_key</tt>), the application context (<tt>ctx</tt>), the Aggregator's unique
identifier (<tt>agg_id</tt>), the aggregation parameter (<tt>agg_param</tt>), the nonce
provided by the environment (<tt>nonce</tt>, see <xref target="run-vdaf"/>), the public share
(<tt>public_share</tt>), and one of the input shares generated by the Client
(<tt>input_share</tt>). Its output is the Aggregator's initial preparation state and
initial prep share.  </t>
            <t>
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>
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 <tt>range(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_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 preparation state (<tt>prep_state</tt>) and returns either its next
preparation state and its message share for the current round or, if this is
the last round, its output share. An exception is raised if a valid output
share could not be recovered. The input of this algorithm is the inbound
preparation message.</t>
          </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 generated by the
Aggregators in the previous round into the prep message consumed by each in
the next round.</t>
          </li>
        </ul>
        <t>In effect, each Aggregator moves through a linear state machine with <tt>ROUNDS</tt>
states.  The Aggregator enters the first state on using the initialization
algorithm, and the update algorithm advances the Aggregator to the next state.
Thus, in addition to defining the number of rounds (<tt>ROUNDS</tt>), a VDAF instance
defines the state of the Aggregator after each round.</t>
        <t>The preparation-state update 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 it 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>Similar to DAFs (see <xref target="sec-daf-validity-scopes"/>), VDAFs <bcp14>MAY</bcp14> impose
restrictions for input shares and aggregation parameters. Protocols using a VDAF
<bcp14>MUST</bcp14> ensure that for each input share and aggregation parameter <tt>agg_param</tt>, the
preparation phase (including <tt>vdaf.prep_init</tt>, <tt>vdaf.prep_next</tt>, and
<tt>vdaf.prep_shares_to_prep</tt>; see <xref target="sec-vdaf-prepare"/>) is only called if
<tt>vdaf.is_valid(agg_param, previous_agg_params)</tt> returns True, where
<tt>previous_agg_params</tt> contains all aggregation parameters that have previously
been used with the same input share.</t>
        <t>VDAFs <bcp14>MUST</bcp14> implement the following function:</t>
        <ul spacing="normal">
          <li>
            <t><tt>vdaf.is_valid(agg_param: AggParam, previous_agg_params: list[AggParam]) -&gt;
bool</tt>: checks if the <tt>agg_param</tt> is compatible with all elements of
<tt>previous_agg_params</tt>.</t>
          </li>
        </ul>
      </section>
      <section anchor="sec-vdaf-aggregate">
        <name>Aggregation</name>
        <t>VDAF Aggregation is identical to DAF Aggregation (cf. <xref target="sec-daf-aggregate"/>):</t>
        <ul spacing="normal">
          <li>
            <t><tt>vdaf.aggregate(agg_param: AggParam, out_shares: list[OutShare]) -&gt; AggShare</tt>
is the deterministic aggregation algorithm. It is run by each Aggregator over
the output shares it has computed for a batch of measurements.</t>
          </li>
        </ul>
        <t>The data flow for this stage is illustrated in <xref target="aggregate-flow"/>. Here again,
we have the aggregation algorithm in a "one-shot" form, where all shares for a
batch are provided at the same time. VDAFs typically also support a "streaming"
form, where shares are processed one at a time.</t>
      </section>
      <section anchor="sec-vdaf-unshard">
        <name>Unsharding</name>
        <t>VDAF Unsharding is identical to DAF Unsharding (cf. <xref target="sec-daf-unshard"/>):</t>
        <ul spacing="normal">
          <li>
            <t><tt>vdaf.unshard(agg_param: AggParam, agg_shares: list[AggShare],
num_measurements: int) -&gt; AggResult</tt> is run by the Collector in order to
compute the aggregate result from the Aggregators' shares. The length of
<tt>agg_shares</tt> <bcp14>MUST</bcp14> be <tt>SHARES</tt>. <tt>num_measurements</tt> is the number of
measurements that contributed to each of the aggregate shares. This algorithm
is deterministic.</t>
          </li>
        </ul>
        <t>The data flow for this stage is illustrated in <xref target="unshard-flow"/>.</t>
      </section>
      <section anchor="vdaf-execution">
        <name>Execution of a VDAF</name>
        <t>Secure execution of a VDAF involves simulating the following procedure.</t>
        <figure anchor="run-vdaf">
          <name>Execution of a VDAF.</name>
          <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,
        nonces: list[bytes],
        measurements: list[Measurement]) -> AggResult:
    """
    Run the VDAF on a list of measurements.

    Pre-conditions:

        - `len(verify_key) == vdaf.VERIFY_KEY_SIZE`
        - `len(nonces) == len(measurements)`
        - `all(len(nonce) == vdaf.NONCE_SIZE for nonce in nonces)`
    """

    if len(verify_key) != vdaf.VERIFY_KEY_SIZE:
        raise ValueError("incorrect verify_key size")
    if any(len(nonce) != vdaf.NONCE_SIZE for nonce in nonces):
        raise ValueError("incorrect nonce size")
    if len(nonces) != len(measurements):
        raise ValueError(
            "measurements and nonces lists have different lengths"
        )

    out_shares = []
    for (nonce, measurement) in zip(nonces, measurements):
        assert len(nonce) == vdaf.NONCE_SIZE

        # Each Client shards its measurement into input shares.
        rand = gen_rand(vdaf.RAND_SIZE)
        (public_share, input_shares) = \
            vdaf.shard(ctx, measurement, nonce, rand)

        # Each Aggregator initializes its preparation state.
        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)

        # Aggregators recover their output shares.
        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)

        # The final outputs of the prepare phase are the output
        # shares.
        prep_msg = vdaf.prep_shares_to_prep(ctx,
                                            agg_param,
                                            outbound_prep_shares)

        outbound_out_shares = []
        for j in range(vdaf.SHARES):
            out_share = vdaf.prep_next(ctx, prep_states[j], prep_msg)
            assert not isinstance(out_share, tuple)
            outbound_out_shares.append(out_share)

        out_shares.append(outbound_out_shares)

    # Each Aggregator aggregates its output shares into an
    # aggregate share. In a distributed VDAF computation, the
    # aggregate shares are sent over the network.
    agg_shares = []
    for j in range(vdaf.SHARES):
        out_shares_j = [out[j] for out in out_shares]
        agg_share_j = vdaf.aggregate(agg_param, out_shares_j)
        agg_shares.append(agg_share_j)

    # Collector unshards the aggregate.
    num_measurements = len(measurements)
    agg_result = vdaf.unshard(agg_param, agg_shares,
                              num_measurements)
    return agg_result
]]></sourcecode>
        </figure>
        <t>The inputs to this algorithm are the aggregation parameter, a list of
measurements, and a nonce for each measurement. This document does not specify
how the nonces are chosen, but security requires that the nonces be unique. See
<xref target="security"/> for details. 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>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. In this section we describe some approaches to realizing
this broadcast channel functionality in protocols that use VDAFs.</t>
        <t>The state machine of each Aggregator is shown in <xref target="vdaf-prep-state-machine"/>.</t>
        <figure anchor="vdaf-prep-state-machine">
          <name>State machine for VDAF preparation.</name>
          <artwork><![CDATA[
                  +----------------+
                  |                |
                  v                |
Start ----> Continued(prep_state, prep_round) --> Finished(out_share)
 |                |
 |                |
 +--> Rejected <--+
]]></artwork>
        </figure>
        <t>State transitions are made when the state is acted upon by the host's local
inputs and/or messages sent by the peers. The initial state is <tt>Start</tt>. The
terminal states are <tt>Rejected</tt>, which indicates that the report cannot be
processed any further, and <tt>Finished(out_share)</tt>, which indicates that the
Aggregator has recovered an output share <tt>out_share</tt>.</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>
        <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 scheme specified in
<xref target="prio3-encode"/> and <xref target="poplar1-encode"/> respectively.</t>
      </section>
      <section anchor="ping-pong-topology-only-two-aggregators">
        <name>Ping-Pong Topology (Only Two Aggregators)</name>
        <t>For VDAFs with precisely two Aggregators (i.e., <tt>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 party the "Leader" and the responding party 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 (<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 (<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 there are <tt>ceil((ROUNDS+1)/2)</tt>
requests sent.</t>
        <t>Each message in the ping-pong protocol is structured as follows (expressed in
TLS syntax as defined in <xref section="3" sectionFormat="of" target="RFC8446"/>):</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 are used to transition between the states described in
<xref target="vdaf-prep-comm"/>. The Leader's initial transition is computed with the
following method, implemented on <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. Function
<tt>encode</tt>  is used to encode the outbound message, here the <tt>initialize</tt> variant
(hence <tt>0</tt>).</t>
        <t>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>Procedure <tt>decode</tt> decodes the inbound message and returns the MessageType
variant (<tt>initialize</tt>, <tt>continue</tt>, or <tt>finalize</tt>) and the sequence of fields.
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>Next, the Helper sends the outbound message to the Leader. The Leader computes
its next state transition using the function <tt>ping_pong_leader_continued</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 function
<tt>ping_pong_helper_continued</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, there may be one more
message to send before the peer can also finish processing (i.e., <tt>outbound !=
None</tt>).</t>
      </section>
      <section anchor="star-topo">
        <name>Star Topology (Any Number of Aggregators)</name>
        <t>The ping-pong topology of the previous section is only suitable for VDAFs
involving exactly two Aggregators. If the VDAF supports more than two
Aggregators, then 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>prep_shares_to_prep()</tt>) and broadcasts it to the Helpers. At
this point, each Aggregator runs <tt>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 more are 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 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>A concrete <tt>Field</tt> also implements the following class methods:</t>
        <ul spacing="normal">
          <li>
            <t><tt>Field.zeros(length: int) -&gt; list[Self]</tt> returns a vector of
zeros.  </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. Same pre- and post-conditions as for <tt>Field.zeros()</tt>.</t>
          </li>
        </ul>
        <t>A field element is an instance of a concrete <tt>Field</tt>. The concrete class defines
the usual arithmetic operations on field elements. In addition, it defines the
following instance method for converting a field element to an unsigned integer:</t>
        <ul spacing="normal">
          <li>
            <t><tt>elem.as_unsigned() -&gt; int</tt> returns the integer representation of
field element <tt>elem</tt>.</t>
          </li>
        </ul>
        <t>Likewise, each concrete <tt>Field</tt> implements a constructor for converting an
unsigned 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 non-negative and less than <tt>Field.MODULUS</tt>.</t>
          </li>
        </ul>
        <t>Each concrete <tt>Field</tt> has two derived class methods, one for encoding
a vector of field elements as a byte string and another for decoding a vector of
field elements.</t>
        <figure anchor="field-derived-methods">
          <name>Derived class methods for finite fields.</name>
          <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.as_unsigned(), cls.ENCODED_SIZE)
    return encoded

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

    vec = []
    for i in range(0, len(encoded), L):
        encoded_x = encoded[i:i+L]
        x = from_le_bytes(encoded_x)
        if x >= cls.MODULUS:
            raise ValueError('modulus overflow')
        vec.append(cls(x))
    return vec
]]></sourcecode>
        </figure>
        <t>Finally, <tt>Field</tt> implements the following methods for representing a value as
a sequence of field elements, each of which represents a bit of the input.</t>
        <figure anchor="field-bit-rep">
          <name>Derived class methods to encode integers into bit vector representation.</name>
          <sourcecode type="python"><![CDATA[
def encode_into_bit_vector(
        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_vector(cls, vec: list[Self]) -> Self:
    """
    Decode the field element from the bit representation, expressed
    as a vector of field elements `vec`.
    """
    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>
        </figure>
        <section anchor="auxiliary-functions">
          <name>Auxiliary Functions</name>
          <t>The following auxiliary functions on vectors of field elements are used in the
remainder of this document. Note that an exception is raised by each function if
the operands are not the same length.</t>
          <figure anchor="field-helper-functions">
            <name>Common functions for finite fields.</name>
            <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>
          </figure>
        </section>
        <section anchor="field-ntt-friendly">
          <name>NTT-Friendly Fields</name>
          <t>Some VDAFs require fields that are suitable for efficient computation of the
number theoretic transform (NTT) <xref target="SML24"/>, as this allows for fast polynomial
interpolation. (One example is Prio3 (<xref target="prio3"/>) when instantiated with the FLP
of <xref target="flp-bbcggi19-construction"/>.) Specifically, a field is said to be
"NTT-friendly" if, in addition to satisfying the interface described in
<xref target="field"/>, it implements the following method:</t>
          <ul spacing="normal">
            <li>
              <t><tt>Field.gen() -&gt; Field</tt> 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. In addition, 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>
            </li>
          </ul>
          <t>NTT-friendly fields also define the following parameter:</t>
          <ul spacing="normal">
            <li>
              <t><tt>GEN_ORDER: int</tt> is the order of a multiplicative subgroup generated by
<tt>Field.gen()</tt>.</t>
            </li>
          </ul>
        </section>
        <section anchor="parameters">
          <name>Parameters</name>
          <t>The tables below define 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</name>
        <t>VDAFs in this specification use extendable output functions (XOFs) to extract
short, fixed-length strings we call "seeds" from long input strings and expand
seeds into long output strings. We specify a single interface that is suitable
for both purposes.</t>
        <t>XOFs are defined by a class <tt>Xof</tt> with the following associated parameter and
methods:</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 <tt>Xof</tt>
from the given seed, domain separation tag, and binder string. (See below for
definitions of these.) 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 <tt>length</tt> bytes of output of
<tt>xof</tt>.</t>
          </li>
        </ul>
        <t>Each <tt>Xof</tt> has three derived methods. The first is used to derive a fresh seed
from an existing one. The second is used to compute a sequence of field
elements. The third is a convenience method to construct an <tt>Xof</tt> from a seed,
domain separation tag, and binder string, and then use it to compute a sequence
of field elements.</t>
        <figure anchor="xof-derived-methods">
          <name>Derived methods for XOFs.</name>
          <sourcecode type="python"><![CDATA[
def derive_seed(cls,
                seed: bytes,
                dst: bytes,
                binder: bytes) -> bytes:
    """
    Derive a new seed.

    Pre-conditions:

        - `len(seed) == Xof.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 vector of `length` field elements.

    Pre-conditions:

        - `field` is sub-class of `Field`
        - `len(seed) == Xof.SEED_SIZE`
        - `length > 0`
    """
    xof = cls(seed, dst, binder)
    return xof.next_vec(field, length)
]]></sourcecode>
        </figure>
        <section anchor="xof-turboshake128">
          <name>XofTurboShake128</name>
          <t>This section describes XofTurboShake128, an XOF based on the TurboSHAKE128
<xref target="TurboSHAKE"/>. (RFC EDITOR: Update this
reference to the RFC for draft-irtf-cfrg-kangarootwelve once published.) This
XOF is <bcp14>RECOMMENDED</bcp14> for all use cases within VDAFs. The length of the domain
separation string <tt>dst</tt> passed to XofTurboShake128 <bcp14>MUST NOT</bcp14> exceed 65535 bytes.</t>
          <figure>
            <name>Definition of XOF XofTurboShake128.</name>
            <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>
          </figure>
        </section>
        <section anchor="xof-fixed-key-aes128">
          <name>XofFixedKeyAes128</name>
          <t>While XofTurboShake128 as described above can be securely used in all cases
where a XOF is needed in the VDAFs described in this document, there are some
cases where a more efficient instantiation based on fixed-key AES is possible.
For now, this is limited to the XOF used inside the Idpf <xref target="idpf"/>
implementation in Poplar1 <xref target="idpf-bbcggi21"/>. It is <bcp14>NOT RECOMMENDED</bcp14> to use this
XOF anywhere else. The length of the domain separation string <tt>dst</tt> passed to
XofFixedKeyAes128 <bcp14>MUST NOT</bcp14> exceed 65535 bytes. See <xref target="security"/> for a more
detailed discussion.</t>
          <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, the derivation is needs to be
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., VDAF);</t>
            </li>
            <li>
              <t>A unique identifier for the algorithm; 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 for use within a (V)DAF.

    Pre-conditions:

        - `algo_class` in `range(0, 2 ** 8)`
        - `algo` in `range(0, 2 ** 32)`
        - `usage` in `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 Prio <xref target="CGB17"/>. Prio is suitable for
a wide variety of aggregation functions, including (but not limited to) sum,
mean, standard deviation, estimation of quantiles (e.g., median), and linear
regression. In fact, the scheme described in this section 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.) The circuit's output is a single field
element: if zero, then the measurement is said to be "valid"; otherwise, if
the output is non-zero, then the measurement is said to be "invalid".</t>
        </li>
        <li>
          <t>The aggregate result is obtained by summing up the encoded measurement
vectors and computing some function of the sum.</t>
        </li>
      </ul>
      <t>At a high level, Prio3 distributes this computation as follows. Each Client
first shards its measurement by first encoding it, then splitting the vector into
secret shares and sending a share to each Aggregator. Next, in the preparation
phase, the Aggregators carry out a multi-party computation to determine if their
shares correspond to a valid measurement (as determined by the arithmetic
circuit). This computation involves a "proof" of validity generated by the
Client. Next, each Aggregator sums up its shares locally. Finally, the
Collector sums up the aggregate shares and computes the aggregate result.</t>
      <t>This VDAF does not have an aggregation parameter. Instead, the output share is
derived from the measurement 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 core component of Prio3 is a "Fully Linear Proof (FLP)" system. Introduced
by <xref target="BBCGGI19"/>, the FLP encapsulates the functionality required for encoding
and validating measurements. Prio3 can be thought of as a transformation of a
particular class of FLPs into a VDAF.</t>
      <t>The remainder of this section is structured as follows. The syntax for 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, instantiations of
Prio3 for various types of measurements are specified in
<xref target="prio3-instantiations"/>. Test vectors can be found in <xref target="test-vectors"/>.</t>
      <section anchor="flp">
        <name>Fully Linear Proof (FLP) Systems</name>
        <t>Conceptually, an FLP is a two-party protocol executed by a prover and a
verifier. In actual use, 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. Each Aggregator then
performs some computation on its measurement share and proof share locally and
sends the result to the other Aggregators. Combining the exchanged messages
allows each Aggregator to decide if it holds a share of a valid measurement.
(See <xref target="prio3-construction"/> for details.)</t>
        <t>As usual, we will describe the interface implemented by a concrete FLP in terms
of an abstract base class <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"/>.</t>
        <table anchor="flp-param">
          <name>Constants and types defined by a concrete FLP.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>PROVE_RAND_LEN</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</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</tt></td>
              <td align="left">Length of the joint randomness, the number of random field elements consumed by both the prover and verifier</td>
            </tr>
            <tr>
              <td align="left">
                <tt>MEAS_LEN</tt></td>
              <td align="left">Length of the encoded measurement (<xref target="flp-encode"/>)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>OUTPUT_LEN</tt></td>
              <td align="left">Length of the aggregatable output (<xref target="flp-encode"/>)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>PROOF_LEN</tt></td>
              <td align="left">Length of the proof</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VERIFIER_LEN</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</tt></td>
              <td align="left">Class object for the field (<xref target="field"/>)</td>
            </tr>
          </tbody>
        </table>
        <t>An 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 deterministic 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 query-generation algorithm run
by the verifier. This is used to "query" the 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
how many shares were generated.</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-generation algorithm
outputs a share of the verifier message. Furthermore, the privacy property of
the FLP system ensures that the verifier message reveals nothing about the measurement
other than whether it is valid. Therefore, to decide if a measurement is valid, the
Aggregators will run the query-generation algorithm locally, exchange verifier
shares, combine them to recover the verifier message, and run the decision
algorithm.</t>
        <t>The query-generation algorithm includes a parameter <tt>num_shares</tt> that specifies
the number of shares that were generated. If these data are not secret shared,
then <tt>num_shares == 1</tt>. This parameter is useful for certain FLP constructions.
For example, the FLP in <xref target="flp-bbcggi19"/> is defined in terms of an arithmetic
circuit; when the circuit contains constants, it is sometimes necessary to
normalize those constants to ensure that the circuit's output, when run on a
valid measurement, is the same regardless of the number of shares.</t>
        <t>An FLP is executed by the prover and verifier as follows:</t>
        <figure anchor="run-flp">
          <name>Execution of an FLP.</name>
          <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>
        </figure>
        <t>The proof system is constructed so that, if <tt>meas</tt> is valid, then <tt>run_flp(flp,
meas, 1)</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 a VDAF
In particular, soundness of the FLP is necessary, but insufficient for
robusntess of Prio3 (<xref target="prio3"/>). See <xref target="security-multiproof"/> for details.</t>
        <t>We remark that <xref target="BBCGGI19"/> defines a much 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>
        <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. The return value <bcp14>MUST</bcp14> be of length <tt>MEAS_LEN</tt>.</t>
            </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 "integer sum" data type from
<xref target="CGB17"/> in which an integer in <tt>range(2**k)</tt> is encoded as a vector of <tt>k</tt>
field elements, each representing a bit of the integer (this type is also
defined in <xref target="prio3sum"/>). After consuming this vector, all that is needed is
the integer it represents. Thus the FLP defines an algorithm for truncating the
encoded measurement to the length of the aggregated 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). The length of the input <bcp14>MUST</bcp14> be
<tt>MEAS_LEN</tt> and the length of the output <bcp14>MUST</bcp14> be <tt>OUTPUT_LEN</tt>.</t>
            </li>
          </ul>
          <t>Once the aggregate shares have been computed and combined together, 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.</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 <tt>output</tt> <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 contributed
to the <tt>output</tt>.</t>
                </li>
              </ul>
            </li>
          </ul>
          <t>We remark that, taken together, these three functionalities correspond roughly
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, see <xref target="flp-bbcggi19"/>)
without sacrificing soundness. Generally, choosing a smaller field can
significantly reduce communication cost. (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 an independently generated prover
and joint randomness string. The verifier checks each proof independently, each
time with an independently generated query randomness string. It accepts the
measurement only if all the decision algorithm accepts on each proof.</t>
          <t>See <xref target="security-multiproof"/> below for discussions on choosing the right number
of proofs.</t>
        </section>
      </section>
      <section anchor="prio3-construction">
        <name>Construction</name>
        <t>This section specifies <tt>Prio3</tt>, an implementation of the <tt>Vdaf</tt> interface
(<xref target="vdaf"/>). It has three generic parameters: an <tt>NttField ({{ntt-field}}), an
</tt>Flp<tt> ({{flp}}) and a </tt>Xof<tt> ({{xof}}). It also has an associated constant,
</tt>PROOFS<tt>, with a value in </tt>range(1, 256)`, denoting the number of FLPs
generated by the Client (<xref target="multiproofs"/>).</t>
        <t>The associated constants 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>VDAF parameters for Prio3.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <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">in <tt>[2, 256)</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">
                <tt>Flp.Measurement</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">
                <tt>Flp.AggResult</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 for 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>Run the FLP proof-generation algorithm using the derived joint randomness</t>
            </li>
            <li>
              <t>Shard the proof into a sequence of proof shares</t>
            </li>
            <li>
              <t>Return the public share, consisting of the joint randomness parts, and the
input shares, each consisting of the measurement share, proof share, and
blind of one of the Aggregators</t>
            </li>
          </ol>
          <t>As described in <xref target="multiproofs"/>, the soundness of the FLP can be amplified
by generating and verifying multiple FLPs. (This in turn improves the
robustness of Prio3.) To support this, in Prio3:</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). The sharding algorithm is specified below.</t>
          <figure anchor="prio3-eval-input">
            <name>Input-distribution algorithm for Prio3.</name>
            <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>
          </figure>
          <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="flps-without-joint-randomness">
            <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>:</t>
            <figure anchor="prio3-shard-without-joint-rand">
              <name>Sharding an encoded measurement without joint randomness.</name>
              <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]]]:
    k_helper_shares, seeds = front(self.SHARES - 1, seeds)
    (k_prove,), 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, k_helper_shares[j]),
        )

    # Generate and shard each proof into shares.
    prove_rands = self.prove_rands(ctx, k_prove)
    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,
                k_helper_shares[j],
            ),
        )

    # Each Aggregator's input share contains its measurement share
    # and share of 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((
            k_helper_shares[j],
            None,
        ))
    return (None, input_shares)
]]></sourcecode>
            </figure>
            <t>The steps in this method are as follows:</t>
            <ol spacing="normal" type="1"><li>
                <t>Shard the encoded measurement into shares</t>
              </li>
              <li>
                <t>Generate and shard each proof into shares</t>
              </li>
              <li>
                <t>Encode each measurement and shares of each proof into an input share</t>
              </li>
            </ol>
            <t>Notice that only one pair of measurement and proof(s) share (called the
"leader" shares above) 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.</t>
            <t>The methods on <tt>Prio3</tt> for deriving the prover randomness, measurement shares,
and proof shares and the methods for encoding the input shares are defined in
<xref target="prio3-auxiliary"/>.</t>
          </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>:</t>
            <figure anchor="prio3-shard-with-joint-rand">
              <name>Sharding an encoded measurement with joint randomness.</name>
              <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]]]:
    k_helper_seeds, seeds = front((self.SHARES - 1) * 2, seeds)
    k_helper_shares = [
        k_helper_seeds[i]
        for i in range(0, (self.SHARES - 1) * 2, 2)
    ]
    k_helper_blinds = [
        k_helper_seeds[i]
        for i in range(1, (self.SHARES - 1) * 2, 2)
    ]
    (k_leader_blind, k_prove), seeds = front(2, seeds)

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

    # Generate the proof and shard it into proof shares.
    prove_rands = self.prove_rands(ctx, k_prove)
    joint_rands = self.joint_rands(
        ctx, self.joint_rand_seed(ctx, k_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,
                k_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,
        k_leader_blind,
    ))
    for j in range(self.SHARES - 1):
        input_shares.append((
            k_helper_shares[j],
            k_helper_blinds[j],
        ))
    return (k_joint_rand_parts, input_shares)
]]></sourcecode>
            </figure>
            <t>The difference between this procedure and previous one is that here we compute
joint randomnesses <tt>joint_rands</tt>, split it into multiple <tt>joint_rand</tt>, and pass
each <tt>joint_rand</tt> to the proof generationg algorithm. (In
<xref target="prio3-shard-without-joint-rand"/> the joint randomness is the empty vector,
<tt>[]</tt>.) This requires generating an additional value, called the "blind", that
is incorporated into each input share.</t>
            <t>The joint randomness 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 bootstrap the required check, the Client encodes the joint
randomness parts in the public share. (See <xref target="prio3-preparation"/> for details.)</t>
            <t>The methods used in this computation are defined in <xref target="prio3-auxiliary"/>.</t>
          </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 and share of proof(s) locally, then exchanges its share of
verifier(s) with the other Aggregators. The shares of verifier(s) are then
combined into the verifier message(s) used to decide whether to accept.</t>
          <t>In addition, for FLPs that require joint randomness, the Aggregators must
ensure that they have all used the same joint randomness for the
query-generation algorithm. To do so, they collectively re-derive the joint
randomness from their measurement shares just as the Client did during
sharding.</t>
          <t>In order to avoid extra round of communication, the Client sends each
Aggregator a "hint" consisting of the joint randomness parts. 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 preparation 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 input share, then truncate
the input share to get the output share.</t>
          <t>The definitions of constants and a few auxiliary functions are defined in
<xref target="prio3-auxiliary"/>.</t>
          <figure anchor="prio3-prep-state">
            <name>Preparation state for Prio3.</name>
            <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]]:
    k_joint_rand_parts = public_share
    (meas_share, proofs_share, k_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] = []
    k_corrected_joint_rand, k_joint_rand_part = None, None
    if self.flp.JOINT_RAND_LEN > 0:
        assert k_blind is not None
        assert k_joint_rand_parts is not None
        k_joint_rand_part = self.joint_rand_part(
            ctx, agg_id, k_blind, meas_share, nonce)
        k_joint_rand_parts[agg_id] = k_joint_rand_part
        k_corrected_joint_rand = self.joint_rand_seed(
            ctx, k_joint_rand_parts)
        joint_rands = self.joint_rands(ctx, k_corrected_joint_rand)

    # Query the measurement and proof share.
    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, k_corrected_joint_rand)
    prep_share = (verifiers_share, k_joint_rand_part)
    return (prep_state, prep_share)

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

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

    return out_share

def prep_shares_to_prep(
        self,
        ctx: bytes,
        _agg_param: None,
        prep_shares: list[Prio3PrepShare[F]]) -> Optional[bytes]:
    # Unshard the verifier shares into the verifier message.
    verifiers = self.flp.field.zeros(
        self.flp.VERIFIER_LEN * self.PROOFS)
    k_joint_rand_parts = []
    for (verifiers_share, k_joint_rand_part) in prep_shares:
        verifiers = vec_add(verifiers, verifiers_share)
        if self.flp.JOINT_RAND_LEN > 0:
            assert k_joint_rand_part is not None
            k_joint_rand_parts.append(k_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.
    k_joint_rand = None
    if self.flp.JOINT_RAND_LEN > 0:
        k_joint_rand = self.joint_rand_seed(ctx, k_joint_rand_parts)
    return k_joint_rand
]]></sourcecode>
          </figure>
        </section>
        <section anchor="validity-of-aggregation-parameters">
          <name>Validity of Aggregation Parameters</name>
          <t>Every input share <bcp14>MUST</bcp14> only be used once, regardless of the aggregation
parameters used.</t>
          <figure anchor="prio3-validity-scope">
            <name>Validity of aggregation parameters for Prio3.</name>
            <sourcecode type="python"><![CDATA[
def is_valid(
        self,
        _agg_param: None,
        previous_agg_params: list[None]) -> bool:
    """
    Checks if `previous_agg_params` is empty, as input shares in
    Prio3 may only be used once.
    """
    return len(previous_agg_params) == 0
]]></sourcecode>
          </figure>
        </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>
          <figure anchor="prio3-out2agg">
            <name>Aggregation algorithm for Prio3.</name>
            <sourcecode type="python"><![CDATA[
def aggregate(
        self,
        _agg_param: None,
        out_shares: list[list[F]]) -> list[F]:
    agg_share = self.flp.field.zeros(self.flp.OUTPUT_LEN)
    for out_share in out_shares:
        agg_share = vec_add(agg_share, out_share)
    return agg_share
]]></sourcecode>
          </figure>
        </section>
        <section anchor="unsharding">
          <name>Unsharding</name>
          <t>To unshard a set of aggregate shares, the Collector first adds up the vectors
element-wise. It then converts each element of the vector into an integer.</t>
          <figure anchor="prio3-agg-output">
            <name>Computation of the aggregate result for Prio3.</name>
            <sourcecode type="python"><![CDATA[
def unshard(
        self,
        _agg_param: None,
        agg_shares: list[list[F]],
        num_measurements: int) -> AggResult:
    agg = self.flp.field.zeros(self.flp.OUTPUT_LEN)
    for agg_share in agg_shares:
        agg = vec_add(agg, agg_share)
    return self.flp.decode(agg, num_measurements)
]]></sourcecode>
          </figure>
        </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>
          <t>The following methods are called by the sharding and preparation algorithms.</t>
          <sourcecode type="python"><![CDATA[
def helper_meas_share(
        self,
        ctx: bytes,
        agg_id: int,
        k_share: bytes) -> list[F]:
    return self.xof.expand_into_vec(
        self.flp.field,
        k_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,
        k_share: bytes) -> list[F]:
    return self.xof.expand_into_vec(
        self.flp.field,
        k_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
        (k_share, k_blind) = input_share
        meas_share = self.helper_meas_share(ctx, agg_id, k_share)
        proofs_share = self.helper_proofs_share(ctx, agg_id, k_share)
    else:
        assert len(input_share) == 3
        (meas_share, proofs_share, k_blind) = input_share
    return (meas_share, proofs_share, k_blind)

def prove_rands(self, ctx: bytes, k_prove: bytes) -> list[F]:
    return self.xof.expand_into_vec(
        self.flp.field,
        k_prove,
        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,
        k_blind: bytes,
        meas_share: list[F],
        nonce: bytes) -> bytes:
    return self.xof.derive_seed(
        k_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,
                    k_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(k_joint_rand_parts),
    )

def joint_rands(self,
                ctx: bytes,
                k_joint_rand_seed: bytes) -> list[F]:
    """Derive the joint randomness from its seed."""
    return self.xof.expand_into_vec(
        self.flp.field,
        k_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. It is <bcp14>RECOMMENDED</bcp14> that implementations provide
serialization methods for them.</t>
          <t>Message structures are defined following <xref section="3" sectionFormat="of" target="RFC8446"/>). 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 encoding of the public share depends 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. If
joint randomness is used, then the public share encodes the joint randomness
parts as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Seed k_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 encoding 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 and share of proof(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 k_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 k_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 k_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 * prio3.flp.VERIFIER_LEN * prio3.PROOFS
    ];
} Prio3PrepShare;
]]></sourcecode>
            <t>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 * prio3.flp.VERIFIER_LEN * prio3.PROOFS
    ];
    Prio3Seed k_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 k_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>The FLP of <xref target="BBCGGI19"/></name>
        <t>This section describes an FLP based on the construction from <xref target="BBCGGI19"/>,
Section 4.2. We begin in <xref target="flp-bbcggi19-overview"/> with an overview of their
proof system and some extensions to it. The construction is specified in
<xref target="flp-bbcggi19-construction"/>.</t>
        <section anchor="flp-bbcggi19-overview">
          <name>Overview</name>
          <t>Conventional zero-knowledge proof systems involve 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 an
encryption of 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 in range(2)</tt>.</t>
          <t>Our goal is to allow each Aggregator, who holds a secret share of <tt>x</tt>, to
correctly compute a secret share of <tt>C(x)</tt>. This allows the Aggregators to
determine validity by combining their shares of the output.</t>
          <t>Suppose for a moment that the validity circuit <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 sends secret shares of <tt>x</tt> and
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>This idea provides the needed functionality, but it has one more problem: 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"/>.</t>
          <section anchor="flp-bbcggi19-overview-extensions">
            <name>Extensions</name>
            <t>The FLP described in {#flp-bbcggi19-construction} 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
<tt>range(2)</tt>), then the circuit will evaluate to 0 regardless of the value of
<tt>r</tt>; but if some <tt>x[j]</tt> is not in <tt>range(2)</tt>, then 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(meas, r) = r * Range2(meas[0]) + ... + r^L * Range2(meas[L-1]) + \
            r^(L+1) * Range3(meas[L]) + ... + r^N * Range3(meas[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 <tt>range(2)</tt> and the last <tt>N-L</tt> inputs are in <tt>range(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 powers of
<tt>alpha</tt>, where <tt>alpha</tt> is a root 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. This requires the field to
be "NTT-friendly" as defined in <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>The FLP described in <xref target="flp-bbcggi19-construction"/> is defined in terms of a
validity circuit <tt>Valid</tt> that implements the interface described here.</t>
          <t>A concrete <tt>Valid</tt> defines the following parameters:</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</tt></td>
                <td align="left">A list of gadgets</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">Number of times each gadget is called</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>MEAS_LEN</tt></td>
                <td align="left">Length of the measurement</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">Length of the aggregatable output</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">Length of the random input</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>EVAL_OUTPUT_LEN</tt></td>
                <td align="left">Length of the circuit output</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">The type of 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</tt></td>
                <td align="left">Class object for the field</td>
              </tr>
            </tbody>
          </table>
          <t>Each gadget <tt>G</tt> in <tt>GADGETS</tt> defines a constant <tt>DEGREE</tt> that specifies the
circuit's "arithmetic degree". This is defined to be the degree of the
polynomial that computes it. For example, the <tt>Mul</tt> circuit in
<xref target="flp-bbcggi19-overview"/> is defined by the polynomial <tt>Mul(x) = x * x</tt>, which
has degree <tt>2</tt>. Hence, the arithmetic degree of this gadget is <tt>2</tt>.</t>
          <t>Each gadget also defines a parameter <tt>ARITY</tt> that specifies the circuit's arity
(i.e., the number of input wires).</t>
          <t>Gadgets provide a method to evaluate their circuit on a list of inputs,
<tt>eval()</tt>. The inputs can either belong to the validity circuit's field, or the
polynomial ring over that field.</t>
          <t>A concrete <tt>Valid</tt> provides the following methods for encoding a measurement as
an input vector, truncating an input vector to the length of an aggregatable
output, and converting an aggregated output to an aggregate result:</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.</t>
            </li>
            <li>
              <t><tt>valid.truncate(meas: list[F]) -&gt; list[F]</tt> returns a vector of length
<tt>OUTPUT_LEN</tt> representing an aggregatable output.</t>
            </li>
            <li>
              <t><tt>valid.decode(output: list[F], num_measurements: int) -&gt; AggResult</tt>
returns an aggregate result.</t>
            </li>
          </ul>
          <t>Finally, the following methods are derived for each concrete <tt>Valid</tt>:</t>
          <figure>
            <name>Derived methods for validity circuits.</name>
            <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

def check_valid_eval(
        self,
        meas: list[F],
        joint_rand: list[F]) -> None:
    if len(meas) != self.MEAS_LEN:
        raise ValueError('incorrect measurement length')
    if len(joint_rand) != self.JOINT_RAND_LEN:
        raise ValueError('incorrect joint randomness length')
]]></sourcecode>
          </figure>
        </section>
        <section anchor="flp-bbcggi19-construction">
          <name>Construction</name>
          <t>This section specifies an implementation of the <tt>Flp</tt> interface (<xref target="flp"/>). It
has as a generic parameter a validity circuit <tt>Valid</tt> implementing the
interface defined in <xref target="flp-bbcggi19-valid"/>.</t>
          <t>The parameters are defined in <xref target="flp-bbcggi19-param"/>. The required methods for
generating the proof, generating the verifier, and deciding validity are
specified in the remaining subsections.</t>
          <t>In the remainder, we let <tt>[n]</tt> denote the set <tt>{1, ..., n}</tt> for positive integer
<tt>n</tt>. We also define the following constants:</t>
          <ul spacing="normal">
            <li>
              <t>Let <tt>H = len(valid.GADGETS)</tt></t>
            </li>
            <li>
              <t>For each <tt>i</tt> in <tt>[H]</tt>:
              </t>
              <ul spacing="normal">
                <li>
                  <t>Let <tt>G_i = valid.GADGETS[i]</tt></t>
                </li>
                <li>
                  <t>Let <tt>L_i = valid.GADGETS[i].ARITY</tt></t>
                </li>
                <li>
                  <t>Let <tt>M_i = valid.GADGET_CALLS[i]</tt></t>
                </li>
                <li>
                  <t>Let <tt>P_i = next_power_of_2(M_i+1)</tt></t>
                </li>
                <li>
                  <t>Let <tt>alpha_i = field.gen()^(field.GEN_ORDER / P_i)</tt></t>
                </li>
              </ul>
            </li>
          </ul>
          <table anchor="flp-bbcggi19-param">
            <name>Parameters of FLP of BBCGGI19.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>PROVE_RAND_LEN</tt></td>
                <td align="left">
                  <tt>valid.prove_rand_len()</tt> (see <xref target="flp-bbcggi19-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>QUERY_RAND_LEN</tt></td>
                <td align="left">
                  <tt>valid.query_rand_len()</tt> (see <xref target="flp-bbcggi19-valid"/>)</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> (see <xref target="flp-bbcggi19-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>VERIFIER_LEN</tt></td>
                <td align="left">
                  <tt>valid.verifier_len()</tt> (see <xref target="flp-bbcggi19-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>valid.Measurement</tt></td>
              </tr>
            </tbody>
          </table>
          <section anchor="flp-bbcggi19-construction-prove">
            <name>Proof Generation</name>
            <figure anchor="flp-bbcggi19-prove-illustration">
              <name>The proof generation algorithm invokes the validity circuit on the encoded measurement and joint randomness. The validity circuit in turn invokes the gadget(s) defined by the circuit. The prove randomness is used to construct the gadget polynomial(s).</name>
              <artwork><![CDATA[
+------------------+
| Prove            |
| +-------------+  |
| | Valid       |<---- meas
| | +--------+  |<---- joint rand
| | | Gadget |  |  |<- prove rand
| | +--------+  |  |
| +-------------+  |
+------------------+
 |
 V proof
]]></artwork>
            </figure>
            <t>On input of <tt>meas</tt>, <tt>prove_rand</tt>, and <tt>joint_rand</tt>, the proof is computed as
follows:</t>
            <ol spacing="normal" type="1"><li>
                <t>For each <tt>i</tt> in <tt>[H]</tt> create an empty table <tt>wire_i</tt>.</t>
              </li>
              <li>
                <t>Partition the prover randomness <tt>prove_rand</tt> into sub-vectors <tt>seed_1, ...,
seed_H</tt> where <tt>len(seed_i) == L_i</tt> for all <tt>i</tt> in <tt>[H]</tt>. Let us call these
the "wire seeds" of each gadget.</t>
              </li>
              <li>
                <t>Evaluate <tt>Valid</tt> on input of <tt>meas</tt> and <tt>joint_rand</tt>, recording the inputs
of each gadget in the corresponding table. Specifically, for every <tt>i</tt> in
<tt>[H]</tt>, set <tt>wire_i[j-1,k-1]</tt> to the value on the <tt>j</tt>th wire into the <tt>k</tt>th
call to gadget <tt>G_i</tt>.</t>
              </li>
              <li>
                <t>Compute the "wire polynomials". That is, for every <tt>i</tt> in <tt>[H]</tt> and <tt>j</tt> in
<tt>[L_i]</tt>, construct <tt>poly_wire_i[j-1]</tt>, the <tt>j</tt>th wire polynomial for the
<tt>i</tt>th gadget, as follows:  </t>
                <ul spacing="normal">
                  <li>
                    <t>Let <tt>w = [seed_i[j-1], wire_i[j-1,0], ..., wire_i[j-1,M_i-1]]</tt>.</t>
                  </li>
                  <li>
                    <t>Let <tt>padded_w = w + field.zeros(P_i - len(w))</tt>.</t>
                  </li>
                  <li>
                    <t>Let <tt>poly_wire_i[j-1]</tt> be the lowest degree polynomial for which
<tt>poly_wire_i[j-1](alpha_i^k) == padded_w[k]</tt> for all <tt>k</tt> in <tt>[P_i]</tt>.</t>
                  </li>
                </ul>
              </li>
              <li>
                <t>Compute the "gadget polynomials". That is, for every <tt>i</tt> in <tt>[H]</tt>:  </t>
                <ul spacing="normal">
                  <li>
                    <t>Let <tt>poly_gadget_i = G_i(poly_wire_i[0], ..., poly_wire_i[L_i-1])</tt>. That
is, evaluate the circuit <tt>G_i</tt> on the wire polynomials for the <tt>i</tt>th
gadget. (Arithmetic is in the ring of polynomials over <tt>field</tt>.)</t>
                  </li>
                </ul>
              </li>
            </ol>
            <t>The proof is the vector <tt>proof = seed_1 + coeff_1 + ... + seed_H + coeff_H</tt>,
where <tt>coeff_i</tt> is the vector of coefficients of <tt>poly_gadget_i</tt> for each <tt>i</tt> in
<tt>[H]</tt>.</t>
          </section>
          <section anchor="flp-bbcggi19-construction-query">
            <name>Query Generation</name>
            <figure anchor="flp-bbcggi19-query-illustration">
              <name>The query generation algorithm invokes the validity circuit on the encoded measurement and joint randomness. It evaluates the gadget polynomials(s) 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 tests consume the query randomness.</name>
              <artwork><![CDATA[
 | proof (share)
 +--------+
 V        |
+---------|--------+
| Query   |        |
| +-------|-----+  |
| | Valid |     |<---- meas (share)
| | +-----|--+  |<---- joint rand
| | |     V  |  |  |<- query rand
| | +--------+  |  |
| +-------------+  |
+------------------+
 |
 V verifier (share)
]]></artwork>
            </figure>
            <t>On input of <tt>meas</tt>, <tt>proof</tt>, <tt>query_rand</tt>, and <tt>joint_rand</tt>, the verifier message
is generated as follows:</t>
            <ol spacing="normal" type="1"><li>
                <t>For every <tt>i</tt> in <tt>[H]</tt> create an empty table <tt>wire_i</tt>.</t>
              </li>
              <li>
                <t>Partition <tt>proof</tt> into the sub-vectors <tt>seed_1</tt>, <tt>coeff_1</tt>, ..., <tt>seed_H</tt>,
<tt>coeff_H</tt> defined in <xref target="flp-bbcggi19-construction-prove"/>.</t>
              </li>
              <li>
                <t>Evaluate <tt>Valid</tt> on input of <tt>meas</tt> and <tt>joint_rand</tt>, recording the inputs
of each gadget in the corresponding table. This step is similar to the
prover's step (3.) except the verifier does not evaluate the gadgets.
Instead, it computes the output of the <tt>k</tt>th call to <tt>G_i</tt> by evaluating
<tt>poly_gadget_i(alpha_i^k)</tt>. Let <tt>out</tt> denote the output of the circuit
evaluation.</t>
              </li>
              <li>
                <t>Next, reduce <tt>out</tt> as follows. If <tt>EVAL_OUTPUT_LEN &gt; 1</tt>, then consume the
first <tt>EVAL_OUTPUT_LEN</tt> elements of <tt>query_rand</tt> by letting <tt>r, query_rand =
front(1, query_rand)</tt>. Then let
<tt>v = r[0]*out[0] + r[1]*out[1] + r[2]*out[2] + ...</tt>.</t>
              </li>
              <li>
                <t>Compute the wire polynomials just as in the prover's step (4.).</t>
              </li>
              <li>
                <t>Compute the tests for well-formedness of the gadget polynomials. That is, for
every <tt>i</tt> in <tt>[H]</tt>:  </t>
                <ul spacing="normal">
                  <li>
                    <t>Let <tt>t = query_rand[i]</tt>. Check if <tt>t^(P_i) == 1</tt>: if so, then raise
ERR_ABORT and halt. (This prevents the verifier from inadvertently leaking
a gadget output in the verifier message.)</t>
                  </li>
                  <li>
                    <t>Let <tt>y_i = poly_gadget_i(t)</tt>.</t>
                  </li>
                  <li>
                    <t>For each <tt>j</tt> in <tt>[0,L_i)</tt> let <tt>x_i[j-1] = poly_wire_i[j-1](t)</tt>.</t>
                  </li>
                </ul>
              </li>
            </ol>
            <t>The verifier message is the vector <tt>verifier = [v] + x_1 + [y_1] + ... + x_H +
[y_H]</tt>.</t>
          </section>
          <section anchor="decision">
            <name>Decision</name>
            <figure anchor="flp-bbcggi19-decide-illustration">
              <name>The decision algorithm consumes the verifier, consisting of the reduced output of the validity circuit and each gadget test. The verifier is produced by adding up the verifier shares output by each Aggregator.</name>
              <artwork><![CDATA[
 | verifier
 V
+------------------+
| Decide           |
+------------------+
 |
 V is_valid
]]></artwork>
            </figure>
            <t>On input of vector <tt>verifier</tt>, the verifier decides if the measurement is valid
as follows:</t>
            <ol spacing="normal" type="1"><li>
                <t>Parse <tt>verifier</tt> into <tt>v</tt>, <tt>x_1</tt>, <tt>y_1</tt>, ..., <tt>x_H</tt>, <tt>y_H</tt> as defined in
<xref target="flp-bbcggi19-construction-query"/>.</t>
              </li>
              <li>
                <t>Check for well-formedness of the gadget polynomials. For every <tt>i</tt> in <tt>[H]</tt>:  </t>
                <ul spacing="normal">
                  <li>
                    <t>Let <tt>z = G_i(x_i)</tt>. That is, evaluate the circuit <tt>G_i</tt> on <tt>x_i</tt> and set
<tt>z</tt> to the output.</t>
                  </li>
                  <li>
                    <t>If <tt>z != y_i</tt>, then return <tt>False</tt> and halt.</t>
                  </li>
                </ul>
              </li>
              <li>
                <t>Return <tt>True</tt> if <tt>v == 0</tt> and <tt>False</tt> otherwise.</t>
              </li>
            </ol>
          </section>
          <section anchor="encoding">
            <name>Encoding</name>
            <t>The FLP encoding and truncation methods invoke <tt>valid.encode</tt>,
<tt>valid.truncate</tt>, and <tt>valid.decode</tt> in the natural way.</t>
          </section>
        </section>
      </section>
      <section anchor="prio3-instantiations">
        <name>Instantiations</name>
        <t>This section specifies instantiations of Prio3 for various measurement types.
Each is determined by a field (<xref target="field"/>), a validity circuit
(<xref target="flp-bbcggi19-valid"/>), an XOF (<xref target="xof"/>). and the number of proofs to
generate and verify. 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>Valid</tt></td>
                <td align="left">
                  <tt>Count(Field64)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field64</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Xof</tt></td>
                <td align="left">
                  <tt>XofTurboShake128</tt> (<xref target="xof-turboshake128"/>)</td>
              </tr>
            </tbody>
          </table>
          <t>Our first instance of Prio3 is for a simple counter: each measurement is either
one or zero and the aggregate result is the sum of the measurements.</t>
          <t>Its validity circuit, denoted <tt>Count</tt>, uses the following degree-2, arity-2
gadget, denoted <tt>Mul</tt>:</t>
          <sourcecode type="python"><![CDATA[
def eval(self, _field: type[F], inp: list[F]) -> F:
    self.check_gadget_eval(inp)
    return inp[0] * inp[1]
]]></sourcecode>
          <t>The call to <tt>check_gadget_eval()</tt> raises an error if the length of the input is
not equal to the gadget's <tt>ARITY</tt> parameter.</t>
          <t>The <tt>Count</tt> validity circuit is defined as</t>
          <sourcecode type="python"><![CDATA[
def eval(
        self,
        meas: list[F],
        joint_rand: list[F],
        _num_shares: int) -> list[F]:
    self.check_valid_eval(meas, joint_rand)
    squared = self.GADGETS[0].eval(self.field, [meas[0], meas[0]])
    return [squared - meas[0]]
]]></sourcecode>
          <t>The measurement is encoded and decoded as a singleton vector in the natural
way. The parameters for this circuit are summarized below.</t>
          <table>
            <name>Parameters of validity circuit Count.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">
                  <tt>[Mul]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[1]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>MEAS_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>0</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>EVAL_OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>int</tt> in <tt>range(2)</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">
                  <tt>int</tt></td>
              </tr>
            </tbody>
          </table>
        </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>Valid</tt></td>
                <td align="left">
                  <tt>Sum(Field64, max_measurement)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field64</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Xof</tt></td>
                <td align="left">
                  <tt>XofTurboShake128</tt> (<xref target="xof-turboshake128"/>)</td>
              </tr>
            </tbody>
          </table>
          <t>The next instance of Prio3 supports summing of integers in a pre-determined
range. Each measurement is an integer in <tt>range(max_measurement+1)</tt>, where
<tt>max_measurement</tt> is an associated parameter equal to 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
<tt>bits</tt> 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, denoted <tt>Sum</tt>, 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 <tt>offset</tt> 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>range(2**bits)</tt>, this means that the
measurement itself is between <tt>0</tt> and <tt>max_measurement</tt>.</t>
          <t>The measurement is encoded in <tt>2*bits</tt> field elements as follows:</t>
          <sourcecode type="python"><![CDATA[
def encode(self, measurement: int) -> list[F]:
    encoded = []
    encoded += self.field.encode_into_bit_vector(
        measurement,
        self.bits
    )
    encoded += self.field.encode_into_bit_vector(
        measurement + self.offset.as_unsigned(),
        self.bits
    )
    return encoded

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

def decode(self, output: list[F], _num_measurements: int) -> int:
    return output[0].as_unsigned()
]]></sourcecode>
          <t>The validity circuit checks that the input consists of ones and zeros. Its
gadget, denoted <tt>Range2</tt>, is the degree-2, arity-1 gadget defined as</t>
          <sourcecode type="python"><![CDATA[
def eval(self, _field: type[F], inp: list[F]) -> F:
    self.check_gadget_eval(inp)
    return inp[0] * inp[0] - inp[0]
]]></sourcecode>
          <t>The <tt>Sum</tt> validity circuit is defined as</t>
          <sourcecode type="python"><![CDATA[
def eval(
        self,
        meas: list[F],
        joint_rand: list[F],
        num_shares: int) -> list[F]:
    self.check_valid_eval(meas, joint_rand)
    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_vector(meas[:self.bits]) - \
        self.field.decode_from_bit_vector(meas[self.bits:])
    out.append(range_check)
    return out
]]></sourcecode>
          <table>
            <name>Parameters of validity circuit Sum.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">
                  <tt>[Range2]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[2*bits]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>MEAS_LEN</tt></td>
                <td align="left">
                  <tt>2*bits</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>0</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>EVAL_OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>2*bits + 1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>int</tt> in <tt>range(max_measurement+1)</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">
                  <tt>int</tt></td>
              </tr>
            </tbody>
          </table>
        </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>Valid</tt></td>
                <td align="left">
                  <tt>SumVec(Field128, length, bits, chunk_lengh)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Xof</tt></td>
                <td align="left">
                  <tt>XofTurboShake128</tt> (<xref target="xof-turboshake128"/>)</td>
              </tr>
            </tbody>
          </table>
          <t>This instance of Prio3 supports summing a vector 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 <tt>range(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 validity circuit is denoted <tt>SumVec</tt>. Measurements are encoded as a vector
of field elements with length <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>
          <sourcecode type="python"><![CDATA[
def encode(self, measurement: list[int]) -> list[F]:
    if len(measurement) != self.length:
        raise ValueError('incorrect measurement length')

    encoded = []
    for val in measurement:
        if val not in range(2**self.bits):
            raise ValueError(
                'entry of measurement vector is out of range'
            )

        encoded += self.field.encode_into_bit_vector(val, self.bits)
    return encoded

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

def decode(
        self,
        output: list[F],
        _num_measurements: int) -> list[int]:
    return [x.as_unsigned() for x in output]
]]></sourcecode>
          <t>This validity circuit uses a <tt>ParallelSum</tt> gadget to achieve a smaller proof
size. This optimization for "parallel-sum circuits" is described in
<xref target="BBCGGI19"/>, section 4.4. Briefly, for circuits that add up the output of
multiple identical subcircuits, it is possible to achieve smaller proof sizes
(on the order of O(sqrt(MEAS_LEN)) instead of O(MEAS_LEN)) by packaging more
than one such subcircuit into a gadget.</t>
          <t>The <tt>ParallelSum</tt> gadget is parameterized with an arithmetic subcircuit, and a
<tt>count</tt> of how many times it evaluates that 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. 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> as an implementation of the
<tt>Gadget</tt> interface.</t>
          <sourcecode type="python"><![CDATA[
def eval(self, field: type[F], inp: list[F]) -> F:
    self.check_gadget_eval(inp)
    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
]]></sourcecode>
          <t>The <tt>SumVec</tt> validity circuit checks that the encoded measurement consists of
ones and zeros. Rather than use the <tt>Range2</tt> gadget on each element, as in the
<tt>Sum</tt> validity circuit, it instead uses <tt>Mul</tt> subcircuits 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>
          <sourcecode type="python"><![CDATA[
def eval(
        self,
        meas: list[F],
        joint_rand: list[F],
        num_shares: int) -> list[F]:
    self.check_valid_eval(meas, joint_rand)

    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]
]]></sourcecode>
          <table>
            <name>Parameters of validity circuit SumVec.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">
                  <tt>[ParallelSum(Mul(), chunk_length)]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[(length * bits + chunk_length - 1) // chunk_length]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>MEAS_LEN</tt></td>
                <td align="left">
                  <tt>length * bits</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>length</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>GADGET_CALLS[0]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>EVAL_OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>list[int]</tt>, each element in <tt>range(2**bits)</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">
                  <tt>list[int]</tt></td>
              </tr>
            </tbody>
          </table>
          <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 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 measurement. However, the relationship between VDAF
parameters and proof length is complicated, involving two forms of rounding (the
circuit pads the inputs to its last <tt>ParallelSum</tt> gadget call, up to the chunk
length, and 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).
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>Valid</tt></td>
                <td align="left">
                  <tt>Histogram(Field128, length, chunk_lengh)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Xof</tt></td>
                <td align="left">
                  <tt>XofTurboShake128</tt> (<xref target="xof-turboshake128"/>)</td>
              </tr>
            </tbody>
          </table>
          <t>This instance 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 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:</t>
          <sourcecode type="python"><![CDATA[
def encode(self, measurement: int) -> list[F]:
    encoded = [self.field(0)] * self.length
    encoded[measurement] = self.field(1)
    return encoded

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

def decode(
        self,
        output: list[F],
        _num_measurements: int) -> list[int]:
    return [bucket_count.as_unsigned() for bucket_count in output]
]]></sourcecode>
          <t>The <tt>Histogram</tt> validity 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> gadget to perform range checks while
achieving a smaller proof size. The <tt>ParallelSum</tt> gadget uses <tt>Mul</tt> subcircuits
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[
def eval(
        self,
        meas: list[F],
        joint_rand: list[F],
        num_shares: int) -> list[F]:
    self.check_valid_eval(meas, joint_rand)

    # 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]
]]></sourcecode>
          <t>Note that this circuit depends on the number of shares into which the
measurement is sharded. This is provided to the FLP by Prio3.</t>
          <table>
            <name>Parameters of validity circuit Histogram.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">
                  <tt>[ParallelSum(Mul(), chunk_length)]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[(length + chunk_length - 1) // chunk_length]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>MEAS_LEN</tt></td>
                <td align="left">
                  <tt>length</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>length</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>GADGET_CALLS[0]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>EVAL_OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>2</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>int</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">
                  <tt>list[int]</tt></td>
              </tr>
            </tbody>
          </table>
        </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>Valid</tt></td>
                <td align="left">
                  <tt>MultihotCountVec(Field128, length, max_weight, chunk_lengh)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Xof</tt></td>
                <td align="left">
                  <tt>XofTurboShake128</tt> (<xref target="xof-turboshake128"/>)</td>
              </tr>
            </tbody>
          </table>
          <t>For this instance of Prio3, each measurement is a vector of ones and zeros,
where the number of ones is bounded. This provides a functionality similar to
Prio3Histogram except that more than one entry 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 to one with some small probability.)</t>
          <t>Prio3MultihotCountVec uses XofTurboShake128 (<xref target="xof-turboshake128"/>) as its XOF.
Its validity circuit is denoted <tt>MultihotCountVec</tt>. It has three parameters:
<tt>length</tt>, the number of of entries in the count vector; <tt>max_weight</tt>, the
maximum number of non-zero 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.</t>
          <t>Encoding, truncation, and decoding are defined as follows:</t>
          <sourcecode type="python"><![CDATA[
def encode(self, measurement: list[int]) -> list[F]:
    if len(measurement) != self.length:
        raise ValueError('invalid Client measurement length')

    # The first part is the vector of counters.
    count_vec = list(map(self.field, 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_vector(
        (self.offset + weight_reported).as_unsigned(),
        self.bits_for_weight)
    return encoded

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.as_unsigned() for bucket_count in output]
]]></sourcecode>
          <t>Circuit evaluation is defined as follows:</t>
          <sourcecode type="python"><![CDATA[
def eval(
        self,
        meas: list[F],
        joint_rand: list[F],
        num_shares: int) -> list[F]:
    self.check_valid_eval(meas, joint_rand)

    # 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_vector(meas[self.length:])
    weight_check = self.offset*shares_inv + weight - \
        weight_reported

    return [range_check, weight_check]
]]></sourcecode>
          <table>
            <name>Parameters of validity circuit MultihotCountVec.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">
                  <tt>[ParallelSum(Mul(), chunk_length)]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[(length + bits_for_weight + chunk_length - 1) // chunk_length]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>MEAS_LEN</tt></td>
                <td align="left">
                  <tt>length + bits_for_weight</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>length</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>GADGET_CALLS[0]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>EVAL_OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>2</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>list[int]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">
                  <tt>list[int]</tt></td>
              </tr>
            </tbody>
          </table>
        </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 Aggregators hold a sequence of
<tt>L</tt>-bit strings, where <tt>L &lt;= BITS</tt>. We will refer to the latter as the set of
"candidate prefixes". The Aggregators' goal is to count how many measurements
are prefixed by each candidate prefix.</t>
      <t>This functionality is the core component of the Poplar protocol <xref target="BBCGGI21"/>,
which was designed to compute the heavy hitters over a set of input strings. At
a high level, the protocol works as follows.</t>
      <ol spacing="normal" type="1"><li>
          <t>Each Client splits its string into input shares and sends one share to each
Aggregator.</t>
        </li>
        <li>
          <t>The Aggregators agree on an initial set of candidate prefixes, say <tt>0</tt> and
<tt>1</tt>.</t>
        </li>
        <li>
          <t>The Aggregators evaluate the VDAF on each set of input shares and aggregate
the recovered output shares. The aggregation parameter is the set of
candidate prefixes.</t>
        </li>
        <li>
          <t>The Aggregators send their aggregate shares to the Collector, who combines
them to recover the counts of each candidate prefix.</t>
        </li>
        <li>
          <t>Let <tt>H</tt> denote the set of prefixes that occurred at least <tt>t</tt> times. If the
prefixes all have length <tt>BITS</tt>, then <tt>H</tt> is the set of <tt>t</tt>-heavy-hitters.
Otherwise compute the next set of candidate prefixes, e.g., for each <tt>p</tt> in
<tt>H</tt>, add <tt>p || 0</tt> and <tt>p || 1</tt> to the set. Repeat step 3 with the new set of
candidate prefixes.</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 that prefix at least <tt>t</tt> of the input
strings. We shall refer to this structure as the "prefix tree" for the batch of
inputs and target threshold. To compute the <tt>t</tt>-heavy hitters for a set of
inputs, 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 may leak more information about the set than the heavy hitters themselves;
see <xref target="agg-param-privacy"/> for details.)</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".)
This protocol ensures that evaluating a set of input shares on a unique set of
candidate prefixes results in shares of a "one-hot" vector, i.e., a vector that
is zero everywhere except for at most one element, which is equal to one.</t>
      <t>The remainder of this section is structured as follows. IDPFs are defined in
<xref target="idpf"/>; a concrete instantiation is given <xref target="idpf-bbcggi21"/>. The Poplar1 VDAF is
defined in <xref target="poplar1-construction"/> in terms of a generic IDPF. Finally, a
concrete instantiation of Poplar1 is specified in <xref target="poplar1-inst"/>;
test vectors 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 <tt>range(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-inst"/>) 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.)</t>
        <t>A concrete IDPF defines the types and constants 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 randomized IDPF-key generation algorithm. Its inputs are
the index <tt>alpha</tt>, the values <tt>beta</tt>, an application context string, and a
nonce string.  </t>
            <t>
The output is a public part (of type <tt>PublicShare</tt>) that is sent to all
Aggregators and a vector of private IDPF keys, one for each aggregator. The
binder string is used to derive the key in the underlying XofFixedKeyAes128
XOF that is used for expanding seeds at each level.  </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
 <tt>range(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 of length <tt>Idpf.NONCE_SIZE</tt> and chosen uniformly at
random by the Client (see <xref target="nonce-requirements"/>).</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 deterministic, stateless 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, an
application context string, and a nonce string. It returns the share of the
value corresponding to each candidate prefix.  </t>
            <t>
The output type (i.e., <tt>Output</tt>) depends on the value of <tt>level</tt>: if <tt>level &lt;
BITS-1</tt>, the output is the value for an inner node, which has type
<tt>list[list[FieldInner]]</tt>; otherwise, if <tt>level == BITS-1</tt>, then the output is
the value for a leaf node, which has type <tt>list[list[FieldLeaf]]</tt>.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>agg_id</tt> <bcp14>MUST</bcp14> be in <tt>range(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 <tt>range(0, BITS)</tt>.</t>
              </li>
              <li>
                <t>Each <tt>prefix</tt> in <tt>prefixes</tt> <bcp14>MUST</bcp14> be distinct and have length <tt>level + 1</tt>.</t>
              </li>
            </ul>
          </li>
        </ul>
        <t>In addition, the following method is derived for each concrete <tt>Idpf</tt>:</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">SHARES</td>
              <td align="left">Number of IDPF keys output by IDPF-key generator</td>
            </tr>
            <tr>
              <td align="left">BITS</td>
              <td align="left">Length in bits of each input string</td>
            </tr>
            <tr>
              <td align="left">VALUE_LEN</td>
              <td align="left">Number of field elements of each output value</td>
            </tr>
            <tr>
              <td align="left">RAND_SIZE</td>
              <td align="left">Size of the random string consumed by the IDPF-key generator. Equal to twice the XOF's seed size.</td>
            </tr>
            <tr>
              <td align="left">NONCE_SIZE</td>
              <td align="left">Size of the randon nonce generated by the Client.</td>
            </tr>
            <tr>
              <td align="left">KEY_SIZE</td>
              <td align="left">Size in bytes of each IDPF key</td>
            </tr>
            <tr>
              <td align="left">FieldInner</td>
              <td align="left">Implementation of <tt>Field</tt> (<xref target="field"/>) used for values of inner nodes</td>
            </tr>
            <tr>
              <td align="left">FieldLeaf</td>
              <td align="left">Implementation of <tt>Field</tt> used for values of leaf nodes</td>
            </tr>
            <tr>
              <td align="left">PublicShare</td>
              <td align="left">Type of public share for this IDPF</td>
            </tr>
            <tr>
              <td align="left">Output</td>
              <td align="left">Alias of <tt>list[list[FieldInner]] | list[list[FieldLeaf]]</tt></td>
            </tr>
            <tr>
              <td align="left">FieldVec</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>Construction</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 any <tt>Idpf</tt> (<xref target="idpf"/>) for which
<tt>SHARES == 2</tt> and <tt>VALUE_LEN == 2</tt> and an implementation of <tt>Xof</tt>
(<xref target="xof"/>). 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>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">same as the IDPF</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>. (See
<xref target="poplar1-idpf-index-encoding"/> for guidelines on index encoding.) 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 sketching protocol is used by
the Aggregators to verify that they hold shares of a one-hot vector. In
addition, for each level of the tree, the prover 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 the Aggregators.
Putting everything together, the sharding algorithm is defined as
follows.</t>
          <figure anchor="poplar1-mes2inp">
            <name>The sharding algorithm for Poplar1.</name>
            <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)
    (k_shard,), seeds = front(1, seeds)

    xof = self.xof(
        k_shard,
        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>
          </figure>
        </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 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>prep_init()</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>
          <figure anchor="poplar1-prep-state">
            <name>Preparation state for Poplar1.</name>
            <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)

    # 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]:
            raise ValueError('out of order prefix')

    # 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>
          </figure>
        </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 levels are
increasing between calls, and also enforces that the prefixes at each level are
suffixes of the previous level's prefixes.</t>
          <figure anchor="poplar1-validity-scope">
            <name>Validity of aggregation parameters for Poplar1.</name>
            <sourcecode type="python"><![CDATA[
def get_ancestor(
        index: tuple[bool, ...],
        level: int) -> tuple[bool, ...]:
    """
    Helper function to determine the prefix of `index` at
    `level`.
    """
    return index[:level + 1]

def is_valid(
        self,
        agg_param: Poplar1AggParam,
        previous_agg_params: list[Poplar1AggParam]) -> bool:
    """
    Checks that levels are increasing between calls, and also
    enforces that the prefixes at each level are suffixes of the
    previous level's prefixes.
    """
    if len(previous_agg_params) < 1:
        return True

    (level, prefixes) = agg_param
    (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
]]></sourcecode>
          </figure>
        </section>
        <section anchor="aggregation-2">
          <name>Aggregation</name>
          <t>Aggregation involves simply adding up the output shares.</t>
          <figure anchor="poplar1-out2agg">
            <name>Aggregation algorithm for Poplar1.</name>
            <sourcecode type="python"><![CDATA[
def aggregate(
        self,
        agg_param: Poplar1AggParam,
        out_shares: list[FieldVec]) -> FieldVec:
    (level, prefixes) = agg_param
    field = self.idpf.current_field(level)
    agg_share = cast(list[Field], field.zeros(len(prefixes)))
    for out_share in out_shares:
        agg_share = vec_add(agg_share, cast(list[Field], out_share))
    return cast(FieldVec, agg_share)
]]></sourcecode>
          </figure>
        </section>
        <section anchor="unsharding-1">
          <name>Unsharding</name>
          <t>Finally, the Collector unshards the aggregate result by adding up the aggregate
shares.</t>
          <figure anchor="poplar1-agg-output">
            <name>Computation of the aggregate result for Poplar1.</name>
            <sourcecode type="python"><![CDATA[
def unshard(
        self,
        agg_param: Poplar1AggParam,
        agg_shares: list[FieldVec],
        _num_measurements: int) -> list[int]:
    (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 [x.as_unsigned() for x in agg]
]]></sourcecode>
          </figure>
        </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>. It is <bcp14>RECOMMENDED</bcp14> that implementations
provide serialization methods for them.</t>
          <t>Message structures are defined following <xref section="3" sectionFormat="of" target="RFC8446"/>). 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[Field2, Field2]</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.as_unsigned() << (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(Field2(
        (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 * (poplar1.idpf.BITS - 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>. 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 = []
bytes_per_prefix = ((level + 1) + 7) // 8
for chunk in itertools.batched(encoded_prefixes, bytes_per_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>The IDPF scheme of <xref target="BBCGGI21"/></name>
        <t>In this section we specify a concrete IDPF suitable for instantiating
Poplar1. The scheme gets its name from the name of the protocol of
<xref target="BBCGGI21"/>.</t>
        <t>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 more information.</t>
        <table anchor="idpf-bbcggi21-param">
          <name>Constants and type definitions for the IDPF of BBCGGI21.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">SHARES</td>
              <td align="left">
                <tt>2</tt></td>
            </tr>
            <tr>
              <td align="left">BITS</td>
              <td align="left">any positive integer</td>
            </tr>
            <tr>
              <td align="left">VALUE_LEN</td>
              <td align="left">any positive integer</td>
            </tr>
            <tr>
              <td align="left">KEY_SIZE</td>
              <td align="left">
                <tt>Xof.SEED_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">FieldInner</td>
              <td align="left">
                <tt>Field64</tt> (<xref target="fields"/>)</td>
            </tr>
            <tr>
              <td align="left">FieldLeaf</td>
              <td align="left">
                <tt>Field255</tt> (<xref target="fields"/>)</td>
            </tr>
          </tbody>
        </table>
        <section anchor="key-generation">
          <name>Key Generation</name>
          <ul empty="true">
            <li>
              <t>TODO Describe the construction in prose, beginning with a gentle introduction
to the high level idea.</t>
            </li>
          </ul>
          <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"/>. In the following, we let <tt>Field2</tt> denote
the field <tt>GF(2)</tt>.</t>
          <figure anchor="idpf-bbcggi21-gen">
            <name>IDPF-key generation algorithm of BBCGGI21.</name>
            <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 = [Field2(0), Field2(1)]
    public_share = []
    for level in range(self.BITS):
        keep = int(alpha[level])
        lose = 1 - keep
        bit = Field2(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] + bit + Field2(1),
            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].as_unsigned():
            x0 = xor(s0[keep], seed_cw)
            ctrl[0] = t0[keep] + ctrl_cw[keep]
        else:
            x0 = s0[keep]
            ctrl[0] = t0[keep]
        if ctrl[1].as_unsigned():
            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].as_unsigned():
            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>
          </figure>
        </section>
        <section anchor="key-evaluation">
          <name>Key Evaluation</name>
          <ul empty="true">
            <li>
              <t>TODO Describe in prose how IDPF-key evaluation algorithm works.</t>
            </li>
          </ul>
          <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>
          <figure anchor="idpf-bbcggi21-eval">
            <name>IDPF-evaluation generation algorithm of BBCGGI21.</name>
            <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 = Field2(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: Field2,
        correction_word: CorrectionWord,
        level: int,
        bit: int,
        ctx: bytes,
        nonce: bytes) -> tuple[bytes, Field2, 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.as_unsigned():
        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.as_unsigned():
        for i in range(len(y)):
            y[i] += w_cw[i]

    return (next_seed, next_ctrl, cast(FieldVec, y))
]]></sourcecode>
          </figure>
        </section>
        <section anchor="idpf-bbcggi21-helper-functions">
          <name>Auxiliary Functions</name>
          <figure anchor="idpf-bbcggi21-helpers">
            <name>Helper functions for the IDPF.</name>
            <sourcecode type="python"><![CDATA[
def extend(
        self,
        level: int,
        seed: bytes,
        ctx: bytes,
        nonce: bytes) -> tuple[list[bytes], list[Field2]]:
    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 = [Field2(s[0][0] & 1), Field2(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>
          </figure>
        </section>
      </section>
      <section anchor="poplar1-inst">
        <name>Instantiation</name>
        <t>By default, Poplar1 is instantiated with the IDPF in <xref target="idpf-bbcggi21"/> (<tt>VALUE_LEN
== 2</tt>) and XofTurboShake128 (<xref target="xof-turboshake128"/>). This VDAF is suitable for
any positive value of <tt>BITS</tt>. Test vectors can be found in <xref target="test-vectors"/>.</t>
      </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. 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 measurement, 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="requirements-for-the-verification-key">
        <name>Requirements for 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,
a malicious Aggregator 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 conditions is required in order to leverage security analysis in
the framework of <xref target="DPRS23"/>. Their definition of robustness allows the attacker,
playing the role of a cohort of malicious Clients, to submit arbitrary reports
to the Aggregators and eavesdrop on their communications as they process them.
Security in this model is achievable as long as the verification key is kept
secret from the attacker.</t>
        <t>The privacy definition of <xref target="DPRS23"/> considers an active attacker that controls
the network and a subset of Aggregators; in addition, the attacker is allowed to
choose the verification key used by each honest Aggregator over the course of
the experiment. Security is achievable in this model as long as the key is
picked at the start of the experiment, prior to any reports being generated.
(The model also requires nonces to be generated at random; see
<xref target="nonce-requirements"/> below.)</t>
        <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 could bind reports to a shared context string
derived from the key. 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>Requirements for 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.</t>
        <t>Other security considerations may require the nonce to be non-repeating. For
example, to achieve differential privacy it is necessary to avoid "over
exposing" a report by including it too many times in a single batch or across
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="requirements-for-the-public-share">
        <name>Requirements for 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="requirements-for-aggregation-parameters">
        <name>Requirements for Aggregation Parameters</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 input
shares. This is to ensure that correlated randomness provided by the Client
through the input share is not used more than once, which might compromise
confidentiality of the Client's measurements.</t>
        <t>Protocols that make use of VDAFs therefore <bcp14>MUST</bcp14> call <tt>vdaf.is_valid</tt>
on the set of all aggregation parameters used for a Client's input share, and
only proceed with the preparation and aggregation phases if that function call
returns <tt>True</tt>.</t>
        <section anchor="agg-param-privacy">
          <name>Additional Privacy Considerations</name>
          <t>Aggregating a batch of reports multiple times, each time with a different
aggregation parameter, could 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.</t>
          <t>The only practical, general-purpose approach to mitigating these leakages is via
differential privacy, which is <bcp14>RECOMMENDED</bcp14> for all protocols using Poplar1 for
heavy-hitter type applications.</t>
        </section>
        <section anchor="safe-usage-of-idpf-outputs">
          <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
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 the heavy-hitters tree traversal.</t>
        </section>
      </section>
      <section anchor="xof-vs-ro">
        <name>Requirements for XOFs</name>
        <t>As described in <xref target="xof"/>, our constructions rely on eXtendable Output Functions
(XOFs). In the security analyses of our protocols, these 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>Our construction at <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 16 byte seeds, 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 FLPs (<xref target="flp-bbcggi19"/> in particular) 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>. This is because there is no
binding of the circuit parameters to the computation.</t>
      </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 0x00000000
and the maximum possible value is 0xffffffff.</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-inst"/> 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 failures of entropy sources, by ensuring that
invocations of different VDAFs use different derived values, even if they are
invoked with the same underlying random data.</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="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="9" month="May" 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-14"/>
        </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">
              <organization/>
            </author>
            <author initials="K." surname="Garbe">
              <organization/>
            </author>
            <author initials="E." surname="Jaffe">
              <organization/>
            </author>
            <author initials="R." surname="Ostrovsky">
              <organization/>
            </author>
            <author initials="A." surname="Polychroniadou">
              <organization/>
            </author>
            <date year="2021"/>
          </front>
        </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">
              <organization/>
            </author>
            <author initials="E." surname="Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2019"/>
          </front>
          <seriesInfo name="CRYPTO 2019" value=""/>
        </reference>
        <reference anchor="BBCGGI21" target="https://ia.cr/2021/017">
          <front>
            <title>Lightweight Techniques for Private Heavy Hitters</title>
            <author initials="D." surname="Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2021"/>
          </front>
          <seriesInfo name="IEEE S&amp;P 2021" value=""/>
        </reference>
        <reference anchor="BBCGGI23" target="https://ia.cr/2023/1012">
          <front>
            <title>Arithmetic Sketching</title>
            <author initials="D." surname="Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2023"/>
          </front>
          <seriesInfo name="CRYPTO 2023" value=""/>
        </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">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2015"/>
          </front>
          <seriesInfo name="EUROCRYPT 2015" value=""/>
        </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="H." surname="Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="D." surname="Boneh">
              <organization/>
            </author>
            <date year="2017"/>
          </front>
          <seriesInfo name="NSDI 2017" value=""/>
        </reference>
        <reference anchor="Dou02" target="https://doi.org/10.1007/3-540-45748-8_24">
          <front>
            <title>The Sybil Attack</title>
            <author initials="J." surname="Douceur">
              <organization/>
            </author>
            <date year="2002"/>
          </front>
          <seriesInfo name="IPTPS 2002" value=""/>
        </reference>
        <reference anchor="DPRS23" target="https://ia.cr/2023/130">
          <front>
            <title>Verifiable Distributed Aggregation Functions</title>
            <author initials="H." surname="Davis">
              <organization/>
            </author>
            <author initials="C." surname="Patton">
              <organization/>
            </author>
            <author initials="M." surname="Rosulek">
              <organization/>
            </author>
            <author initials="P." surname="Schoppmann">
              <organization/>
            </author>
            <date year="2023"/>
          </front>
          <seriesInfo name="PETS 2023" value=""/>
        </reference>
        <reference anchor="Dwo06" target="https://link.springer.com/chapter/10.1007/11787006_1">
          <front>
            <title>Differential Privacy</title>
            <author initials="C." surname="Dwork">
              <organization/>
            </author>
            <date year="2006"/>
          </front>
          <seriesInfo name="ICALP 2006" value=""/>
        </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">
              <organization/>
            </author>
            <author initials="V." surname="Pihur">
              <organization/>
            </author>
            <author initials="A." surname="Korolova">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <seriesInfo name="CCS 2014" value=""/>
        </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">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <seriesInfo name="EUROCRYPT 2014" value=""/>
        </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">
              <organization/>
            </author>
            <author initials="Y." surname="Song">
              <organization/>
            </author>
            <author initials="C." surname="Zhu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <seriesInfo name="CRYPTO 2020" value=""/>
        </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">
              <organization/>
            </author>
            <author initials="J." surname="Katz">
              <organization/>
            </author>
            <author initials="X." surname="Wang">
              <organization/>
            </author>
            <author initials="C." surname="Weng">
              <organization/>
            </author>
            <author initials="Y." surname="Yu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <seriesInfo name="CRYPTO 2020" value=""/>
        </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">
              <organization/>
            </author>
            <author initials="J." surname="Katz">
              <organization/>
            </author>
            <author initials="X." surname="Wang">
              <organization/>
            </author>
            <author initials="Y." surname="Yu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <seriesInfo name="S&amp;P 2020" value=""/>
        </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">
              <organization/>
            </author>
            <author initials="C." surname="Patton">
              <organization/>
            </author>
            <author initials="H." surname="Davis">
              <organization/>
            </author>
            <author initials="P." surname="Sarkar">
              <organization/>
            </author>
            <author initials="N. G." surname="Tsoutsos">
              <organization/>
            </author>
            <date year="2025"/>
          </front>
          <seriesInfo name="PETS 2025" value=""/>
        </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">
              <organization/>
            </author>
            <author initials="O." surname="Pandey">
              <organization/>
            </author>
            <author initials="O." surname="Reingold">
              <organization/>
            </author>
            <author initials="S." surname="Vadhan">
              <organization/>
            </author>
            <date>n.d.</date>
          </front>
          <seriesInfo name="CRYPTO 2009" value=""/>
        </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>ETH Zurich</organization>
            </author>
            <author initials="R." surname="Renner" fullname="Renato Renner">
              <organization>ETH Zurich</organization>
            </author>
            <author initials="C." surname="Holenstein" fullname="Clemens Holenstein">
              <organization>ETH Zurich</organization>
            </author>
            <date year="2004" month="February"/>
          </front>
          <seriesInfo name="In" value="TCC 2004: Theory of Cryptography"/>
          <seriesInfo name="pages" value="21-39"/>
          <seriesInfo name="DOI" value="10.1007/978-3-540-24638-1_2"/>
        </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">
              <organization/>
            </author>
            <author initials="R." surname="Mareta">
              <organization/>
            </author>
            <author initials="H." surname="Lee">
              <organization/>
            </author>
            <date year="2024"/>
          </front>
        </reference>
        <reference anchor="TestVectors" target="https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/test_vec/vdaf">
          <front>
            <title>Test vectors for Prio3 and Poplar1</title>
            <author>
              <organization/>
            </author>
            <date year="2024" month="September"/>
          </front>
          <seriesInfo name="commit hash &lt;TODO&gt;" value=""/>
        </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>Mozilla</organization>
            </author>
            <author fullname="Christopher A. Wood" initials="C. A." surname="Wood">
              <organization>Cloudflare</organization>
            </author>
            <date day="21" month="May" 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-11"/>
        </reference>
      </references>
    </references>
    <?line 5805?>

<section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The impetus of this work is the success of recent deployments of predecessors
of Prio3. The Mozilla Origin Telemetry project <xref target="OriginTelemetry"/> and the
Exposure Notification Private Analytics collaboration among the Internet
Security Research Group (ISRG), Google, Apple, and others <xref target="ENPA"/> have
together 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>
    <section numbered="false" anchor="test-vectors">
      <name>Test Vectors</name>
      <ul empty="true">
        <li>
          <t>TODO Update the reference in <xref target="TestVectors"/> by replacing <tt>&lt;TODO&gt;</tt> with
the commit hash with the final version of the test vectors.)</t>
        </li>
      </ul>
      <t>The test vectors are available at <xref target="TestVectors"/>. The directory contains a set
of JSON files. Each file contains a test vector for an instance of <tt>Vdaf</tt>
(<xref target="vdaf"/>). A test vector covers sharding, preparation, aggregation, and
unsharding of each of several measurements. The test vector schema is defined
below.</t>
      <section numbered="false" 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 of type <tt>Vdaf.AggParam</tt>.</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>Vdaf.Measurement</tt>.</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 incoded 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>Vdaf.AggResult</tt>.</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 numbered="false" 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 numbered="false" 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 measurement, an integer. Each element is in range
<tt>range(max_measurement+1)</tt>.</t>
            </dd>
          </dl>
        </section>
        <section numbered="false" 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 lengh of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>the length of each vector chunk, 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
<tt>range(2 ** bits)</tt>.</t>
            </dd>
          </dl>
        </section>
        <section numbered="false" 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 lengh of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>the length of each vector chunk, an integer.</t>
            </dd>
          </dl>
        </section>
        <section numbered="false" 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 lengh of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>the length of each vector chunk, an integer.</t>
            </dd>
            <dt><tt>max_weight</tt>:</dt>
            <dd>
              <t>The largest vector weight, an integer. The sum of the elements must be in
<tt>range(max_weight+1)</tt>.</t>
            </dd>
          </dl>
        </section>
        <section numbered="false" anchor="poplar1-test-vec-param">
          <name>Poplar1</name>
          <dl>
            <dt><tt>bits</tt>:</dt>
            <dd>
              <t>The length of each input, an integer.</t>
            </dd>
          </dl>
        </section>
      </section>
    </section>
  </back>
  <!-- ##markdown-source:
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
NdM5NYy/qa59W2tJmBR7w7Eqs8zati3R41TYBMhih0rLkG0eW1F5w5lpu0aC
kl8vObmuPCWFpk+55HXhyvE/tV3CaaGzeJ5OkkLq053H+XCqfUVeBfwPG5fB
MKF/PqM/9ktXW1551/db+m/Nn33zHzvEPzEFu4U8o774VV+qBQ40/vz0pWcp
LoF+Mvk7s/aNr/qCX8knnmrlp372U3Wg5nHfhs++DZ99q58lqsALONsIf26G
P98xnehtvv/SjDx8whn5yIq3JvgtP+nZIMDHhFEw4W87H8ZaFEkJj4IQiFPv
/afwALJTFjX3f0gcxbQZ2shEQqzZNoPyq0g3sTUXBtDZDEj9Bkq8IABpsuFl
IEsOouiIWa1e7AXlQZJvnTO6g+9yclEl6k0YaMSC7bVUAkqlrxB9q/p0WFtb
Z4JTouZCmut5f5O3Qjget+2EI8pI07IRth9KxxJb6XoRbRurp1VkpCg8YNsm
kI0Ubm4bLyNRgKLX0FJrMcQGnlhDmRqJBeX1Qu4s0ZzWmtoEaipS0wjsSpS+
oF73Bq5Ac/P7/G0h3FHZP24yRLOd3kkaMJZy27Oc5QU3lWMQmjibJSmSdnjL
wuB8tr7w8ZPCk5y7z+AYJ9ecDIF/A7VNrunU2oCYhSq86VmzDe1YK9hpeY5V
jLeqm5u2Tx77anz+4Nl65r1ilIEeCgdwV6mpRa3S2KudP3HPd1AHk5xiIFT1
jEJKpfhlkW+wcf8K6g0o/TCtXIfKDMtnSopxGpg+rWvH1a2ju/4wDlwcrnjz
0klEN9PijICg+1zbCoZn7lrR8SG/p/kykUyFaNDwKEnICJqCg5cbV89Lo51c
uIr2EbUAcjWHvUddG4GiiHaGwOS2p0KRrDfBE6T6MjXtaViFTemQZyivA6Pr
s2w62OZQ5MKKkZVu3bUu9QAFlZ4hCbw1sDH6apT1eOoEtjUsguOiAr8DF0xf
Y3bn3aObSREo7nX7ZYfMG9q9MHMqtQpEimqBSCJc+k1wd5p3IbPUwgLf0nJO
qnGmjchYVTik7BrTQsqOwShKK1aQQw+Q+AzXeBy0bFyRUGoiyjoxBa8/U39N
v6vXnmnpO/OSGspq6vcm/Q6f8fLa2Ubt9c3K65s3vb5Ze32r8vrWTa9v+bDX
IKK34be6Xvvm88o3n9/0zefN0nhj4HAgo6q/6m+6VlM+7jX8rj0jeo4/FJ8a
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
AXE6oe3b/W2SqXb397/fVs7E0qkDAA==

-->

</rfc>
