<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.29 (Ruby 3.4.4) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-irtf-cfrg-vdaf-16" category="info" submissionType="IRTF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.30.2 -->
  <?v3xml2rfc silence="Found SVG with width or height specified"?>
  <front>
    <title abbrev="VDAF">Verifiable Distributed Aggregation Functions</title>
    <seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-vdaf-16"/>
    <author initials="R. L." surname="Barnes" fullname="Richard L. Barnes">
      <organization>Cisco</organization>
      <address>
        <email>rlb@ipv.sx</email>
      </address>
    </author>
    <author initials="D." surname="Cook" fullname="David Cook">
      <organization>ISRG</organization>
      <address>
        <email>divergentdave@gmail.com</email>
      </address>
    </author>
    <author initials="C." surname="Patton" fullname="Christopher Patton">
      <organization>Cloudflare</organization>
      <address>
        <email>chrispatton+ietf@gmail.com</email>
      </address>
    </author>
    <author initials="P." surname="Schoppmann" fullname="Phillipp Schoppmann">
      <organization>Google</organization>
      <address>
        <email>schoppmann@google.com</email>
      </address>
    </author>
    <date year="2025" month="September" day="22"/>
    <area>IRTF</area>
    <workgroup>CFRG</workgroup>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <?line 269?>

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

<section anchor="introduction">
      <name>Introduction</name>
      <t>(RFC EDITOR: remove this paragraph.) The source for this draft and the
reference implementation can be found at
https://github.com/cfrg/draft-irtf-cfrg-vdaf.</t>
      <t>The ubiquity of the Internet makes it an ideal platform for measurement of
large-scale phenomena, whether public health trends or the behavior of computer
systems at scale. There is substantial overlap, however, between information
that is valuable to measure and information that users consider private.</t>
      <t>For example, consider an application that provides health information to users.
The operator of an application might want to know which parts of their
application are used most often, as a way to guide future development of the
application. Specific users' patterns of usage, though, could reveal sensitive
things about them, such as which users are researching a given health
condition.</t>
      <t>In many situations, the measurement collector is only interested in aggregate
statistics, e.g., which portions of an application are most used or what
fraction of people have experienced a given disease. Thus systems that provide
aggregate statistics while protecting individual measurements can deliver the
value of the measurements while protecting users' privacy.</t>
      <t>This problem is often formulated in terms of differential privacy (DP)
<xref target="Dwo06"/>. Roughly speaking, a data aggregation system that is differentially
private ensures that the degree to which any individual measurement influences
the value of the aggregate result can be precisely controlled. For example, in
systems like RAPPOR <xref target="EPK14"/>, each user samples noise from a well-known
distribution and adds it to their measurement before submitting to the
aggregation server. The aggregation server then adds up the noisy measurements,
and because it knows the distribution from which the noise was sampled, it can
estimate the true sum with reasonable accuracy.</t>
      <t>Even when noise is added to the measurements, collecting them in the clear
still reveals a significant amount of information to the collector. On the one
hand, depending on the "amount" of noise a client adds to its measurement, it
may be possible for a curious collector to make a reasonable guess of the
measurement's true value. On the other hand, the more noise the clients add,
the less reliable will be the server's estimate of the aggregate. Thus systems
relying solely on a DP mechanism must strike a delicate balance between privacy
and utility.</t>
      <t>Another way of constructing a privacy-preserving measurement system is to use
multi-party computation (MPC). The goal of such a system is that no participant
in the protocol should learn anything about an individual measurement beyond
what it can deduce from the aggregate. MPC achieves this goal by distributing
the computation of the aggregate across multiple aggregation servers, one of
which is presumed to be honest, i.e., not under control of the attacker.
Moreover, MPC can be composed with various DP mechanisms to ensure the
aggregate itself does not leak too much information about any one of the
measurements <xref target="MPRV09"/>.</t>
      <t>This document describes two classes of MPC protocols, each aiming for a
different set of goals.</t>
      <t>In a Distributed Aggregation Function (DAF, <xref target="daf"/>), each client splits its
measurement into multiple secret shares, one for each aggregation
server. DAFs require two properties of the secret sharing scheme. First, one
can reconstruct the underlying measurement by simply adding up all of the
shares. (Typically the shares are vectors over some finite field.) Second,
given all but one of the shares, it is impossible to learn anything about the
underlying measurement. These properties give rise to a simple strategy for
privately aggregating the measurements: each aggregation server adds up its
measurement shares locally before revealing their sum to the data collector;
then all the data collector has to do is add up these sums to get the aggregate
result.</t>
      <t>This strategy is compatible with any aggregation function that can be
represented as the sum of some encoding of the measurements. Examples include:
summary statistics such as sum, mean, and standard deviation; estimation of
quantiles, e.g., median; histograms; linear regression; or counting data
structures, e.g., Bloom filters. However, not all functions fit into this
rubric, as it is constrained to linear computations over the encoded
measurements.</t>
      <t>In fact, this document's framework admits DAFs with slightly more
functionality, computing aggregation functions of the form</t>
      <artwork><![CDATA[
F(agg_param, meas_1, ..., meas_M) =
    G(agg_param, meas_1) + ... + G(agg_param, meas_M)
]]></artwork>
      <t>where <tt>meas_1, ..., meas_M</tt> are the measurements, <tt>G</tt> is a possibly
non-linear function, and <tt>agg_param</tt> is a parameter of that function chosen by
the data collector. This paradigm, known as function secret sharing <xref target="BGI15"/>,
allows for more sophisticated data analysis tasks, such as grouping metrics by
private client attributes <xref target="MPDST25"/> or computing heavy hitters <xref target="BBCGGI21"/>.
(More on the latter task below.)</t>
      <t>The second class of protocols defined in this document are called Verifiable
Distributed Aggregation Functions (VDAFs, <xref target="vdaf"/>). In addition to being
private, VDAFs are verifiable in the following sense. By design, a secret
sharing of a valid measurement, e.g., a number between 1 and 10, is
indistinguishable from a secret sharing of an invalid measurement, e.g., a
number larger than 10. This means that DAFs are vulnerable to attacks from
malicious clients attempting to disrupt the computation by submitting invalid
measurements. VDAFs are designed to allow the servers to interact with one
another in order to detect and remove these measurements prior to
aggregation. This document refers to this property as verifiability. (This is
also called robustness in prior work <xref target="CGB17"/>, <xref target="DPRS23"/>.)</t>
      <t>Achieving verifiability using the cryptographic techniques described in this
document requires a significant amount of interaction between the servers. DAFs
on the other hand are non-interactive, making them easier to deploy; but they
do not on their own allow for verifying the validity of the measurements. This
may be tolerable in some applications. For instance, if the client's software
is executed in a trusted execution environment, it may be reasonable to assume
that no client is malicious.</t>
      <t>The DAF and VDAF abstractions encompass a variety of MPC techniques in the
literature. These protocols vary in their operational and security
requirements, sometimes in subtle but consequential ways. This document
therefore has two important goals:</t>
      <ol spacing="normal" type="1"><li>
          <t>Provide higher-level protocols, like <xref target="DAP"/>, with
a simple, uniform interface for accessing privacy-preserving measurement
schemes, document relevant operational and security requirements, and
specify constraints for safe usage:  </t>
          <ol spacing="normal" type="1"><li>
              <t>General patterns of communications among the various actors involved in
the system (clients, aggregation servers, and the collector of the
aggregate result);</t>
            </li>
            <li>
              <t>Capabilities of a malicious coalition of parties attempting to divulge
information about client measurements; and</t>
            </li>
            <li>
              <t>Conditions that are necessary to ensure that malicious clients cannot
corrupt the computation.</t>
            </li>
          </ol>
        </li>
        <li>
          <t>Provide cryptographers with design criteria that provide a clear deployment
roadmap for new constructions of privacy-preserving measurement systems.</t>
        </li>
      </ol>
      <t>This document also specifies two concrete VDAF schemes, each based on a protocol
from the literature.</t>
      <ul spacing="normal">
        <li>
          <t>The Prio system <xref target="CGB17"/> allows for the privacy-preserving computation of a
variety of aggregate statistics, combining additive secret sharing as
described above with a mechanism for checking the validity of each
measurement. <xref target="prio3"/> specifies Prio3, a VDAF that follows the same overall
framework as the original Prio protocol, but incorporates techniques
introduced in <xref target="BBCGGI19"/> that result in significant performance gains.</t>
        </li>
        <li>
          <t>The Poplar protocol <xref target="BBCGGI21"/> solves a problem known as private
heavy-hitters. In this problem, each client holds a bit-string, and the goal
of the aggregation servers is to compute the set of strings that occur at
least <tt>T</tt> times for some threshold <tt>T</tt>. The core primitive in their protocol
is a secret sharing of a point function <xref target="GI14"/> (denoted <tt>G</tt> above) that
allows the servers to privately count how many of the clients' strings begin
with a given prefix (<tt>agg_param</tt> in the notation above). <xref target="poplar1"/>
specifies a VDAF called Poplar1 that implements this prefix counting
functionality and describe how it is used in the heavy hitters protocol.</t>
        </li>
      </ul>
      <t>The remainder of this document is organized as follows: <xref target="conventions"/> lists
definitions and conventions used in the remainder of the document; <xref target="overview"/>
gives a brief overview of DAFs and VDAFs, the parties involved in the
computation, and the requirements for non-collusion; <xref target="daf"/> defines the syntax
for DAFs; <xref target="vdaf"/> defines the syntax for VDAFs; <xref target="prelim"/> defines various
functionalities that are common to the constructions defined in this document;
<xref target="prio3"/> specifies Prio3; <xref target="poplar1"/> specifies Poplar1; and <xref target="security"/>
enumerates security considerations for DAFs and VDAFs in general and the
Prio3 and Poplar1 constructions in particular.</t>
      <section anchor="change-log">
        <name>Change Log</name>
        <t>(RFC EDITOR: remove this section.)</t>
        <t>(*) Indicates a change that breaks wire compatibility with the previous draft.</t>
        <t>16:</t>
        <ul spacing="normal">
          <li>
            <t>Align document with guidelines for ASCII-safe mathematical notation from
<xref section="3.3.1.6" sectionFormat="of" target="I-D.draft-irtf-cfrg-cryptography-specification-02"/>.</t>
          </li>
          <li>
            <t>Address feedback from Crypto Review Panel <xref target="PANEL-FEEDBACK"/>.</t>
          </li>
        </ul>
        <t>15:</t>
        <ul spacing="normal">
          <li>
            <t>Simplify the ping-pong API for 2-party preparation by merging the outbound
message into the state object. This reduces the number of cases the caller
has to handle.</t>
          </li>
          <li>
            <t>Update the test vector format. First, enrich the test vector schema to
express negative test cases. Second, change the encoding of output shares to
match the aggregate shares.</t>
          </li>
        </ul>
        <t>14:</t>
        <ul spacing="normal">
          <li>
            <t>Poplar1: When decoding an aggregation parameter, require the padding bits
after each prefix to be cleared.</t>
          </li>
        </ul>
        <t>13:</t>
        <ul spacing="normal">
          <li>
            <t>(V)DAF: Replace the one-shot aggregation API with a streaming API. Each
Aggregator initializes aggregation, then updates its aggregate share as
output shares are produced. The scheme also specifies a method for merging
multiple aggregate shares.</t>
          </li>
          <li>
            <t>Poplar1: Move prefix uniqueness and ordering checks from <tt>prep_init()</tt> to
<tt>is_valid()</tt>.</t>
          </li>
          <li>
            <t>Poplar1: Use <tt>bool</tt> to represent control bits instead of <tt>Field2</tt>.</t>
          </li>
          <li>
            <t>Prio3MultihotCountVec: Change the measurement type from <tt>list[int]</tt> to
<tt>list[bool]</tt>.</t>
          </li>
          <li>
            <t>Security considerations: Define our threat model for side channel attacks and
enumerate the parts of the spec that are most relevant to implementers.</t>
          </li>
          <li>
            <t>Improve the specification of each Prio3 variant by listing each
implementation of <tt>Valid</tt> and <tt>Gadget</tt> in full. Gadgets are listed in a new
appendix section.</t>
          </li>
          <li>
            <t>Improve the specification of the FLP system by listing the proof-generation,
query, and decision algorithms in full. The wrapper gadgets are listed in the
new section of the appendix for gadgets.</t>
          </li>
          <li>
            <t>Add a section with a high-level overview of the IDPF construction.</t>
          </li>
          <li>
            <t>Move some sections around: move ping-pong and star topologies under
communication patterns for VDAF preparation; move FLP proof generation,
query, and decision algorithms up one level; move privacy considerations for
aggregation parameters up one level; and move safe usage of IDPF outputs up
one level.</t>
          </li>
        </ul>
        <t>12:</t>
        <ul spacing="normal">
          <li>
            <t>(V)DAF: Add an application context string parameter to sharding and
preparation. The motivation for this change is to harden Prio3 against
offline attacks. More generally, however, it allows designing schemes for
which correct execution requires agreement on the application context.
Accordingly, both Prio3 and Poplar1 have been modified to include the context
in the domain separation tag of each XOF invocation. (*)</t>
          </li>
          <li>
            <t>Prio3: Improve soundness of the base proof system and the circuits of some
variants. Generally speaking, wherever we evaluate a univariate polynomial at
a random point, we can instead evaluate a multivariate polynomial of lower
degree. (*)</t>
          </li>
          <li>
            <t>Prio3: Replace the helper's measurement and proof share seeds with a single
seed. (*)</t>
          </li>
          <li>
            <t>Prio3Sum: Update the circuit to support a more general range check and avoid
using joint randomness. (*)</t>
          </li>
          <li>
            <t>Prio3Histogram, Prio3MultihotCountVec: Move the final reduction of the
intermediate outputs out of the circuit. (*)</t>
          </li>
          <li>
            <t>IDPF: Add the application context string to key generation and evaluation and
bind it to the fixed AES key. (*)</t>
          </li>
          <li>
            <t>IDPF: Use XofTurboShake128 for deriving the leaf nodes in order to ensure the
construction is extractable. (*)</t>
          </li>
          <li>
            <t>IDPF: Simplify the public share encoding. (*)</t>
          </li>
          <li>
            <t>XofTurboShake128: Change <tt>SEED_SIZE</tt> from 16 bytes to 32 to mitigate offline
attacks on Prio3 robustness. In addition, allow seeds of different lengths so
that we can continue to use XofTurboShake128 with IDPF. (*)</t>
          </li>
          <li>
            <t>XofTurboShake128, XofFixedKeyAes128: Increase the length prefix for the
domain separation tag from one by to two bytes. This is to accommodate the
application context. (*)</t>
          </li>
          <li>
            <t>Reassign codepoints for all Prio3 variants and Poplar1. (*)</t>
          </li>
          <li>
            <t>Security considerations: Add a section on defense-in-depth measures taken by
Prio3 and Poplar1 and more discussion about choosing FLP parameters.</t>
          </li>
        </ul>
        <t>11:</t>
        <ul spacing="normal">
          <li>
            <t>Define message formats for the Poplar1 aggregation parameter and IDPF public
share.</t>
          </li>
          <li>
            <t>IDPF: Require the IDPF binder must be a random nonce.</t>
          </li>
          <li>
            <t>VDAF: Replace the pseudocode description of the ping-ping topology with
Python and sketch the star topology.</t>
          </li>
          <li>
            <t>DAF: Align aggregation parameter validation with VDAF.</t>
          </li>
          <li>
            <t>Replace <tt>Union[A, B]</tt> type with <tt>A | B</tt>.</t>
          </li>
          <li>
            <t>Rename FFT ("Fast Fourier Transform") with NTT ("Number Theoretic
Transform").</t>
          </li>
        </ul>
        <t>10:</t>
        <ul spacing="normal">
          <li>
            <t>Define Prio3MultihotCountVec, a variant of Prio3 for aggregating bit vectors
with bounded weight.</t>
          </li>
          <li>
            <t>FLP: Allow the output of the circuit to be a vector. This makes it possible
to skip joint randomness derivation in more cases.</t>
          </li>
          <li>
            <t>Poplar1: On the first round of preparation, handle <tt>None</tt> as an error.
Previously this message was interpreted as a length-3 vector of zeros.</t>
          </li>
          <li>
            <t>Prio3: Move specification of the field from the FLP validity circuit to the
VDAF itself.</t>
          </li>
          <li>
            <t>Clarify the extent to which the attacker controls the network in our threat
models for privacy and robustness.</t>
          </li>
          <li>
            <t>Clean up various aspects of the code, including: Follow existing
object-oriented programming patterns for Python more closely; make the type
hints enforceable; and avoid shadowing variables.</t>
          </li>
          <li>
            <t>Poplar1: Align terminology with <xref target="BBCGGI23"/>.</t>
          </li>
          <li>
            <t>IDPF: Add guidance for encoding byte strings as indices.</t>
          </li>
        </ul>
        <t>09:</t>
        <ul spacing="normal">
          <li>
            <t>Poplar1: Make prefix tree traversal stricter by requiring each node to be a
child of a node that was already visited. This change is intended to make it
harder for a malicious Aggregator to steer traversal towards
non-heavy-hitting measurements.</t>
          </li>
          <li>
            <t>Prio3: Add more explicit guidance for choosing the field size.</t>
          </li>
          <li>
            <t>IDPF: Define extractability and clarify (un)safe usage of intermediate prefix
counts. Accordingly, add text ensuring public share consistency to security
considerations.</t>
          </li>
        </ul>
        <t>08:</t>
        <ul spacing="normal">
          <li>
            <t>Poplar1: Bind the report nonce to the authenticator vector programmed into
the IDPF. (*)</t>
          </li>
          <li>
            <t>IdpfPoplar: Modify <tt>extend()</tt> by stealing each control bit from its
corresponding seed. This improves performance by reducing the number of AES
calls per level from 3 to 2. The cost is a slight reduction in the concrete
privacy bound. (*)</t>
          </li>
          <li>
            <t>Prio3: Add support for generating and verifying multiple proofs per
measurement. This enables a trade-off between communication cost and runtime:
if more proofs are used, then a smaller field can be used without impacting
robustness. (*)</t>
          </li>
          <li>
            <t>Replace SHAKE128 with TurboSHAKE128. (*)</t>
          </li>
        </ul>
        <t>07:</t>
        <ul spacing="normal">
          <li>
            <t>Rename PRG to XOF ("eXtendable Output Function"). Accordingly, rename PrgSha3
to XofShake128 and PrgFixedKeyAes128 to XofFixedKeyAes128. "PRG" is a misnomer
since we don't actually treat this object as a pseudorandom generator in
existing security analysis.</t>
          </li>
          <li>
            <t>Replace cSHAKE128 with SHAKE128, re-implementing domain separation for the
customization string using a simpler scheme. This change addresses the
reality that implementations of cSHAKE128 are less common. (*)</t>
          </li>
          <li>
            <t>Define a new VDAF, called Prio3SumVec, that generalizes Prio3Sum to a vector
of summands.</t>
          </li>
          <li>
            <t>Prio3Histogram: Update the codepoint and use the parallel sum optimization
introduced by Prio3SumVec to reduce the proof size. (*)</t>
          </li>
          <li>
            <t>Daf, Vdaf: Rename interface methods to match verbiage in the draft.</t>
          </li>
          <li>
            <t>Daf: Align with Vdaf by adding a nonce to <tt>shard()</tt> and <tt>prep()</tt>.</t>
          </li>
          <li>
            <t>Vdaf: Have <tt>prep_init()</tt> compute the first prep share. This change is
intended to simplify the interface by making the input to <tt>prep_next()</tt> not
optional.</t>
          </li>
          <li>
            <t>Prio3: Split sharding into two auxiliary functions, one for sharding with
joint randomness and another without. This change is intended to improve
readability.</t>
          </li>
          <li>
            <t>Fix bugs in the ping-pong interface discovered after implementing it.</t>
          </li>
        </ul>
        <t>06:</t>
        <ul spacing="normal">
          <li>
            <t>Vdaf: Define a wrapper interface for preparation that is suitable for the
"ping-pong" topology in which two Aggregators exchange messages over a
request/response protocol, like HTTP, and take turns executing the
computation until input from the peer is required.</t>
          </li>
          <li>
            <t>Prio3Histogram: Generalize the measurement type so that the histogram can be
used more easily with discrete domains. (*)</t>
          </li>
          <li>
            <t>Daf, Vdaf: Change the aggregation parameter validation algorithm to take the
set of previous parameters rather than a list. (The order of the parameters
is irrelevant.)</t>
          </li>
          <li>
            <t>Daf, Vdaf, Idpf: Add parameter <tt>RAND_SIZE</tt> that specifies the number of
random bytes consumed by the randomized algorithm (<tt>shard()</tt> for Daf and Vdaf
and <tt>gen()</tt> for Idpf).</t>
          </li>
        </ul>
        <t>05:</t>
        <ul spacing="normal">
          <li>
            <t>IdpfPoplar: Replace PrgSha3 with PrgFixedKeyAes128, a fixed-key mode for
AES-128 based on a construction from <xref target="GKWWY20"/>. This change is intended to
improve performance of IDPF evaluation. Note that the new PRG is not suitable
for all applications. (*)</t>
          </li>
          <li>
            <t>Idpf: Add a binder string to the key-generation and evaluation algorithms.
This is used to plumb the nonce generated by the Client to the PRG.</t>
          </li>
          <li>
            <t>Plumb random coins through the interface of randomized algorithms.
Specifically, add a random input to (V)DAF sharding algorithm and IDPF
key-generation algorithm and require implementations to specify the length of
the random input. Accordingly, update Prio3, Poplar1, and IdpfPoplar to match
the new interface. This change is intended to improve coverage of test
vectors.</t>
          </li>
          <li>
            <t>Use little-endian byte-order for field element encoding. (*)</t>
          </li>
          <li>
            <t>Poplar1: Move the last step of sketch evaluation from <tt>prep_next()</tt> to
<tt>prep_shares_to_prep()</tt>.</t>
          </li>
        </ul>
        <t>04:</t>
        <ul spacing="normal">
          <li>
            <t>Align security considerations with the security analysis of <xref target="DPRS23"/>.</t>
          </li>
          <li>
            <t>Vdaf: Pass the nonce to the sharding algorithm.</t>
          </li>
          <li>
            <t>Vdaf: Rather than allow the application to choose the nonce length, have each
implementation of the Vdaf interface specify the expected nonce length. (*)</t>
          </li>
          <li>
            <t>Prg: Split "info string" into two components: the "customization string",
intended for domain separation; and the "binder string", used to bind the
output to ephemeral values, like the nonce, associated with execution of a
(V)DAF.</t>
          </li>
          <li>
            <t>Replace PrgAes128 with PrgSha3, an implementation of the Prg interface based
on SHA-3, and use the new scheme as the default. Accordingly, replace
Prio3Aes128Count with Prio3Count, Poplar1Aes128 with Poplar1, and so on. SHA-3
is a safer choice for instantiating a random oracle, which is used in the
analysis of Prio3 of <xref target="DPRS23"/>. (*)</t>
          </li>
          <li>
            <t>Prio3, Poplar1: Ensure each invocation of the Prg uses a distinct
customization string, as suggested by <xref target="DPRS23"/>. This is intended to make
domain separation clearer, thereby simplifying security analysis. (*)</t>
          </li>
          <li>
            <t>Prio3: Replace "joint randomness hints" sent in each input share with "joint
randomness parts" sent in the public share. This reduces communication
overhead when the number of shares exceeds two. (*)</t>
          </li>
          <li>
            <t>Prio3: Bind nonce to joint randomness parts. This is intended to address
birthday attacks on robustness pointed out by <xref target="DPRS23"/>. (*)</t>
          </li>
          <li>
            <t>Poplar1: Use different Prg invocations for producing the correlated randomness
for inner and leaf nodes of the IDPF tree. This is intended to simplify
implementations. (*)</t>
          </li>
          <li>
            <t>Poplar1: Don't bind the candidate prefixes to the verifier randomness. This is
intended to improve performance, while not impacting security. According to
the analysis of <xref target="DPRS23"/>, it is necessary to restrict Poplar1 usage such
that no report is aggregated more than once at a given level of the IDPF tree;
otherwise, attacks on privacy may be possible. In light of this restriction,
there is no added benefit of binding to the prefixes themselves. (*)</t>
          </li>
          <li>
            <t>Poplar1: During preparation, assert that all candidate prefixes are unique
and appear in order. Uniqueness is required to avoid erroneously rejecting a
valid report; the ordering constraint ensures the uniqueness check can be
performed efficiently. (*)</t>
          </li>
          <li>
            <t>Poplar1: Increase the maximum candidate prefix count in the encoding of the
aggregation parameter. (*)</t>
          </li>
          <li>
            <t>Poplar1: Bind the nonce to the correlated randomness derivation. This is
intended to provide defense-in-depth by ensuring the Aggregators reject the
report if the nonce does not match what the Client used for sharding. (*)</t>
          </li>
          <li>
            <t>Poplar1: Clarify that the aggregation parameter encoding is <bcp14>OPTIONAL</bcp14>.
Accordingly, update implementation considerations around cross-aggregation
state.</t>
          </li>
          <li>
            <t>IdpfPoplar: Add implementation considerations around branching on the values
of control bits.</t>
          </li>
          <li>
            <t>IdpfPoplar: When decoding the control bits in the public share, assert
that the trailing bits of the final byte are all zero. (*)</t>
          </li>
        </ul>
        <t>03:</t>
        <ul spacing="normal">
          <li>
            <t>Define codepoints for (V)DAFs and use them for domain separation in Prio3 and
Poplar1. (*)</t>
          </li>
          <li>
            <t>Prio3: Align joint randomness computation with revised paper <xref target="BBCGGI19"/>.
This change mitigates an attack on robustness. (*)</t>
          </li>
          <li>
            <t>Prio3: Remove an intermediate PRG evaluation from query randomness generation.
(*)</t>
          </li>
          <li>
            <t>Add additional guidance for choosing FFT-friendly fields.</t>
          </li>
        </ul>
        <t>02:</t>
        <ul spacing="normal">
          <li>
            <t>Complete the initial specification of Poplar1.</t>
          </li>
          <li>
            <t>Extend (V)DAF syntax to include a "public share" output by the Client and
distributed to all of the Aggregators. This is to accommodate "extractable"
IDPFs as required for Poplar1. (See <xref target="BBCGGI21"/>, Section 4.3 for details.)</t>
          </li>
          <li>
            <t>Extend (V)DAF syntax to allow the unsharding step to take into account the
number of measurements aggregated.</t>
          </li>
          <li>
            <t>Extend FLP syntax by adding a method for decoding the aggregate result from a
vector of field elements. The new method takes into account the number of
measurements.</t>
          </li>
          <li>
            <t>Prio3: Align aggregate result computation with updated FLP syntax.</t>
          </li>
          <li>
            <t>Prg: Add a method for statefully generating a vector of field elements.</t>
          </li>
          <li>
            <t>Field: Require that field elements are fully reduced before decoding. (*)</t>
          </li>
          <li>
            <t>Define new field Field255.</t>
          </li>
        </ul>
        <t>01:</t>
        <ul spacing="normal">
          <li>
            <t>Require that VDAFs specify serialization of aggregate shares.</t>
          </li>
          <li>
            <t>Define Distributed Aggregation Functions (DAFs).</t>
          </li>
          <li>
            <t>Prio3: Move proof verifier check from <tt>prep_next()</tt> to
<tt>prep_shares_to_prep()</tt>. (*)</t>
          </li>
          <li>
            <t>Remove public parameter and replace verification parameter with a
"verification key" and "Aggregator ID".</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="conventions">
      <name>Conventions</name>
      <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>
      <?line -18?>

<t>Algorithms in this document are written in Python (compatible with Python 3.12
or later). A fatal error in a program (e.g., failure to parse one of the
function parameters) is usually handled by raising an exception.</t>
      <t>In Python, array indexing starts with <tt>0</tt>, e.g., <tt>x[0]</tt> is the first element
and <tt>x[len(x)-1]</tt> is the last of <tt>x</tt>. It is also possible to index from the end
of the list, e.g., <tt>x[-1]</tt> is the last element of <tt>x</tt>.</t>
      <t>Python uses the symbols <tt>+</tt>, <tt>-</tt>, <tt>*</tt>, and <tt>/</tt> as binary operators. When the
operands are integers, these have the usual meaning, except:</t>
      <ul spacing="normal">
        <li>
          <t>Division results in a floating point number. Python includes a similar
operator, <tt>x // y</tt>, which is short for <tt>floor(x / y)</tt>.</t>
        </li>
        <li>
          <t>When <tt>x</tt> and <tt>y</tt> are byte strings, <tt>x + y</tt> denotes their concatenation, i.e.,
<tt>concat(x, y)</tt> as defined below.</t>
        </li>
      </ul>
      <t>Finite field arithmetic overloads these operators; see <xref target="field"/>.</t>
      <t>Exponentiation is denoted by <tt>x ** y</tt> in Python.</t>
      <t>Bitwise exclusive or is denoted by <tt>x ^ y</tt> in Python.</t>
      <t>Type hints are used to define input and output types:</t>
      <ul spacing="normal">
        <li>
          <t>The type variable <tt>F</tt> is used in signatures to signify any type that is a
subclass of <tt>Field</tt> (<xref target="field"/>).</t>
        </li>
        <li>
          <t><tt>bytes</tt> is a byte string.</t>
        </li>
        <li>
          <t><tt>int</tt> is an integer.</t>
        </li>
        <li>
          <t><tt>Generic</tt> is used in class definitions to explicitly declare type variables
of generic classes.</t>
        </li>
        <li>
          <t><tt>Any</tt> is the universal supertype, which admits values of any type.</t>
        </li>
        <li>
          <t><tt>Optional[T]</tt> is shorthand for <tt>T | None</tt>. Its value may be <tt>None</tt> or have
type <tt>T</tt>.</t>
        </li>
        <li>
          <t><tt>Self</tt> represents the containing class of the method definition in which it
appears.</t>
        </li>
        <li>
          <t><tt>Sequence[T]</tt> is either a list or tuple of values of type <tt>T</tt>.</t>
        </li>
      </ul>
      <t>This document defines several byte-string constants. When comprised of printable
ASCII characters, they are written as Python 3 byte-string literals (e.g.,
<tt>b'some constant string'</tt>).</t>
      <t>A global constant <tt>VERSION</tt> of type <tt>int</tt> is defined, which algorithms are free
to use as desired. Its value <bcp14>SHALL</bcp14> be <tt>12</tt>.</t>
      <t>This document describes algorithms for multi-party computations in which the
parties typically communicate over a network. Wherever a quantity is defined
that must be transmitted from one party to another, this document prescribes
a particular encoding of that quantity as a byte string.</t>
      <t>Some common functionalities:</t>
      <ul spacing="normal">
        <li>
          <t><tt>additive_secret_share(x: list[F], num_shares: int, field: type[F]) -&gt;
list[list[F]]</tt> takes a vector <tt>x</tt> of field elements and returns <tt>num_shares</tt>
vectors of length <tt>len(x)</tt> such that they all add up to the input vector.
Note that this function is not used normatively in this document.</t>
        </li>
        <li>
          <t><tt>byte(x: int) -&gt; bytes</tt> returns the representation of the integer <tt>x</tt> in the
range <tt>[0, 256)</tt> as a single-byte byte string.</t>
        </li>
        <li>
          <t><tt>cast(typ: type[T], x: object) -&gt; T</tt> returns the input value unchanged.
This is only present to assist with static analysis of the Python code.
Type checkers will ignore the inferred type of the input value, and assume
the output value has the given type.</t>
        </li>
        <li>
          <t><tt>concat(parts: list[bytes]) -&gt; bytes</tt> returns the concatenation of the input
byte strings, i.e., <tt>parts[0] + ... + parts[len(parts)-1]</tt>.</t>
        </li>
        <li>
          <t><tt>from_be_bytes(encoded: bytes) -&gt; int</tt> decodes a big-endian byte string,
i.e., returns the integer <tt>x</tt> for which <tt>to_be_bytes(x, len(encoded)) ==
encoded</tt>.</t>
        </li>
        <li>
          <t><tt>from_le_bytes(encoded: bytes) -&gt; int</tt> decodes a little-endian byte string,
i.e., returns the integer <tt>x</tt> for which <tt>to_le_bytes(x, len(encoded)) ==
encoded</tt>.</t>
        </li>
        <li>
          <t><tt>front(len: int, x: list[Any]) -&gt; tuple[list[Any], list[Any]]</tt> splits <tt>x</tt>
into two vectors, where the first vector is made up of the first <tt>len</tt>
elements of <tt>x</tt> and the second is made up of the remaining elements. This
function is equivalent to <tt>(x[:len], x[len:])</tt>.</t>
        </li>
        <li>
          <t><tt>gen_rand(len: int) -&gt; bytes</tt> returns a byte array of the requested length
(<tt>len</tt>) generated by a cryptographically secure pseudorandom number generator
(CSPRNG).</t>
        </li>
        <li>
          <t><tt>next_power_of_2(x: int) -&gt; int</tt> returns the smallest integer
greater than or equal to <tt>x</tt> that is also a power of two.</t>
        </li>
        <li>
          <t><tt>range(stop: int)</tt> or <tt>range(start: int, stop: int[, step: int])</tt> is the range
function from the Python standard library. The one-argument form returns the
integers from zero (inclusive) to <tt>stop</tt> (exclusive). The two- and
three-argument forms allow overriding the start of the range and overriding
the step between successive output values.</t>
        </li>
        <li>
          <t><tt>to_be_bytes(x: int, len: int) -&gt; bytes</tt> converts an integer <tt>x</tt> whose value
is in the range <tt>[0, 2**(8*len))</tt> to a big-endian byte string of length <tt>len</tt>.</t>
        </li>
        <li>
          <t><tt>to_le_bytes(x: int, len: int) -&gt; bytes</tt> converts an integer <tt>x</tt> whose value
is in the range <tt>[0, 2**(8*len))</tt> to a little-endian byte string of length
<tt>len</tt>.</t>
        </li>
        <li>
          <t><tt>poly_eval(field: type[F], p: list[F], x: F) -&gt; F</tt> returns the result of
evaluating the polynomial, <tt>p(x)</tt>. The coefficients of polynomials are stored
in lists in ascending order of degree, starting with the constant
coefficient. The <tt>field</tt> parameter is the class object for <tt>F</tt> and is used by
the implementation to construct field elements. (See <xref target="field"/>.)</t>
        </li>
        <li>
          <t><tt>poly_interp(field: type[F], inputs: list[F], outputs: list[F]) -&gt; list[F]</tt>
returns the coefficients of the lowest degree polynomial <tt>p</tt> for which
<tt>p(inputs[k]) == outputs[k]</tt> for all <tt>k</tt>. Normally this will be computed
using the Number Theoretic Transform (NTT) <xref target="SML24"/>.</t>
        </li>
        <li>
          <t><tt>poly_mul(field: type[F], p: list[F], q: list[F]) -&gt; list[F]</tt> returns
the product of two polynomials.</t>
        </li>
        <li>
          <t><tt>poly_strip(field: type[F], p: list[F]) -&gt; list[F]</tt> strips the zeros from the
end of the input polynomial's list of coefficients. That is, it returns
<tt>p[:i]</tt> where <tt>i</tt> is the index of the highest-degree non-zero coefficient of
<tt>p</tt>.</t>
        </li>
        <li>
          <t><tt>xor(left: bytes, right: bytes) -&gt; bytes</tt> returns the bitwise XOR of <tt>left</tt>
and <tt>right</tt>. An exception is raised if the inputs are not the same length.</t>
        </li>
        <li>
          <t><tt>zeros(len: int) -&gt; bytes</tt> returns an array of bytes of the requested
length (<tt>len</tt>). Each element of the array is set to zero.</t>
        </li>
      </ul>
      <section anchor="mathematical-notation">
        <name>Mathematical Notation</name>
        <t>The following symbols are used in mathematical notation.</t>
        <table anchor="mathematical-operators-and-symbols">
          <name>Mathematical Operators and Symbols</name>
          <thead>
            <tr>
              <th align="left">ASCII glyph(s)</th>
              <th align="left">Description</th>
              <th align="left">Comment</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">+, -</td>
              <td align="left">Addition / subtraction</td>
              <td align="left">Needs to be constant time. Used for addition and subtraction of field elements as well as numbers.</td>
            </tr>
            <tr>
              <td align="left">*</td>
              <td align="left">Addition / subtraction</td>
              <td align="left">Needs to be constant time. Used for multiplication of field elements as well as numbers.</td>
            </tr>
            <tr>
              <td align="left">**</td>
              <td align="left">Exponentiation</td>
              <td align="left">Needs to be constant time. Used for exponentiation of field elements as well as numbers.</td>
            </tr>
            <tr>
              <td align="left">/</td>
              <td align="left">Division</td>
              <td align="left">Needs to be constant time. Used for division of field elements (i.e. multiplication by inverse) as well as numbers.</td>
            </tr>
            <tr>
              <td align="left">||</td>
              <td align="left">Concatenation</td>
              <td align="left">Used for concatenation of byte strings and bit strings.</td>
            </tr>
          </tbody>
        </table>
      </section>
    </section>
    <section anchor="overview">
      <name>Overview</name>
      <figure anchor="overall-flow">
        <name>Overall data flow of a (V)DAF.</name>
        <artset>
          <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="336" width="536" viewBox="0 0 536 336" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
              <path d="M 8,176 L 8,208" fill="none" stroke="black"/>
              <path d="M 80,176 L 80,208" fill="none" stroke="black"/>
              <path d="M 96,48 L 96,176" fill="none" stroke="black"/>
              <path d="M 96,208 L 96,304" fill="none" stroke="black"/>
              <path d="M 112,144 L 112,192" fill="none" stroke="black"/>
              <path d="M 136,288 L 136,320" fill="none" stroke="black"/>
              <path d="M 144,32 L 144,64" fill="none" stroke="black"/>
              <path d="M 144,128 L 144,160" fill="none" stroke="black"/>
              <path d="M 208,72 L 208,120" fill="none" stroke="black"/>
              <path d="M 208,168 L 208,192" fill="none" stroke="black"/>
              <path d="M 208,272 L 208,280" fill="none" stroke="black"/>
              <path d="M 264,32 L 264,64" fill="none" stroke="black"/>
              <path d="M 264,128 L 264,160" fill="none" stroke="black"/>
              <path d="M 272,288 L 272,320" fill="none" stroke="black"/>
              <path d="M 288,144 L 288,192" fill="none" stroke="black"/>
              <path d="M 304,48 L 304,176" fill="none" stroke="black"/>
              <path d="M 304,208 L 304,304" fill="none" stroke="black"/>
              <path d="M 328,176 L 328,208" fill="none" stroke="black"/>
              <path d="M 424,176 L 424,208" fill="none" stroke="black"/>
              <path d="M 144,32 L 264,32" fill="none" stroke="black"/>
              <path d="M 96,48 L 136,48" fill="none" stroke="black"/>
              <path d="M 264,48 L 304,48" fill="none" stroke="black"/>
              <path d="M 144,64 L 264,64" fill="none" stroke="black"/>
              <path d="M 144,128 L 264,128" fill="none" stroke="black"/>
              <path d="M 112,144 L 136,144" fill="none" stroke="black"/>
              <path d="M 272,144 L 288,144" fill="none" stroke="black"/>
              <path d="M 144,160 L 264,160" fill="none" stroke="black"/>
              <path d="M 8,176 L 96,176" fill="none" stroke="black"/>
              <path d="M 304,176 L 424,176" fill="none" stroke="black"/>
              <path d="M 80,192 L 112,192" fill="none" stroke="black"/>
              <path d="M 288,192 L 320,192" fill="none" stroke="black"/>
              <path d="M 424,192 L 448,192" fill="none" stroke="black"/>
              <path d="M 8,208 L 96,208" fill="none" stroke="black"/>
              <path d="M 304,208 L 424,208" fill="none" stroke="black"/>
              <path d="M 136,288 L 272,288" fill="none" stroke="black"/>
              <path d="M 96,304 L 128,304" fill="none" stroke="black"/>
              <path d="M 280,304 L 304,304" fill="none" stroke="black"/>
              <path d="M 136,320 L 272,320" fill="none" stroke="black"/>
              <polygon class="arrowhead" points="456,192 444,186.4 444,197.6" fill="black" transform="rotate(0,448,192)"/>
              <polygon class="arrowhead" points="328,208 316,202.4 316,213.6" fill="black" transform="rotate(0,320,208)"/>
              <polygon class="arrowhead" points="328,192 316,186.4 316,197.6" fill="black" transform="rotate(0,320,192)"/>
              <polygon class="arrowhead" points="328,176 316,170.4 316,181.6" fill="black" transform="rotate(0,320,176)"/>
              <polygon class="arrowhead" points="216,280 204,274.4 204,285.6" fill="black" transform="rotate(90,208,280)"/>
              <polygon class="arrowhead" points="216,168 204,162.4 204,173.6" fill="black" transform="rotate(270,208,168)"/>
              <polygon class="arrowhead" points="216,120 204,114.4 204,125.6" fill="black" transform="rotate(90,208,120)"/>
              <polygon class="arrowhead" points="216,72 204,66.4 204,77.6" fill="black" transform="rotate(270,208,72)"/>
              <polygon class="arrowhead" points="144,144 132,138.4 132,149.6" fill="black" transform="rotate(0,136,144)"/>
              <polygon class="arrowhead" points="144,48 132,42.4 132,53.6" fill="black" transform="rotate(0,136,48)"/>
              <polygon class="arrowhead" points="136,304 124,298.4 124,309.6" fill="black" transform="rotate(0,128,304)"/>
              <g class="text">
                <text x="196" y="52">Aggregator</text>
                <text x="248" y="52">0</text>
                <text x="64" y="68">input</text>
                <text x="352" y="68">aggregate</text>
                <text x="60" y="84">shares</text>
                <text x="340" y="84">shares</text>
                <text x="196" y="148">Aggregator</text>
                <text x="248" y="148">1</text>
                <text x="44" y="196">Client</text>
                <text x="376" y="196">Collector</text>
                <text x="496" y="196">aggregate</text>
                <text x="484" y="212">result</text>
                <text x="208" y="228">...</text>
                <text x="208" y="260">|</text>
                <text x="188" y="308">Aggregator</text>
                <text x="248" y="308">N-1</text>
              </g>
            </svg>
          </artwork>
          <artwork type="ascii-art"><![CDATA[
                 +--------------+
           +---->| Aggregator 0 +----+
     input |     +--------------+    | aggregate
    shares |             ^           | shares
           |             |           |
           |             V           |
           |     +--------------+    |
           | +-->| Aggregator 1 |--+ |
           | |   +--------------+  | |
+--------+-+ |           ^         | +->+-----------+
| Client +---+           |         +--->| Collector +--> aggregate
+--------+-+                         +->+-----------+    result
           |            ...          |
           |                         |
           |             |           |
           |             V           |
           |    +----------------+   |
           +--->| Aggregator N-1 |---+
                +----------------+
]]></artwork>
        </artset>
      </figure>
      <t>There are three types of actors in a DAF- or VDAF-based private measurement
system: Clients, Aggregators, and the Collector. The overall flow of the
measurement process is illustrated in <xref target="overall-flow"/>. The steps are as
follows:</t>
      <ol spacing="normal" type="1"><li>
          <t>To submit an individual measurement, a Client shards its measurement into
"input shares" and sends one input share to each Aggregator. This document
sometimes refers to this sequence of input shares collectively as the
Client's "report". (The report contains a few more items needed to process
the measurement; these are described in <xref target="daf"/>.)</t>
        </li>
        <li>
          <t>Once an Aggregator receives an input share from each Client, it processes
the input shares into a value called an "aggregate share" and sends it the
Collector. The aggregate share is a secret share of the aggregate
representation of the measurements.</t>
        </li>
        <li>
          <t>Once the Collector has received an aggregate share from each Aggregator, it
combines them into the aggregate representation of the measurements, called
the "aggregate result".</t>
        </li>
      </ol>
      <t>This second step involves a process called "preparation" in which the
Aggregator refines each input share into an intermediate representation called
an "output share". The output shares are then combined into the aggregate share
as shown in <xref target="overall-flow-prep"/>.</t>
      <figure anchor="overall-flow-prep">
        <name>Preparation of input shares into output shares and aggregation of output shares into an aggregate share. Executed by each Aggregator. M denotes the number of measurements being aggregated.</name>
        <artset>
          <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="304" width="416" viewBox="0 0 416 304" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
              <path d="M 8,80 L 8,112" fill="none" stroke="black"/>
              <path d="M 8,208 L 8,240" fill="none" stroke="black"/>
              <path d="M 24,48 L 24,72" fill="none" stroke="black"/>
              <path d="M 24,112 L 24,144" fill="none" stroke="black"/>
              <path d="M 24,168 L 24,200" fill="none" stroke="black"/>
              <path d="M 64,80 L 64,112" fill="none" stroke="black"/>
              <path d="M 128,80 L 128,112" fill="none" stroke="black"/>
              <path d="M 144,48 L 144,72" fill="none" stroke="black"/>
              <path d="M 144,112 L 144,144" fill="none" stroke="black"/>
              <path d="M 144,168 L 144,200" fill="none" stroke="black"/>
              <path d="M 144,240 L 144,272" fill="none" stroke="black"/>
              <path d="M 184,80 L 184,112" fill="none" stroke="black"/>
              <path d="M 280,80 L 280,112" fill="none" stroke="black"/>
              <path d="M 296,48 L 296,72" fill="none" stroke="black"/>
              <path d="M 296,112 L 296,144" fill="none" stroke="black"/>
              <path d="M 296,168 L 296,200" fill="none" stroke="black"/>
              <path d="M 336,80 L 336,112" fill="none" stroke="black"/>
              <path d="M 336,208 L 336,240" fill="none" stroke="black"/>
              <path d="M 8,80 L 64,80" fill="none" stroke="black"/>
              <path d="M 128,80 L 184,80" fill="none" stroke="black"/>
              <path d="M 280,80 L 336,80" fill="none" stroke="black"/>
              <path d="M 8,112 L 64,112" fill="none" stroke="black"/>
              <path d="M 128,112 L 184,112" fill="none" stroke="black"/>
              <path d="M 280,112 L 336,112" fill="none" stroke="black"/>
              <path d="M 8,208 L 336,208" fill="none" stroke="black"/>
              <path d="M 8,240 L 336,240" fill="none" stroke="black"/>
              <polygon class="arrowhead" points="304,200 292,194.4 292,205.6" fill="black" transform="rotate(90,296,200)"/>
              <polygon class="arrowhead" points="304,144 292,138.4 292,149.6" fill="black" transform="rotate(90,296,144)"/>
              <polygon class="arrowhead" points="304,72 292,66.4 292,77.6" fill="black" transform="rotate(90,296,72)"/>
              <polygon class="arrowhead" points="152,272 140,266.4 140,277.6" fill="black" transform="rotate(90,144,272)"/>
              <polygon class="arrowhead" points="152,200 140,194.4 140,205.6" fill="black" transform="rotate(90,144,200)"/>
              <polygon class="arrowhead" points="152,144 140,138.4 140,149.6" fill="black" transform="rotate(90,144,144)"/>
              <polygon class="arrowhead" points="152,72 140,66.4 140,77.6" fill="black" transform="rotate(90,144,72)"/>
              <polygon class="arrowhead" points="32,200 20,194.4 20,205.6" fill="black" transform="rotate(90,24,200)"/>
              <polygon class="arrowhead" points="32,144 20,138.4 20,149.6" fill="black" transform="rotate(90,24,144)"/>
              <polygon class="arrowhead" points="32,72 20,66.4 20,77.6" fill="black" transform="rotate(90,24,72)"/>
              <g class="text">
                <text x="56" y="36">input_share_0</text>
                <text x="176" y="36">input_share_1</text>
                <text x="256" y="36">...</text>
                <text x="344" y="36">input_share_[M-1]</text>
                <text x="36" y="100">prep</text>
                <text x="156" y="100">prep</text>
                <text x="308" y="100">prep</text>
                <text x="48" y="164">out_share_0</text>
                <text x="168" y="164">out_share_1</text>
                <text x="256" y="164">...</text>
                <text x="336" y="164">out_share_[M-1]</text>
                <text x="56" y="228">aggregate</text>
                <text x="160" y="292">agg_share</text>
              </g>
            </svg>
          </artwork>
          <artwork type="ascii-art"><![CDATA[
input_share_0  input_share_1  ... input_share_[M-1]
  |              |                  |
  v              v                  v
+------+       +------+           +------+
| prep |       | prep |           | prep |
+-+----+       +-+----+           +-+----+
  |              |                  |
  v              v                  v
out_share_0    out_share_1    ... out_share_[M-1]
  |              |                  |
  v              v                  v
+----------------------------------------+
| aggregate                              |
+----------------+-----------------------+
                 |
                 v
               agg_share
]]></artwork>
        </artset>
      </figure>
      <t>In the case of VDAFs (<xref target="vdaf"/>), preparation involves interacting with the
other Aggregators. This process will fail if the underlying measurement is
invalid, in which case the report is rejected and not included in the aggregate
result.</t>
      <t>Aggregators are a new class of actor relative to traditional measurement systems
where Clients submit measurements to a single server.  They are critical for
both the privacy properties of the system and, in the case of VDAFs, the
validity of the aggregate results obtained.  The privacy properties of the
system are assured by non-collusion among Aggregators, and Aggregators are the
entities that perform validation of Client measurements.  Thus Clients trust
Aggregators not to collude (typically it is required that at least one
Aggregator is honest; see <xref target="num-aggregators"/>), and Collectors trust
Aggregators to correctly run the protocol.</t>
      <t>Within the bounds of the non-collusion requirements of a given (V)DAF instance,
it is possible for the same entity to play more than one role.  For example, the
Collector could also act as an Aggregator, effectively using the other
Aggregator(s) to augment a basic client-server protocol.</t>
      <t>This document describes the computations performed by the actors in this
system. It is up to the higher-level protocol making use of the (V)DAF to
arrange for the required information to be delivered to the proper actors in
the proper sequence. In general, it is assumed that all communications are
confidential and mutually authenticated, with the exception that Clients
submitting measurements may be anonymous.</t>
    </section>
    <section anchor="daf">
      <name>Definition of DAFs</name>
      <t>By way of a gentle introduction to VDAFs, this section describes a simpler class
of schemes called Distributed Aggregation Functions (DAFs). Unlike VDAFs, DAFs
do not provide verifiability of the computation. Clients must therefore be
trusted to compute their input shares correctly. Because of this fact, the use
of a DAF is <bcp14>NOT RECOMMENDED</bcp14> for most applications. See <xref target="security"/> for
additional discussion.</t>
      <t>A DAF scheme is used to compute a particular "aggregation function" over a set
of measurements generated by Clients. Depending on the aggregation function, the
Collector might select an "aggregation parameter" and disseminate it to the
Aggregators. The semantics of this parameter is specific to the aggregation
function, but in general it is used to represent the set of "queries" that can
be made by the Collector on the batch of measurements. For example, the
aggregation parameter is used to represent the prefixes in the prefix-counting
functionality of of Poplar1 discussed in <xref target="introduction"/>.</t>
      <t>Execution of a DAF has four distinct stages:</t>
      <ul spacing="normal">
        <li>
          <t>Sharding: Each Client generates input shares from its measurement and
distributes them among the Aggregators. In addition to the input shares, the
client generates a "public share" during this step that is disseminated to
all of the Aggregators.</t>
        </li>
        <li>
          <t>Preparation: Each Aggregator converts each input share into an output share
compatible with the aggregation function. This computation involves the
aggregation parameter. In general, each aggregation parameter may result in a
different output share.</t>
        </li>
        <li>
          <t>Aggregation: Each Aggregator combines a sequence of output shares into its
aggregate share and sends the aggregate share to the Collector.</t>
        </li>
        <li>
          <t>Unsharding: The Collector combines the aggregate shares into the aggregate
result.</t>
        </li>
      </ul>
      <t>Sharding and preparation are done once per measurement. Aggregation and
unsharding are done over a batch of measurements (more precisely, over the
recovered output shares).</t>
      <t>A concrete DAF specifies the algorithm for the computation needed in each of
these stages. The interface, denoted <tt>Daf</tt>, is defined in the remainder of this
section. In addition, a concrete DAF defines the associated constants and types
enumerated in the following table.</t>
      <table anchor="daf-param">
        <name>Constants and types defined by each concrete DAF.</name>
        <thead>
          <tr>
            <th align="left">Parameter</th>
            <th align="left">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>ID: int</tt></td>
            <td align="left">Algorithm identifier for this DAF, in the range <tt>[0, 2**32)</tt>.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>SHARES: int</tt></td>
            <td align="left">Number of input shares into which each measurement is sharded.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>NONCE_SIZE: int</tt></td>
            <td align="left">Size of the nonce associated with each report.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>RAND_SIZE: int</tt></td>
            <td align="left">Size of each random byte string consumed by the sharding algorithm.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>Measurement</tt></td>
            <td align="left">Type of each measurement.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PublicShare</tt></td>
            <td align="left">Type of each public share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>InputShare</tt></td>
            <td align="left">Type of each input share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggParam</tt></td>
            <td align="left">Type of the aggregation parameter.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>OutShare</tt></td>
            <td align="left">Type of each output share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggShare</tt></td>
            <td align="left">Type of each aggregate share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggResult</tt></td>
            <td align="left">Type of the aggregate result.</td>
          </tr>
        </tbody>
      </table>
      <t>The types in this table define the inputs and outputs of DAF methods at various
stages of the computation. Some of these values need to be written to the
network in order to carry out the computation. In particular, it is <bcp14>RECOMMENDED</bcp14>
that concrete instantiations of the <tt>Daf</tt> interface specify a standard encoding
for the <tt>PublicShare</tt>, <tt>InputShare</tt>, <tt>AggParam</tt>, and <tt>AggShare</tt> types.</t>
      <section anchor="sec-daf-shard">
        <name>Sharding</name>
        <figure anchor="shard-flow">
          <name>Illustration of the sharding algorithm.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="384" width="432" viewBox="0 0 432 384" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,144 L 8,176" fill="none" stroke="black"/>
                <path d="M 24,96 L 24,136" fill="none" stroke="black"/>
                <path d="M 24,176 L 24,272" fill="none" stroke="black"/>
                <path d="M 24,304 L 24,336" fill="none" stroke="black"/>
                <path d="M 64,240 L 64,272" fill="none" stroke="black"/>
                <path d="M 64,296 L 64,336" fill="none" stroke="black"/>
                <path d="M 144,176 L 144,272" fill="none" stroke="black"/>
                <path d="M 144,304 L 144,336" fill="none" stroke="black"/>
                <path d="M 192,240 L 192,272" fill="none" stroke="black"/>
                <path d="M 192,304 L 192,336" fill="none" stroke="black"/>
                <path d="M 264,176 L 264,272" fill="none" stroke="black"/>
                <path d="M 264,304 L 264,336" fill="none" stroke="black"/>
                <path d="M 312,176 L 312,192" fill="none" stroke="black"/>
                <path d="M 312,224 L 312,272" fill="none" stroke="black"/>
                <path d="M 312,304 L 312,336" fill="none" stroke="black"/>
                <path d="M 384,144 L 384,176" fill="none" stroke="black"/>
                <path d="M 8,46 L 48,46" fill="none" stroke="black"/>
                <path d="M 8,50 L 48,50" fill="none" stroke="black"/>
                <path d="M 8,144 L 384,144" fill="none" stroke="black"/>
                <path d="M 8,176 L 384,176" fill="none" stroke="black"/>
                <path d="M 64,240 L 136,240" fill="none" stroke="black"/>
                <path d="M 152,240 L 256,240" fill="none" stroke="black"/>
                <path d="M 272,240 L 312,240" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="320,336 308,330.4 308,341.6" fill="black" transform="rotate(90,312,336)"/>
                <polygon class="arrowhead" points="272,336 260,330.4 260,341.6" fill="black" transform="rotate(90,264,336)"/>
                <polygon class="arrowhead" points="272,272 260,266.4 260,277.6" fill="black" transform="rotate(90,264,272)"/>
                <polygon class="arrowhead" points="200,336 188,330.4 188,341.6" fill="black" transform="rotate(90,192,336)"/>
                <polygon class="arrowhead" points="152,336 140,330.4 140,341.6" fill="black" transform="rotate(90,144,336)"/>
                <polygon class="arrowhead" points="152,272 140,266.4 140,277.6" fill="black" transform="rotate(90,144,272)"/>
                <polygon class="arrowhead" points="72,336 60,330.4 60,341.6" fill="black" transform="rotate(90,64,336)"/>
                <polygon class="arrowhead" points="32,336 20,330.4 20,341.6" fill="black" transform="rotate(90,24,336)"/>
                <polygon class="arrowhead" points="32,272 20,266.4 20,277.6" fill="black" transform="rotate(90,24,272)"/>
                <polygon class="arrowhead" points="32,136 20,130.4 20,141.6" fill="black" transform="rotate(90,24,136)"/>
                <g class="text">
                  <text x="28" y="36">Client</text>
                  <text x="48" y="84">measurement</text>
                  <text x="40" y="164">shard</text>
                  <text x="232" y="212">...</text>
                  <text x="348" y="212">public_share</text>
                  <text x="64" y="292">input_share_0</text>
                  <text x="184" y="292">input_share_1</text>
                  <text x="340" y="292">input_share_[SHARES-1]</text>
                  <text x="232" y="324">...</text>
                  <text x="44" y="356">Aggregator</text>
                  <text x="96" y="356">0</text>
                  <text x="164" y="356">Aggregator</text>
                  <text x="216" y="356">1</text>
                  <text x="292" y="356">Aggregator</text>
                  <text x="372" y="356">SHARES-1</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
    Client
    ======

    measurement
      |
      |
      V
    +----------------------------------------------+
    | shard                                        |
    +-+--------------+--------------+-----+--------+
      |              |              |     |
      |              |         ...  |    public_share
      |              |              |     |
      |    +---------|-----+--------|-----+
      |    |         |     |        |     |
      v    |         v     |        v     |
     input_share_0  input_share_1  input_share_[SHARES-1]
      |    |         |     |        |     |
      |    |         |     |   ...  |     |
      v    v         v     v        v     v
    Aggregator 0   Aggregator 1    Aggregator SHARES-1
]]></artwork>
          </artset>
        </figure>
        <t>The sharding algorithm run by each Client is defined as follows:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.shard(ctx: bytes, measurement: Measurement, nonce: bytes, rand: bytes)
-&gt; tuple[PublicShare, list[InputShare]]</tt> consumes the "application context"
(defined below), a measurement, and a nonce and produces the public share,
distributed to each of the Aggregators, and the input shares, one for each
Aggregator.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>nonce</tt> <bcp14>MUST</bcp14> have length equal to <tt>daf.NONCE_SIZE</tt> and <bcp14>MUST</bcp14> be generated
using a cryptographically secure random number generator (CSPRNG).</t>
              </li>
              <li>
                <t><tt>rand</tt> consists of the random bytes consumed by the algorithm. It <bcp14>MUST</bcp14> have
length equal to <tt>daf.RAND_SIZE</tt> and <bcp14>MUST</bcp14> be generated using a CSPRNG.</t>
              </li>
            </ul>
            <t>
Post-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t>The number of input shares <bcp14>MUST</bcp14> equal <tt>daf.SHARES</tt>.</t>
              </li>
            </ul>
          </li>
        </ul>
        <t>Sharding is bound to a specific "application context". The application context
is a string intended to uniquely identify an instance of the higher level
protocol that uses the DAF. The goal of binding the application to DAF
execution is to ensure that aggregation succeeds only if the Clients and
Aggregators agree on the application context. (Preparation binds the
application context, too; see <xref target="sec-daf-prepare"/>.) Note that, unlike VDAFs
(<xref target="vdaf"/>), there is no explicit signal of disagreement; it may only manifest
as a garbled aggregate result.</t>
        <t>The nonce is a public random value associated with the report. It is referred
to as a nonce because normally it will also be used as a unique identifier for
that report in the context of some application. The randomness requirement is
especially important for VDAFs, where it may be used by the Aggregators to
derive per-report randomness for verification of the computation. See
<xref target="nonce-requirements"/> for details.</t>
      </section>
      <section anchor="sec-daf-prepare">
        <name>Preparation</name>
        <figure anchor="daf-prep-flow">
          <name>Illustration of preparation.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="240" width="488" viewBox="0 0 488 240" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,128 L 8,160" fill="none" stroke="black"/>
                <path d="M 24,96 L 24,120" fill="none" stroke="black"/>
                <path d="M 24,160 L 24,192" fill="none" stroke="black"/>
                <path d="M 104,128 L 104,160" fill="none" stroke="black"/>
                <path d="M 128,128 L 128,160" fill="none" stroke="black"/>
                <path d="M 144,96 L 144,120" fill="none" stroke="black"/>
                <path d="M 144,160 L 144,192" fill="none" stroke="black"/>
                <path d="M 224,128 L 224,160" fill="none" stroke="black"/>
                <path d="M 312,128 L 312,160" fill="none" stroke="black"/>
                <path d="M 328,96 L 328,120" fill="none" stroke="black"/>
                <path d="M 328,160 L 328,192" fill="none" stroke="black"/>
                <path d="M 408,128 L 408,160" fill="none" stroke="black"/>
                <path d="M 8,46 L 96,46" fill="none" stroke="black"/>
                <path d="M 8,50 L 96,50" fill="none" stroke="black"/>
                <path d="M 128,46 L 216,46" fill="none" stroke="black"/>
                <path d="M 128,50 L 216,50" fill="none" stroke="black"/>
                <path d="M 312,46 L 456,46" fill="none" stroke="black"/>
                <path d="M 312,50 L 456,50" fill="none" stroke="black"/>
                <path d="M 8,128 L 104,128" fill="none" stroke="black"/>
                <path d="M 128,128 L 224,128" fill="none" stroke="black"/>
                <path d="M 312,128 L 408,128" fill="none" stroke="black"/>
                <path d="M 8,160 L 104,160" fill="none" stroke="black"/>
                <path d="M 128,160 L 224,160" fill="none" stroke="black"/>
                <path d="M 312,160 L 408,160" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="336,192 324,186.4 324,197.6" fill="black" transform="rotate(90,328,192)"/>
                <polygon class="arrowhead" points="336,120 324,114.4 324,125.6" fill="black" transform="rotate(90,328,120)"/>
                <polygon class="arrowhead" points="152,192 140,186.4 140,197.6" fill="black" transform="rotate(90,144,192)"/>
                <polygon class="arrowhead" points="152,120 140,114.4 140,125.6" fill="black" transform="rotate(90,144,120)"/>
                <polygon class="arrowhead" points="32,192 20,186.4 20,197.6" fill="black" transform="rotate(90,24,192)"/>
                <polygon class="arrowhead" points="32,120 20,114.4 20,125.6" fill="black" transform="rotate(90,24,120)"/>
                <g class="text">
                  <text x="44" y="36">Aggregator</text>
                  <text x="96" y="36">0</text>
                  <text x="164" y="36">Aggregator</text>
                  <text x="216" y="36">1</text>
                  <text x="348" y="36">Aggregator</text>
                  <text x="428" y="36">SHARES-1</text>
                  <text x="56" y="84">input_share_0</text>
                  <text x="176" y="84">input_share_1</text>
                  <text x="396" y="84">input_share_[SHARES-1]</text>
                  <text x="296" y="100">...</text>
                  <text x="36" y="148">prep</text>
                  <text x="156" y="148">prep</text>
                  <text x="340" y="148">prep</text>
                  <text x="296" y="180">...</text>
                  <text x="48" y="212">out_share_0</text>
                  <text x="168" y="212">out_share_1</text>
                  <text x="388" y="212">out_share_[SHARES-1]</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
    Aggregator 0   Aggregator 1           Aggregator SHARES-1
    ============   ============           ===================

    input_share_0  input_share_1          input_share_[SHARES-1]
      |              |                 ...  |
      v              v                      v
    +-----------+  +-----------+          +-----------+
    | prep      |  | prep      |          | prep      |
    +-+---------+  +-+---------+          +-+---------+
      |              |                 ...  |
      v              v                      v
    out_share_0    out_share_1            out_share_[SHARES-1]
]]></artwork>
          </artset>
        </figure>
        <t>Once an Aggregator has received the public share and its input share, the next
step is to prepare the input share for aggregation. This is accomplished using
the preparation algorithm:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.prep(ctx: bytes, agg_id: int, agg_param: AggParam, nonce: bytes,
public_share: PublicShare, input_share: InputShare) -&gt; OutShare</tt> consumes the
public share and one of the input shares generated by the Client, the
application context, the Aggregator's unique identifier, the aggregation
parameter selected by the Collector, and the report nonce and returns an
output share.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>agg_id</tt> <bcp14>MUST</bcp14> be in the range <tt>[0, daf.SHARES)</tt> and match the index of
<tt>input_share</tt> in the sequence of input shares produced by the Client.</t>
              </li>
              <li>
                <t><tt>nonce</tt> <bcp14>MUST</bcp14> have length <tt>daf.NONCE_SIZE</tt>.</t>
              </li>
            </ul>
          </li>
        </ul>
        <t>The Aggregators <bcp14>MUST</bcp14> agree on the value of the aggregation parameter.
Otherwise, the aggregate result may be computed incorrectly by the Collector.</t>
      </section>
      <section anchor="sec-daf-validity-scopes">
        <name>Validity of Aggregation Parameters</name>
        <t>In general, it is permissible to aggregate a batch of reports multiple times.
However, to prevent privacy violations, DAFs may impose certain restrictions on
the aggregation parameters selected by the Collector. Restrictions are
expressed by the aggregation parameter validity function:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.is_valid(agg_param: AggParam, previous_agg_params: list[AggParam]) -&gt;
bool</tt> returns <tt>True</tt> if <tt>agg_param</tt> is allowed given the sequence
<tt>previous_agg_params</tt> of previously accepted aggregation parameters.</t>
          </li>
        </ul>
        <t>Prior to accepting an aggregation parameter from the Collector and beginning
preparation, each Aggregator <bcp14>MUST</bcp14> validate it using this function.</t>
      </section>
      <section anchor="sec-daf-aggregate">
        <name>Aggregation</name>
        <figure anchor="aggregate-flow">
          <name>Illustration of aggregation. The number of measurements in the batch is denoted by M.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="432" width="424" viewBox="0 0 424 432" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,80 L 8,112" fill="none" stroke="black"/>
                <path d="M 112,80 L 112,112" fill="none" stroke="black"/>
                <path d="M 152,80 L 152,112" fill="none" stroke="black"/>
                <path d="M 152,160 L 152,192" fill="none" stroke="black"/>
                <path d="M 152,320 L 152,352" fill="none" stroke="black"/>
                <path d="M 176,112 L 176,152" fill="none" stroke="black"/>
                <path d="M 176,192 L 176,224" fill="none" stroke="black"/>
                <path d="M 176,288 L 176,312" fill="none" stroke="black"/>
                <path d="M 176,352 L 176,384" fill="none" stroke="black"/>
                <path d="M 256,80 L 256,112" fill="none" stroke="black"/>
                <path d="M 256,160 L 256,192" fill="none" stroke="black"/>
                <path d="M 256,320 L 256,352" fill="none" stroke="black"/>
                <path d="M 8,46 L 96,46" fill="none" stroke="black"/>
                <path d="M 8,50 L 96,50" fill="none" stroke="black"/>
                <path d="M 8,80 L 112,80" fill="none" stroke="black"/>
                <path d="M 152,80 L 256,80" fill="none" stroke="black"/>
                <path d="M 112,96 L 144,96" fill="none" stroke="black"/>
                <path d="M 264,96 L 288,96" fill="none" stroke="black"/>
                <path d="M 8,112 L 112,112" fill="none" stroke="black"/>
                <path d="M 152,112 L 256,112" fill="none" stroke="black"/>
                <path d="M 152,160 L 256,160" fill="none" stroke="black"/>
                <path d="M 264,176 L 288,176" fill="none" stroke="black"/>
                <path d="M 152,192 L 256,192" fill="none" stroke="black"/>
                <path d="M 152,320 L 256,320" fill="none" stroke="black"/>
                <path d="M 264,336 L 288,336" fill="none" stroke="black"/>
                <path d="M 152,352 L 256,352" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="272,336 260,330.4 260,341.6" fill="black" transform="rotate(180,264,336)"/>
                <polygon class="arrowhead" points="272,176 260,170.4 260,181.6" fill="black" transform="rotate(180,264,176)"/>
                <polygon class="arrowhead" points="272,96 260,90.4 260,101.6" fill="black" transform="rotate(180,264,96)"/>
                <polygon class="arrowhead" points="184,384 172,378.4 172,389.6" fill="black" transform="rotate(90,176,384)"/>
                <polygon class="arrowhead" points="184,312 172,306.4 172,317.6" fill="black" transform="rotate(90,176,312)"/>
                <polygon class="arrowhead" points="184,224 172,218.4 172,229.6" fill="black" transform="rotate(90,176,224)"/>
                <polygon class="arrowhead" points="184,152 172,146.4 172,157.6" fill="black" transform="rotate(90,176,152)"/>
                <polygon class="arrowhead" points="152,96 140,90.4 140,101.6" fill="black" transform="rotate(0,144,96)"/>
                <g class="text">
                  <text x="44" y="36">Aggregator</text>
                  <text x="96" y="36">j</text>
                  <text x="52" y="100">agg_init</text>
                  <text x="204" y="100">agg_update</text>
                  <text x="344" y="100">out_share_0</text>
                  <text x="204" y="180">agg_update</text>
                  <text x="344" y="180">out_share_1</text>
                  <text x="176" y="260">...</text>
                  <text x="204" y="340">agg_update</text>
                  <text x="360" y="340">out_share_[M-1]</text>
                  <text x="200" y="404">agg_share_j</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
    Aggregator j
    ============

    +------------+    +------------+
    | agg_init   +--->| agg_update |<--- out_share_0
    +------------+    +--+---------+
                         |
                         v
                      +------------+
                      | agg_update |<--- out_share_1
                      +--+---------+
                         |
                         v

                        ...

                         |
                         v
                      +------------+
                      | agg_update |<--- out_share_[M-1]
                      +--+---------+
                         |
                         v
                       agg_share_j
]]></artwork>
          </artset>
        </figure>
        <t>Once an Aggregator holds an output share, it adds it into its aggregate share
for the batch. This streaming aggregation process is implemented by the
following pair of algorithms:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.agg_init(agg_param: AggParam) -&gt; AggShare</tt> returns an empty aggregate
share. It is called to initialize aggregation of a batch of measurements.</t>
          </li>
          <li>
            <t><tt>daf.agg_update(agg_param: AggParam, agg_share: AggShare, out_share:
OutShare) -&gt; AggShare</tt> accumulates an output share into an aggregate share
and returns the updated aggregate share.</t>
          </li>
        </ul>
        <t>In many situations it is desirable to split an aggregate share across multiple
storage elements, then merge the aggregate shares together just before
releasing the completed aggregate share to the Collector. DAFs facilitate this
with the following method:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.merge(agg_param: AggParam, agg_shares: list[AggShare]) -&gt; AggShare</tt>
merges a sequence of aggregate shares into a single aggregate share.</t>
          </li>
        </ul>
        <section anchor="agg-order">
          <name>Aggregation Order</name>
          <t>For most DAFs and VDAFs, the outcome of aggregation is not sensitive to the
order in which output shares are aggregated. This means that aggregate shares
can be updated or merged with other aggregate shares in any order. For
instance, for both Prio3 (<xref target="prio3"/>) and Poplar1 (<xref target="poplar1"/>), the aggregate
shares and output shares both have the same type, a vector over some finite
field (<xref target="field"/>); and aggregation involves simply adding vectors together.</t>
          <t>In theory, however, there may be a DAF or VDAF for which correct execution
requires each Aggregator to aggregate output shares in the same order.</t>
        </section>
      </section>
      <section anchor="sec-daf-unshard">
        <name>Unsharding</name>
        <figure anchor="unshard-flow">
          <name>Illustration of unsharding.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="288" width="456" viewBox="0 0 456 288" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,128 L 8,160" fill="none" stroke="black"/>
                <path d="M 24,88 L 24,120" fill="none" stroke="black"/>
                <path d="M 24,160 L 24,192" fill="none" stroke="black"/>
                <path d="M 152,88 L 152,120" fill="none" stroke="black"/>
                <path d="M 312,88 L 312,120" fill="none" stroke="black"/>
                <path d="M 392,128 L 392,160" fill="none" stroke="black"/>
                <path d="M 8,46 L 96,46" fill="none" stroke="black"/>
                <path d="M 8,50 L 96,50" fill="none" stroke="black"/>
                <path d="M 136,46 L 224,46" fill="none" stroke="black"/>
                <path d="M 136,50 L 224,50" fill="none" stroke="black"/>
                <path d="M 296,46 L 440,46" fill="none" stroke="black"/>
                <path d="M 296,50 L 440,50" fill="none" stroke="black"/>
                <path d="M 8,128 L 392,128" fill="none" stroke="black"/>
                <path d="M 8,160 L 392,160" fill="none" stroke="black"/>
                <path d="M 8,254 L 72,254" fill="none" stroke="black"/>
                <path d="M 8,258 L 72,258" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="320,120 308,114.4 308,125.6" fill="black" transform="rotate(90,312,120)"/>
                <polygon class="arrowhead" points="160,120 148,114.4 148,125.6" fill="black" transform="rotate(90,152,120)"/>
                <polygon class="arrowhead" points="32,192 20,186.4 20,197.6" fill="black" transform="rotate(90,24,192)"/>
                <polygon class="arrowhead" points="32,120 20,114.4 20,125.6" fill="black" transform="rotate(90,24,120)"/>
                <g class="text">
                  <text x="44" y="36">Aggregator</text>
                  <text x="96" y="36">0</text>
                  <text x="172" y="36">Aggregator</text>
                  <text x="224" y="36">1</text>
                  <text x="332" y="36">Aggregator</text>
                  <text x="412" y="36">SHARES-1</text>
                  <text x="48" y="84">agg_share_0</text>
                  <text x="176" y="84">agg_share_1</text>
                  <text x="372" y="84">agg_share_[SHARES-1]</text>
                  <text x="48" y="148">unshard</text>
                  <text x="44" y="212">agg_result</text>
                  <text x="40" y="244">Collector</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
    Aggregator 0    Aggregator 1        Aggregator SHARES-1
    ============    ============        ===================

    agg_share_0     agg_share_1         agg_share_[SHARES-1]
      |               |                   |
      v               v                   v
    +-----------------------------------------------+
    | unshard                                       |
    +-+---------------------------------------------+
      |
      v
    agg_result

    Collector
    =========
]]></artwork>
          </artset>
        </figure>
        <t>After the Aggregators have aggregated all measurements in the batch, each sends
its aggregate share to the Collector, who runs the unsharding algorithm to
recover the aggregate result:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.unshard(agg_param: AggParam, agg_shares: list[AggShare],
num_measurements: int) -&gt; AggResult</tt> consumes the aggregate shares
and produces the aggregate result.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t>The length of <tt>agg_shares</tt> <bcp14>MUST</bcp14> be <tt>SHARES</tt>.</t>
              </li>
              <li>
                <t><tt>num_measurements</tt> <bcp14>MUST</bcp14> equal the number of measurements in the batch.</t>
              </li>
            </ul>
          </li>
        </ul>
      </section>
      <section anchor="daf-execution">
        <name>Execution of a DAF</name>
        <t>Secure execution of a DAF involves simulating the following procedure over an
insecure network.</t>
        <sourcecode type="python"><![CDATA[
def run_daf(
        daf: Daf[
            Measurement,
            AggParam,
            PublicShare,
            InputShare,
            OutShare,
            AggShare,
            AggResult,
        ],
        ctx: bytes,
        agg_param: AggParam,
        measurements: list[Measurement]) -> AggResult:
    agg_shares: list[AggShare]
    agg_shares = [daf.agg_init(agg_param)
                  for _ in range(daf.SHARES)]
    for measurement in measurements:
        # Sharding
        nonce = gen_rand(daf.NONCE_SIZE)
        rand = gen_rand(daf.RAND_SIZE)
        (public_share, input_shares) = \
            daf.shard(ctx, measurement, nonce, rand)

        # Preparation, aggregation
        for j in range(daf.SHARES):
            out_share = daf.prep(ctx, j, agg_param, nonce,
                                 public_share, input_shares[j])
            agg_shares[j] = daf.agg_update(agg_param,
                                           agg_shares[j],
                                           out_share)

    # Unsharding
    num_measurements = len(measurements)
    agg_result = daf.unshard(agg_param, agg_shares,
                             num_measurements)
    return agg_result
]]></sourcecode>
        <t>The inputs to this procedure include the parameters of the aggregation function
computed by the DAF: an aggregation parameter and a sequence of measurements.
They also include the application context. The procedure prescribes how a DAF is
executed in a "benign" environment in which there is no adversary and the
messages are passed among the protocol participants over secure point-to-point
channels. In reality, these channels need to be instantiated by some "wrapper
protocol", such as <xref target="DAP"/>, that realizes these channels using suitable
cryptographic mechanisms. Moreover, some fraction of the Aggregators (or
Clients) may be malicious and diverge from their prescribed behaviors.
<xref target="security"/> describes the execution of the DAF in various adversarial
environments and what properties the wrapper protocol needs to provide in each.</t>
      </section>
    </section>
    <section anchor="vdaf">
      <name>Definition of VDAFs</name>
      <t>VDAFs are identical to DAFs except that preparation is an interactive process
carried out by the Aggregators. If successful, this process results in each
Aggregator computing an output share. The process will fail if, for example,
the underlying measurement is invalid.</t>
      <t>Failure manifests as an exception raised by one of the algorithms defined in
this section. If an exception is raised during preparation, the Aggregators
<bcp14>MUST</bcp14> remove the report from the batch and not attempt to aggregate it.
Otherwise, a malicious Client can cause the Collector to compute a malformed
aggregate result.</t>
      <t>The remainder of this section defines the VDAF interface, denoted by <tt>Vdaf</tt>.
The attributes listed in <xref target="vdaf-param"/> are defined by each concrete VDAF.</t>
      <table anchor="vdaf-param">
        <name>Constants and types defined by each concrete VDAF.</name>
        <thead>
          <tr>
            <th align="left">Parameter</th>
            <th align="left">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>ID: int</tt></td>
            <td align="left">Algorithm identifier for this VDAF, in the range <tt>[0, 2**32)</tt>.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>SHARES: int</tt></td>
            <td align="left">Number of input shares into which each measurement is sharded.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>ROUNDS: int</tt></td>
            <td align="left">Number of rounds of communication during preparation.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>NONCE_SIZE: int</tt></td>
            <td align="left">Size of each report nonce.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>RAND_SIZE: int</tt></td>
            <td align="left">Size of each random byte string consumed during sharding.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>VERIFY_KEY_SIZE: int</tt></td>
            <td align="left">Size of the verification key used during preparation.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>Measurement</tt></td>
            <td align="left">Type of each measurement.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PublicShare</tt></td>
            <td align="left">Type of each public share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>InputShare</tt></td>
            <td align="left">Type of each input share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggParam</tt></td>
            <td align="left">Type of the aggregation parameter.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>OutShare</tt></td>
            <td align="left">Type of each output share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggShare</tt></td>
            <td align="left">Type of each aggregate share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggResult</tt></td>
            <td align="left">Type of the aggregate result.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PrepState</tt></td>
            <td align="left">Type of each prep state.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PrepShare</tt></td>
            <td align="left">Type of each prep share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PrepMessage</tt></td>
            <td align="left">Type of each prep message.</td>
          </tr>
        </tbody>
      </table>
      <t>Some of the types in the table above need to be written to the network in
order to carry out the computation. It is <bcp14>RECOMMENDED</bcp14> that concrete
instantiations of the <tt>Vdaf</tt> interface specify a method of encoding the
<tt>PublicShare</tt>, <tt>InputShare</tt>, <tt>AggParam</tt>, <tt>AggShare</tt>, <tt>PrepShare</tt>, and
<tt>PrepMessage</tt> types.</t>
      <t>Each VDAF is identified by a unique 32-bit integer, denoted <tt>ID</tt>. Identifiers
for each VDAF specified in this document are defined in <xref target="codepoints"/>. The
following method is used by both Prio3 and Poplar1:</t>
      <sourcecode type="python"><![CDATA[
def domain_separation_tag(self, usage: int, ctx: bytes) -> bytes:
    """
    Format domain separation tag for this VDAF with the given
    application context and usage.

    Pre-conditions:

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

    input_share_0  input_share_1          input_share_[SHARES-1]
      |              |                 ...  |
      v              v                      v
    +-----------+  +-----------+          +-----------+
    | prep_init |  | prep_init |          | prep_init |
    +-+-------+-+  +-+-------+-+          +-+-------+-+
      |       |      |       |         ...  |       |
      v       |      v       |              v       |
    +---------|--------------|----------------------|--+ -.
    |         |              |  prep_shares_to_prep |  |   |
    +-+-------|------+-------|--------------+-------|--+   |
      |       |      |       |         ...  |       |      |
      v       v      v       v              v       v      | x ROUNDS
    +-----------+  +-----------+          +-----------+    |
    | prep_next |  | prep_next |          | prep_next |    |
    +-+-------+-+  +-+-------+-+          +-+-------+-+    |
      |       |      |       |         ...  |       |      |
      v       v      v       v              v       v    -'

     ...            ...                    ...

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

        # Initialize preparation: Each Aggregator receives its report
        # share (the public share and its input share) from the
        # Client and initializes preparation.
        prep_states = []
        outbound_prep_shares = []
        for j in range(vdaf.SHARES):
            (state, share) = vdaf.prep_init(verify_key, ctx, j,
                                            agg_param,
                                            nonce,
                                            public_share,
                                            input_shares[j])
            prep_states.append(state)
            outbound_prep_shares.append(share)

        # Complete preparation: The Aggregators execute each round of
        # preparation until each computes an output share. A round
        # begins by gathering the prep shares and combining them into
        # the prep message. The round ends when each uses the prep
        # message to transition to the next state.
        for i in range(vdaf.ROUNDS - 1):
            prep_msg = vdaf.prep_shares_to_prep(ctx,
                                                agg_param,
                                                outbound_prep_shares)

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

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

        # Aggregation: Each Aggregator updates its aggregate share
        # with its output share.
        for j in range(vdaf.SHARES):
            out_share = vdaf.prep_next(ctx, prep_states[j], prep_msg)
            assert not isinstance(out_share, tuple)
            agg_shares[j] = vdaf.agg_update(agg_param,
                                            agg_shares[j],
                                            out_share)

    # Unsharding: The Collector receives the aggregate shares from
    # the Aggregators and combines them into the aggregate result.
    num_measurements = len(measurements)
    agg_result = vdaf.unshard(agg_param, agg_shares,
                              num_measurements)
    return agg_result
]]></sourcecode>
        <t>Depending on the VDAF, preparation and aggregation may be carried out multiple
times on the same sequence of reports.</t>
        <t>In practice, VDAF execution is distributed across Clients, Aggregators, and
Collectors that exchange messages (i.e., report shares, prep shares, and
aggregate shares) over an insecure network. The application must therefore take
some additional steps in order to securely execute the VDAF in this
environment. See <xref target="security"/> for details.</t>
      </section>
      <section anchor="vdaf-prep-comm">
        <name>Communication Patterns for Preparation</name>
        <t>The only stage of VDAF execution that requires interaction is preparation
(<xref target="sec-vdaf-prepare"/>). There are a number of ways to coordinate this
interaction; the best strategy depends largely on the number of Aggregators
(i.e., <tt>vdaf.SHARES</tt>). This section describes two strategies, one specialized
for two Aggregators and another that is suitable for any number of Aggregators.</t>
        <t>In each round of preparation, each Aggregator writes a prep share to some
broadcast channel, which is then processed into the prep message using the
public <tt>prep_shares_to_prep()</tt> algorithm and broadcast to the Aggregators to
start the next round. The goal of this section is to realize this broadcast
channel.</t>
        <t>The state machine of each Aggregator is shown below.</t>
        <figure anchor="vdaf-prep-state-machine">
          <name>State machine of VDAF preparation.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="144" width="504" viewBox="0 0 504 144" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 16,32 L 16,64" fill="none" stroke="black"/>
                <path d="M 16,96 L 16,128" fill="none" stroke="black"/>
                <path d="M 152,32 L 152,64" fill="none" stroke="black"/>
                <path d="M 184,32 L 184,64" fill="none" stroke="black"/>
                <path d="M 320,32 L 320,64" fill="none" stroke="black"/>
                <path d="M 416,40 L 416,64" fill="none" stroke="black"/>
                <path d="M 416,96 L 416,120" fill="none" stroke="black"/>
                <path d="M 16,32 L 40,32" fill="none" stroke="black"/>
                <path d="M 128,32 L 152,32" fill="none" stroke="black"/>
                <path d="M 184,32 L 320,32" fill="none" stroke="black"/>
                <path d="M 56,80 L 88,80" fill="none" stroke="black"/>
                <path d="M 16,128 L 160,128" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="424,120 412,114.4 412,125.6" fill="black" transform="rotate(90,416,120)"/>
                <polygon class="arrowhead" points="424,40 412,34.4 412,45.6" fill="black" transform="rotate(270,416,40)"/>
                <polygon class="arrowhead" points="328,64 316,58.4 316,69.6" fill="black" transform="rotate(90,320,64)"/>
                <polygon class="arrowhead" points="168,128 156,122.4 156,133.6" fill="black" transform="rotate(0,160,128)"/>
                <polygon class="arrowhead" points="136,32 124,26.4 124,37.6" fill="black" transform="rotate(180,128,32)"/>
                <polygon class="arrowhead" points="96,80 84,74.4 84,85.6" fill="black" transform="rotate(0,88,80)"/>
                <polygon class="arrowhead" points="48,32 36,26.4 36,37.6" fill="black" transform="rotate(0,40,32)"/>
                <g class="text">
                  <text x="84" y="36">Rejected</text>
                  <text x="424" y="36">Finished(out_share)</text>
                  <text x="24" y="84">Start</text>
                  <text x="184" y="84">Continued(prep_state,</text>
                  <text x="320" y="84">prep_round,</text>
                  <text x="408" y="84">outbound)</text>
                  <text x="296" y="132">FinishedWithOutbound(out_share,</text>
                  <text x="464" y="132">outbound)</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
 +--> Rejected <--+   +----------------+   Finished(out_share)
 |                |   |                |           ^
 |                |   |                v           |
Start ----> Continued(prep_state, prep_round, outbound)
 |                                                 |
 |                                                 v
 +-----------------> FinishedWithOutbound(out_share, outbound)
]]></artwork>
          </artset>
        </figure>
        <t>State transitions are made when the state is acted upon by the Aggregator's
local inputs and/or messages sent by its co-Aggregators. The initial state is
<tt>Start</tt>. The terminal states are: <tt>Rejected</tt>, indicating that the report cannot
be processed any further; <tt>Finished(out_share)</tt>, indicating that the
Aggregator has recovered an output share <tt>out_share</tt>; and
<tt>FinishedWithOutbound(out_share, outbound)</tt>, indicating that the Aggregator has
recovered an output share, and has one more outbound message to send. For
completeness, these states are defined in <xref target="topo-states"/>.</t>
        <t>The methods described in this section are defined in terms of opaque byte
strings. A compatible <tt>Vdaf</tt> <bcp14>MUST</bcp14> specify methods for encoding public shares,
input shares, prep shares, prep messages, and aggregation parameters.</t>
        <t>Implementations of Prio3 and Poplar1 <bcp14>MUST</bcp14> use the encoding schemes specified in
<xref target="prio3-encode"/> and <xref target="poplar1-encode"/> respectively.</t>
        <section anchor="ping-pong-topo">
          <name>The Ping-Pong Topology (Only Two Aggregators)</name>
          <t>For VDAFs with precisely two Aggregators (i.e., <tt>vdaf.SHARES == 2</tt>), the
following "ping pong" communication pattern can be used. It is compatible with
any request/response transport protocol, such as HTTP.</t>
          <t>In this section, the initiating Aggregator is called the Leader and the
responding Aggregator is called the Helper. The high-level idea is that the
Leader and Helper will take turns running the computation locally until input
from their peer is required:</t>
          <ul spacing="normal">
            <li>
              <t>For a 1-round VDAF (e.g., Prio3 in <xref target="prio3"/>), the Leader sends its prep share
to the Helper, who computes the prep message locally, computes its output
share, then sends the prep message to the Leader. Preparation requires just
one round trip between the Leader and the Helper.</t>
            </li>
            <li>
              <t>For a 2-round VDAF (e.g., Poplar1 in <xref target="poplar1"/>), the Leader sends its
first-round prep share to the Helper, who replies with the first-round prep
message and its second-round prep share. In the next request, the Leader
computes its second-round prep share locally, computes its output share, and
sends the second-round prep message to the Helper. Finally, the Helper
computes its own output share.</t>
            </li>
            <li>
              <t>In general, each request includes the Leader's prep share for the previous
round and/or the prep message for the current round; correspondingly, each
response consists of the prep message for the current round and the Helper's
prep share for the next round.</t>
            </li>
          </ul>
          <t>The Aggregators proceed in this ping-ponging fashion until a step of the
computation fails (indicating the report is invalid and should be rejected) or
preparation is completed. All told there are <tt>ceil((vdaf.ROUNDS+1)/2)</tt>
requests sent.</t>
          <t>Protocol messages are specified in the presentation language of TLS; see
<xref section="3" sectionFormat="of" target="RFC8446"/>. Each message is structured as follows:</t>
          <sourcecode type="tls-presentation"><![CDATA[
enum {
  initialize(0),
  continue(1),
  finish(2),
  (255)
} MessageType;

struct {
  MessageType type;
  select (Message.type) {
    case initialize:
      opaque prep_share<0..4294967295>;
    case continue:
      opaque prep_msg<0..4294967295>;
      opaque prep_share<0..4294967295>;
    case finish:
      opaque prep_msg<0..4294967295>;
  };
} Message;

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

        encoded_prep_share = self.encode_prep_share(prep_share)
        return Continued(
            prep_state, 0,
            encode(0, encoded_prep_share),  # initialize
        )
    except Exception:
        return Rejected()
]]></sourcecode>
          <t>The output is the <tt>State</tt> to which the Leader has transitioned. If the Leader's
state is <tt>Rejected</tt>, then processing halts. Otherwise, if the state is
<tt>Continued</tt>, then processing continues. In this case, the state also includes
the Leader's outbound message. The function <tt>encode</tt> is used to encode the
outbound message, which has the message type of <tt>initialize</tt> (identified by the
number <tt>0</tt>).</t>
          <t>To continue processing the report, the Leader sends the outbound message to the
Helper. The Helper's initial transition is computed using the following
procedure:</t>
          <sourcecode type="python"><![CDATA[
def ping_pong_helper_init(
    self,
    vdaf_verify_key: bytes,
    ctx: bytes,
    agg_param: bytes,
    nonce: bytes,
    public_share: bytes,
    input_share: bytes,
    inbound: bytes,  # encoded ping pong Message
) -> Continued | FinishedWithOutbound | Rejected:
    """
    Called by the Helper in response to the Leader's initial
    message.
    """

    try:
        (prep_state, prep_share) = self.prep_init(
            vdaf_verify_key,
            ctx,
            1,
            self.decode_agg_param(agg_param),
            nonce,
            self.decode_public_share(public_share),
            self.decode_input_share(1, input_share),
        )

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

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

def ping_pong_continued(
    self,
    is_leader: bool,
    ctx: bytes,
    agg_param: bytes,
    state: Continued,
    inbound: bytes,  # encoded ping pong Message
) -> State:
    try:
        prep_round = state.prep_round

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

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

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

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

    Pre-conditions:

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

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

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

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

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

    Pre-conditions:

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

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

    Pre-conditions:

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

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

    Pre-conditions:

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

    # Associated parameters
    SEED_SIZE = 32

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

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

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

    # Associated parameters
    SEED_SIZE = 16

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

        self.length_consumed = 0

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

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

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

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

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

    Pre-conditions:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

def verifier_len(self) -> int:
    """Length of the verifier message."""
    length = 1
    for g in self.GADGETS:
        length += g.ARITY + 1
    return length
]]></sourcecode>
        </section>
        <section anchor="flp-bbcggi19-construction-prove">
          <name>Generating the Proof</name>
          <figure>
            <name>Components of the proof generation algorithm.</name>
            <artset>
              <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="240" width="296" viewBox="0 0 296 240" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                  <path d="M 8,32 L 8,192" fill="none" stroke="black"/>
                  <path d="M 24,192 L 24,224" fill="none" stroke="black"/>
                  <path d="M 32,64 L 32,160" fill="none" stroke="black"/>
                  <path d="M 56,96 L 56,128" fill="none" stroke="black"/>
                  <path d="M 128,96 L 128,128" fill="none" stroke="black"/>
                  <path d="M 152,64 L 152,160" fill="none" stroke="black"/>
                  <path d="M 176,32 L 176,72" fill="none" stroke="black"/>
                  <path d="M 176,104 L 176,192" fill="none" stroke="black"/>
                  <path d="M 8,32 L 176,32" fill="none" stroke="black"/>
                  <path d="M 32,64 L 152,64" fill="none" stroke="black"/>
                  <path d="M 160,80 L 200,80" fill="none" stroke="black"/>
                  <path d="M 56,96 L 128,96" fill="none" stroke="black"/>
                  <path d="M 160,96 L 200,96" fill="none" stroke="black"/>
                  <path d="M 184,112 L 200,112" fill="none" stroke="black"/>
                  <path d="M 56,128 L 128,128" fill="none" stroke="black"/>
                  <path d="M 32,160 L 152,160" fill="none" stroke="black"/>
                  <path d="M 8,192 L 176,192" fill="none" stroke="black"/>
                  <polygon class="arrowhead" points="192,112 180,106.4 180,117.6" fill="black" transform="rotate(180,184,112)"/>
                  <polygon class="arrowhead" points="168,96 156,90.4 156,101.6" fill="black" transform="rotate(180,160,96)"/>
                  <polygon class="arrowhead" points="168,80 156,74.4 156,85.6" fill="black" transform="rotate(180,160,80)"/>
                  <polygon class="arrowhead" points="32,224 20,218.4 20,229.6" fill="black" transform="rotate(90,24,224)"/>
                  <g class="text">
                    <text x="48" y="52">prove()</text>
                    <text x="64" y="84">Valid</text>
                    <text x="228" y="84">meas</text>
                    <text x="232" y="100">joint</text>
                    <text x="276" y="100">rand</text>
                    <text x="92" y="116">Gadget</text>
                    <text x="232" y="116">prove</text>
                    <text x="276" y="116">rand</text>
                    <text x="56" y="228">proof</text>
                  </g>
                </svg>
              </artwork>
              <artwork type="ascii-art"><![CDATA[
+--------------------+
| prove()            |
|  +--------------+  |
|  | Valid        |<----- meas
|  |  +--------+  |<----- joint rand
|  |  | Gadget |  |  |<-- prove rand
|  |  +--------+  |  |
|  |              |  |
|  +--------------+  |
|                    |
+-+------------------+
  |
  v proof
]]></artwork>
            </artset>
          </figure>
          <t>The proof generation algorithm invokes the validity circuit on the encoded
measurement and joint randomness. The validity circuit in turn invokes the
gadgets defined by the circuit. The prover records the values on input wires of
gadget instances during circuit evaluation, and constructs gadget polynomials
that the verifier will use to compute the outputs of each gadget. Additionally,
the prove randomness is used as a blinding factor when constructing gadget
polynomials.</t>
          <t>To generate the gadget polynomials, the prover evaluates the validity circuit,
and records the values on each input wire of each call to each gadget. This is
accomplished by "wrapping" each gadget in a class <tt>ProveGadget</tt> that records
the wire inputs. This class is listed in <xref target="gadget-wrappers"/>. Denote the value
of the <tt>j</tt>-th wire for the <tt>k</tt>-th invocation of gadget <tt>g</tt> as <tt>g.wires[j][k]</tt>.</t>
          <t>Next, the prover computes each of the "wire polynomials" for each gadget. For
each wire polynomial, take one prove randomness value and designate it the
"wire seed" for that polynomial. The <tt>j</tt>-th wire polynomial is the lowest
degree polynomial that evaluates to the "wire seed" at one point and
<tt>g.wires[j][k]</tt> at a sequence of other points. The gadget polynomial is
obtained by evaluating the gadget on the wire polynomials.</t>
          <sourcecode type="python"><![CDATA[
def prove(self,
          meas: list[F],
          prove_rand: list[F],
          joint_rand: list[F]) -> list[F]:
    # Evaluate the validity circuit, recording the value of each
    # input wire for each evaluation of each gadget.
    valid = ProveGadget.wrap(self.valid, prove_rand)
    valid.eval(meas, joint_rand, 1)

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

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

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

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

    return proof
]]></sourcecode>
        </section>
        <section anchor="flp-bbcggi19-construction-query">
          <name>Querying the Proof</name>
          <figure>
            <name>Components of the query algorithm.</name>
            <artset>
              <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="272" width="312" viewBox="0 0 312 272" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                  <path d="M 8,64 L 8,224" fill="none" stroke="black"/>
                  <path d="M 24,224 L 24,256" fill="none" stroke="black"/>
                  <path d="M 32,96 L 32,192" fill="none" stroke="black"/>
                  <path d="M 56,128 L 56,160" fill="none" stroke="black"/>
                  <path d="M 96,48 L 96,128" fill="none" stroke="black"/>
                  <path d="M 128,128 L 128,160" fill="none" stroke="black"/>
                  <path d="M 152,96 L 152,192" fill="none" stroke="black"/>
                  <path d="M 176,64 L 176,104" fill="none" stroke="black"/>
                  <path d="M 176,136 L 176,224" fill="none" stroke="black"/>
                  <path d="M 8,64 L 88,64" fill="none" stroke="black"/>
                  <path d="M 104,64 L 176,64" fill="none" stroke="black"/>
                  <path d="M 32,96 L 88,96" fill="none" stroke="black"/>
                  <path d="M 104,96 L 152,96" fill="none" stroke="black"/>
                  <path d="M 160,112 L 200,112" fill="none" stroke="black"/>
                  <path d="M 56,128 L 88,128" fill="none" stroke="black"/>
                  <path d="M 104,128 L 128,128" fill="none" stroke="black"/>
                  <path d="M 160,128 L 200,128" fill="none" stroke="black"/>
                  <path d="M 184,144 L 200,144" fill="none" stroke="black"/>
                  <path d="M 56,160 L 128,160" fill="none" stroke="black"/>
                  <path d="M 32,192 L 152,192" fill="none" stroke="black"/>
                  <path d="M 8,224 L 176,224" fill="none" stroke="black"/>
                  <polygon class="arrowhead" points="192,144 180,138.4 180,149.6" fill="black" transform="rotate(180,184,144)"/>
                  <polygon class="arrowhead" points="168,128 156,122.4 156,133.6" fill="black" transform="rotate(180,160,128)"/>
                  <polygon class="arrowhead" points="168,112 156,106.4 156,117.6" fill="black" transform="rotate(180,160,112)"/>
                  <polygon class="arrowhead" points="104,128 92,122.4 92,133.6" fill="black" transform="rotate(90,96,128)"/>
                  <polygon class="arrowhead" points="32,256 20,250.4 20,261.6" fill="black" transform="rotate(90,24,256)"/>
                  <g class="text">
                    <text x="72" y="36">proof</text>
                    <text x="128" y="36">(share)</text>
                    <text x="48" y="84">query()</text>
                    <text x="64" y="116">Valid</text>
                    <text x="228" y="116">meas</text>
                    <text x="280" y="116">(share)</text>
                    <text x="232" y="132">joint</text>
                    <text x="276" y="132">rand</text>
                    <text x="92" y="148">Gadget</text>
                    <text x="232" y="148">query</text>
                    <text x="276" y="148">rand</text>
                    <text x="68" y="260">verifier</text>
                    <text x="136" y="260">(share)</text>
                  </g>
                </svg>
              </artwork>
              <artwork type="ascii-art"><![CDATA[
      proof (share)
           |
+----------|---------+
| query()  |         |
|  +-------|------+  |
|  | Valid |      |<----- meas (share)
|  |  +----v---+  |<----- joint rand
|  |  | Gadget |  |  |<-- query rand
|  |  +--------+  |  |
|  |              |  |
|  +--------------+  |
|                    |
+-+------------------+
  |
  v verifier (share)
]]></artwork>
            </artset>
          </figure>
          <t>The query algorithm invokes the validity circuit on the encoded measurement and
joint randomness. It evaluates the gadget polynomials encoded by the proof
(share) to produce (a share of) each gadget output. The verifier (share)
consists of (a share of) the validity circuit's output and (a share of) each
gadget test. The gadget tests consume the query randomness.</t>
          <t>The goal of each gadget test is to ensure the inputs used by the prover to
generate the gadget polynomial match the inputs used to evaluate it. This is
done by partially reconstructing the gadget polynomial and evaluating it at a
random point: when the gadget polynomial is evaluated at the same point, the
result should be the same.</t>
          <t>To start a gadget test, first construct the (shares of the) wire polynomials
just as the prover did. Then record the input (share) of the <tt>j</tt>-th wire of the
<tt>k</tt>-th invocation of the gadget as <tt>g.wires[j][k]</tt>. Again, this is accomplished
by a wrapper gadget, <tt>QueryGadget</tt>, listed in <xref target="gadget-wrappers"/>. This gadget
also evaluates the gadget polynomial for each gadget invocation in order to
produce the gadget's output. Then compute the wire polynomials from the
recorded values.</t>
          <t>Next, choose a random point <tt>t</tt> (parsed from the query randomness), evaluate
each wire polynomial at <tt>t</tt>, and evaluate the gadget polynomial at <tt>t</tt>. The
results are recorded in the verifier message passed to the decision algorithm,
where the test is finished.</t>
          <t>The random point <tt>t</tt> <bcp14>MUST NOT</bcp14> be one of the fixed evaluation points used to
interpolate the wire polynomials. Otherwise, the verifier message may partially
leak the encoded measurement.</t>
          <sourcecode type="python"><![CDATA[
def query(self,
          meas: list[F],
          proof: list[F],
          query_rand: list[F],
          joint_rand: list[F],
          num_shares: int) -> list[F]:
    # Evaluate the validity circuit, recording the value of each
    # input wire for each evaluation of each gadget. Use the gadget
    # polynomials encoded by `proof` to compute the gadget outputs.
    valid = QueryGadget.wrap(self.valid, proof)
    out = valid.eval(meas, joint_rand, num_shares)

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

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

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

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

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

        verifier += wire_checks
        verifier.append(gadget_check)

    return verifier
]]></sourcecode>
        </section>
        <section anchor="flp-bbcggi19-construction-decide">
          <name>Deciding Validity</name>
          <figure>
            <name>Components of the decision algorithm.</name>
            <artset>
              <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="144" width="168" viewBox="0 0 168 144" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                  <path d="M 8,64 L 8,96" fill="none" stroke="black"/>
                  <path d="M 24,32 L 24,56" fill="none" stroke="black"/>
                  <path d="M 24,96 L 24,128" fill="none" stroke="black"/>
                  <path d="M 160,64 L 160,96" fill="none" stroke="black"/>
                  <path d="M 8,64 L 160,64" fill="none" stroke="black"/>
                  <path d="M 8,96 L 160,96" fill="none" stroke="black"/>
                  <polygon class="arrowhead" points="32,128 20,122.4 20,133.6" fill="black" transform="rotate(90,24,128)"/>
                  <polygon class="arrowhead" points="32,56 20,50.4 20,61.6" fill="black" transform="rotate(90,24,56)"/>
                  <g class="text">
                    <text x="68" y="36">verifier</text>
                    <text x="44" y="84">Decide</text>
                    <text x="68" y="132">is_valid</text>
                  </g>
                </svg>
              </artwork>
              <artwork type="ascii-art"><![CDATA[
  | verifier
  v
+------------------+
| Decide           |
+-+----------------+
  |
  v is_valid
]]></artwork>
            </artset>
          </figure>
          <t>The decision algorithm consumes the verifier message. (Each of the Aggregators
computes an additive share of the verifier message after the previous step.) The
verifier message consists of the reduced circuit output and the gadget tests.</t>
          <t>To finish each gadget test, evaluate the gadget on the wire checks: if the
encoded measurement and joint randomness used to generate the proof are the
same as the measurement (share) and joint randomness used to verify the proof,
then the output of the gadget will be equal to the gadget check; otherwise, the
output will not equal the gadget check with high probability.</t>
          <sourcecode type="python"><![CDATA[
def decide(self, verifier: list[F]) -> bool:
    # Check the output of the validity circuit.
    ([v], verifier) = front(1, verifier)
    if v != self.field(0):
        return False

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                r_power *= r

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

        return [out]

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

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

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

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

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

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

                r_power *= r

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

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

        return [range_check, sum_check]

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

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

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

        Pre-conditions:

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

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

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

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

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

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

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

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

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

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

                r_power *= r

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

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

        return [range_check, weight_check]

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

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

    l = self.xof.SEED_SIZE

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

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

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

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

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

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

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

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

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

    # Evaluate the Aggregator's share of the sketch. These are
    # called the "masked input values" [BBCGGI21, Appendix C.4].
    verify_rand_xof = self.xof(
        verify_key,
        self.domain_separation_tag(USAGE_VERIFY_RAND, ctx),
        nonce + to_be_bytes(level, 2),
    )
    verify_rand = cast(
        list[Field],
        verify_rand_xof.next_vec(field, len(prefixes)),
    )
    sketch_share = cast(
        list[Field],
        [a_share, b_share, c_share],
    )
    out_share = []
    for (i, r) in enumerate(verify_rand):
        data_share = cast(Field, value[i][0])
        auth_share = cast(Field, value[i][1])
        sketch_share[0] += data_share * r
        sketch_share[1] += data_share * r ** 2
        sketch_share[2] += auth_share * r
        out_share.append(data_share)

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

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

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

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

    raise ValueError('invalid prep state')

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

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

    if len(previous_agg_params) < 1:
        return True

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

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

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

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

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

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

last_byte_mask = 0
leftover_bits = (level + 1) % 8
if leftover_bits > 0:
    for bit_index in range(8 - leftover_bits, 8):
        last_byte_mask |= 1 << bit_index
    last_byte_mask ^= 255

bytes_per_prefix = ((level + 1) + 7) // 8
for chunk in itertools.batched(encoded_prefixes, bytes_per_prefix):
    if chunk[-1] & last_byte_mask > 0:
        raise ValueError('trailing bits in prefix')

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-ppm-dap-16"/>
        </reference>
        <reference anchor="I-D.draft-irtf-cfrg-cryptography-specification-02">
          <front>
            <title>Guidelines for Writing Cryptography Specifications</title>
            <author fullname="Nick Sullivan" initials="N." surname="Sullivan">
              <organization>Cryptography Consulting LLC</organization>
            </author>
            <author fullname="Christopher A. Wood" initials="C. A." surname="Wood">
              <organization>Cloudflare, Inc.</organization>
            </author>
            <date day="7" month="July" year="2025"/>
            <abstract>
              <t>   This document provides guidelines and best practices for writing
   technical specifications for cryptography protocols and primitives,
   targeting the needs of implementers, researchers, and protocol
   designers.  It highlights the importance of technical specifications
   and discusses strategies for creating high-quality specifications
   that cater to the needs of each community, including guidance on
   representing mathematical operations, security definitions, and
   threat models.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-cryptography-specification-02"/>
        </reference>
      </references>
    </references>
    <?line 6151?>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

class Start(State):
    pass

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

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

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

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

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

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

class Rejected(State):
    pass
]]></sourcecode>
    </section>
    <section anchor="test-vectors">
      <name>Test Vectors</name>
      <t>Test vectors for Prio3 (<xref target="prio3"/>) and Poplar1 (<xref target="poplar1"/>) are available at
<xref target="TestVectors"/>. The test vector directory, <tt>test_vec/vdaf</tt>, contains a set of
JSON files. Each file contains a test vector for an instance of class <tt>Vdaf</tt> as
defined in <xref target="vdaf"/>. A test vector covers sharding, preparation, aggregation,
and unsharding of a batch of several measurements. The test vector schema is
defined below.</t>
      <section anchor="schema">
        <name>Schema</name>
        <dl>
          <dt><tt>ctx</tt>:</dt>
          <dd>
            <t>The application context string encoded in hexadecimal.</t>
          </dd>
          <dt><tt>verify_key</tt>:</dt>
          <dd>
            <t>The verification key encoded in hexadecimal.</t>
          </dd>
          <dt><tt>agg_param</tt>:</dt>
          <dd>
            <t>The aggregation parameter encoded in hexadecimal.</t>
          </dd>
          <dt><tt>prep</tt>:</dt>
          <dd>
            <t>A list of objects with the following schema:
</t>
            <dl>
              <dt><tt>measurement</tt>:</dt>
              <dd>
                <t>The measurement of type <tt>Measurement</tt> defined by the VDAF.</t>
              </dd>
              <dt><tt>nonce</tt>:</dt>
              <dd>
                <t>The nonce encoded in hexadecimal.</t>
              </dd>
              <dt><tt>rand</tt>:</dt>
              <dd>
                <t>The sharding randomness encoded in hexadecimal.</t>
              </dd>
              <dt><tt>public_share</tt>:</dt>
              <dd>
                <t>The expected public share encoded in hexadecimal.</t>
              </dd>
              <dt><tt>input_shares</tt>:</dt>
              <dd>
                <t>The expected list of input shares, each encoded in hexadecimal.</t>
              </dd>
              <dt><tt>prep_shares</tt>:</dt>
              <dd>
                <t>The expected list of prep shares generated by each Aggregator at each
round of preparation, encoded in hexadecimal.</t>
              </dd>
              <dt><tt>prep_messages</tt>:</dt>
              <dd>
                <t>The expected list of prep messages for each round of preparation, encoded
in hexadecimal.</t>
              </dd>
              <dt><tt>out_shares</tt>:</dt>
              <dd>
                <t>The expected list of output shares, encoded in hexadecimal.</t>
              </dd>
            </dl>
          </dd>
          <dt><tt>agg_shares</tt>:</dt>
          <dd>
            <t>The expected aggregate shares encoded in hexadecimal.</t>
          </dd>
          <dt><tt>agg_result</tt>:</dt>
          <dd>
            <t>The expected aggregate result of type <tt>AggResult</tt> defined by the VDAF.</t>
          </dd>
          <dt><tt>operations</tt>:</dt>
          <dd>
            <t>This lists the VDAF operations that should be executed as part of known
answer tests, using messages from this test vector as input. Operations
should be executed in the order they appear, to ensure that prepare state
values are computed before they are consumed. Prepare state values are not
included in test vectors because this document does not specify their
representation or encoding.</t>
          </dd>
        </dl>
        <t>Each operation in the <tt>operations</tt> list has the following schema:</t>
        <dl>
          <dt><tt>operation</tt>:</dt>
          <dd>
            <t>The type of operation to be performed. This is one of "shard", "prep_init",
"prep_shares_to_prep", "prep_next", "aggregate", or "unshard".</t>
          </dd>
          <dt><tt>round</tt>:</dt>
          <dd>
            <t>For any preparation operation, the round number of the operation to be
performed. This determines which prepare share, prepare state, and/or prepare
message to use.</t>
          </dd>
          <dt><tt>aggregator_id</tt>:</dt>
          <dd>
            <t>The aggregator ID to use when performing this operation. This determines
which messages and which prepare state to use, in addition to the aggregator ID
argument itself.</t>
          </dd>
          <dt><tt>report_index</tt>:</dt>
          <dd>
            <t>The index of the report on which to perform this operation. This is an index
into the <tt>prep</tt> array.</t>
          </dd>
          <dt><tt>success</tt>:</dt>
          <dd>
            <t>If this is <tt>True</tt>, the operation should succeed, and its output should match
the corresponding values in the test vector. If this is <tt>False</tt>, the operation
should fail, terminating preparation of this report.</t>
          </dd>
        </dl>
        <t>The test vector schema also includes whatever parameters are required to
instantiate the VDAF. These are listed in the subsections below.</t>
        <section anchor="prio3count-1">
          <name>Prio3Count</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3sum-1">
          <name>Prio3Sum</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>max_measurement</tt>:</dt>
            <dd>
              <t>The largest valid measurement, an integer. Each measurement is in the range
  <tt>[0, max_measurement]</tt>.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3sumvec-1">
          <name>Prio3SumVec</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>length</tt>:</dt>
            <dd>
              <t>The length of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>a parameter of the ParallelSum gadget, an integer.</t>
            </dd>
            <dt><tt>bits</tt>:</dt>
            <dd>
              <t>the bit length of each element of the vector, an integer. Each element is in
the range <tt>[0, 2**bits)</tt>.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3histogram-1">
          <name>Prio3Histogram</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>length</tt>:</dt>
            <dd>
              <t>The length of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>a parameter of the ParallelSum gadget, an integer.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3multihotcountvec-1">
          <name>Prio3MultihotCountVec</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>length</tt>:</dt>
            <dd>
              <t>The length of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>a parameter of the ParallelSum gadget, an integer.</t>
            </dd>
            <dt><tt>max_weight</tt>:</dt>
            <dd>
              <t>The largest vector weight, an integer. The sum of the elements of the
measurement must be in the range <tt>[0, max_weight]</tt>.</t>
            </dd>
          </dl>
        </section>
        <section anchor="poplar1-test-vec-param">
          <name>Poplar1</name>
          <dl>
            <dt><tt>bits</tt>:</dt>
            <dd>
              <t>The length of each input in bits, an integer.</t>
            </dd>
          </dl>
        </section>
      </section>
    </section>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The impetus of this work is the success of recent deployments of predecessors
of Prio3. These include the Mozilla Origin Telemetry project
<xref target="OriginTelemetry"/> and the Exposure Notification Private Analytics system
<xref target="ENPA"/> developed jointly by ISRG, Google, Apple, and others. Together these
systems have aggregated data from hundreds of millions of users.</t>
      <t>As the name implies, Prio3 is a descendant of the original Prio construction
<xref target="CGB17"/>. A second iteration was deployed in the <xref target="ENPA"/> system, and like the
VDAF described here, the ENPA system was built from techniques introduced in
<xref target="BBCGGI19"/> that significantly improve communication cost. That system was
specialized for a particular aggregation function; the goal of Prio3 is to
provide the same level of generality as the original construction.</t>
      <t>The security considerations in <xref target="security"/> are based largely on the security
analysis of <xref target="DPRS23"/>. Thanks to Hannah Davis and Mike Rosulek, who lent their
time to developing definitions and security proofs.</t>
      <t>Thanks to Julia Hesse who provided feedback on behalf of the Crypto Review
Panel.</t>
      <t>Thanks to Junye Chen, Henry Corrigan-Gibbs, Armando Faz-Hernández, Simon
Friedberger, Tim Geoghegan, Albert Liu, Brandon Pitman, Mariana Raykova,
Michael Rosenberg, Jacob Rothstein, Shan Wang, Xiao Wang, Bas Westerbaan, and
Christopher Wood for useful feedback on and contributions to the spec.</t>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA+y963YbR3Yw+r+fokKvE4MWAJHUxTY1dkJRlKyxJfGItGYm
jkM0gQbZIwCN6W6QwkjOg5xfeZacFzv7WrWru0FRmknyZa3DNWssAN112bVr
3y+DwSCp83qW7butN1mZT/P0fJa5J3lVl/n5qs4m7uDioswu0jovFu7pajHG
f1RbSXp+XmZX+NqTg6dbyaQYL9I5DDMp02k9yMt6OhhPy4vB1SSdDnYfJuO0
zi6Kcr3v8sW0SJJ8We67ulxV9d7Ozrc7e0laZum+e/769GlSrc7neVXBRPV6
mcmX10X59qIsVst9d/j09bPkbbaGrybw66LOykVWD57g1ElS1elicpbOigW8
us6qpJqnZX32l1VRZ9W+WxTJMt93v9TFuO+qoqzLbFrBv9Zz/MevSZKu6sui
3E/cIHHwx9t6nY8v03Lifhq6xynMVtFvRXmRLvK/EnBgWXk1Luj7bJ7ms31X
zs7/OV9eDat38WBP0qt84g6L4m3HKM9PYHNmkEl+lZUX2aKepFfZP1/gl8Nx
MY9HPLws4ciK5WVWuuO0rotF1/pmxWoynQGg7fhjfHVJ79zJs3q6aYrjy3w2
y5dLdzK+LJbLebromuNZUVzMovEr//g/X9CPNHSyKMo5vHOV7Sfw9MHRyT69
pMh4MLlKF2NAv6PFuFwvCftO8GDxEHrw+PYWPe8Pi/4GstYXRQmbcr8fuieI
Nvmi8fvRLM0XGZ7k26xs/PZ7+P/KvR66l9n48iqt01nnA0+LOm/88FN6XWaw
aHeESFJVl+m8Oe/QvS7O0/Hb7iFhuWW6dr8vh/K7g8sCKPv78IP7wr2bz/bK
6djxDczhXlVuC8fZcin86/c0zhAfZhBN4Il9B7dslyGcAjbV++6yrpfV/t27
19fXwwUgz/CiuLq7XJ3P8jGdZXU3lTMYZP4MBpWcwSCFK5DgVY6O8dnvXx3v
7cZHeVzmxR3AnzK/Ssdr+G9WZeVVvrjwpCXDo61hDfm4crAj97goZlkKJw53
LqtuOumTVblO3cFkki7eNs/jR4DOwj1Ly/Osdf45wHw6bX7/Op0CzrpXQP2K
q+rtuvHzwaLOL4pF7o6L2RruDfwznRSrCMp7e/QRaMkYyBdcW4DASTZelXm9
dgA7d4igLC7KdHm5dgA+wLMakbRyvZPDl4LWzUPK0+G4vAuj79598PVDBPXj
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
LJJpKwV0fIAOH5i1/IhXPwrK/G2bQIbCNnc19oE41+laGtIWeF99QSozwSPO
VsRgVooRyi7WGrjjZml5gQAUlAvj2kRIOf+RoaajbS3F1mrvicZpmSfXhgFS
dBsjjNiOCM80iUMqdlrtuKd5x1zDd7HuXhxfhkhOjLM6m6Y7zNDI4tgKQiVA
tsRH72gOdF/sU+xZWBhTfrdPyJtuE9GQRl38GOvPet8KFbn088qgsY016fQk
RYXyo5xPLoksWd38k59Bk8slXofdM3OAUb4IWTcGXJRiWFwvuPPEMKozfmcw
+N691mDn33FEYrt5O3z5FN1Nl9mkZ1hNO6Lug+sIs7Nf/NttX7Lhdx+SEwIf
ruV7uOHYDXOVTYxwJtxdXEYqxXSt8KN/Hz7npauko6TT9x5o2E76lSzKyhZh
oRoXGKgS7Wug5ypRgifNw+4MDeSngirC9ljqaErKTO3RhspoUxeLZbFoZ59/
WSUcrhcaSt0l04+wFepcer4maW5cDBrRPJmPL9DJkhEd5Ih/ZSem/kyL3Hcj
xUbsOwh8eaylfLyfi1jYGK5AUWOj1k7f3CM36kDY7iFt0rzUMhdPWtPVNfJD
jR5x/tStD3jDbuKpk41Tc/iHBmFS80gd2mqfWPaKK+NpOUTsZKCFJwKY4wSb
ulgWjG4VWcnxbLRPWGRUj0hUYxg8TArbLJYpJoihuTXhLJIKlXfTA1Wy3cgD
o4luOh9li2mim7VRgdAXd7GJhBdLwqXvTac3p2o5bWnNrbQxXpzm9PsFaZNr
m8WmuTgDzg/CzHoYxwfFhq9LalzBjdilgCNC+hgGHhxjpZFTOIdZAay99wrF
kNOYw26DzLLEZ+GmXgzwzKTCIwfJkFa11IaiLfbcIQC4775zeyOugmgy67aW
BHqYZKuRYL5kYcpp8cYKPTtSHzXucJvgVURJCSSWu7hvgLMQJLq96tYM9Ux+
OD091kqHAcn64v3OKWESlhWzNRMk+1OWTqQCTU1dVHHOyY2v/JDNlho9iTGC
0mo+n2QpSwtCHszQ/AqXzEAB13EARLlaqHkpcqwR7YTDYPsWm6VtTZSMIzS1
Tz2F7uGJpm53wKIQkXfJBGMkpRurYdl9u3duqIukOFwNjC0pzG652p03srWk
H1lxPzzSDr+Qcq2hf280gkzHaxpGMrcXnbGKK4wW4smBTCx9MHj7OPWoAnz2
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
myt1h5T74AzFAoQ46plnRrm0qa9bOUwO8fKERtJoZEASBQYeYl6ORpmQBts1
DJ3uXdKGYcKitGoOLCx81sRij/PXcnWJn0fdwC+amBYum6Cc0bIsuEBOvaJJ
Y4HDxALFZ9vukuF9tBZXhvqdz/PYsV59IhEcI2stGg+jp12Nx/B1xvWwO/ol
pWwfOAJXtUKVAI7qtHKhHDSL1wag5nVT7ma1wOcMQ6W+3lXMAoQ30R6bUlJ9
Xt+K1yhMjUQNQm1YwiNXr5hnlAWC7NCh8QImPKl00Oy43jCXYS5XuSt8han6
KYQLF1mZSTXZioA/eOS2KCQQdt7JW62FbrpG9JgJwxfuEgoriW/C0OpFA3bK
q6RQEBckGSz1SeWCJierxTCDOefi7bUVa1r7ClrtmpVpNe0lxwxpoaZi97Fa
VKT2ZoEH5hMpXD/QAs6eMSd1qD7HSrsR5AnYcit6HCt8VypMxM7sBffswWb2
IeaMoxjzgHuSq/tRvxyOv8vA4XYfB/r8nsjTSu3woy3sfp5bRJrnWqqHHXoO
YJ9fVD0kxe2Pq5G226plfEfbDjq8r4O/qjBAAMdP2/xb1jDgN0DjHgmCQfRP
Oza+i/1Jd/bdHY+e6rOKs8k6wEOusDqt17gdEELaoL7BO878GnG+l3hZPWxZ
6nvtQ5xtgc2KC5U3X3Fiw08fSqAjQN+JHlL8LVCzBk7uMT+SxcC05j6xrfsB
9FzPtlrQhpicQKjFV8ni2p7c9erJgVfx48X0lpFgNzSEdxgfwHJP5F8OCpZW
UJ5sYV/cB3rH/6H+5f8DWD2Y8qj92Ik+xv+HbhAeGMZl+Kpdejb4iJtEY4Eu
HeKt9U12I4zlmhvqgwQrmuu0ubYai2TeLYqpChv3vrkax9uK9TMYTeqol4rY
+Hcrw9+9TqzsA4IRbqoipxZYbavgC7gmU7BcuFREXCPQctKCpVdFH+/HjQB1
vB/ZBrXAcOVlenirD9KK6gbJ53if1IEB4E6sg8802xnxSXvEJzbik8+P+ISb
Pvn5I0Yn1sFnmnWHwo7MbTxUJiH1aHy8f+hA2Zm5PTn47kkPnqEu1Wcq1+Pv
sjeXrYM7fReY8R1NCBJcMiISRZGjxzreSYsdpt7OacyPoq2NjqTM6RLXaNEH
Y2Iqedkt0K2wEUu2M2zpS94pXvLPc4OqSZjByu6OwiF3TSTHXe4h5EbBHXMB
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
/h/euRD+QAsEAA==

-->

</rfc>
