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

<t>This document describes Verifiable Distributed Aggregation Functions (VDAFs), a
family of multi-party protocols for computing aggregate statistics over user
measurements. These protocols are designed to ensure that, as long as at least
one aggregation server executes the protocol honestly, individual measurements
are never seen by any server in the clear. At the same time, VDAFs allow the
servers to detect if a malicious or misconfigured client submitted an invalid
measurement. Two concrete VDAFs are specified, one for general-purpose
aggregation (Prio3) and another for heavy hitters (Poplar1).</t>
      <t>This document is a product of the Crypto Forum Research Group (CFRG) in the
IRTF.</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 287?>

<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>
      <t>This document represents the consensus of the Crypto Forum Research Group
(CFRG).</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>21:</t>
        <ul spacing="normal">
          <li>
            <t>Updated commit referenced for test vectors.</t>
          </li>
          <li>
            <t>Added text required of IRTF stream documents.</t>
          </li>
          <li>
            <t>Replaced RFC8446 with RFC9846.</t>
          </li>
          <li>
            <t>Fixed idnits warnings.</t>
          </li>
          <li>
            <t>Editorial changes.</t>
          </li>
        </ul>
        <t>20:</t>
        <ul spacing="normal">
          <li>
            <t>Take an editorial suggestion from Crypto Review Panel <xref target="PANEL-FEEDBACK"/>.</t>
          </li>
        </ul>
        <t>19:</t>
        <ul spacing="normal">
          <li>
            <t>Editorial changes only.</t>
          </li>
        </ul>
        <t>18:</t>
        <ul spacing="normal">
          <li>
            <t>FLP: Represent the gadget polynomials in the Lagrange basis instead of the
monomial basis. This allows us to take advantage of additional algorithmic
improvements described in <xref target="Faz25"/>. (*)</t>
          </li>
          <li>
            <t>Prio3Sum, Prio3SumVec, Prio3MultihotCountVec: Unify the bit decomposition
used in range proofs. The new technique allows for arbitrary ranges with only
<tt>ceil(log2(max_measurement))</tt> field elements. The previous technique required
twice as many. (*)</t>
          </li>
        </ul>
        <t>17:</t>
        <ul spacing="normal">
          <li>
            <t>Rename VDAF preparation to VDAF verification.</t>
          </li>
          <li>
            <t>Update the reference for TurboSHAKE128 to <xref target="RFC9861"/>.</t>
          </li>
          <li>
            <t>Prio3: Acknowledge an optimization pointed out in <xref target="Faz25"/>.</t>
          </li>
        </ul>
        <t>16:</t>
        <ul spacing="normal">
          <li>
            <t>Align document with guidelines for ASCII-safe mathematical notation from
<xref section="3.3.1.6" sectionFormat="of" target="I-D.draft-irtf-cfrg-cryptography-specification-02"/>.</t>
          </li>
          <li>
            <t>Address feedback from Crypto Review Panel <xref target="PANEL-FEEDBACK"/>.</t>
          </li>
        </ul>
        <t>15:</t>
        <ul spacing="normal">
          <li>
            <t>Simplify the ping-pong API for 2-party preparation by merging the outbound
message into the state object. This reduces the number of cases the caller
has to handle.</t>
          </li>
          <li>
            <t>Update the test vector format. First, enrich the test vector schema to
express negative test cases. Second, change the encoding of output shares to
match the aggregate shares.</t>
          </li>
        </ul>
        <t>14:</t>
        <ul spacing="normal">
          <li>
            <t>Poplar1: When decoding an aggregation parameter, require the padding bits
after each prefix to be cleared.</t>
          </li>
        </ul>
        <t>13:</t>
        <ul spacing="normal">
          <li>
            <t>(V)DAF: Replace the one-shot aggregation API with a streaming API. Each
Aggregator initializes aggregation, then updates its aggregate share as
output shares are produced. The scheme also specifies a method for merging
multiple aggregate shares.</t>
          </li>
          <li>
            <t>Poplar1: Move prefix uniqueness and ordering checks from <tt>prep_init()</tt> to
<tt>is_valid()</tt>.</t>
          </li>
          <li>
            <t>Poplar1: Use <tt>bool</tt> to represent control bits instead of <tt>Field2</tt>.</t>
          </li>
          <li>
            <t>Prio3MultihotCountVec: Change the measurement type from <tt>list[int]</tt> to
<tt>list[bool]</tt>.</t>
          </li>
          <li>
            <t>Security considerations: Define our threat model for side channel attacks and
enumerate the parts of the spec that are most relevant to implementers.</t>
          </li>
          <li>
            <t>Improve the specification of each Prio3 variant by listing each
implementation of <tt>Valid</tt> and <tt>Gadget</tt> in full. Gadgets are listed in a new
appendix section.</t>
          </li>
          <li>
            <t>Improve the specification of the FLP system by listing the proof-generation,
query, and decision algorithms in full. The wrapper gadgets are listed in the
new section of the appendix for gadgets.</t>
          </li>
          <li>
            <t>Add a section with a high-level overview of the IDPF construction.</t>
          </li>
          <li>
            <t>Move some sections around: move ping-pong and star topologies under
communication patterns for VDAF preparation; move FLP proof generation,
query, and decision algorithms up one level; move privacy considerations for
aggregation parameters up one level; and move safe usage of IDPF outputs up
one level.</t>
          </li>
        </ul>
        <t>12:</t>
        <ul spacing="normal">
          <li>
            <t>(V)DAF: Add an application context string parameter to sharding and
preparation. The motivation for this change is to harden Prio3 against
offline attacks. More generally, however, it allows designing schemes for
which correct execution requires agreement on the application context.
Accordingly, both Prio3 and Poplar1 have been modified to include the context
in the domain separation tag of each XOF invocation. (*)</t>
          </li>
          <li>
            <t>Prio3: Improve soundness of the base proof system and the circuits of some
variants. Generally speaking, wherever we evaluate a univariate polynomial at
a random point, we can instead evaluate a multivariate polynomial of lower
degree. (*)</t>
          </li>
          <li>
            <t>Prio3: Replace the helper's measurement and proof share seeds with a single
seed. (*)</t>
          </li>
          <li>
            <t>Prio3Sum: Update the circuit to support a more general range check and avoid
using joint randomness. (*)</t>
          </li>
          <li>
            <t>Prio3Histogram, Prio3MultihotCountVec: Move the final reduction of the
intermediate outputs out of the circuit. (*)</t>
          </li>
          <li>
            <t>IDPF: Add the application context string to key generation and evaluation and
bind it to the fixed AES key. (*)</t>
          </li>
          <li>
            <t>IDPF: Use XofTurboShake128 for deriving the leaf nodes in order to ensure the
construction is extractable. (*)</t>
          </li>
          <li>
            <t>IDPF: Simplify the public share encoding. (*)</t>
          </li>
          <li>
            <t>XofTurboShake128: Change <tt>SEED_SIZE</tt> from 16 bytes to 32 to mitigate offline
attacks on Prio3 robustness. In addition, allow seeds of different lengths so
that we can continue to use XofTurboShake128 with IDPF. (*)</t>
          </li>
          <li>
            <t>XofTurboShake128, XofFixedKeyAes128: Increase the length prefix for the
domain separation tag from one by to two bytes. This is to accommodate the
application context. (*)</t>
          </li>
          <li>
            <t>Reassign codepoints for all Prio3 variants and Poplar1. (*)</t>
          </li>
          <li>
            <t>Security considerations: Add a section on defense-in-depth measures taken by
Prio3 and Poplar1 and more discussion about choosing FLP parameters.</t>
          </li>
        </ul>
        <t>11:</t>
        <ul spacing="normal">
          <li>
            <t>Define message formats for the Poplar1 aggregation parameter and IDPF public
share.</t>
          </li>
          <li>
            <t>IDPF: Require the IDPF binder must be a random nonce.</t>
          </li>
          <li>
            <t>VDAF: Replace the pseudocode description of the ping-ping topology with
Python and sketch the star topology.</t>
          </li>
          <li>
            <t>DAF: Align aggregation parameter validation with VDAF.</t>
          </li>
          <li>
            <t>Replace <tt>Union[A, B]</tt> type with <tt>A | B</tt>.</t>
          </li>
          <li>
            <t>Rename FFT ("Fast Fourier Transform") with NTT ("Number Theoretic
Transform").</t>
          </li>
        </ul>
        <t>10:</t>
        <ul spacing="normal">
          <li>
            <t>Define Prio3MultihotCountVec, a variant of Prio3 for aggregating bit vectors
with bounded weight.</t>
          </li>
          <li>
            <t>FLP: Allow the output of the circuit to be a vector. This makes it possible
to skip joint randomness derivation in more cases.</t>
          </li>
          <li>
            <t>Poplar1: On the first round of preparation, handle <tt>None</tt> as an error.
Previously this message was interpreted as a length-3 vector of zeros.</t>
          </li>
          <li>
            <t>Prio3: Move specification of the field from the FLP validity circuit to the
VDAF itself.</t>
          </li>
          <li>
            <t>Clarify the extent to which the attacker controls the network in our threat
models for privacy and robustness.</t>
          </li>
          <li>
            <t>Clean up various aspects of the code, including: Follow existing
object-oriented programming patterns for Python more closely; make the type
hints enforceable; and avoid shadowing variables.</t>
          </li>
          <li>
            <t>Poplar1: Align terminology with <xref target="BBCGGI23"/>.</t>
          </li>
          <li>
            <t>IDPF: Add guidance for encoding byte strings as indices.</t>
          </li>
        </ul>
        <t>09:</t>
        <ul spacing="normal">
          <li>
            <t>Poplar1: Make prefix tree traversal stricter by requiring each node to be a
child of a node that was already visited. This change is intended to make it
harder for a malicious Aggregator to steer traversal towards
non-heavy-hitting measurements.</t>
          </li>
          <li>
            <t>Prio3: Add more explicit guidance for choosing the field size.</t>
          </li>
          <li>
            <t>IDPF: Define extractability and clarify (un)safe usage of intermediate prefix
counts. Accordingly, add text ensuring public share consistency to security
considerations.</t>
          </li>
        </ul>
        <t>08:</t>
        <ul spacing="normal">
          <li>
            <t>Poplar1: Bind the report nonce to the authenticator vector programmed into
the IDPF. (*)</t>
          </li>
          <li>
            <t>IdpfPoplar: Modify <tt>extend()</tt> by stealing each control bit from its
corresponding seed. This improves performance by reducing the number of AES
calls per level from 3 to 2. The cost is a slight reduction in the concrete
privacy bound. (*)</t>
          </li>
          <li>
            <t>Prio3: Add support for generating and verifying multiple proofs per
measurement. This enables a trade-off between communication cost and runtime:
if more proofs are used, then a smaller field can be used without impacting
robustness. (*)</t>
          </li>
          <li>
            <t>Replace SHAKE128 with TurboSHAKE128. (*)</t>
          </li>
        </ul>
        <t>07:</t>
        <ul spacing="normal">
          <li>
            <t>Rename PRG to XOF ("eXtendable Output Function"). Accordingly, rename PrgSha3
to XofShake128 and PrgFixedKeyAes128 to XofFixedKeyAes128. "PRG" is a misnomer
since we don't actually treat this object as a pseudorandom generator in
existing security analysis.</t>
          </li>
          <li>
            <t>Replace cSHAKE128 with SHAKE128, re-implementing domain separation for the
customization string using a simpler scheme. This change addresses the
reality that implementations of cSHAKE128 are less common. (*)</t>
          </li>
          <li>
            <t>Define a new VDAF, called Prio3SumVec, that generalizes Prio3Sum to a vector
of summands.</t>
          </li>
          <li>
            <t>Prio3Histogram: Update the codepoint and use the parallel sum optimization
introduced by Prio3SumVec to reduce the proof size. (*)</t>
          </li>
          <li>
            <t>Daf, Vdaf: Rename interface methods to match verbiage in the draft.</t>
          </li>
          <li>
            <t>Daf: Align with Vdaf by adding a nonce to <tt>shard()</tt> and <tt>prep()</tt>.</t>
          </li>
          <li>
            <t>Vdaf: Have <tt>prep_init()</tt> compute the first prep share. This change is
intended to simplify the interface by making the input to <tt>prep_next()</tt> not
optional.</t>
          </li>
          <li>
            <t>Prio3: Split sharding into two auxiliary functions, one for sharding with
joint randomness and another without. This change is intended to improve
readability.</t>
          </li>
          <li>
            <t>Fix bugs in the ping-pong interface discovered after implementing it.</t>
          </li>
        </ul>
        <t>06:</t>
        <ul spacing="normal">
          <li>
            <t>Vdaf: Define a wrapper interface for preparation that is suitable for the
"ping-pong" topology in which two Aggregators exchange messages over a
request/response protocol, like HTTP, and take turns executing the
computation until input from the peer is required.</t>
          </li>
          <li>
            <t>Prio3Histogram: Generalize the measurement type so that the histogram can be
used more easily with discrete domains. (*)</t>
          </li>
          <li>
            <t>Daf, Vdaf: Change the aggregation parameter validation algorithm to take the
set of previous parameters rather than a list. (The order of the parameters
is irrelevant.)</t>
          </li>
          <li>
            <t>Daf, Vdaf, Idpf: Add parameter <tt>RAND_SIZE</tt> that specifies the number of
random bytes consumed by the randomized algorithm (<tt>shard()</tt> for Daf and Vdaf
and <tt>gen()</tt> for Idpf).</t>
          </li>
        </ul>
        <t>05:</t>
        <ul spacing="normal">
          <li>
            <t>IdpfPoplar: Replace PrgSha3 with PrgFixedKeyAes128, a fixed-key mode for
AES-128 based on a construction from <xref target="GKWWY20"/>. This change is intended to
improve performance of IDPF evaluation. Note that the new PRG is not suitable
for all applications. (*)</t>
          </li>
          <li>
            <t>Idpf: Add a binder string to the key-generation and evaluation algorithms.
This is used to plumb the nonce generated by the Client to the PRG.</t>
          </li>
          <li>
            <t>Plumb random coins through the interface of randomized algorithms.
Specifically, add a random input to (V)DAF sharding algorithm and IDPF
key-generation algorithm and require implementations to specify the length of
the random input. Accordingly, update Prio3, Poplar1, and IdpfPoplar to match
the new interface. This change is intended to improve coverage of test
vectors.</t>
          </li>
          <li>
            <t>Use little-endian byte-order for field element encoding. (*)</t>
          </li>
          <li>
            <t>Poplar1: Move the last step of sketch evaluation from <tt>prep_next()</tt> to
<tt>prep_shares_to_prep()</tt>.</t>
          </li>
        </ul>
        <t>04:</t>
        <ul spacing="normal">
          <li>
            <t>Align security considerations with the security analysis of <xref target="DPRS23"/>.</t>
          </li>
          <li>
            <t>Vdaf: Pass the nonce to the sharding algorithm.</t>
          </li>
          <li>
            <t>Vdaf: Rather than allow the application to choose the nonce length, have each
implementation of the Vdaf interface specify the expected nonce length. (*)</t>
          </li>
          <li>
            <t>Prg: Split "info string" into two components: the "customization string",
intended for domain separation; and the "binder string", used to bind the
output to ephemeral values, like the nonce, associated with execution of a
(V)DAF.</t>
          </li>
          <li>
            <t>Replace PrgAes128 with PrgSha3, an implementation of the Prg interface based
on SHA-3, and use the new scheme as the default. Accordingly, replace
Prio3Aes128Count with Prio3Count, Poplar1Aes128 with Poplar1, and so on. SHA-3
is a safer choice for instantiating a random oracle, which is used in the
analysis of Prio3 of <xref target="DPRS23"/>. (*)</t>
          </li>
          <li>
            <t>Prio3, Poplar1: Ensure each invocation of the Prg uses a distinct
customization string, as suggested by <xref target="DPRS23"/>. This is intended to make
domain separation clearer, thereby simplifying security analysis. (*)</t>
          </li>
          <li>
            <t>Prio3: Replace "joint randomness hints" sent in each input share with "joint
randomness parts" sent in the public share. This reduces communication
overhead when the number of shares exceeds two. (*)</t>
          </li>
          <li>
            <t>Prio3: Bind nonce to joint randomness parts. This is intended to address
birthday attacks on robustness pointed out by <xref target="DPRS23"/>. (*)</t>
          </li>
          <li>
            <t>Poplar1: Use different Prg invocations for producing the correlated randomness
for inner and leaf nodes of the IDPF tree. This is intended to simplify
implementations. (*)</t>
          </li>
          <li>
            <t>Poplar1: Don't bind the candidate prefixes to the verifier randomness. This is
intended to improve performance, while not impacting security. According to
the analysis of <xref target="DPRS23"/>, it is necessary to restrict Poplar1 usage such
that no report is aggregated more than once at a given level of the IDPF tree;
otherwise, attacks on privacy may be possible. In light of this restriction,
there is no added benefit of binding to the prefixes themselves. (*)</t>
          </li>
          <li>
            <t>Poplar1: During preparation, assert that all candidate prefixes are unique
and appear in order. Uniqueness is required to avoid erroneously rejecting a
valid report; the ordering constraint ensures the uniqueness check can be
performed efficiently. (*)</t>
          </li>
          <li>
            <t>Poplar1: Increase the maximum candidate prefix count in the encoding of the
aggregation parameter. (*)</t>
          </li>
          <li>
            <t>Poplar1: Bind the nonce to the correlated randomness derivation. This is
intended to provide defense-in-depth by ensuring the Aggregators reject the
report if the nonce does not match what the Client used for sharding. (*)</t>
          </li>
          <li>
            <t>Poplar1: Clarify that the aggregation parameter encoding is <bcp14>OPTIONAL</bcp14>.
Accordingly, update implementation considerations around cross-aggregation
state.</t>
          </li>
          <li>
            <t>IdpfPoplar: Add implementation considerations around branching on the values
of control bits.</t>
          </li>
          <li>
            <t>IdpfPoplar: When decoding the control bits in the public share, assert
that the trailing bits of the final byte are all zero. (*)</t>
          </li>
        </ul>
        <t>03:</t>
        <ul spacing="normal">
          <li>
            <t>Define codepoints for (V)DAFs and use them for domain separation in Prio3 and
Poplar1. (*)</t>
          </li>
          <li>
            <t>Prio3: Align joint randomness computation with revised paper <xref target="BBCGGI19"/>.
This change mitigates an attack on robustness. (*)</t>
          </li>
          <li>
            <t>Prio3: Remove an intermediate PRG evaluation from query randomness generation.
(*)</t>
          </li>
          <li>
            <t>Add additional guidance for choosing FFT-friendly fields.</t>
          </li>
        </ul>
        <t>02:</t>
        <ul spacing="normal">
          <li>
            <t>Complete the initial specification of Poplar1.</t>
          </li>
          <li>
            <t>Extend (V)DAF syntax to include a "public share" output by the Client and
distributed to all of the Aggregators. This is to accommodate "extractable"
IDPFs as required for Poplar1. (See <xref target="BBCGGI21"/>, Section 4.3 for details.)</t>
          </li>
          <li>
            <t>Extend (V)DAF syntax to allow the unsharding step to take into account the
number of measurements aggregated.</t>
          </li>
          <li>
            <t>Extend FLP syntax by adding a method for decoding the aggregate result from a
vector of field elements. The new method takes into account the number of
measurements.</t>
          </li>
          <li>
            <t>Prio3: Align aggregate result computation with updated FLP syntax.</t>
          </li>
          <li>
            <t>Prg: Add a method for statefully generating a vector of field elements.</t>
          </li>
          <li>
            <t>Field: Require that field elements are fully reduced before decoding. (*)</t>
          </li>
          <li>
            <t>Define new field Field255.</t>
          </li>
        </ul>
        <t>01:</t>
        <ul spacing="normal">
          <li>
            <t>Require that VDAFs specify serialization of aggregate shares.</t>
          </li>
          <li>
            <t>Define Distributed Aggregation Functions (DAFs).</t>
          </li>
          <li>
            <t>Prio3: Move proof verifier check from <tt>prep_next()</tt> to
<tt>prep_shares_to_prep()</tt>. (*)</t>
          </li>
          <li>
            <t>Remove public parameter and replace verification parameter with a
"verification key" and "Aggregator ID".</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="conventions">
      <name>Conventions</name>
      <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>
      <?line -18?>

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

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

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

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

                        ...

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

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

    Collector
    =========
]]></artwork>
          </artset>
        </figure>
        <t>After the Aggregators have aggregated all measurements in the batch, each sends
its aggregate share to the Collector, who runs the unsharding algorithm to
recover the aggregate result:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.unshard(agg_param: AggParam, agg_shares: list[AggShare],
num_measurements: int) -&gt; AggResult</tt> consumes the aggregate shares
and produces the aggregate result.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t>The length of <tt>agg_shares</tt> <bcp14>MUST</bcp14> be <tt>SHARES</tt>.</t>
              </li>
              <li>
                <t><tt>num_measurements</tt> <bcp14>MUST</bcp14> equal the number of measurements in the batch.</t>
              </li>
            </ul>
          </li>
        </ul>
      </section>
      <section anchor="daf-execution">
        <name>Execution of a DAF</name>
        <t>Secure execution of a DAF involves simulating the following procedure over an
insecure network.</t>
        <sourcecode type="python"><![CDATA[
<CODE BEGINS>
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
<CODE ENDS>
]]></sourcecode>
        <t>The inputs to this procedure include the parameters of the aggregation function
computed by the DAF: an aggregation parameter and a sequence of measurements.
They also include the application context. The procedure prescribes how a DAF is
executed in a "benign" environment in which there is no adversary and the
messages are passed among the protocol participants over secure point-to-point
channels. In reality, these channels need to be instantiated by some "wrapper
protocol", such as <xref target="DAP"/>, that realizes these channels using suitable
cryptographic mechanisms. Moreover, some fraction of the Aggregators (or
Clients) may be malicious and diverge from their prescribed behaviors.
<xref target="security"/> describes the execution of the DAF in various adversarial
environments and what properties the wrapper protocol needs to provide in each.</t>
      </section>
    </section>
    <section anchor="vdaf">
      <name>Definition of VDAFs</name>
      <t>VDAFs are identical to DAFs except that the non-interactive preparation process
is replaced by an interactive process called "verification" in which, in
addition to refining their input shares into output shares, the Aggregators
also verify that they hold valid output shares.</t>
      <t>Failure manifests as an exception raised by one of the algorithms defined in
this section. If an exception is raised during verification, the Aggregators
<bcp14>MUST</bcp14> remove the report from the batch and not attempt to aggregate it.
Otherwise, a malicious Client can cause the Collector to compute a malformed
aggregate result.</t>
      <t>The remainder of this section defines the VDAF interface, denoted by <tt>Vdaf</tt>.
The attributes listed in <xref target="vdaf-param"/> are defined by each concrete VDAF.</t>
      <table anchor="vdaf-param">
        <name>Constants and types defined by each concrete VDAF.</name>
        <thead>
          <tr>
            <th align="left">Parameter</th>
            <th align="left">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>ID: int</tt></td>
            <td align="left">Algorithm identifier for this VDAF, in the range <tt>[0, 2**32)</tt>.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>SHARES: int</tt></td>
            <td align="left">Number of input shares into which each measurement is sharded.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>ROUNDS: int</tt></td>
            <td align="left">Number of rounds of communication during verification.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>NONCE_SIZE: int</tt></td>
            <td align="left">Size of each report nonce.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>RAND_SIZE: int</tt></td>
            <td align="left">Size of each random byte string consumed during sharding.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>VERIFY_KEY_SIZE: int</tt></td>
            <td align="left">Size of the verification key used during verification.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>Measurement</tt></td>
            <td align="left">Type of each measurement.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PublicShare</tt></td>
            <td align="left">Type of each public share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>InputShare</tt></td>
            <td align="left">Type of each input share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggParam</tt></td>
            <td align="left">Type of the aggregation parameter.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>OutShare</tt></td>
            <td align="left">Type of each output share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggShare</tt></td>
            <td align="left">Type of each aggregate share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggResult</tt></td>
            <td align="left">Type of the aggregate result.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>VerifyState</tt></td>
            <td align="left">Type of each verification state.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>VerifierShare</tt></td>
            <td align="left">Type of each verifier share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>VerifierMessage</tt></td>
            <td align="left">Type of each verifier message.</td>
          </tr>
        </tbody>
      </table>
      <t>Some of the types in the table above need to be written to the network in
order to carry out the computation. It is <bcp14>RECOMMENDED</bcp14> that concrete
instantiations of the <tt>Vdaf</tt> interface specify a method of encoding the
<tt>PublicShare</tt>, <tt>InputShare</tt>, <tt>AggParam</tt>, <tt>AggShare</tt>, <tt>VerifierShare</tt>, and
<tt>VerifierMessage</tt> types.</t>
      <t>Each VDAF is identified by a unique 32-bit integer, denoted <tt>ID</tt>. Identifiers
for each VDAF specified in this document are defined in <xref target="codepoints"/>. The
following method is used by both Prio3 and Poplar1:</t>
      <sourcecode type="python"><![CDATA[
<CODE BEGINS>
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
<CODE ENDS>
]]></sourcecode>
      <t>The output, called the "domain separation tag", is used in the constructions
for domain separation. Function <tt>format_dst()</tt> is defined in <xref target="dst-binder"/>.</t>
      <section anchor="sec-vdaf-shard">
        <name>Sharding</name>
        <t>Sharding is as described for DAFs in <xref target="sec-daf-shard"/>. The public share and
input shares encode additional information used during verification to validate
the output shares before they are aggregated (e.g., the "proof shares" in
<xref target="prio3"/>).</t>
        <t>As in DAFs, sharding is bound to the application context via the application
context string. Again, this is intended to ensure that aggregation succeeds
only if the Clients and Aggregators agree on the application context. Unlike
DAFs, however, disagreement on the context should manifest as a verification
failure, causing the report to be rejected without garbling the aggregate
result. The application context also provides some defense-in-depth against
cross protocol attacks; see <xref target="deep"/>.</t>
      </section>
      <section anchor="sec-vdaf-verify">
        <name>Verification</name>
        <figure anchor="verify-flow">
          <name>Illustration of interactive VDAF verification.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="496" width="520" viewBox="0 0 520 496" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,128 L 8,160" fill="none" stroke="black"/>
                <path d="M 8,208 L 8,240" fill="none" stroke="black"/>
                <path d="M 8,288 L 8,320" fill="none" stroke="black"/>
                <path d="M 24,96 L 24,120" fill="none" stroke="black"/>
                <path d="M 24,160 L 24,200" fill="none" stroke="black"/>
                <path d="M 24,240 L 24,280" fill="none" stroke="black"/>
                <path d="M 24,320 L 24,352" fill="none" stroke="black"/>
                <path d="M 24,416 L 24,448" fill="none" stroke="black"/>
                <path d="M 104,160 L 104,280" fill="none" stroke="black"/>
                <path d="M 104,320 L 104,352" fill="none" stroke="black"/>
                <path d="M 120,128 L 120,160" fill="none" stroke="black"/>
                <path d="M 120,288 L 120,320" fill="none" stroke="black"/>
                <path d="M 144,128 L 144,160" fill="none" stroke="black"/>
                <path d="M 144,288 L 144,320" fill="none" stroke="black"/>
                <path d="M 160,96 L 160,120" fill="none" stroke="black"/>
                <path d="M 160,160 L 160,200" fill="none" stroke="black"/>
                <path d="M 160,240 L 160,280" fill="none" stroke="black"/>
                <path d="M 160,320 L 160,352" fill="none" stroke="black"/>
                <path d="M 160,416 L 160,448" fill="none" stroke="black"/>
                <path d="M 240,160 L 240,208" fill="none" stroke="black"/>
                <path d="M 240,240 L 240,280" fill="none" stroke="black"/>
                <path d="M 240,320 L 240,352" fill="none" stroke="black"/>
                <path d="M 256,128 L 256,160" fill="none" stroke="black"/>
                <path d="M 256,288 L 256,320" fill="none" stroke="black"/>
                <path d="M 328,128 L 328,160" fill="none" stroke="black"/>
                <path d="M 328,288 L 328,320" fill="none" stroke="black"/>
                <path d="M 344,96 L 344,120" fill="none" stroke="black"/>
                <path d="M 344,160 L 344,200" fill="none" stroke="black"/>
                <path d="M 344,240 L 344,280" fill="none" stroke="black"/>
                <path d="M 344,320 L 344,352" fill="none" stroke="black"/>
                <path d="M 344,416 L 344,448" fill="none" stroke="black"/>
                <path d="M 424,160 L 424,280" fill="none" stroke="black"/>
                <path d="M 424,320 L 424,352" fill="none" stroke="black"/>
                <path d="M 440,128 L 440,160" fill="none" stroke="black"/>
                <path d="M 440,288 L 440,320" fill="none" stroke="black"/>
                <path d="M 448,208 L 448,240" fill="none" stroke="black"/>
                <path d="M 480,224 L 480,336" fill="none" stroke="black"/>
                <path d="M 8,46 L 96,46" fill="none" stroke="black"/>
                <path d="M 8,50 L 96,50" fill="none" stroke="black"/>
                <path d="M 128,46 L 216,46" fill="none" stroke="black"/>
                <path d="M 128,50 L 216,50" fill="none" stroke="black"/>
                <path d="M 312,46 L 456,46" fill="none" stroke="black"/>
                <path d="M 312,50 L 456,50" fill="none" stroke="black"/>
                <path d="M 8,128 L 120,128" fill="none" stroke="black"/>
                <path d="M 144,128 L 256,128" fill="none" stroke="black"/>
                <path d="M 328,128 L 440,128" fill="none" stroke="black"/>
                <path d="M 8,160 L 120,160" fill="none" stroke="black"/>
                <path d="M 144,160 L 256,160" fill="none" stroke="black"/>
                <path d="M 328,160 L 440,160" fill="none" stroke="black"/>
                <path d="M 8,208 L 96,208" fill="none" stroke="black"/>
                <path d="M 112,208 L 232,208" fill="none" stroke="black"/>
                <path d="M 248,208 L 416,208" fill="none" stroke="black"/>
                <path d="M 432,208 L 448,208" fill="none" stroke="black"/>
                <path d="M 8,240 L 96,240" fill="none" stroke="black"/>
                <path d="M 112,240 L 232,240" fill="none" stroke="black"/>
                <path d="M 248,240 L 416,240" fill="none" stroke="black"/>
                <path d="M 432,240 L 448,240" fill="none" stroke="black"/>
                <path d="M 8,288 L 120,288" fill="none" stroke="black"/>
                <path d="M 144,288 L 256,288" fill="none" stroke="black"/>
                <path d="M 328,288 L 440,288" fill="none" stroke="black"/>
                <path d="M 8,320 L 120,320" fill="none" stroke="black"/>
                <path d="M 144,320 L 256,320" fill="none" stroke="black"/>
                <path d="M 328,320 L 440,320" fill="none" stroke="black"/>
                <path d="M 464,208 C 472.83064,208 480,215.16936 480,224" fill="none" stroke="black"/>
                <path d="M 464,352 C 472.83064,352 480,344.83064 480,336" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="432,352 420,346.4 420,357.6" fill="black" transform="rotate(90,424,352)"/>
                <polygon class="arrowhead" points="432,280 420,274.4 420,285.6" fill="black" transform="rotate(90,424,280)"/>
                <polygon class="arrowhead" points="352,448 340,442.4 340,453.6" fill="black" transform="rotate(90,344,448)"/>
                <polygon class="arrowhead" points="352,352 340,346.4 340,357.6" fill="black" transform="rotate(90,344,352)"/>
                <polygon class="arrowhead" points="352,280 340,274.4 340,285.6" fill="black" transform="rotate(90,344,280)"/>
                <polygon class="arrowhead" points="352,200 340,194.4 340,205.6" fill="black" transform="rotate(90,344,200)"/>
                <polygon class="arrowhead" points="352,120 340,114.4 340,125.6" fill="black" transform="rotate(90,344,120)"/>
                <polygon class="arrowhead" points="248,352 236,346.4 236,357.6" fill="black" transform="rotate(90,240,352)"/>
                <polygon class="arrowhead" points="248,280 236,274.4 236,285.6" fill="black" transform="rotate(90,240,280)"/>
                <polygon class="arrowhead" points="168,448 156,442.4 156,453.6" fill="black" transform="rotate(90,160,448)"/>
                <polygon class="arrowhead" points="168,352 156,346.4 156,357.6" fill="black" transform="rotate(90,160,352)"/>
                <polygon class="arrowhead" points="168,280 156,274.4 156,285.6" fill="black" transform="rotate(90,160,280)"/>
                <polygon class="arrowhead" points="168,200 156,194.4 156,205.6" fill="black" transform="rotate(90,160,200)"/>
                <polygon class="arrowhead" points="168,120 156,114.4 156,125.6" fill="black" transform="rotate(90,160,120)"/>
                <polygon class="arrowhead" points="112,352 100,346.4 100,357.6" fill="black" transform="rotate(90,104,352)"/>
                <polygon class="arrowhead" points="112,280 100,274.4 100,285.6" fill="black" transform="rotate(90,104,280)"/>
                <polygon class="arrowhead" points="32,448 20,442.4 20,453.6" fill="black" transform="rotate(90,24,448)"/>
                <polygon class="arrowhead" points="32,352 20,346.4 20,357.6" fill="black" transform="rotate(90,24,352)"/>
                <polygon class="arrowhead" points="32,280 20,274.4 20,285.6" fill="black" transform="rotate(90,24,280)"/>
                <polygon class="arrowhead" points="32,200 20,194.4 20,205.6" fill="black" transform="rotate(90,24,200)"/>
                <polygon class="arrowhead" points="32,120 20,114.4 20,125.6" fill="black" transform="rotate(90,24,120)"/>
                <g class="text">
                  <text x="44" y="36">Aggregator</text>
                  <text x="96" y="36">0</text>
                  <text x="164" y="36">Aggregator</text>
                  <text x="216" y="36">1</text>
                  <text x="348" y="36">Aggregator</text>
                  <text x="428" y="36">SHARES-1</text>
                  <text x="56" y="84">input_share_0</text>
                  <text x="192" y="84">input_share_1</text>
                  <text x="404" y="84">input_share_[SHARES-1]</text>
                  <text x="312" y="100">...</text>
                  <text x="64" y="148">verify_init</text>
                  <text x="200" y="148">verify_init</text>
                  <text x="384" y="148">verify_init</text>
                  <text x="312" y="180">...</text>
                  <text x="260" y="228">verifier_shares_to_message</text>
                  <text x="512" y="244">R</text>
                  <text x="312" y="260">...</text>
                  <text x="512" y="260">O</text>
                  <text x="496" y="276">x</text>
                  <text x="512" y="276">U</text>
                  <text x="512" y="292">N</text>
                  <text x="64" y="308">verify_next</text>
                  <text x="200" y="308">verify_next</text>
                  <text x="384" y="308">verify_next</text>
                  <text x="512" y="308">D</text>
                  <text x="512" y="324">S</text>
                  <text x="312" y="340">...</text>
                  <text x="24" y="388">...</text>
                  <text x="144" y="388">...</text>
                  <text x="312" y="388">...</text>
                  <text x="312" y="420">...</text>
                  <text x="48" y="468">out_share_0</text>
                  <text x="184" y="468">out_share_1</text>
                  <text x="396" y="468">out_share_[SHARES-1]</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
    Aggregator 0   Aggregator 1           Aggregator SHARES-1
    ============   ============           ===================

    input_share_0    input_share_1         input_share_[SHARES-1]
      |                |                 ...  |
      v                v                      v
    +-------------+  +-------------+        +-------------+
    | verify_init |  | verify_init |        | verify_init |
    +-+---------+-+  +-+---------+-+        +-+---------+-+
      |         |      |         |       ...  |         |
      v         |      v         |            v         |
    +-----------|----------------|----------------------|--+ -.
    |           |      verifier_shares_to_message       |  |   |
    +-+---------|------+---------|------------+---------|--+   |   R
      |         |      |         |       ...  |         |      |   O
      v         v      v         v            v         v      | x U
    +-------------+  +-------------+        +-------------+    |   N
    | verify_next |  | verify_next |        | verify_next |    |   D
    +-+---------+-+  +-+---------+-+        +-+---------+-+    |   S
      |         |      |         |       ...  |         |      |
      v         v      v         v            v         v    -'

     ...            ...                  ...

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

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

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

            outbound_verifier_shares = []
            for j in range(vdaf.SHARES):
                out = vdaf.verify_next(ctx,
                                       verify_states[j],
                                       verifier_message)
                assert isinstance(out, tuple)
                (verify_states[j], verifier_share) = out
                outbound_verifier_shares.append(verifier_share)

        verifier_message = vdaf.verifier_shares_to_message(
            ctx, agg_param, outbound_verifier_shares)

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

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

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

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

        encoded_verifier_share = self.encode_verifier_share(
            verifier_share)
        return Continued(
            verify_state, 0,
            encode(0, encoded_verifier_share),  # initialize
        )
    except Exception:
        return Rejected()
<CODE ENDS>
]]></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[
<CODE BEGINS>
def ping_pong_helper_init(
    self,
    vdaf_verify_key: bytes,
    ctx: bytes,
    agg_param: bytes,
    nonce: bytes,
    public_share: bytes,
    input_share: bytes,
    inbound: bytes,  # encoded ping pong Message
) -> Continued | FinishedWithOutbound | Rejected:
    """
    Called by the Helper in response to the Leader's initial
    message.
    """

    try:
        (verify_state, verifier_share) = self.verify_init(
            vdaf_verify_key,
            ctx,
            1,
            self.decode_agg_param(agg_param),
            nonce,
            self.decode_public_share(public_share),
            self.decode_input_share(1, input_share),
        )

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

        encoded_verifier_share = inbound_items[0]
        verifier_shares = [
            self.decode_verifier_share(
                verify_state, encoded_verifier_share),
            verifier_share,
        ]
        return self.ping_pong_transition(
            ctx, self.decode_agg_param(agg_param),
            verifier_shares, verify_state, 0)
    except Exception:
        return Rejected()
<CODE ENDS>
]]></sourcecode>
          <t>The procedure <tt>decode()</tt> decodes the inbound message and returns the
MessageType variant (<tt>initialize</tt>, <tt>continue</tt>, or <tt>finish</tt>) and the fields of
the message. The procedure <tt>ping_pong_transition()</tt> takes in the verifier
shares, combines them into the verifier message, and computes the next
verification state of the caller:</t>
          <sourcecode type="python"><![CDATA[
<CODE BEGINS>
def ping_pong_transition(
        self,
        ctx: bytes,
        agg_param: AggParam,
        verifier_shares: list[VerifierShare],
        verify_state: VerifyState,
        verify_round: int) -> Continued | FinishedWithOutbound:
    verifier_message = self.verifier_shares_to_message(
        ctx, agg_param, verifier_shares)
    encoded_verifier_message = self.encode_verifier_message(
        verifier_message)
    out = self.verify_next(ctx, verify_state, verifier_message)
    if verify_round+1 == self.ROUNDS:
        return FinishedWithOutbound(
            out, encode(2, encoded_verifier_message))  # finalize
    (verify_state, verifier_share) = cast(
        tuple[VerifyState, VerifierShare], out)
    encoded_verifier_share = self.encode_verifier_share(
        verifier_share)
    return Continued(
        verify_state, verify_round+1,
        encode(1, encoded_verifier_message,
               encoded_verifier_share))  # continue
<CODE ENDS>
]]></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 includes 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[
<CODE BEGINS>
def ping_pong_leader_continued(
    self,
    ctx: bytes,
    agg_param: bytes,
    state: Continued,
    inbound: bytes,  # encoded ping pong Message
) -> State:
    """
    Called by the Leader to start the next step of ping-ponging.
    """
    return self.ping_pong_continued(
        True, ctx, agg_param, state, inbound)

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

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

        encoded_verifier_message = inbound_items[0]
        verifier_message = self.decode_verifier_message(
            state.verify_state,
            encoded_verifier_message,
        )
        out = self.verify_next(
            ctx, state.verify_state, verifier_message)
        if verify_round+1 < self.ROUNDS and \
                inbound_type == 1:  # continue
            (verify_state, verifier_share) = cast(
                tuple[VerifyState, VerifierShare], out)
            encoded_verifier_share = inbound_items[1]
            verifier_shares = [
                self.decode_verifier_share(
                    verify_state, encoded_verifier_share),
                verifier_share,
            ]
            if is_leader:
                verifier_shares.reverse()
            return self.ping_pong_transition(
                ctx, self.decode_agg_param(agg_param),
                verifier_shares, verify_state, verify_round+1)
        elif verify_round+1 == self.ROUNDS and \
                inbound_type == 2:  # finish
            return Finished(out)
        else:
            return Rejected()
    except Exception:
        return Rejected()
<CODE ENDS>
]]></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[
<CODE BEGINS>
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)
<CODE ENDS>
]]></sourcecode>
          <t>They continue in this way until processing halts.</t>
        </section>
        <section anchor="star-topo">
          <name>The Star Topology (Any Number of Aggregators)</name>
          <t>The ping-pong topology of the previous section is only suitable for applications
of VDAFs involving exactly two Aggregators. In applications with more than two
Aggregators, the star topology described in this section can
be used instead.</t>
          <t>Again, one Aggregator initiates the computation. This Aggregator is called the
Leader and all other Aggregators are called Helpers.</t>
          <t>At the start of each round, the Leader requests from each Helper its verifier
share. After gathering each of the verifier shares, the Leader computes the
next verifier message (via <tt>vdaf.verifier_shares_to_message()</tt>) and broadcasts
it to the Helpers. At this point, each Aggregator runs <tt>vdaf.verify_next()</tt>
locally to either recover an output share or, if more rounds of verification
are required, compute its updated state and verifier share. If another round is
required, then the Helper responds to the broadcast message with its next
verifier share.</t>
          <t>The Aggregators proceed in this way until each recovers an output share or some
step of the computation fails.</t>
        </section>
      </section>
    </section>
    <section anchor="prelim">
      <name>Preliminaries</name>
      <t>This section describes the primitives that are common to the VDAFs specified in
this document.</t>
      <section anchor="field">
        <name>Finite Fields</name>
        <t>Both Prio3 and Poplar1 use finite fields of prime order. Finite field
elements are represented by a class <tt>Field</tt> with the following associated
parameters:</t>
        <ul spacing="normal">
          <li>
            <t><tt>MODULUS: int</tt> is the prime modulus that defines the field.</t>
          </li>
          <li>
            <t><tt>ENCODED_SIZE: int</tt> is the number of bytes used to encode a field element
as a byte string.</t>
          </li>
        </ul>
        <t>Concrete fields, i.e., subclasses of <tt>Field</tt>, implement the following class
methods:</t>
        <ul spacing="normal">
          <li>
            <t><tt>Field.zeros(length: int) -&gt; list[Self]</tt> returns a vector of zeros of the
requested length.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>length</tt> <bcp14>MUST</bcp14> be greater than or equal <tt>0</tt>.</t>
              </li>
            </ul>
            <t>
Post-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t>The length of the output <bcp14>MUST</bcp14> be <tt>length</tt>.</t>
              </li>
            </ul>
          </li>
          <li>
            <t><tt>Field.rand_vec(length: int) -&gt; list[Self]</tt> returns a vector of random field
elements and has the same pre- and post-conditions as for <tt>Field.zeros()</tt>.
Note that this function is not used normatively in the specification of
either Prio3 or Poplar1.</t>
          </li>
        </ul>
        <t>A field element is an instance of a concrete <tt>Field</tt>. Addition,
subtraction, multiplication, division, negation, and inversion are denoted,
respectively, <tt>x + y</tt>, <tt>x - y</tt>, <tt>x * y</tt>, <tt>x / y</tt>, <tt>-x</tt>, and <tt>x.inv()</tt>.</t>
        <t>Conversion of a field element to an <tt>int</tt> is denoted by <tt>x.int()</tt>. Likewise,
each concrete <tt>Field</tt> implements a constructor for converting an integer into a
field element:</t>
        <ul spacing="normal">
          <li>
            <t><tt>Field(integer: int)</tt> returns <tt>integer</tt> represented as a field element. The
value of <tt>integer</tt> <bcp14>MUST</bcp14> be in the range <tt>(-Field.MODULUS, Field.MODULUS)</tt>;
negative values are treated as negations.</t>
          </li>
        </ul>
        <section anchor="auxiliary-functions">
          <name>Auxiliary Functions</name>
          <t>The following class methods on <tt>Field</tt> are used to encode and decode vectors of
field elements as byte strings:</t>
          <sourcecode type="python"><![CDATA[
<CODE BEGINS>
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
<CODE ENDS>
]]></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[
<CODE BEGINS>
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))
<CODE ENDS>
]]></sourcecode>
        </section>
        <section anchor="field-ntt-friendly">
          <name>NTT-Friendly Fields</name>
          <t>Some VDAFs, including Prio3, require fields that are suitable for efficient
computation of the number theoretic transform (NTT) <xref target="Pol71"/>, as this allows
for fast conversion between polynomial representations. Refer to <xref target="SML24"/>
for an overview regarding NTT.
Specifically, a field is said to be "NTT-friendly" if, in addition to the
interface described in <xref target="field"/>, it provides the following interface:</t>
          <ul spacing="normal">
            <li>
              <t><tt>Field.gen() -&gt; Self</tt> is a class method that returns the generator of a large
subgroup of the multiplicative group. To be NTT-friendly, the order of this
subgroup <bcp14>MUST</bcp14> be a power of two.</t>
            </li>
            <li>
              <t><tt>GEN_ORDER: int</tt> is the order of the multiplicative subgroup generated by
<tt>Field.gen()</tt>. This is the smallest positive integer for which
<tt>Field.gen() ** Field.GEN_ORDER == Field(1)</tt>.</t>
            </li>
            <li>
              <t><tt>Field.nth_root(n: int) -&gt; F</tt> returns the principal <tt>n</tt>-th root of
unity that is uniquely determined as <tt>Wn = Field.gen() ** (GEN_ORDER // n)</tt>
to ensure interoperability.
Note that <tt>n</tt> must be a power of two such that <tt>1 &lt;= n &lt;= GEN_ORDER</tt>.</t>
            </li>
            <li>
              <t><tt>Field.nth_root_powers(n: int) -&gt; list[F]</tt> returns a list <tt>v</tt> with
the first <tt>n</tt> powers of the principal <tt>n</tt>-th root of unity.
It sets <tt>v[i] = Wn ** i</tt>, such that <tt>Wn = Field.nth_root(n)</tt>.</t>
            </li>
            <li>
              <t><tt>Field.ntt(p: list[F], n: int, set_s: bool = False) -&gt; list[F]</tt> returns
a list <tt>v</tt> with the evaluations of a polynomial <tt>p</tt>
(given its coefficients) at <tt>n</tt> points.
When <tt>set_s=False</tt>, it sets <tt>v[i] = p(Wn ** i)</tt> (this is the Lagrange
representation of the polynomial, see <xref target="poly-repr"/>);
otherwise, it sets <tt>v[i] = p(s * (Wn ** i))</tt>,
such that <tt>Wn = Field.nth_root(n)</tt>, and <tt>s = Field.nth_root(2 * n)</tt>.</t>
            </li>
            <li>
              <t><tt>Field.inv_ntt(v: list[F], n: int) -&gt; list[F]</tt> returns the coefficients of
a polynomial <tt>p</tt> such that <tt>v</tt> are the evaluations of <tt>p</tt> at the first <tt>n</tt>
powers of the principal <tt>n</tt>-th root of unity. (This is the monomial
representation of the polynomial, see <xref target="poly-repr"/>.)</t>
            </li>
          </ul>
          <t>The size of the subgroup dictates how large the polynomials can be. It
is <bcp14>RECOMMENDED</bcp14> that a generator is chosen with order at least <tt>2**20</tt>.</t>
        </section>
        <section anchor="poly-repr">
          <name>Polynomial Representation</name>
          <t>Two standard representations of polynomials are described.
While it is possible to convert between representations
(using the NTT algorithm), polynomials are maintained in the most
efficient representation according to the target operation.</t>
          <section anchor="monomial-basis">
            <name>Monomial Basis</name>
            <t>The monomial basis is the standard way of representing a polynomial,
where each element of the list corresponds to one of their coefficients
stored in ascending degree order,
that is, starting with the coefficient of the constant term.</t>
            <t>The following function denotes polynomial evaluation in the
coefficient representation.</t>
            <ul spacing="normal">
              <li>
                <t><tt>poly_eval(field: type[F], p: list[F], x: F) -&gt; F</tt> returns the
evaluation of the polynomial <tt>p</tt> (in the monomial basis) at <tt>x</tt>.
The <tt>field</tt> parameter is the class object for <tt>F</tt> and is used by
the implementation to construct field elements. (See <xref target="field"/>.)</t>
              </li>
            </ul>
          </section>
          <section anchor="lagrange-basis">
            <name>Lagrange Basis</name>
            <t>In the Lagrange basis, polynomials are represented as a list of
evaluations over a set of points.
This set is fixed to the first <tt>n</tt> powers of the
principal <tt>n</tt>-th root of unity.
So any polynomial <tt>p</tt> of degree less than <tt>n</tt> is represented as a
list <tt>v</tt> of <tt>n</tt> values such that <tt>v[i] = p(Wn ** i)</tt>,
where <tt>Wn = Field.nth_root(n)</tt>.</t>
            <t>The <tt>Lagrange</tt> class defines operations over polynomials in the
Lagrange basis. It implements the following methods:</t>
            <ul spacing="normal">
              <li>
                <t><tt>poly_mul(self, p: list[F], q: list[F]) -&gt; list[F]</tt> multiplies two
polynomials, where the input and output polynomials are in the Lagrange basis.
The inputs must have lengths that are equal and a power of two.</t>
              </li>
              <li>
                <t><tt>poly_eval(self, p: list[F], x: F) -&gt; F</tt> evaluates a polynomial
<tt>p</tt> (in the Lagrange basis) at <tt>x</tt> in linear time.
It avoids conversion to the monomial basis as shown below.</t>
              </li>
              <li>
                <t><tt>poly_eval_batched(self, polys: list[list[F]], x: F) -&gt; list[F]</tt> evaluates
every polynomial in the input list at <tt>x</tt>.
This function runs faster than invoking <tt>poly_eval</tt> multiple times
because some intermediate calculations are shared.</t>
              </li>
              <li>
                <t><tt>extend_values_to_power_of_2(self, p: list[F], n: int)</tt> appends evaluations
to the polynomial <tt>p</tt> (in-place) until the number of evaluations is <tt>n</tt>.
The output length <tt>n</tt> must be a power of two.</t>
              </li>
              <li>
                <t><tt>double_evaluations(self, p: list[F]) -&gt; list[F]</tt> returns a list of
<tt>2*n</tt> evaluations of a polynomial <tt>p</tt> given <tt>n=len(p)</tt> evaluations.
The length of the input must be a power of two.</t>
              </li>
            </ul>
            <t>An instance of the <tt>Lagrange</tt> class is initialized with an NTT-friendly field.
For algorithm derivations, refer to <xref target="Faz25"/>.
In the following, <tt>prod</tt> computes the product of its inputs.</t>
            <sourcecode type="python"><![CDATA[
<CODE BEGINS>
class Lagrange[F: NttField]():
    def __init__(self, field: type[F]) -> None:
        self.field = field

    def poly_mul(self, p: list[F], q: list[F]) -> list[F]:
        """Multiply two polynomials in the Lagrange basis."""
        n = len(p)
        assert_power_of_2(n)
        assert len(p) == len(q)
        p_2n = self.double_evaluations(p)
        q_2n = self.double_evaluations(q)
        return [pi*qi for pi, qi in zip(p_2n, q_2n)]

    def poly_eval(self, p: list[F], x: F) -> F:
        """Evaluate a polynomial p in the Lagrange basis at x."""
        return self.poly_eval_batched([p], x).pop()

    def poly_eval_batched(
            self,
            polys: list[list[F]],
            x: F) -> list[F]:
        """Evaluate each polynomial in the Lagrange basis at x."""
        assert len({len(p) for p in polys}) == 1
        n = len(polys[0])
        assert_power_of_2(n)

        nodes = self.field.nth_root_powers(n)
        k = self.field(1)
        u = [p[0] for p in polys]
        d = nodes[0] - x
        for i in range(1, n):
            k *= d
            d = nodes[i] - x
            t = k * nodes[i]
            for j, p in enumerate(polys):
                u[j] *= d
                if i < len(p):
                    u[j] += t * p[i]

        factor = self.field(-1)**(n-1) * self.field(n).inv()
        for i in range(len(u)):
            u[i] *= factor
        return u

    def extend_values_to_power_of_2(
            self,
            p: list[F],
            n: int) -> None:
        """
        Appends evaluations to the polynomial p (in-place) until the
        number of evaluations is n, and n must be a power of two.
        """
        assert_power_of_2(n)
        assert len(p) <= n
        x = self.field.nth_root_powers(n)

        w = [self.field(0)]*n
        for i in range(len(p)):
            diff = (x[i] - x[j] for j in range(len(p)) if i != j)
            w[i] = prod(diff, start=self.field(1))

        for k in range(len(p), n):
            for i in range(k):
                w[i] *= x[i] - x[k]

            y_num, y_den = self.field(0), self.field(1)
            for i, v in enumerate(p):
                y_num = y_num * w[i] + y_den * v
                y_den *= w[i]

            diff = (x[k] - x[j] for j in range(k))
            w[k] = prod(diff, start=self.field(1))
            p.append(-w[k] * y_num * y_den.inv())

    def double_evaluations(self, p: list[F]) -> list[F]:
        """
        Returns 2n evaluations of a polynomial from n Lagrange-basis
        evaluations, such that n=len(p) is a power of two.
        """
        n = len(p)
        assert_power_of_2(n)
        even = p
        odd = self.field.ntt(self.field.inv_ntt(even, n), n, True)
        return [i for pair in zip(even, odd) for i in pair]
<CODE ENDS>
]]></sourcecode>
          </section>
        </section>
        <section anchor="parameters">
          <name>Parameters</name>
          <t><xref target="fields"/> defines finite fields used in the remainder of this document.</t>
          <table anchor="fields">
            <name>Parameters for the finite fields used in this document.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Field64</th>
                <th align="left">Field128</th>
                <th align="left">Field255</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">MODULUS</td>
                <td align="left">2**32 * 4294967295 + 1</td>
                <td align="left">2**66 * 4611686018427387897 + 1</td>
                <td align="left">2**255 - 19</td>
              </tr>
              <tr>
                <td align="left">ENCODED_SIZE</td>
                <td align="left">8</td>
                <td align="left">16</td>
                <td align="left">32</td>
              </tr>
              <tr>
                <td align="left">Generator</td>
                <td align="left">7**4294967295</td>
                <td align="left">7**4611686018427387897</td>
                <td align="left">n/a</td>
              </tr>
              <tr>
                <td align="left">GEN_ORDER</td>
                <td align="left">2**32</td>
                <td align="left">2**66</td>
                <td align="left">n/a</td>
              </tr>
            </tbody>
          </table>
        </section>
      </section>
      <section anchor="xof">
        <name>Extendable Output Functions (XOFs)</name>
        <t>VDAFs in this specification use eXtendable Output Functions (XOFs) for two
purposes:</t>
        <ol spacing="normal" type="1"><li>
            <t>Extracting short, pseudorandom strings called "seeds" from high entropy
inputs</t>
          </li>
          <li>
            <t>Expanding seeds into long, pseudorandom outputs</t>
          </li>
        </ol>
        <t>Concrete XOFs implement a class <tt>Xof</tt> providing the following interface:</t>
        <ul spacing="normal">
          <li>
            <t><tt>SEED_SIZE: int</tt> is the size (in bytes) of a seed.</t>
          </li>
          <li>
            <t><tt>Xof(seed: bytes, dst: bytes, binder: bytes)</tt> constructs an instance of the
XOF from the given seed and a domain separation tag and binder string as
defined in <xref target="dst-binder"/>. The length of the seed will typically be
<tt>SEED_SIZE</tt>, but some XOFs may support multiple seed sizes. The seed <bcp14>MUST</bcp14> be
generated securely, i.e., it is either the output of a CSPRNG or a
previous invocation of the XOF.</t>
          </li>
          <li>
            <t><tt>xof.next(length: int)</tt> returns the next chunk of the output of the
initialized XOF as a byte string. The length of the chunk <bcp14>MUST</bcp14> be <tt>length</tt>.</t>
          </li>
        </ul>
        <t>The following methods are provided for all concrete XOFs. The first is a class
method used to derive a fresh seed from an existing one. The second is an
instance method used to compute a sequence of field elements. The third is a
class method that provides a one-shot interface for expanding a seed into a
field vector.</t>
        <sourcecode type="python"><![CDATA[
<CODE BEGINS>
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)
<CODE ENDS>
]]></sourcecode>
        <section anchor="xof-turboshake128">
          <name>XofTurboShake128</name>
          <t>This section describes XofTurboShake128, an XOF based on the TurboSHAKE128
function specified in <xref target="RFC9861"/>. This XOF is <bcp14>RECOMMENDED</bcp14> for all use cases
for DAFs and VDAFs.</t>
          <t>Pre-conditions:</t>
          <ul spacing="normal">
            <li>
              <t>The default seed length is <tt>32</tt>. The seed <bcp14>MAY</bcp14> have a different length, but it
<bcp14>MUST NOT</bcp14> 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[
<CODE BEGINS>
class XofTurboShake128(Xof):
    """XOF wrapper for TurboSHAKE128."""

    # Associated parameters
    SEED_SIZE = 32

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

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

        # Function `TurboSHAKE128(M, D, L)` is as defined in
        # Section 2.1 of [RFC9861].
        #
        # Implementation note: rather than re-generate the output
        # stream each time `next()` is invoked, most implementations
        # of TurboSHAKE128 will expose an "absorb-then-squeeze" API
        # that allows stateful handling of the stream.
        stream = TurboSHAKE128(self.m, 1, self.l)
        return stream[-length:]
<CODE ENDS>
]]></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[
<CODE BEGINS>
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)
<CODE ENDS>
]]></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[
<CODE BEGINS>
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),
    ])
<CODE ENDS>
]]></sourcecode>
          <t>It is also sometimes necessary to bind the output to some ephemeral value that
multiple parties need to agree on. This input is called the "binder string".</t>
        </section>
      </section>
    </section>
    <section anchor="prio3">
      <name>Prio3</name>
      <t>This section describes Prio3, a VDAF for general-purpose aggregation. Prio3 is
suitable for a wide variety of aggregation functions, including (but not
limited to) sum, mean, standard deviation, histograms, and linear regression.
It is compatible with any aggregation function that has the following
structure:</t>
      <ul spacing="normal">
        <li>
          <t>Each measurement is encoded as a vector over some finite field.</t>
        </li>
        <li>
          <t>Measurement validity is determined by an "arithmetic circuit" evaluated over
the encoded measurement. An arithmetic circuit is a function comprised of
arithmetic operations in the field. (These are specified in full detail in
<xref target="flp-bbcggi19-valid"/>.)</t>
        </li>
        <li>
          <t>The aggregate result is obtained by summing up the encoded measurements and
computing some function of the sum.</t>
        </li>
      </ul>
      <t>Clients protect the privacy of their measurements by secret sharing them and
distributing the shares among the Aggregators. To ensure each measurement is
valid, the Aggregators run a multi-party computation on their shares, the
result of which is the output of the arithmetic circuit. This involves
verification of a "Fully Linear Proof (FLP)" (<xref target="flp"/>) generated by the Client.
FLPs are the core component of Prio3, as they specify the types of
measurements and how they are encoded, verified, and aggregated. In fact Prio3
can be thought of as a transformation of an FLP into a VDAF.</t>
      <t>Prio3 does not have an aggregation parameter. Instead, each output share is
derived from each input share by applying a fixed map. See <xref target="poplar1"/> for an
example of a VDAF that makes meaningful use of the aggregation parameter.</t>
      <t>The remainder of this section is structured as follows. The interface of FLPs is
described in <xref target="flp"/>. The generic transformation of an FLP into Prio3 is
specified in <xref target="prio3-construction"/>. Next, a concrete FLP suitable for any
validity circuit is specified in <xref target="flp-bbcggi19"/>. Finally, variants of Prio3
for various types of aggregation tasks are specified in
<xref target="prio3-instantiations"/>. Test vectors for each variant can be found in
<xref target="test-vectors"/>.</t>
      <section anchor="flp">
        <name>Fully Linear Proofs (FLPs)</name>
        <t>Conceptually, an FLP is a two-party protocol executed by a prover and a
verifier. The verifier is restricted to only access the messages it receives
from the prover via linear queries. In actual use in Prio3, however, the
prover's computation is carried out by the Client, and the verifier's
computation is distributed among the Aggregators. The Client generates a
"proof" of its measurement's validity and distributes shares of the proof to
the Aggregators. During verification, each Aggregator performs some computation
on its measurement share and proof share locally, then broadcasts the result in
its verifier share. The validity decision is then made by the
<tt>verifier_shares_to_message()</tt> algorithm (<xref target="sec-vdaf-verify"/>).</t>
        <t>As usual, the interface implemented by a concrete FLP is described in terms of
an object <tt>flp</tt> of type <tt>Flp</tt> that specifies the set of methods and parameters
a concrete FLP must provide.</t>
        <t>The parameters provided by a concrete FLP are listed in <xref target="flp-param"/>. A
concrete FLP specifies the following algorithms for generating and verifying
proofs of validity (encoding is described below in <xref target="flp-encode"/>):</t>
        <ul spacing="normal">
          <li>
            <t><tt>flp.prove(meas: list[F], prove_rand: list[F], joint_rand: list[F]) -&gt;
list[F]</tt> is the proof-generation algorithm run by the prover. Its inputs are
the encoded measurement, the "prover randomness" <tt>prove_rand</tt>, and the "joint
randomness" <tt>joint_rand</tt>. The prover randomness is used only by the prover,
but the joint randomness is shared by both the prover and verifier.</t>
          </li>
          <li>
            <t><tt>flp.query(meas: list[F], proof: list[F], query_rand: list[F], joint_rand:
list[F], num_shares: int) -&gt; list[F]</tt> is the linear query algorithm run by the
verifier on the encoded measurement and proof. The result of the query (i.e.,
the output of this function) is called the "verifier message". In addition to
the measurement and proof, this algorithm takes as input the query randomness
<tt>query_rand</tt> and the joint randomness <tt>joint_rand</tt>. The former is used only
by the verifier. <tt>num_shares</tt> specifies the number of shares (more on this
below).</t>
          </li>
          <li>
            <t><tt>flp.decide(verifier: list[F]) -&gt; bool</tt> is the deterministic decision
algorithm run by the verifier. It takes as input the verifier message and
outputs a boolean indicating if the measurement from which it was generated
is valid.</t>
          </li>
        </ul>
        <t>This application requires that the FLP is "fully linear" in the sense defined in
<xref target="BBCGGI19"/>. As a practical matter, what this property implies is that, when
run on a share of the measurement and proof, the query algorithm outputs a
share of the verifier message (hereafter the "verifier share"). Furthermore,
the privacy property of the FLP system ensures that the verifier message
reveals nothing about the measurement other than the fact that it is valid.
Therefore, to decide if a measurement is valid, the Aggregators will run the
query algorithm locally, exchange verifier shares, combine them to recover the
verifier message, and run the decision algorithm.</t>
        <t>The query algorithm includes a parameter <tt>num_shares</tt> that specifies the number
of shares of the measurement and proof that were generated. If these data are
not secret shared, then <tt>num_shares == 1</tt>. This parameter is useful for
normalizing constants in arithmetic circuits so that each Aggregator properly
computes a secret share of the circuit's output. See <xref target="flp-bbcggi19"/> for
details.</t>
        <t>An FLP is executed by the prover and verifier as follows:</t>
        <sourcecode type="python"><![CDATA[
<CODE BEGINS>
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)
<CODE ENDS>
]]></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 randomly using a uniform distribution,
the output is <tt>False</tt> with high probability. False positives are
possible: there is a small probability that a verifier accepts an invalid input
as valid. An FLP is said to be "sound" if this probability is sufficiently
small. The soundness of the FLP depends on a variety of parameters, like the
length of the input and the size of the field. See <xref target="flp-bbcggi19"/> for
details.</t>
        <t>Note that soundness of an FLP system is not the same as verifiability for the
VDAF that uses it. In particular, soundness of the FLP is necessary, but
insufficient for verifiability of Prio3 (<xref target="prio3"/>). See
<xref target="security-multiproof"/> for details.</t>
        <t>In addition, note that <xref target="BBCGGI19"/> defines a larger class of fully linear
proof systems than is considered here. In particular, what is called an "FLP"
here is called a 1.5-round, public-coin, interactive oracle proof system in
their paper.</t>
        <table anchor="flp-param">
          <name>FLP parameters.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>PROVE_RAND_LEN: int</tt></td>
              <td align="left">Length of the prover randomness, the number of random field elements consumed by the prover when generating a proof.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>QUERY_RAND_LEN: int</tt></td>
              <td align="left">Length of the query randomness, the number of random field elements consumed by the verifier.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>JOINT_RAND_LEN: int</tt></td>
              <td align="left">Length of the joint randomness, the number of random field elements shared by the prover and verifier.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>MEAS_LEN: int</tt></td>
              <td align="left">Length of the encoded measurement (<xref target="flp-encode"/>).</td>
            </tr>
            <tr>
              <td align="left">
                <tt>OUTPUT_LEN: int</tt></td>
              <td align="left">Length of the aggregatable output (<xref target="flp-encode"/>).</td>
            </tr>
            <tr>
              <td align="left">
                <tt>PROOF_LEN: int</tt></td>
              <td align="left">Length of the proof.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VERIFIER_LEN: int</tt></td>
              <td align="left">Length of the verifier message generated by querying the measurement and proof.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">Type of the measurement.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">Type of the aggregate result.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>field: type[F]</tt></td>
              <td align="left">Class object for the field (<xref target="field"/>).</td>
            </tr>
          </tbody>
        </table>
        <section anchor="flp-encode">
          <name>Encoding the Input</name>
          <t>The type of measurement being aggregated is defined by the FLP. Hence, the FLP
also specifies a method of encoding raw measurements as a vector of field
elements:</t>
          <ul spacing="normal">
            <li>
              <t><tt>flp.encode(measurement: Measurement) -&gt; list[F]</tt> encodes a raw measurement
as a vector of field elements.  </t>
              <t>
Post-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The encoded measurement <bcp14>MUST</bcp14> have length <tt>flp.MEAS_LEN</tt>.</t>
                </li>
              </ul>
            </li>
          </ul>
          <t>For some FLPs, the encoded measurement also includes redundant field elements
that are useful for checking the proof, but which are not needed after the
proof has been checked. An example is the <tt>Sum</tt> type defined in <xref target="prio3sum"/>
for which each measurement is an integer in the range <tt>[0, max_measurement]</tt>.
The range check requires encoding the measurement with several field elements,
though just one is needed for aggregation. Thus the FLP defines an algorithm
for truncating the encoded measurement to the length of the aggregatable output:</t>
          <ul spacing="normal">
            <li>
              <t><tt>flp.truncate(meas: list[F]) -&gt; list[F]</tt> maps an encoded measurement (e.g.,
the bit-encoding of the measurement) to an aggregatable output (e.g., the
singleton vector containing the measurement).  </t>
              <t>
Pre-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The length of the input <bcp14>MUST</bcp14> be <tt>flp.MEAS_LEN</tt></t>
                </li>
              </ul>
              <t>
Post-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The length of the output <bcp14>MUST</bcp14> be <tt>flp.OUTPUT_LEN</tt>.</t>
                </li>
              </ul>
            </li>
          </ul>
          <t>Once the aggregate shares have been transmitted to the Collector, their sum can
be converted into the aggregate result. This could be a projection from the
FLP's field to the integers, or it could include additional post-processing.
Either way, this functionality is implemented by the following method:</t>
          <ul spacing="normal">
            <li>
              <t><tt>flp.decode(output: list[F], num_measurements: int) -&gt; AggResult</tt> maps a sum
of aggregate shares to an aggregate result.  </t>
              <t>
Pre-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The length of the output <bcp14>MUST</bcp14> be <tt>OUTPUT_LEN</tt>.</t>
                </li>
                <li>
                  <t><tt>num_measurements</tt> <bcp14>MUST</bcp14> equal the number of measurements that were
aggregated.</t>
                </li>
              </ul>
            </li>
          </ul>
          <t>Taken together, these three functionalities correspond to the notion of
"Affine-aggregatable encodings (AFEs)" from <xref target="CGB17"/>.</t>
        </section>
        <section anchor="multiproofs">
          <name>Multiple Proofs</name>
          <t>It is sometimes desirable to generate and verify multiple independent proofs
for the same input. First, this improves the soundness of the proof system
without having to change any of its parameters. Second, it allows a smaller
field to be used (e.g., replace Field128 with Field64)
without sacrificing soundness. This is useful because it reduces the overall
communication of the protocol. (This is a trade-off, of course, since
generating and verifying more proofs requires more time.) Given these benefits,
this feature is implemented by Prio3 (<xref target="prio3"/>).</t>
          <t>To generate these proofs for a specific measurement, the prover calls
<tt>flp.prove()</tt> multiple times, each time using fresh prover and joint
randomness. The verifier checks each proof independently, each time with fresh
query randomness. It accepts the measurement only if the decision algorithm
accepts on each proof.</t>
          <t>See <xref target="security-multiproof"/> for guidance on choosing the field size and number
of proofs.</t>
        </section>
      </section>
      <section anchor="prio3-construction">
        <name>Specification</name>
        <t>This section specifies <tt>Prio3</tt>, an implementation of the <tt>Vdaf</tt> interface
defined in <xref target="vdaf"/>. The parameters and types required by the <tt>Vdaf</tt> interface
are defined in <xref target="prio3-param"/>. The methods required for sharding,
verification, aggregation, and unsharding are described in the remaining
subsections. These methods refer to constants enumerated in <xref target="prio3-const"/>.</t>
        <table anchor="prio3-param">
          <name>Parameters for Prio3.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>flp</tt></td>
              <td align="left">An instance of <tt>Flp</tt> (<xref target="flp"/>).</td>
            </tr>
            <tr>
              <td align="left">
                <tt>xof</tt></td>
              <td align="left">
                <tt>XofTurboShake128</tt> (<xref target="xof-turboshake128"/>)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>PROOFS</tt></td>
              <td align="left">Any <tt>int</tt> in the range <tt>[1, 256)</tt>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VERIFY_KEY_SIZE</tt></td>
              <td align="left">
                <tt>xof.SEED_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>RAND_SIZE</tt></td>
              <td align="left">
                <tt>xof.SEED_SIZE * SHARES if flp.JOINT_RAND_LEN == 0 else 2 * xof.SEED_SIZE * SHARES</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>NONCE_SIZE</tt></td>
              <td align="left">
                <tt>16</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>ROUNDS</tt></td>
              <td align="left">
                <tt>1</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>SHARES</tt></td>
              <td align="left">Any <tt>int</tt> in the range <tt>[2, 256)</tt>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">As defined by <tt>flp</tt>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggParam</tt></td>
              <td align="left">
                <tt>None</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PublicShare</tt></td>
              <td align="left">
                <tt>Optional[list[bytes]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>InputShare</tt></td>
              <td align="left">
                <tt>tuple[list[F], list[F], Optional[bytes]] | tuple[bytes, Optional[bytes]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>OutShare</tt></td>
              <td align="left">
                <tt>list[F]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggShare</tt></td>
              <td align="left">
                <tt>list[F]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">As defined by <tt>flp</tt>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VerifyState</tt></td>
              <td align="left">
                <tt>tuple[list[F], Optional[bytes]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>VerifierShare</tt></td>
              <td align="left">
                <tt>tuple[list[F], Optional[bytes]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>VerifierMessage</tt></td>
              <td align="left">
                <tt>Optional[bytes]</tt></td>
            </tr>
          </tbody>
        </table>
        <table anchor="prio3-const">
          <name>Constants used by Prio3.</name>
          <thead>
            <tr>
              <th align="left">Variable</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>USAGE_MEAS_SHARE: int</tt></td>
              <td align="left">1</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_PROOF_SHARE: int</tt></td>
              <td align="left">2</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_JOINT_RANDOMNESS: int</tt></td>
              <td align="left">3</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_PROVE_RANDOMNESS: int</tt></td>
              <td align="left">4</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_QUERY_RANDOMNESS: int</tt></td>
              <td align="left">5</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_JOINT_RAND_SEED: int</tt></td>
              <td align="left">6</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_JOINT_RAND_PART: int</tt></td>
              <td align="left">7</td>
            </tr>
          </tbody>
        </table>
        <section anchor="sharding">
          <name>Sharding</name>
          <t>Recall from <xref target="flp"/> that the FLP syntax calls for "joint randomness" shared by
the prover (i.e., the Client) and the verifier (i.e., the Aggregators). VDAFs
have no such notion. Instead, the Client derives the joint randomness from its
measurement in a way that allows the Aggregators to reconstruct it from their
shares. (This idea is based on the Fiat-Shamir heuristic and is described in
Section 6.2.3 of <xref target="BBCGGI19"/>.)</t>
          <t>The sharding algorithm involves the following steps:</t>
          <ol spacing="normal" type="1"><li>
              <t>Encode the Client's measurement as specified by the FLP</t>
            </li>
            <li>
              <t>Shard the measurement into a sequence of measurement shares</t>
            </li>
            <li>
              <t>Derive the joint randomness from the measurement shares and nonce</t>
            </li>
            <li>
              <t>Generate the proof using the derived joint randomness</t>
            </li>
            <li>
              <t>Shard the proof into a sequence of proof shares</t>
            </li>
          </ol>
          <t>As described in <xref target="multiproofs"/>, the probability of an invalid measurement
being deemed valid can be decreased by generating and verifying multiple
proofs. To support this:</t>
          <ul spacing="normal">
            <li>
              <t>In step 3, derive as much joint randomness as required by <tt>PROOFS</tt> proofs</t>
            </li>
            <li>
              <t>Repeat step 4 <tt>PROOFS</tt> times, each time with a unique joint randomness</t>
            </li>
          </ul>
          <t>Depending on the FLP, joint randomness may not be required. In particular, when
<tt>flp.JOINT_RAND_LEN == 0</tt>, the Client does not derive the joint randomness
(Step 3).</t>
          <t>The sharding algorithm is specified below:</t>
          <sourcecode type="python"><![CDATA[
<CODE BEGINS>
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)
<CODE ENDS>
]]></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[
<CODE BEGINS>
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)
<CODE ENDS>
]]></sourcecode>
          </section>
          <section anchor="flps-with-joint-randomness">
            <name>FLPs With Joint Randomness</name>
            <t>The following method is used for FLPs that require joint randomness, i.e., for
which <tt>flp.JOINT_RAND_LEN &gt; 0</tt>. Joint randomness derivation involves an
additional XOF seed for each Aggregator called the "blind". The computation
involves the following steps:</t>
            <ol spacing="normal" type="1"><li>
                <t>Compute a "joint randomness part" from each measurement share and blind</t>
              </li>
              <li>
                <t>Compute a "joint randomness seed" from the joint randomness parts</t>
              </li>
              <li>
                <t>Compute the joint randomness for each proof evaluation from the joint
randomness seed</t>
              </li>
            </ol>
            <t>This three-step process is designed to ensure that the joint randomness does
not leak the measurement to the Aggregators while preventing a malicious Client
from tampering with the joint randomness in a way that causes the Aggregators
to accept an invalid measurement. To save a round of communication between the
Aggregators later, the Client encodes the joint randomness parts in the public
share. (See <xref target="prio3-verification"/> for details.)</t>
            <t>All functions used in the following listing are defined in <xref target="prio3-auxiliary"/>:</t>
            <sourcecode type="python"><![CDATA[
<CODE BEGINS>
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)
<CODE ENDS>
]]></sourcecode>
          </section>
        </section>
        <section anchor="prio3-verification">
          <name>Verification</name>
          <t>This section describes the process of recovering output shares from the input
shares. The high-level idea is that each Aggregator first queries its
measurement share and proof(s) share(s) locally, then broadcasts its verifier
share(s). The shares of verifier(s) are then combined into the verifier
message(s) used to decide whether to accept.</t>
          <t>In addition, the Aggregators must recompute the same joint randomness used by
the Client to generate the proof(s). In order to avoid an extra round of
communication, the Client includes the joint randomness parts in the public
share. This leaves open the possibility that the Client cheated by, say,
forcing the Aggregators to use joint randomness that biases the proof check
procedure some way in its favor. To mitigate this, the Aggregators also check
that they have all computed the same joint randomness seed before accepting
their output shares. To do so, they exchange their parts of the joint
randomness along with their shares of verifier(s).</t>
          <t>Implementation note: the verification state for Prio3 includes the output share
that will be released once verification is complete. In some situations, it may
be necessary for the Aggregator to encode this state as bytes and store it for
retrieval later on. For all but the first Aggregator, it is possible to save
storage by storing the measurement share rather than output share itself. It is
relatively inexpensive to expand this seed into the measurement share, then
truncate the measurement share to get the output share.</t>
          <t>All functions used in the following listing are defined in <xref target="prio3-auxiliary"/>:</t>
          <sourcecode type="python"><![CDATA[
<CODE BEGINS>
def verify_init(
        self,
        verify_key: bytes,
        ctx: bytes,
        agg_id: int,
        _agg_param: None,
        nonce: bytes,
        public_share: Optional[list[bytes]],
        input_share: Prio3InputShare[F]) -> tuple[
            Prio3VerifyState[F],
            Prio3VerifierShare[F]]:
    joint_rand_parts = public_share
    (meas_share, proofs_share, blind) = \
        self.expand_input_share(ctx, agg_id, input_share)
    out_share = self.flp.truncate(meas_share)

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

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

    verify_state = (out_share, corrected_joint_rand_seed)
    verifier_share = (verifiers_share, joint_rand_part)
    return (verify_state, verifier_share)

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

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

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

def verify_next(
    self,
    _ctx: bytes,
    verify_state: Prio3VerifyState[F],
    verifier_message: Optional[bytes]
) -> tuple[Prio3VerifyState[F], Prio3VerifierShare[F]] | list[F]:
    joint_rand_seed = verifier_message
    (out_share, corrected_joint_rand_seed) = verify_state

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

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

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

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

def verifier_len(self) -> int:
    """Length of the verifier message."""
    length = 1
    for g in self.GADGETS:
        length += g.ARITY + 1
    return length

def wire_poly_len(gadget_calls: int) -> int:
    """
    Calculates the number of coordinates in each wire polynomial for
    a gadget.
    """
    return next_power_of_2(1 + gadget_calls)

def gadget_poly_len(gadget_degree: int,
                    wire_polynomial_len: int) -> int:
    """
    Calculates the number of coordinates in a gadget polynomial.
    """
    return gadget_degree * (wire_polynomial_len - 1) + 1
<CODE ENDS>
]]></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[
<CODE BEGINS>
def prove(self,
          meas: list[F],
          prove_rand: list[F],
          joint_rand: list[F]) -> list[F]:
    # Evaluate the validity circuit, recording the value of each
    # input wire for each evaluation of each gadget.
    valid = ProveGadget.wrap(self.valid, prove_rand)
    valid.eval(meas, joint_rand, 1)

    # Construct the proof, which consists of the wire seeds and
    # gadget polynomial for each gadget.
    proof = []
    for g, g_calls in zip(valid.GADGETS, valid.GADGET_CALLS):
        g = cast(ProveGadget[F], g)

        # Define the wire polynomial length `p` as the smallest power
        # of two accommodating all gadget calls plus one constant
        # term for the seed.
        p = wire_poly_len(g_calls)

        # The validity circuit evaluation defines one polynomial for
        # each input wire of each gadget.
        # For each wire `j`, the vector `g.wires[j]` of length `p`
        # is built as follows:
        # - `g.wires[j][0]` is set to the seed for wire `j` (from
        #   the prover's randomness).
        # - The subsequent entries are the assigned values from each
        #   gadget call.
        # - Pad the vector with zeros to reach length `p`.
        # The wire polynomial is then defined by its evaluations:
        #   `wire_poly(alpha**k) = g.wires[j][k]`
        # for all `k`, where `alpha` is a `p`-th root of unity.
        wire_polys = [g.wires[j] for j in range(g.ARITY)]
        wire_seeds = [g.wires[j][0] for j in range(g.ARITY)]
        proof += wire_seeds

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

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

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

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

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

        # To test the gadget, we re-compute the wire polynomials and
        # check for consistency with the gadget polynomial provided
        # by the prover. Here, we evaluate secret shares of the
        # gadget polynomial and secret shares of each of the wire
        # polynomials at the random point `t`. These secret shares
        # will be combined into polynomial evaluations at `t` when
        # verifier shares are combined into a verifier message.
        # Then, the `decide()` procedure will perform nonlinear
        # computations and the final consistency checks.
        wire_checks = lag.poly_eval_batched(g.wires[:g.ARITY], t)
        gadget_check = lag.poly_eval(g.poly, t)

        verifier += wire_checks
        verifier.append(gadget_check)

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

    # Complete each gadget test. Check if the evaluations of gadget
    # polynomials are consistent with evaluations of wire polynomials
    # by evaluating the gadgets on the evaluations of the wire
    # polynomials.
    for g in self.valid.GADGETS:
        (wire_checks, verifier) = front(g.ARITY, verifier)
        ([gadget_check], verifier) = front(1, verifier)
        if g.eval(self.field, wire_checks) != gadget_check:
            return False

    return True
<CODE ENDS>
]]></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[
<CODE BEGINS>
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()
<CODE ENDS>
]]></sourcecode>
        </section>
        <section anchor="prio3sum">
          <name>Prio3Sum</name>
          <table>
            <name>Parameters for Prio3Sum.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>field</tt></td>
                <td align="left">
                  <tt>Field64</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Valid</tt></td>
                <td align="left">
                  <tt>Sum(field, max_measurement)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
            </tbody>
          </table>
          <t>The next variant of Prio3 supports summing of integers in a pre-determined
range. Each measurement is an integer in the range <tt>[0, max_measurement]</tt>,
where <tt>max_measurement</tt> defines the largest valid measurement.</t>
          <t>The range check is accomplished by encoding the measurement as a vector of field
elements with value zero or one, such that a weighted sum of these values can only
be in the range <tt>[0, max_measurement]</tt>.</t>
          <t>All but the last of the weights are successive powers of two, as in
the binary bit decomposition, and the last weight is chosen such that the sum of
all weights is equal to <tt>max_measurement</tt>. With these weights, valid
measurements have either one or two possible representations as vectors of
field elements with value zero or one, and invalid measurements cannot be
represented.</t>
          <t>The validity circuit checks that each entry of the bit vector has a value of
zero or one. It uses the polynomial-evaluation gadget <tt>PolyEval</tt> specified in
<xref target="gadget-poly-eval"/>. The polynomial is <tt>p(x) = x**2 - x</tt>, which is equal to <tt>0</tt>
if and only if <tt>x</tt> is in the range <tt>[0, 2)</tt>. The complete circuit is specified
below:</t>
          <t>Note that decoding a sequence of "bits" into an integer is a linear operation,
specifically, a linear combination with the constant weights. Thus, decoding
secret shares of a bit-encoded integer will produce secret shares of the
original integer.</t>
          <sourcecode type="python"><![CDATA[
<CODE BEGINS>
class Sum(Valid[int, int, F]):
    JOINT_RAND_LEN = 0
    OUTPUT_LEN = 1
    field: type[F]

    def __init__(self, field: type[F], max_measurement: int):
        self.field = field
        bits = max_measurement.bit_length()
        self.bits = bits
        self.max_measurement = max_measurement
        self.GADGET_CALLS = [self.bits]
        self.GADGETS = [PolyEval([0, -1, 1], self.bits)]
        self.MEAS_LEN = self.bits
        self.EVAL_OUTPUT_LEN = self.bits

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

    def eval(
            self,
            meas: list[F],
            joint_rand: list[F],
            _num_shares: int) -> list[F]:
        out = []
        for b in meas:
            out.append(self.GADGETS[0].eval(self.field, [b]))

        return out

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

    def decode(self, output: list[F], _num_measurements: int) -> int:
        return output[0].int()


def encode_range_checked_int(
        field: type[F],
        value: int,
        max_measurement: int) -> list[F]:
    """
    Encode an integer into multiple field elements, representing a
    weighted sum of zeros and ones, to allow for efficient range
    proofs.

    Pre-conditions:

        - `value >= 0`
        - `max_measurement > 0`
        - `value <= max_measurement`
        - `value < field.MODULUS`
        - `max_measurement < field.MODULUS`
    """
    if value > max_measurement:
        raise ValueError("measurement is too large")

    bits = max_measurement.bit_length()
    rest_all_ones_value = 2 ** (bits - 1) - 1
    last_weight = max_measurement - rest_all_ones_value

    # Implementation note: this conditional should be replaced with
    # constant time operations in order to reduce leakage via timing
    # side channels.
    if value <= rest_all_ones_value:
        rest = value
        last_elem = field(0)
    else:
        rest = value - last_weight
        last_elem = field(1)

    encoded = []
    for l in range(bits - 1):
        encoded.append(field((rest >> l) & 1))
    encoded.append(last_elem)
    return encoded


def decode_range_checked_int(
        field: type[F],
        encoded: list[F],
        max_measurement: int) -> F:
    """
    Decode a field element from a vector of field elements produced
    by `encode_range_checked_int()`.

    This may also be applied to secret shares of an encoded integer,
    since it is a linear function.
    """
    bits = max_measurement.bit_length()
    rest_all_ones_value = 2 ** (bits - 1) - 1
    last_weight = max_measurement - rest_all_ones_value

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

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

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

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

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

                r_power *= r

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

        return [out]

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

    def decode(
            self,
            output: list[F],
            _num_measurements: int) -> list[int]:
        return [x.int() for x in output]
<CODE ENDS>
]]></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[
<CODE BEGINS>
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]
<CODE ENDS>
]]></sourcecode>
        </section>
        <section anchor="prio3multihotcountvec">
          <name>Prio3MultihotCountVec</name>
          <table>
            <name>Parameters for Prio3MultihotCountVec.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Valid</tt></td>
                <td align="left">
                  <tt>MultihotCountVec(field, length, max_weight, chunk_length)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
            </tbody>
          </table>
          <t>For this instance of Prio3, each measurement is a vector of Boolean
values, where the number of <tt>True</tt> values is bounded. This provides a
functionality similar to Prio3Histogram except that more than one entry (or none
at all) may be non-zero. This allows Prio3MultihotCountVec to be composed with a
randomized response mechanism, like <xref target="EPK14"/>, for providing differential
privacy. (For example, each Client would set each entry with some small
probability.)</t>
          <t>The validity circuit is denoted <tt>MultihotCountVec</tt> and has three parameters:
<tt>length</tt>, the number of entries in the count vector; <tt>max_weight</tt>, the maximum
number of <tt>True</tt> entries (i.e., the weight must be at most <tt>max_weight</tt>); and
<tt>chunk_length</tt>, used the same way as in <xref target="prio3sumvec"/> and <xref target="prio3histogram"/>.</t>
          <t>The Client's encoded measurement includes both the count vector and the
weight of the count vector. The weight is encoded as multiple field
elements, using the same modified bit decomposition as in the <tt>Sum</tt>
circuit's encoding procedure (<xref target="prio3sum"/>).</t>
          <t>The verifier checks that each entry of the encoded measurement is a bit (i.e.,
either one or zero), including both the count vector and the encoding of the
reported weight. It then decodes the reported weight and subtracts it from
<tt>sum(count_vec)</tt>, where <tt>count_vec</tt> is the count vector. The result is
zero if and only if the reported weight is equal to the true weight. The two
checks constitute the output of the circuit. The complete circuit is defined
below.</t>
          <sourcecode type="python"><![CDATA[
<CODE BEGINS>
class MultihotCountVec(Valid[list[bool], list[int], F]):
    EVAL_OUTPUT_LEN = 2
    field: type[F]

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

        Pre-conditions:

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

        # Compute the number of bits to represent `max_weight`.
        self.bits_for_weight = max_weight.bit_length()

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

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

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

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

        # The second part is the reported weight.
        weight_reported = sum(measurement)

        encoded = []
        encoded += count_vec
        encoded += encode_range_checked_int(
            self.field,
            weight_reported,
            self.max_weight,
        )
        return encoded

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

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

                r_power *= r

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

        # Check that the sum of the counters is equal to the value
        # claimed by the Client.
        count_vec = meas[:self.length]
        weight = sum(count_vec, self.field(0))
        weight_reported = decode_range_checked_int(
            self.field,
            meas[self.length:],
            self.max_weight,
        )
        weight_check = weight - weight_reported

        return [range_check, weight_check]

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

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

    l = self.xof.SEED_SIZE

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

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

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

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

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

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

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

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

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

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

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

def verify_next(
    self,
    _ctx: bytes,
    verify_state: Poplar1VerifyState,
    verifier_message: Optional[FieldVec]
) -> tuple[Poplar1VerifyState, FieldVec] | FieldVec:
    prev_sketch = cast(list[Field], verifier_message)
    (step, level, verify_mem) = verify_state

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

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

    raise ValueError('invalid verification state')

def verifier_shares_to_message(
        self,
        _ctx: bytes,
        agg_param: Poplar1AggParam,
        verifier_shares: list[FieldVec]) -> Optional[FieldVec]:
    if len(verifier_shares) != 2:
        raise ValueError('incorrect number of verifier shares')
    (level, _) = agg_param
    field = self.idpf.current_field(level)
    sketch = vec_add(
        cast(list[Field], verifier_shares[0]),
        cast(list[Field], verifier_shares[1]),
    )
    if len(sketch) == 3:
        return cast(FieldVec, sketch)
    elif len(sketch) == 1:
        if sketch == field.zeros(1):
            # In order to reduce communication overhead, let `None`
            # denote a successful sketch verification.
            return None
        else:
            raise ValueError('sketch verification failed')
    else:
        raise ValueError('incorrect sketch length')
<CODE ENDS>
]]></sourcecode>
        </section>
        <section anchor="validity-of-aggregation-parameters-1">
          <name>Validity of Aggregation Parameters</name>
          <t>Aggregation parameters are valid for a given input share if no aggregation
parameter with the same level has been used with the same input share before.
The verification phase <bcp14>MUST NOT</bcp14> be run more than once for a given combination
of input share and level. This function checks that candidate prefixes are
unique and lexicographically sorted, checks that levels are increasing between
calls, and also enforces that the prefixes at each level are suffixes of the
previous level's prefixes.</t>
          <sourcecode type="python"><![CDATA[
<CODE BEGINS>
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]
<CODE ENDS>
]]></sourcecode>
        </section>
        <section anchor="aggregation-2">
          <name>Aggregation</name>
          <t>Aggregation involves simply adding up the output shares.</t>
          <sourcecode type="python"><![CDATA[
<CODE BEGINS>
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)
<CODE ENDS>
]]></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[
<CODE BEGINS>
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]
<CODE ENDS>
]]></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="RFC9846"/>.</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[
<CODE BEGINS>
opaque Poplar1FieldInner[Fi];
<CODE ENDS>
]]></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[
<CODE BEGINS>
opaque Poplar1FieldLeaf[Fl];
<CODE ENDS>
]]></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[
<CODE BEGINS>
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;
<CODE ENDS>
]]></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[
<CODE BEGINS>
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)
<CODE ENDS>
]]></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[
<CODE BEGINS>
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')
<CODE ENDS>
]]></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[
<CODE BEGINS>
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;
<CODE ENDS>
]]></sourcecode>
          </section>
          <section anchor="verifier-share-1">
            <name>Verifier Share</name>
            <t>Encoding of the verifier share depends on the round of sketching: if the first
round, then each sketch share has three field elements; if the second round,
then each sketch share has one field element. The field that is used depends on
the level of the IDPF tree specified by the aggregation parameter, either the
inner field or the leaf field.</t>
            <t>For the first round and inner field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
<CODE BEGINS>
struct {
    Poplar1FieldInner sketch_share[Fi * 3];
} Poplar1VerifierShareRoundOneInner;
<CODE ENDS>
]]></sourcecode>
            <t>For the first round and leaf field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
<CODE BEGINS>
struct {
    Poplar1FieldLeaf sketch_share[Fl * 3];
} Poplar1VerifierShareRoundOneLeaf;
<CODE ENDS>
]]></sourcecode>
            <t>For the second round and inner field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
<CODE BEGINS>
struct {
    Poplar1FieldInner sketch_share;
} Poplar1VerifierShareRoundTwoInner;
<CODE ENDS>
]]></sourcecode>
            <t>For the second round and leaf field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
<CODE BEGINS>
struct {
    Poplar1FieldLeaf sketch_share;
} Poplar1VerifierShareRoundTwoLeaf;
<CODE ENDS>
]]></sourcecode>
          </section>
          <section anchor="verifier-message-1">
            <name>Verifier Message</name>
            <t>Likewise, the structure of the verifier message for Poplar1 depends on the
sketching round and field. For the first round and inner field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
<CODE BEGINS>
struct {
    Poplar1FieldInner[Fi * 3];
} Poplar1VerifierMessageRoundOneInner;
<CODE ENDS>
]]></sourcecode>
            <t>For the first round and leaf field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
<CODE BEGINS>
struct {
    Poplar1FieldLeaf sketch[Fl * 3];
} Poplar1VerifierMessageRoundOneLeaf;
<CODE ENDS>
]]></sourcecode>
            <t>Note that these messages have the same structures as the verifier shares for
the first round.</t>
            <t>The second-round verifier message is the empty string. This is because the
sketch shares are expected to sum to a particular value if the output shares
are valid; successful verification is represented with the empty string,
otherwise the procedure returns an error.</t>
          </section>
          <section anchor="aggregate-share">
            <name>Aggregate Share</name>
            <t>The encoding of the aggregate share depends on whether the inner or leaf field
is used, and the number of candidate prefixes. Both of these are determined by
 the aggregation parameter.</t>
            <t>Let <tt>prefix_count</tt> denote the number of candidate prefixes. For the inner field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
<CODE BEGINS>
struct {
    Poplar1FieldInner agg_share[Fi * prefix_count];
} Poplar1AggShareInner;
<CODE ENDS>
]]></sourcecode>
            <t>For the leaf field:</t>
            <sourcecode type="tls-presentation"><![CDATA[
<CODE BEGINS>
struct {
    Poplar1FieldLeaf agg_share[Fl * prefix_count];
} Poplar1AggShareLeaf;
<CODE ENDS>
]]></sourcecode>
          </section>
          <section anchor="aggregation-parameter">
            <name>Aggregation Parameter</name>
            <t>The aggregation parameter is encoded as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
<CODE BEGINS>
struct {
    uint16_t level;
    uint32_t num_prefixes;
    opaque encoded_prefixes[prefixes_len];
} Poplar1AggParam;
<CODE ENDS>
]]></sourcecode>
            <t>The fields in this struct are: <tt>level</tt>, the level of the IDPF tree of each
prefix; <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[
<CODE BEGINS>
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)
<CODE ENDS>
]]></sourcecode>
            <t>Decoding involves the following procedure:</t>
            <sourcecode type="python"><![CDATA[
<CODE BEGINS>
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))
<CODE ENDS>
]]></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[
<CODE BEGINS>
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)
<CODE ENDS>
]]></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[
<CODE BEGINS>
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))
<CODE ENDS>
]]></sourcecode>
        </section>
        <section anchor="idpf-bbcggi21-helper-functions">
          <name>Auxiliary Functions</name>
          <sourcecode type="python"><![CDATA[
<CODE BEGINS>
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)
<CODE ENDS>
]]></sourcecode>
        </section>
      </section>
    </section>
    <section anchor="security">
      <name>Security Considerations</name>
      <t>VDAFs (<xref target="vdaf"/>) have two essential security goals:</t>
      <ol spacing="normal" type="1"><li>
          <t>Privacy: an attacker that controls the Collector and a subset of Clients and
a subset of Aggregators learns nothing about the measurements of honest
Clients beyond what it can deduce from the aggregate result. It is assumed
that the attacker controls the entire network except for channels between
honest Clients and honest Aggregators. In particular, it cannot forge or
prevent transmission of messages on these channels.</t>
        </li>
        <li>
          <t>Verifiability: an attacker that controls a subset of Clients cannot cause
the Collector to compute anything other than the aggregate of the
measurements of honest Clients, plus valid measurements from some of the
attacker-controlled Clients. It is assumed that the attacker eavesdrops on
the network but does not control transmission of messages between honest
parties.</t>
        </li>
      </ol>
      <t>Formal definitions of privacy and verifiability (i.e., robustness) can be found
in <xref target="DPRS23"/>. A VDAF is the core cryptographic primitive of a protocol that
achieves the above privacy and verifiability goals. It is not sufficient on its
own, however. The application will need to assure a few security properties,
for example:</t>
      <ul spacing="normal">
        <li>
          <t>Securely distributing the long-lived parameters, in particular the
verification key.</t>
        </li>
        <li>
          <t>Establishing secure channels:  </t>
          <ul spacing="normal">
            <li>
              <t>Confidential and authentic channels among Aggregators, and between the
Aggregators and the Collector; and</t>
            </li>
            <li>
              <t>Confidential and Aggregator-authenticated channels between Clients and
Aggregators.</t>
            </li>
          </ul>
        </li>
        <li>
          <t>Enforcing the non-collusion properties required of the specific VDAF in use.</t>
        </li>
      </ul>
      <t>In such an environment, a VDAF provides the high-level privacy property
described above: the Collector learns only the aggregate result, and nothing
about individual measurements aside from what can be inferred from the
aggregate result.  The Aggregators learn neither individual measurements nor
the aggregate result.  The Collector is assured that the aggregate statistic
accurately reflects the inputs as long as the Aggregators correctly executed
their role in the VDAF.</t>
      <t>On their own, VDAFs do not provide:</t>
      <ol spacing="normal" type="1"><li>
          <t>Mitigation of Sybil attacks <xref target="Dou02"/>. In this attack, the adversary
observes a subset of input shares transmitted by a Client it is interested
in. It allows the input shares to be processed, but corrupts and picks bogus
measurements for the remaining Clients.  Applications can guard against
these risks by adding additional controls on report submission, such as
Client authentication and rate limits.</t>
        </li>
        <li>
          <t>Differential privacy <xref target="Dwo06"/>. Depending on the distribution of the
measurements, the aggregate result itself can still leak a significant
amount of information about an individual measurement or the person that
generated it.</t>
        </li>
        <li>
          <t>Verifiability in the presence of a malicious Aggregator. An Aggregator can,
without detection, manipulate the aggregate result by modifying its own
aggregate share.</t>
        </li>
        <li>
          <t>Guaranteed output delivery <xref target="GSZ20"/>. An attacker that controls transmission
of messages between honest parties can prevent computation of the aggregate
result by dropping messages.</t>
        </li>
        <li>
          <t>Security against protocol-confusion attacks. Privacy or verifiability may be
compromised if the attacker coerces an honest party into using either an
incorrect (V)DAF or incorrect parameters for the correct (V)DAF.</t>
        </li>
      </ol>
      <section anchor="the-verification-key">
        <name>The Verification Key</name>
        <t>The Aggregators are responsible for exchanging the verification key in advance
of executing the VDAF. Any procedure is acceptable as long as the following
conditions are met:</t>
        <ol spacing="normal" type="1"><li>
            <t>To ensure the computation is verifiably correct, the Aggregators <bcp14>MUST NOT</bcp14>
reveal the verification key to the Clients. Otherwise, a malicious Client
might be able to exploit knowledge of this key to craft an invalid report
that would be accepted by the Aggregators.</t>
          </li>
          <li>
            <t>To ensure privacy of the measurements, the Aggregators <bcp14>MUST</bcp14> commit to the
verification key prior to processing reports generated by Clients.
Otherwise, the attacker may be able to craft a verification key that, for a
given report, causes an honest Aggregator to leak information about the
measurement during verification.</t>
          </li>
        </ol>
        <t>Meeting these requirements is relatively straightforward. For example, the
Aggregators may designate one of their peers to generate the verification key
and distribute it to the others. To assure Clients of key commitment, the
Clients and (honest) Aggregators <bcp14>SHOULD</bcp14> bind the verification key to the
application context. For instance, the "task ID" of DAP <xref target="DAP"/> could be set to
the hash of the verification key; then as long as honest Aggregators only
consume reports for the task indicated by the Client, forging a new key after
the fact would reduce to finding collisions in the underlying hash function.
(Keeping the key secret from the Clients would require the hash function to be
one-way.) However, since rotating the key implies rotating the task ID, this
scheme would not allow key rotation over the lifetime of a task.</t>
      </section>
      <section anchor="nonce-requirements">
        <name>The Nonce</name>
        <t>The sharding and verification phases of VDAF execution depend on a nonce
associated with the Client's report. To ensure privacy of the underlying
measurement, the Client <bcp14>MUST</bcp14> generate this nonce using a CSPRNG. Assuming the
verification key is fixed (<xref target="the-verification-key"/>), this ensures any malicious
Aggregators trying to break privacy cannot control the randomness derived for
the verification process. Uniqueness of the nonce is not sufficient because the
verification key is controlled by the attacker <xref target="DPRS23"/>.</t>
        <t>Applications will need to protect against replay attacks to prevent disallowed
re-use of reports (see <xref target="agg-param-security"/>). Furthermore, in applications
that aim to achieve differential privacy, it is necessary to limit how much
each party contributes to a single batch or multiple batches. It is <bcp14>RECOMMENDED</bcp14>
that the nonce generated by the Client be used by the Aggregators for replay
protection.</t>
      </section>
      <section anchor="the-public-share">
        <name>The Public Share</name>
        <t>The Aggregators <bcp14>MUST</bcp14> ensure they have both received the same public share from
the Client. It is sufficient, for example, to exchange a hash of the public
share over a secure channel.</t>
      </section>
      <section anchor="agg-param-security">
        <name>The Aggregation Parameter</name>
        <t>As described in <xref target="sec-daf-validity-scopes"/> and <xref target="sec-vdaf-validity-scopes"/>
respectively, DAFs and VDAFs may impose restrictions on the re-use of reports.
For Prio3, reports should only be aggregated once; for Poplar1, reports may be
aggregated multiple times, but never twice at the same level of the tree.
Otherwise, one risks re-using correlated randomness, which might compromise
confidentiality of the Client's measurement.</t>
        <t>Higher level applications that use DAFs or VDAFs <bcp14>MUST</bcp14> enforce aggregation
parameter validity. In particular, prior to beginning DAF preparation or VDAF
verification with an aggregation parameter provided by the Collector, they <bcp14>MUST</bcp14>
invoke <tt>is_valid()</tt> to decide if the parameter is valid given the sequence of
previously accepted parameters.</t>
        <t>Note that aggregating a batch of reports multiple times, even with a valid
sequence of aggregation parameters, can result in information leakage beyond
what is used by the application.</t>
        <t>For example, when Poplar1 is used for heavy hitters, the Aggregators learn not
only the heavy hitters themselves, but also the prefix tree (as defined in
<xref target="poplar1"/>) computed along the way. Indeed, this leakage is inherent to any
construction that uses an IDPF (<xref target="idpf"/>) in the same way. Depending on the
distribution of the measurements, the prefix tree can leak a significant amount
of information about unpopular inputs. For instance, it is possible (though
perhaps unlikely) for a large set of non-heavy-hitter values to share a common
prefix, which would be leaked by a prefix tree with a sufficiently small
threshold.</t>
        <t>A malicious adversary controlling the Collector and one of the Aggregators can
further turn arbitrary non-heavy prefixes into heavy ones by tampering with the
IDPF output at any position. While the construction ensures that the nodes
evaluated at one level are children of the nodes evaluated at the previous
level, this still may allow an adversary to discover individual non-heavy
strings. This is called a "steering attack".</t>
        <t>The only practical, general-purpose defense against steering attacks is to
compose Poplar1 with some mechanism for differential privacy. It is therefore
<bcp14>RECOMMENDED</bcp14> to use differential privacy for any heavy-hitter type application.</t>
      </section>
      <section anchor="idpf-extract">
        <name>Safe Usage of IDPF Outputs</name>
        <t>The arithmetic sketch described in <xref target="poplar1"/> is used by the Aggregators to check
that the shares of the vector obtained by evaluating a Client's IDPF at a
sequence of candidate prefixes has at most one non-zero value, and that the
non-zero value is <tt>1</tt>. Depending on how the values are used, the arithmetic
sketch on its own may not be sufficient to verify the correctness of the
computation. In particular, a malicious Client may attempt to influence the
computation by choosing an IDPF that evaluates to <tt>1</tt> at more than one node at
a given level of the tree.</t>
        <t>This issue can be mitigated by using an IDPF that is extractable as defined
in Appendix D of <xref target="BBCGGI21"/>. Extractability ensures that, for a particular
level of the tree, it is infeasible for an attacker to control values of the
IDPF such that it takes on chosen non-zero values at more than one node. (It
can practically only achieve the zero function, a point function, or a
pseudorandom function.)</t>
        <t>The IDPF specified in <xref target="idpf"/> only guarantees extractability at the last level
of the tree. (This is by virtue of using a larger field for the leaves than for
inner nodes and using an XOF to derive leaves that is safe to model as a random
oracle. See <xref target="xof-vs-ro"/>.) For intermediate levels, it is feasible for a
client to produce IDPF shares with two controlled non-zero nodes.</t>
        <t>This is not an issue for running heavy hitters, since (1) each node in the
prefix tree is a child of a previously traversed node, (2) the arithmetic sketch
would detect double voting at every level of the prefix tree, and (3) the IDPF
is extractable at the last level of the tree. However, the lack of
extractability at intermediate levels may result in attacks on the correctness of
the computation in certain applications.</t>
        <t>Thus applications <bcp14>SHOULD NOT</bcp14> use prefix counts for intermediate levels for any
purpose beyond computing the prefix tree for heavy hitters.</t>
      </section>
      <section anchor="xof-vs-ro">
        <name>Safe Usage of XOFs</name>
        <t>In the security analyses of these protocols, XOFs (<xref target="xof"/>) are usually modeled
as random oracles. XofTurboShake128 is designed to be indifferentiable from a
random oracle <xref target="MRH04"/>, making it a suitable choice for most situations.</t>
        <t>The one exception is the IDPF of <xref target="idpf-bbcggi21"/>. Here, a random oracle is not
needed to prove privacy, since the analysis of <xref target="BBCGGI21"/>, Proposition 1, only
requires a Pseudorandom Generator (PRG). As observed in <xref target="GKWY20"/>, a PRG can be
instantiated from a correlation-robust hash function <tt>H</tt>. Informally,
correlation robustness requires that for a random <tt>r</tt>, <tt>H(xor(r, x))</tt> is
computationally indistinguishable from a random function of <tt>x</tt>. A PRG can
therefore be constructed as</t>
        <artwork><![CDATA[
PRG(r) = H(xor(r, 1)) || H(xor(r, 2)) || ...
]]></artwork>
        <t>since each individual hash function evaluation is indistinguishable from a random
function.</t>
        <t>XofFixedKeyAes128 in <xref target="xof-fixed-key-aes128"/> implements a correlation-robust
hash function using fixed-key AES. For security, it assumes that AES with a
fixed key can be modeled as a random permutation <xref target="GKWY20"/>. Additionally, a
different AES key is used for every report, which in the ideal cipher model
leads to better concrete security <xref target="GKWWY20"/>.</t>
        <t>Note that for verifiability, the analysis of <xref target="BBCGGI21"/> still assumes a
random oracle to make the IDPF extractable. Thus XofTurboShake128 is used
instead for the last level of the tree. It is important that XofTurboShake128
supports many seed lengths, in particular 16 bytes, as this is the seed size
for the inner levels.</t>
        <t>While XofFixedKeyAes128 has been shown to be differentiable from a random
oracle <xref target="GKWWY20"/>, there are no known attacks exploiting this difference. And
even if the IDPF is not extractable, Poplar1 guarantees that every client can
contribute to at most one prefix among the ones being evaluated by the helpers.</t>
      </section>
      <section anchor="security-multiproof">
        <name>Choosing FLP Parameters</name>
        <t>Prio3 and other systems built from the FLP of <xref target="flp-bbcggi19"/> may benefit from
choosing a field size that is as small as possible. Generally speaking, a
smaller field results in lower communication and storage costs. Care must be
taken, however, since a smaller field also results in degraded (or even
vacuous) verifiability.</t>
        <t>Different variants of Prio3 (<xref target="prio3"/>) use different field sizes: Prio3Count
and Prio3Sum use Field64; but Prio3SumVec, Prio3Histogram, and
Prio3MultihotCountVec all use Field128, a field that is twice as large as
Field64. This is due to the use of joint randomness (<xref target="flp"/>) in the latter
variants. Joint randomness allows for more flexible circuit design (see
<xref target="flp-bbcggi19-overview-extensions"/>), but opens up Prio3 to offline attacks in
which the attacker searches for input shares for an invalid measurement that
derive joint randomness that causes the circuit to accept. Choosing a large
enough field ensures this computation is too expensive to be feasible. (See
<xref target="DPRS23"/>, Theorem 1.) Note that privacy is not susceptible to such attacks.</t>
        <t>Another way to mitigate this issue (or improve verifiability in general) is to
generate and verify multiple, independent proofs. (See <xref target="multiproofs"/>.) For
Prio3, the <tt>PROOFS</tt> parameter controls the number of proofs (at least one) that
are generated and verified. In general the soundness error of the FLP is given
by the following formula:</t>
        <artwork><![CDATA[
(circuit_soundness + flp_soundness)**PROOFS
]]></artwork>
        <t>where:</t>
        <ul spacing="normal">
          <li>
            <t><tt>circuit_soundness</tt> is the soundness of the validity circuit
(<xref target="flp-bbcggi19-valid"/>)</t>
          </li>
          <li>
            <t><tt>flp_soundness</tt> is the base soundness of the proof system (<xref target="BBCGGI19"/>,
Theorem 4.3)</t>
          </li>
        </ul>
        <t>For circuits involving joint randomness, one should aim for the soundness error
to be close to <tt>2**-128</tt> in order to mitigate offline attacks. Such circuits
<bcp14>MUST</bcp14> use Field128 with at least one proof or Field64 with at least three
proofs. Depending on the circuit, Field64 with two proofs might have
significantly lower soundness than Field128 with one proof.</t>
        <t>Weak parameters (too small a field, too few proofs, or both) can be exploited
to attack any aggregation task using those parameters. To mitigate offline
attacks, it is necessary to disable all tasks that use the weak parameters.</t>
      </section>
      <section anchor="num-aggregators">
        <name>Choosing the Number of Aggregators</name>
        <t>Two Aggregators are required for privacy in the threat model, but some (V)DAFs,
including Prio3 (<xref target="prio3"/>), allow for any number of Aggregators, only one of
which needs to be trusted in order for the computation to be private. To hedge
against corruptions that happen during the course of the attack, deployments
may consider involving more than two Aggregators as described for example in
<xref target="star-topo"/>. Note however that some schemes are not compatible with this mode
of operation, such as Poplar1.</t>
      </section>
      <section anchor="deep">
        <name>Defense-in-Depth Measures</name>
        <t>Prio3 and Poplar1 are designed to resist some attacks that fall outside the
main threat model for VDAFs.</t>
        <t>Broadly speaking, domain separation is used to prevent cross protocol attacks,
in which data from evaluation of one VDAF translates to an attack against another.
For example:</t>
        <ol spacing="normal" type="1"><li>
            <t>Weak entropy sources: the VDAF algorithm ID is bound to each XOF invocation,
thereby ensuring the outputs are different between VDAF invocations, even if
the underlying randomness is the same. For example, two different instances
of Prio3 would compute different measurement shares.</t>
          </li>
          <li>
            <t>Weak parameters: Prio3 variants that require joint randomness are subject to
offline attacks against verifiability. These attacks are feasible if the field
size or number of proofs is sufficiently small. (See
<xref target="security-multiproof"/>.) The joint randomness derivation is bound to both
the field (via the algorithm ID) and the number of proofs, thereby ensuring
that joint randomness derived for weak parameters is not reused for stronger
parameters. In addition, the joint randomness is bound to the application
context, meaning any work the attacker does to attack some application is
not useful for other applications that use the same parameters.</t>
          </li>
        </ol>
        <t>There are also some important limitations to be aware of. For example, Prio3
provides domain separation between families of circuits, but does not provide
domain separation between instances of a circuit. Concretely, it is possible
for Aggregators to accept a report for Prio3SumVec from a Client who disagrees
with them on the value of <tt>max_measurement</tt> and <tt>length</tt> (so long as the encoded
measurement is the same size). This is because there is no
binding of the circuit parameters to the computation.</t>
      </section>
      <section anchor="side-channel-resistance">
        <name>Side-Channel Resistance</name>
        <t>Implementations of VDAFs should incorporate defenses against side-channel
attacks. For side-channel attacks against the privacy security goal, the
relevant threat model includes an attacker that may control the Collector, a
subset of Clients, and a subset of Aggregators, and monitor side-channel
signals from the honest Clients and Aggregators. Side-channel attacks by third
parties may indirectly target verifiability by trying to leak the Aggregators'
verification key. Thus, implementations of Clients and Aggregators should treat
measurements, input shares, output shares, and the verification key as secret,
and avoid leaking those secret values or any intermediate computations that
depend on them.</t>
        <t>For example, the following routines should all be implemented in a side-channel
resistant manner.</t>
        <ul spacing="normal">
          <li>
            <t>Finite field arithmetic</t>
          </li>
          <li>
            <t>XOFs</t>
          </li>
          <li>
            <t>IDPF generation and evaluation, including handling of control bits</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>IANA is requested to make one new registry:</t>
      <ul spacing="normal">
        <li>
          <t>DAF and VDAF Identifiers</t>
        </li>
      </ul>
      <t>This registry should be created under the heading "Verifiable Distributed
Aggregation Functions (VDAF)", and administered under the Specification Required
policy <xref target="RFC8126"/>.</t>
      <t>The "DAF and VDAF Identifiers" registry lists identifiers for Distributed Aggregation
Functions (DAFs) and Verifiable Distributed Aggregation Functions (VDAFs). These
identifiers are four-byte values, so the minimum possible value is <tt>0x00000000</tt>
and the maximum possible value is <tt>0xffffffff</tt>.</t>
      <t>Template:</t>
      <ul spacing="normal">
        <li>
          <t>Value: The four-byte identifier for the DAF or VDAF</t>
        </li>
        <li>
          <t>Scheme: The name of the DAF or VDAF</t>
        </li>
        <li>
          <t>Type: Either "DAF" for a Distributed Aggregation Function or "VDAF" for a
Verifiable Distributed Aggregation Function</t>
        </li>
        <li>
          <t>Reference: Where the algorithm is defined</t>
        </li>
      </ul>
      <t>The initial contents of the registry are as follows:</t>
      <table anchor="codepoints">
        <name>Verifiable Distributed Aggregation Function Identifiers Registry</name>
        <thead>
          <tr>
            <th align="left">Value</th>
            <th align="left">Scheme</th>
            <th align="left">Type</th>
            <th align="left">Reference</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>0x00000000</tt></td>
            <td align="left">Reserved</td>
            <td align="left">n/a</td>
            <td align="left">RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000001</tt></td>
            <td align="left">Prio3Count</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3count"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000002</tt></td>
            <td align="left">Prio3Sum</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3sum"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000003</tt></td>
            <td align="left">Prio3SumVec</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3sumvec"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000004</tt></td>
            <td align="left">Prio3Histogram</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3histogram"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000005</tt></td>
            <td align="left">Prio3MultihotCountVec</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3multihotcountvec"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000006</tt></td>
            <td align="left">Poplar1</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="poplar1-construction"/> of RFC XXXX</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0xFFFF0000</tt> to <tt>0xFFFFFFFF</tt></td>
            <td align="left">Reserved for Private Use</td>
            <td align="left">n/a</td>
            <td align="left">n/a</td>
          </tr>
        </tbody>
      </table>
      <t>(RFC EDITOR: Please replace "RFC XXXX" above with the RFC number assigned to
this document.)</t>
      <t>VDAF identifiers are used for domain separation, as described in
<xref target="dst-binder"/>. Domain separation guards against cross protocol attacks and
certain failures of entropy sources. See <xref target="deep"/>.</t>
      <t>The benefits of domain separation are undermined if different VDAFs are used
with the same VDAF Identifier.  The "Reserved for Private Use" code points
should thus be used judiciously, because they provide no defense against such
collisions.  Applications <bcp14>SHOULD</bcp14> prefer the use of registered code points.</t>
    </section>
  </middle>
  <back>
    <references anchor="sec-combined-references">
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="AES" target="https://www.nist.gov/publications/advanced-encryption-standard-aes">
          <front>
            <title>Advanced Encryption Standard (AES)</title>
            <author initials="M. J." surname="Dworkin" fullname="Morris J. Dworkin">
              <organization/>
            </author>
            <author initials="E." surname="Barker" fullname="Elaine Barker">
              <organization/>
            </author>
            <author initials="J. R." surname="Nechvatal" fullname="James R. Nechvatal">
              <organization/>
            </author>
            <author initials="J." surname="Foti" fullname="James Foti">
              <organization/>
            </author>
            <author initials="L. E." surname="Bassham" fullname="Lawrence E. Bassham">
              <organization/>
            </author>
            <author initials="E." surname="Roback" fullname="E. Roback">
              <organization/>
            </author>
            <author initials="J." surname="Dray Jr" fullname="James F. Dray Jr.">
              <organization/>
            </author>
            <date year="2001"/>
          </front>
        </reference>
        <reference anchor="RFC9861">
          <front>
            <title>KangarooTwelve and TurboSHAKE</title>
            <author fullname="B. Viguier" initials="B." surname="Viguier"/>
            <author fullname="D. Wong" initials="D." role="editor" surname="Wong"/>
            <author fullname="G. Van Assche" initials="G." role="editor" surname="Van Assche"/>
            <author fullname="Q. Dang" initials="Q." role="editor" surname="Dang"/>
            <author fullname="J. Daemen" initials="J." role="editor" surname="Daemen"/>
            <date month="October" year="2025"/>
            <abstract>
              <t>This document defines four eXtendable-Output Functions (XOFs), hash functions with output of arbitrary length, named TurboSHAKE128, TurboSHAKE256, KT128, and KT256.</t>
              <t>All four functions provide efficient and secure hashing primitives, and the last two are able to exploit the parallelism of the implementation in a scalable way.</t>
              <t>This document is a product of the Crypto Forum Research Group. It builds up on the definitions of the permutations and of the sponge construction in NIST FIPS 202 and is meant to serve as a stable reference and an implementation guide.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9861"/>
          <seriesInfo name="DOI" value="10.17487/RFC9861"/>
        </reference>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
            <abstract>
              <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        <reference anchor="RFC8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
        <reference anchor="RFC9846">
          <front>
            <title>The Transport Layer Security (TLS) Protocol Version 1.3</title>
            <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
            <date month="July" year="2026"/>
            <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 obsoletes RFC 8446, which specified TLS 1.3. This document obsoletes RFC 5246 (specifying TLS 1.2) and RFCs 5077, 6961, 7627, and 8422, all of which pertain to TLS 1.2 or earlier, and updates RFCs 5705 and 6066. This document also specifies new requirements for TLS 1.2 implementations.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9846"/>
          <seriesInfo name="DOI" value="10.17487/RFC9846"/>
        </reference>
        <reference anchor="RFC8126">
          <front>
            <title>Guidelines for Writing an IANA Considerations Section in RFCs</title>
            <author fullname="M. Cotton" initials="M." surname="Cotton"/>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <author fullname="T. Narten" initials="T." surname="Narten"/>
            <date month="June" year="2017"/>
            <abstract>
              <t>Many protocols make use of points of extensibility that use constants to identify various protocol parameters. To ensure that the values in these fields do not have conflicting uses and to promote interoperability, their allocations are often coordinated by a central record keeper. For IETF protocols, that role is filled by the Internet Assigned Numbers Authority (IANA).</t>
              <t>To make assignments in a given registry prudently, guidance describing the conditions under which new values should be assigned, as well as when and how modifications to existing values can be made, is needed. This document defines a framework for the documentation of these guidelines by specification authors, in order to assure that the provided guidance for the IANA Considerations is clear and addresses the various issues that are likely in the operation of a registry.</t>
              <t>This is the third edition of this document; it obsoletes RFC 5226.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="26"/>
          <seriesInfo name="RFC" value="8126"/>
          <seriesInfo name="DOI" value="10.17487/RFC8126"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="AGJOP21" target="https://ia.cr/2021/576">
          <front>
            <title>Prio+: Privacy Preserving Aggregate Statistics via Boolean Shares</title>
            <author initials="S." surname="Addanki" fullname="Surya Addanki">
              <organization/>
            </author>
            <author initials="K." surname="Garbe" fullname="Kevin Garbe">
              <organization/>
            </author>
            <author initials="E." surname="Jaffe" fullname="Eli Jaffe">
              <organization/>
            </author>
            <author initials="R." surname="Ostrovsky" fullname="Rafail Ostrovsky">
              <organization/>
            </author>
            <author initials="A." surname="Polychroniadou" fullname="Antigoni Polychroniadou">
              <organization/>
            </author>
            <date year="2022"/>
          </front>
          <refcontent>Security and Cryptography for Networks (SCN)</refcontent>
        </reference>
        <reference anchor="BBCGGI19" target="https://ia.cr/2019/188">
          <front>
            <title>Zero-Knowledge Proofs on Secret-Shared Data via Fully Linear PCPs</title>
            <author initials="D." surname="Boneh" fullname="Dan Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle" fullname="Elette Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs" fullname="Henry Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa" fullname="Niv Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai" fullname="Yuval Ishai">
              <organization/>
            </author>
            <date year="2019"/>
          </front>
          <refcontent>Crypto</refcontent>
        </reference>
        <reference anchor="BBCGGI21" target="https://ia.cr/2021/017">
          <front>
            <title>Lightweight Techniques for Private Heavy Hitters</title>
            <author initials="D." surname="Boneh" fullname="Dan Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle" fullname="Elette Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs" fullname="Henry Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa" fullname="Niv Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai" fullname="Yuval Ishai">
              <organization/>
            </author>
            <date year="2021"/>
          </front>
          <refcontent>IEEE Security &amp; Privacy (S&amp;P)</refcontent>
        </reference>
        <reference anchor="BBCGGI23" target="https://ia.cr/2023/1012">
          <front>
            <title>Arithmetic Sketching</title>
            <author initials="D." surname="Boneh" fullname="Dan Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle" fullname="Elette Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs" fullname="Henry Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa" fullname="Niv Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai" fullname="Yuval Ishai">
              <organization/>
            </author>
            <date year="2023"/>
          </front>
          <refcontent>Crypto</refcontent>
        </reference>
        <reference anchor="BGI15" target="https://www.iacr.org/archive/eurocrypt2015/90560300/90560300.pdf">
          <front>
            <title>Function Secret Sharing</title>
            <author initials="E." surname="Boyle" fullname="Elette Boyle">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa" fullname="Niv Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai" fullname="Yuval Ishai">
              <organization/>
            </author>
            <date year="2015"/>
          </front>
          <refcontent>Eurocrypt</refcontent>
        </reference>
        <reference anchor="CGB17" target="https://dl.acm.org/doi/10.5555/3154630.3154652">
          <front>
            <title>Prio: Private, Robust, and Scalable Computation of Aggregate Statistics</title>
            <author initials="D." surname="Boneh" fullname="Dan Boneh">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs" fullname="Henry Corrigan-Gibbs">
              <organization/>
            </author>
            <date year="2017"/>
          </front>
          <refcontent>USENIX Symposium on Networked Systems Design and Implementation (NSDI)</refcontent>
        </reference>
        <reference anchor="Dou02" target="https://doi.org/10.1007/3-540-45748-8_24">
          <front>
            <title>The Sybil Attack</title>
            <author initials="J. R." surname="Douceur" fullname="John R. Douceur">
              <organization/>
            </author>
            <date year="2002"/>
          </front>
          <refcontent>International Workshop on Peer-to-Peer Systems (IPTPS)</refcontent>
        </reference>
        <reference anchor="DPRS23" target="https://ia.cr/2023/130">
          <front>
            <title>Verifiable Distributed Aggregation Functions</title>
            <author initials="" surname="Hannah Davis">
              <organization/>
            </author>
            <author initials="" surname="Christopher Patton">
              <organization/>
            </author>
            <author initials="" surname="Mike Rosulek">
              <organization/>
            </author>
            <author initials="" surname="Phillipp Schoppmann">
              <organization/>
            </author>
            <date year="2023"/>
          </front>
          <refcontent>Privacy Enhancing Technologies Symposium (PETS)</refcontent>
        </reference>
        <reference anchor="Dwo06" target="https://link.springer.com/chapter/10.1007/11787006_1">
          <front>
            <title>Differential Privacy</title>
            <author initials="" surname="Cynthia Dwork">
              <organization/>
            </author>
            <date year="2006"/>
          </front>
          <refcontent>International Colloquium on Automata, Languages, and Programming (ICALP)</refcontent>
        </reference>
        <reference anchor="EPK14" target="https://dl.acm.org/doi/10.1145/2660267.2660348">
          <front>
            <title>RAPPOR: Randomized Aggregatable Privacy-Preserving Ordinal Response</title>
            <author initials="Ú." surname="Erlingsson" fullname="Úlfar Erlingsson">
              <organization/>
            </author>
            <author initials="V." surname="Pihur" fullname="Vasyl Pihur">
              <organization/>
            </author>
            <author initials="A." surname="Korolova" fullname="Aleksandra Korolova">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <refcontent>ACM Conference on Computer and Communications Security (CCS)</refcontent>
        </reference>
        <reference anchor="ENPA" target="https://covid19-static.cdn-apple.com/applications/covid19/current/static/contact-tracing/pdf/ENPA_White_Paper.pdf">
          <front>
            <title>Exposure Notification Privacy-preserving Analytics (ENPA) White Paper</title>
            <author>
              <organization/>
            </author>
            <date year="2021"/>
          </front>
        </reference>
        <reference anchor="Faz25">
          <front>
            <title>Rhizomes and the Roots of Efficiency—Improving Prio</title>
            <author fullname="Armando Faz-Hernandez" initials="A." surname="Faz-Hernandez">
              <organization/>
            </author>
            <date month="October" year="2025"/>
          </front>
          <seriesInfo name="Lecture Notes in Computer Science" value="pp. 425-449"/>
          <seriesInfo name="DOI" value="10.1007/978-3-032-06754-8_16"/>
          <seriesInfo name="ISBN" value="[&quot;9783032067531&quot;, &quot;9783032067548&quot;]"/>
          <refcontent>Springer Nature Switzerland</refcontent>
        </reference>
        <reference anchor="GI14" target="https://link.springer.com/chapter/10.1007/978-3-642-55220-5_35">
          <front>
            <title>Distributed Point Functions and Their Applications</title>
            <author initials="N." surname="Gilboa" fullname="Niv Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai" fullname="Yuval Ishai">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <refcontent>Eurocrypt</refcontent>
        </reference>
        <reference anchor="GSZ20" target="https://link.springer.com/chapter/10.1007/978-3-030-56880-1_22">
          <front>
            <title>Guaranteed Output Delivery Comes Free in Honest Majority MPC</title>
            <author initials="V." surname="Goyal" fullname="Vipul Goyal">
              <organization/>
            </author>
            <author initials="Y." surname="Song" fullname="Yifan Song">
              <organization/>
            </author>
            <author initials="C." surname="Zhu" fullname="Chenzhi Zhu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <refcontent>Crypto</refcontent>
        </reference>
        <reference anchor="GKWWY20" target="https://link.springer.com/chapter/10.1007/978-3-030-56880-1_28">
          <front>
            <title>Better concrete security for half-gates garbling (in the multi-instance setting)</title>
            <author initials="C." surname="Guo" fullname="Chun Guo">
              <organization/>
            </author>
            <author initials="J." surname="Katz" fullname="Jonathan Katz">
              <organization/>
            </author>
            <author initials="X." surname="Wang" fullname="Xiao Wang">
              <organization/>
            </author>
            <author initials="C." surname="Weng" fullname="Chenkai Weng">
              <organization/>
            </author>
            <author initials="Y." surname="Yu" fullname="Yu Yu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <refcontent>Crypto</refcontent>
        </reference>
        <reference anchor="GKWY20" target="https://eprint.iacr.org/2019/074">
          <front>
            <title>Efficient and Secure Multiparty Computation from Fixed-Key Block Ciphers</title>
            <author initials="C." surname="Guo" fullname="Chun Guo">
              <organization/>
            </author>
            <author initials="J." surname="Katz" fullname="Jonathan Katz">
              <organization/>
            </author>
            <author initials="X." surname="Wang" fullname="Xiao Wang">
              <organization/>
            </author>
            <author initials="Y." surname="Yu" fullname="Yu Yu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <refcontent>IEEE Security &amp; Privacy (S&amp;P)</refcontent>
        </reference>
        <reference anchor="MPDST25" target="https://eprint.iacr.org/2024/221">
          <front>
            <title>Mastic: Private Weighted Heavy-Hitters and Attribute-Based Metrics</title>
            <author initials="D." surname="Mouris" fullname="Dimitris Mouris">
              <organization/>
            </author>
            <author initials="C." surname="Patton" fullname="Christopher Patton">
              <organization/>
            </author>
            <author initials="H." surname="Davis" fullname="Hannah Davis">
              <organization/>
            </author>
            <author initials="P." surname="Sarkar" fullname="Pratik Sarkar">
              <organization/>
            </author>
            <author initials="N. G." surname="Tsoutsos" fullname="Nektarios Georgios Tsoutsos">
              <organization/>
            </author>
            <date year="2025"/>
          </front>
          <refcontent>Privacy Enhancing Technologies Symposium (PETS)</refcontent>
        </reference>
        <reference anchor="MPRV09" target="https://link.springer.com/chapter/10.1007/978-3-642-03356-8_8">
          <front>
            <title>Computational Differential Privacy</title>
            <author initials="I." surname="Mironov" fullname="Ilya Mironov">
              <organization/>
            </author>
            <author initials="O." surname="Pandey" fullname="Omkant Pandey">
              <organization/>
            </author>
            <author initials="O." surname="Reingold" fullname="Omer Reingold">
              <organization/>
            </author>
            <author initials="S." surname="Vadhan" fullname="Salil Vadhan">
              <organization/>
            </author>
            <date year="2009"/>
          </front>
          <refcontent>Crypto</refcontent>
        </reference>
        <reference anchor="MRH04" target="https://doi.org/10.1007/978-3-540-24638-1_2">
          <front>
            <title>Indifferentiability, impossibility results on reductions, and applications to the random oracle methodology</title>
            <author initials="U." surname="Maurer" fullname="Ueli Maurer">
              <organization/>
            </author>
            <author initials="R." surname="Renner" fullname="Renato Renner">
              <organization/>
            </author>
            <author initials="C." surname="Holenstein" fullname="Clemens Holenstein">
              <organization/>
            </author>
            <date year="2004"/>
          </front>
          <refcontent>Theory of Cryptography (TCC)</refcontent>
        </reference>
        <reference anchor="OriginTelemetry" target="https://web.archive.org/web/20221025174046/https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/collection/origin.html">
          <front>
            <title>Origin Telemetry</title>
            <author>
              <organization/>
            </author>
            <date year="2020"/>
          </front>
        </reference>
        <reference anchor="PANEL-FEEDBACK" target="https://mailarchive.ietf.org/arch/msg/cfrg/Omdhr4rO1pla_nlju2l7OJEGWPM/">
          <front>
            <title>Review of draft-irtf-cfrg-vdaf-15</title>
            <author initials="J." surname="Hesse" fullname="Julia Hesse">
              <organization/>
            </author>
            <date year="2025"/>
          </front>
        </reference>
        <reference anchor="SML24" target="https://eprint.iacr.org/2024/585">
          <front>
            <title>A Complete Beginner Guide to the Number Theoretic Transform (NTT)</title>
            <author initials="A." surname="Satriawan" fullname="Ardianto Satriawan">
              <organization/>
            </author>
            <author initials="R." surname="Mareta" fullname="Rella Mareta">
              <organization/>
            </author>
            <author initials="H." surname="Lee" fullname="Hanho Lee">
              <organization/>
            </author>
            <date year="2024"/>
          </front>
          <refcontent>IEEE Access, vol. 11</refcontent>
        </reference>
        <reference anchor="Pol71">
          <front>
            <title>The fast Fourier transform in a finite field</title>
            <author fullname="J. M. Pollard" initials="J." surname="Pollard">
              <organization/>
            </author>
            <date year="1971"/>
          </front>
          <seriesInfo name="Mathematics of Computation" value="vol. 25, no. 114, pp. 365-374"/>
          <seriesInfo name="DOI" value="10.1090/s0025-5718-1971-0301966-0"/>
          <refcontent>American Mathematical Society (AMS)</refcontent>
        </reference>
        <reference anchor="TestVectors" target="https://github.com/cfrg/draft-irtf-cfrg-vdaf">
          <front>
            <title>Test vectors for Prio3 and Poplar1</title>
            <author>
              <organization/>
            </author>
            <date year="2025" month="December"/>
          </front>
          <refcontent>commit hash 888e4b1</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="6" month="July" year="2026"/>
            <abstract>
              <t>   There are many situations in which it is desirable to take
   measurements of data which people consider sensitive.  In these
   cases, the entity taking the measurement is usually not interested in
   people's individual responses but rather in aggregated data.
   Conventional methods require collecting individual responses and then
   aggregating them on some server, thus representing a threat to user
   privacy and rendering many such measurements difficult and
   impractical.  This document describes a multi-party Distributed
   Aggregation Protocol (DAP) for privacy preserving measurement which
   can be used to collect aggregate data without revealing any
   individual contributor's data.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-ppm-dap-19"/>
        </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 6539?>

<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[
<CODE BEGINS>
class Mul(Gadget[F]):
    ARITY = 2
    DEGREE = 2

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

    def eval_poly(self,
                  field: type[F],
                  inp_poly: list[list[F]]) -> list[F]:
        lag = Lagrange(field)
        return lag.poly_mul(inp_poly[0], inp_poly[1])
<CODE ENDS>
]]></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[
<CODE BEGINS>
class PolyEval(Gadget[F]):
    ARITY = 1
    p: list[int]  # polynomial coefficients

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

        self.p = p
        self.DEGREE = len(p) - 1
        wire_poly_length = wire_poly_len(num_calls)
        gadget_poly_length = gadget_poly_len(
            self.DEGREE,
            wire_poly_length,
        )
        self.n = next_power_of_2(gadget_poly_length)

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

    def eval_poly(self,
                  field: type[F],
                  inp_poly: list[list[F]]) -> list[F]:
        inp_poly_len = len(inp_poly[0])
        assert_power_of_2(inp_poly_len)

        # Convert the input polynomial from Lagrange to monomial
        # basis.
        inp_mon = field.inv_ntt(inp_poly[0], inp_poly_len)
        # Obtain n evaluations of the input polynomial I.
        inp_lag = field.ntt(inp_mon, self.n)
        # Returns the polynomial composition (P*I)
        p_mon = [field(coeff) for coeff in self.p]
        return [poly_eval(field, p_mon, x) for x in inp_lag]
<CODE ENDS>
]]></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[
<CODE BEGINS>
class ParallelSum(Gadget[F]):
    subcircuit: Gadget[F]
    count: int

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

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

    def eval_poly(self,
                  field: type[F],
                  inp_poly: list[list[F]]) -> list[F]:
        output_poly_length = next_power_of_2(gadget_poly_len(
            self.DEGREE,
            len(inp_poly[0]),
        ))
        out_sum = [field(0) for _ in range(output_poly_length)]
        for i in range(self.count):
            start_index = i * self.subcircuit.ARITY
            end_index = (i + 1) * self.subcircuit.ARITY
            out_current = self.subcircuit.eval_poly(
                field,
                inp_poly[start_index:end_index]
            )
            for j in range(output_poly_length):
                out_sum[j] += out_current[j]
        return out_sum
<CODE ENDS>
]]></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[
<CODE BEGINS>
class ProveGadget(Gadget[F]):
    """
    Gadget wrapper that records the input wires for each evaluation.
    """

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

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

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

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

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

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

        # Recover all the values of the gadget_poly.
        lag = Lagrange(field)
        n = next_power_of_2(len(gadget_poly))
        gadget_poly = list(gadget_poly)
        lag.extend_values_to_power_of_2(gadget_poly, n)

        # Calculate 'size' evaluations of the gadget_poly.
        size = next_power_of_2(gadget_poly_len(g.DEGREE, p))
        while len(gadget_poly) < size:
            gadget_poly = lag.double_evaluations(gadget_poly)
        self.poly = gadget_poly

        # Get the step size used to index the gadget evaluations.
        log_size = assert_power_of_2(size)
        log_p = assert_power_of_2(p)
        self.step = 1 << (log_size-log_p)

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

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

class Start(State):
    pass

class Continued(State, Generic[VerifyState]):
    def __init__(self,
                 verify_state: VerifyState,
                 verify_round: int,
                 outbound: bytes):
        self.verify_state = verify_state
        self.verify_round = verify_round
        self.outbound = outbound

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

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

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

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

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

class Rejected(State):
    pass
<CODE ENDS>
]]></sourcecode>
    </section>
    <section anchor="test-vectors">
      <name>Test Vectors</name>
      <t>Test vectors for Prio3 (<xref target="prio3"/>) and Poplar1 (<xref target="poplar1"/>) are available at
<xref target="TestVectors"/>. The test vector directory, <tt>test_vec/vdaf</tt>, contains a set of
JSON files. Each file contains a test vector for an instance of class <tt>Vdaf</tt> as
defined in <xref target="vdaf"/>. A test vector covers sharding, verification, aggregation,
and unsharding of a batch of several measurements. The test vector schema is
defined below.</t>
      <section anchor="schema">
        <name>Schema</name>
        <dl>
          <dt><tt>ctx</tt>:</dt>
          <dd>
            <t>The application context string encoded in hexadecimal.</t>
          </dd>
          <dt><tt>verify_key</tt>:</dt>
          <dd>
            <t>The verification key encoded in hexadecimal.</t>
          </dd>
          <dt><tt>agg_param</tt>:</dt>
          <dd>
            <t>The aggregation parameter encoded in hexadecimal.</t>
          </dd>
          <dt><tt>reports</tt>:</dt>
          <dd>
            <t>A list of objects with the following schema:
</t>
            <dl>
              <dt><tt>measurement</tt>:</dt>
              <dd>
                <t>The measurement of type <tt>Measurement</tt> defined by the VDAF.</t>
              </dd>
              <dt><tt>nonce</tt>:</dt>
              <dd>
                <t>The nonce encoded in hexadecimal.</t>
              </dd>
              <dt><tt>rand</tt>:</dt>
              <dd>
                <t>The sharding randomness encoded in hexadecimal.</t>
              </dd>
              <dt><tt>public_share</tt>:</dt>
              <dd>
                <t>The expected public share encoded in hexadecimal.</t>
              </dd>
              <dt><tt>input_shares</tt>:</dt>
              <dd>
                <t>The expected list of input shares, each encoded in hexadecimal.</t>
              </dd>
              <dt><tt>verifier_shares</tt>:</dt>
              <dd>
                <t>The expected list of verifier shares generated by each Aggregator at each
  round of verification, encoded in hexadecimal.</t>
              </dd>
              <dt><tt>verifier_messages</tt>:</dt>
              <dd>
                <t>The expected list of verifier messages for each round of
verification, encoded in hexadecimal.</t>
              </dd>
              <dt><tt>out_shares</tt>:</dt>
              <dd>
                <t>The expected list of output shares, encoded in hexadecimal.</t>
              </dd>
            </dl>
          </dd>
          <dt><tt>agg_shares</tt>:</dt>
          <dd>
            <t>The expected aggregate shares encoded in hexadecimal.</t>
          </dd>
          <dt><tt>agg_result</tt>:</dt>
          <dd>
            <t>The expected aggregate result of type <tt>AggResult</tt> defined by the VDAF.</t>
          </dd>
          <dt><tt>operations</tt>:</dt>
          <dd>
            <t>This lists the VDAF operations that should be executed as part of known
answer tests, using messages from this test vector as input. Operations
should be executed in the order they appear, to ensure that verification state
values are computed before they are consumed. Verification state values are
not included in test vectors because this document does not specify their
representation or encoding.</t>
          </dd>
        </dl>
        <t>Each operation in the <tt>operations</tt> list has the following schema:</t>
        <dl>
          <dt><tt>operation</tt>:</dt>
          <dd>
            <t>The type of operation to be performed. This is one of "shard", "verify_init",
"verifier_shares_to_message", "verify_next", "aggregate", or "unshard".</t>
          </dd>
          <dt><tt>round</tt>:</dt>
          <dd>
            <t>For any verification operation, the round number of the operation to be
performed. This determines which verifier share, verification state, and/or
verifier message to use.</t>
          </dd>
          <dt><tt>aggregator_id</tt>:</dt>
          <dd>
            <t>The aggregator ID to use when performing this operation. This determines
which messages and which verification state to use, in addition to the
aggregator ID argument itself.</t>
          </dd>
          <dt><tt>report_index</tt>:</dt>
          <dd>
            <t>The index of the report on which to perform this operation. This is an index
into the <tt>reports</tt> array.</t>
          </dd>
          <dt><tt>success</tt>:</dt>
          <dd>
            <t>If this is <tt>True</tt>, the operation should succeed, and its output should match
the corresponding values in the test vector. If this is <tt>False</tt>, the operation
should fail, terminating verification of this report.</t>
          </dd>
        </dl>
        <t>The test vector schema also includes whatever parameters are required to
instantiate the VDAF. These are listed in the subsections below.</t>
        <section anchor="prio3count-1">
          <name>Prio3Count</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3sum-1">
          <name>Prio3Sum</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>max_measurement</tt>:</dt>
            <dd>
              <t>The largest valid measurement, an integer. Each measurement is in the range
  <tt>[0, max_measurement]</tt>.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3sumvec-1">
          <name>Prio3SumVec</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>length</tt>:</dt>
            <dd>
              <t>The length of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>a parameter of the ParallelSum gadget, an integer.</t>
            </dd>
            <dt><tt>max_measurement</tt>:</dt>
            <dd>
              <t>The largest allowable value of each element of the vector, an integer. Each
element is in the range <tt>[0, max_measurement]</tt>.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3histogram-1">
          <name>Prio3Histogram</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>length</tt>:</dt>
            <dd>
              <t>The length of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>a parameter of the ParallelSum gadget, an integer.</t>
            </dd>
          </dl>
        </section>
        <section anchor="prio3multihotcountvec-1">
          <name>Prio3MultihotCountVec</name>
          <dl>
            <dt><tt>shares</tt>:</dt>
            <dd>
              <t>The number of shares, an integer.</t>
            </dd>
            <dt><tt>length</tt>:</dt>
            <dd>
              <t>The length of the vector, an integer.</t>
            </dd>
            <dt><tt>chunk_length</tt>:</dt>
            <dd>
              <t>a parameter of the ParallelSum gadget, an integer.</t>
            </dd>
            <dt><tt>max_weight</tt>:</dt>
            <dd>
              <t>The largest vector weight, an integer. The sum of the elements of the
measurement must be in the range <tt>[0, max_weight]</tt>.</t>
            </dd>
          </dl>
        </section>
        <section anchor="poplar1-test-vec-param">
          <name>Poplar1</name>
          <dl>
            <dt><tt>bits</tt>:</dt>
            <dd>
              <t>The length of each input in bits, an integer.</t>
            </dd>
          </dl>
        </section>
      </section>
    </section>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The impetus of this work is the success of recent deployments of predecessors
of Prio3. These include the Mozilla Origin Telemetry project
<xref target="OriginTelemetry"/> and the Exposure Notification Private Analytics system
<xref target="ENPA"/> developed jointly by ISRG, Google, Apple, and others. Together these
systems have aggregated data from hundreds of millions of users.</t>
      <t>As the name implies, Prio3 is a descendant of the original Prio construction
<xref target="CGB17"/>. A second iteration was deployed in the <xref target="ENPA"/> system, and like the
VDAF described here, the ENPA system was built from techniques introduced in
<xref target="BBCGGI19"/> that significantly improve communication cost. That system was
specialized for a particular aggregation function; the goal of Prio3 is to
provide the same level of generality as the original construction.</t>
      <t>The security considerations in <xref target="security"/> are based largely on the security
analysis of <xref target="DPRS23"/>. Thanks to Hannah Davis and Mike Rosulek, who lent their
time to developing definitions and security proofs.</t>
      <t>Thanks to Julia Hesse who provided feedback on behalf of the Crypto Review
Panel.</t>
      <t>Special thanks to Armando Faz-Hernandez who discovered a number of algorithmic
improvements for FLPs <xref target="Faz25"/> that significantly improved the runtime of
Prio3 and other applications. Also, thanks to Ian Goldberg for pointing out the
bit decomposition technique used in the range proofs of the Prio3 variants.</t>
      <t>Thanks to Junye Chen, Henry Corrigan-Gibbs, Simon Friedberger, Tim Geoghegan,
Albert Liu, Brandon Pitman, Mariana Raykova, Michael Rosenberg, Jacob
Rothstein, Martin Thomson, Shan Wang, Xiao Wang, Bas Westerbaan, and
Christopher Wood for useful feedback on and contributions to the spec.</t>
    </section>
  </back>
  <!-- ##markdown-source:
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
nBOoXOOD+vxpckQ+S8D5qQ5Jtz7gjGrtYdhZQekn5EE2dvwHriM/iDJhQbF0
hblZszSLUzTBISjAhYEo2qVC2keNsbrGJynDuUwReebYicpL9DWKszaHSeAR
OdmZevoct0FooWhRCsxzfHdoDggVLApndSdqNVuchx6Y7AE2I6nZ63h4eNod
o1d6BLSM9EHy5HEcqulhwBo7BfPXffoaqpSiRY44o5NzXqMTcxmrDRdfNrQK
4ZsSeLdGTg0hLjmjscehBmvDmDac8DMs3I+sjdzUhpyTu91gxEmSeInWHaUz
cB72HkhAXAWYXLLNbN1CreK4yIy2SQqzNuqRzoYzXWSaiFlp0CuCY/m3C1sO
JqfvufZ7J+nBO7K1Er5csMiYCvCrTXlbqB7JmBWHqwTz9gx/a53fXhCRLSMc
nqyF5DjaxfWM4st2LWd9RBDH1O7YdX6uXxBb3OGSG3+FpQG8x4gS8bAsyI90
pT8N0Jr3CYHEg3CmxqNHeHi2xQnpfIlTXbXKX2L9ialWn/zKCjYnRb5xi1Ja
1OShFnzD3iQj0LJ0cVcLjeOF5cB4Pr1+yJuoyF5GnvMIR/mib8F74FOy2qDX
N5ygi6MXG5h9izVDTB741Tdu5jhnoKP59gJ4bKk2Xv9ycrrR4X/Vm7f0+7uD
//uXo3cHL/B30LZfvTK/RPLEyY9vf3n1wv5m39x/+/r1wZsX/DJcVd6laOP1
3t83WJ3f0Dx/o7kuGgev+OFTkZf++Xz/+P/9f7YfSkLizjYVjeA/nmx/hwUL
UGXkr1EBd/6zwhpNVmxlQXeeVjHW5EE1/BxrQqDAjVjxASHzcVf9ZTCcbz/8
QS7ggr2LGmbeRYJZ/UrtZQZiw6WGzxhoetcDSPvz3fu797eGu3PxL3+lHIXu
9pO//hBF0Z6XMFPfmosCKxuwhMAhV62wdKZcf9Db3olyLNQG24ihAmocA6A5
dI5zgyRsRbW4ths2nl/w9sMhKBO3UK6pSGGdMm025nAEAAfpkfkE5KZSEv/Q
OjCX9JojPWPY6aKIqa57cslshlKtONByq69LzfUvP2x97HPpZe2eFZpHRaLh
/jTJWpft7rZ9jAy9mCx1CTTgiNVJzLNza7rSh60rDphTJAwaPVHO52sDa5Oz
fCCKBNYLndpZrmYDDN7r34dl9Lv4v3t9Kfa4ScGLoDGiWqz7RgDX+lWMKxFd
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
NL4bi0+Twuf6usmCDYy9ro6uIxceVXY5NK/GJTn1extXZFbDc2MQ5mVVh+Gp
5xX05HAalb9LH+Wz1Xc1VMB6ckWIu0rbwhrRTeI+6ncijv1g2dmtJcWFtNAX
w6rHSkmTO11815rkuehZZEzyxKRN7jkKKfT1Sc6970xxsmBG8FF4NrKVLLkK
jWmKFvudcylSnpqJYTqXRFhruy+q4J4vC9vsXdcCUbUcAw9NkQ0sDc92YFa5
djZpVs+mggSDgWzeXQegaG3Zke+/teXbTCcTSpcmGMFxNp0bn6IchIYaWugs
ztIxFqelxLlJXAwoEqjuNz01yhcndjDBkKPAYUShVmadtdr7QmFZ2Fuc0uQM
ORqITZyyB8VhR75i8jrpjhT0AuNRoMCyHKf9wqZjB/VNyblzo7tLjD9OhSbH
zYZV0BJCfp7IDMeMOTND+xDY4ytQ1LOT4+87ASMqskb2na5Mz/nsmFqrFLUW
TL6EnCTR1RXBqeu6A9nQb8oekczo4pwVGzUuheHBN3Bi+WliyHj9mfNT/1P/
PKv/sHR6vQyjf26WZexPPYaF5RRXQrE/DbEsVkYJAmZr8bP848fz8hQocERP
J/jTTtS5XBOM79f+tN+7H3zvPxMG10cV6Z+8aXu0uIbIxw1vrpXZ3E64KKg1
BD56AX+hvEJsk0veGY7HHjVMpos45K7kmEw6CaHE4neYc+ohcskyoBvluebD
4rd1DLma31sBkaozufIhRhulI8lfwj9IR99VWhEM5MTIV1J2lScfOmcCq0tq
OZFSe6xRxBUZzXgOvGzRG19QWFM/XntHmvmXR/e+LetEulPzpynHa8BOPueT
2vRu5UuvR5Wb7x5TBV/PtdAsYpI8xxvRN0JW3dxphSNpscJVKhlOWFCHCqrh
T9/ZCJ2Rvj7QeO60mLFg7ZmZrRN/Q6lXOLHLZugdTyJhdnytlS16W5n6sU12
J83bxDGMNnIb0BLuE3Of907Ikeu/MCb00mFKOj6pWw7zeVJyjFoQ+zDHJni2
oJGdouP0YMQobTstiv/uRT/qptd87JccA88hTss0n7KNh+MBaK3I6UEEGSYF
hkW55XFRJIzWQrJcj7499c4dBe0NIJtRqyWrLqzvO4Kg1I47S1zS8ozuthrp
iG5Dcmbu6tR+/YwuNDHI86mTz3taLBJO3jVvcvUbVH5hulI8wEHxiMvShZ/r
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
TOqLfp2Efk+/S9hH+8PQce+3u1WZHgU8fBTHuectP6p9r+19+C+jP/WUlkQU
SlL05M2aGfmnzzhvbswVqcqOo0QCYKEI8fkro8Yt0RWiTcVw7580KG1VajKg
hAUlEdxatlIA37djxmNg3PFbPRoYrJD/kv7O4s+r9QAPh92nj4nmqsWmnMob
I3EcVefvsA5b/Gj65F0cGDLoU0zxOHeN7H53xYk8O4qZsnp4Js+lLmmL8fru
iAL8n70voq/4Iv5MX7QO84ehb6+Tln8K1wxwWB3nNZLHwA25hG83NqSxVJoB
vhjFNZf45//XlQrptB5KV+mv+7/Ueba+lF93fBknbl/F+QutcCR+c9UllVeb
NSDfd9OJOC35nePc3m5vZXhFVl7++6+99DaFnSvvRuGWwQaTrsO3ZKq/0jX6
66zJ6DZ671+kvzcB9y3AX7SifzktnpQ8aKNFz9h6GPtbThf6PTKT2PVN67oe
C5ws2HmJ7M7zUOGgCy7jU5QHCSA3JnFdVDOFM8w+feL2tDMO0+Sb1HXsIpeM
o3pFon/Cv3Ph6J8xw5+MEDPPsYioSsApUtlv37z6hvRRIO09ZUnC/+3f800H
DBXZLqS5YLUmv+f22TmfhPxJdWRGXvOtwEJrQrGVUSKdRh6VQNKLNotQlwWp
ggHsveGwoVZ5yO56IOm84FxLG9tZOatvNHsOD7Nscr7+ODnOjjulVjXTMxc0
Z0v14+ldlR8Lxrmfc/RTNlEW+KHchnY6eVO7v6ZJnyLZLw6iF5R/dwuKfI/v
H0FrQJ44zl4TA7diBpWsy7Gc3YnPdhRil2EktQIvBNB58tKnRoZV3Ybk8UNt
FHVAkuakMsjOWeAruBb9R2H7XYLu/iakDIfwgKQpBtsB0l9S/2N/Y3BfSVtN
f2O22mk2nbi59jateDSrO7VuLxuiUVJfpaUFAjuVfkJ7IpZDC3bQ7jg0K0x4
x8GFMonB02fdKxv+IYOo77jwrcTF/ecsNNhqrFVIcg+NoRmJrtnXjMLDhmMT
LNddh2YSMC9seFxtIRgAUOXjKwqsEXL9rAYtMNpIJ0eltYVUySwWDcPOMF9s
RorzEndKEl85hNXxzaIRej7MX4UuqaWe/hRaRWF6OAieDSHGCF+74ojFOmWI
pkQ7MPNQfeJM0DmlrZVgdHL18cPUfBJNNTaQSTK9JhTLwLzwjYH6LnciJq1b
FPyaK+BlrJ9IgVOrMabsl9aO9grCMmyGrYHfQaHOq3Ylych448uBikAoHvzE
sGDKFaNNSeSUpJFrqYYDcMeDUX6gEoh1wAO2dA5a3IV9jLrn7nX2B/KfgWwP
ACB0oFL3ALKFTzDG+EwzeZOddEgtCDvDeXehYEwb6XxodO0ZMQI08joahT5J
2d2oh3iQjfqzmreqzX60VIGeVWWKp9W0I15pPi9CYQPUZdGBBSjJMPTOQLPc
igXZSWJ1xY8+oVPpREp6KfpELHKZjqdYXQptSu3fKN8lPCTMQpyeIdwPEAi1
YcfwRYjMpX8iVaN1gcuPGV+masBd0CRoFKuCIRInzeac0Z3Q7QvNm+B8iber
TTkZtTZYGQS+4doEvCbI6DEejcdzVuKyXDENVlLkFUJej7PhNcXze5j0/ayY
NZ3OI3/ixCN6iJ2SAJKUZLUlrccnQZk9WiMANQJAAZf5AaSRw2VIAKfWtUdN
jqzd0FxWJZhC5JnAKtDU46iWfuYhJWn5U4EVT1ZM1Edq/SUy2sPnbzZz/3F+
p6870BfhQ0AbNuu8g5+YtCBGRAsJQycLbzVt0eTdfYbgTvp5P2kNnSycv2D0
CtFhS6XRb0mFj/Yn51ebxYdT92Hh9G390oWSqhvz9mVLVw3QYUXM9OZ8OOiH
s6hb9w8RK0qrZm+21vMOqxnySv+FFjQMvp2p+oPPwz+WJm5KBgLskINyGXma
bvfbNIi7NCzv2mrG+8OlMLk7KEKaj8SgHoZPn1nSrXkqpN7g9zRmhqvoWSoF
NmcGTl2dVesO18kfnVtdacGX+3QsG1NOHx5cMLM+0Nj3ar4s15sm8GDgJln+
lEgayXo8h3YWIesEMqqcAmqQ9LnMshSNvyqjRksv6z9Xs1mRv1pVlzTkt1hH
hgdYrmq2ibNPn+RReGKZjPTx04/LGmrrN/U6Cg3LEH3EUODr6rxRrExq6uk3
rx/R91MGwq75/gSIUjMgvLx4c/J8lD+v60uGMeGUTy1cEWskS34id92UmSE5
o3ylK4YYseCIOqcrjqqhBZjTLO3ul7PSAPKq0fiFAEFxVoHCO0lmG6f9lotp
EflOjaUoZngrqblFk3v8/MujX4kfh4RVDXlu0v4GaZ68RVGoheWQmchkuU4a
CBhWTEw8vkKRBCw6fWToo9ysR7Iuz69QBhbFxSS6Q3NSI0ip2kMJ2qbh2Kag
0ww0zTTDr4f+JK6UhNufNRjKV+5J3DGGnf+FXDfXxSzmywosriUBW0pgRG1X
0FnUymjSpferrhpJwFA6T4BjcisAqkVjoVgwputUGAwAKKVzfSdL4etDsVte
hIVUrv2qWCyKq/xJcV2JIvuSd+yEzsGs/DACdtZM0JLZOkKNZVxCgeJZwYJN
W8kAAettg1cUVZ6Sdfbbzawq8q/oHJdoOcT0XJDOeIZCLAwVdlXMLkKlzdV2
SV+elIwZnb0upJbqG9k0xA1J049Wc3YT5c+KP4+/KlcL+qP8s0F/wfeIImxR
agSokeo8U3oRdsNEgFTmT5+osQe/2EtiwjhWJKSk+nQHoD2p9JI/IsVy5Eb9
grjp83o2pTFdCm4pMxD4PLVQ/BnQtH3eUzgVciWYyABFADRZlUAWtnZisaXF
veL74K/KBTHIx6SOV5fFYvy8OjsjxvGm4oSqZ6uqxOjYQf+24roi9eUVHYnF
KHs0O+O0tK+rzSj/Ek46YpbVmvZhlL9Ep0V+Umw/1NcF/UC2ScFYZVyiihsc
5b8tzuuz7ITWiQ5jJR+tmWlf1fOGzco3HBX2bcHO4j9URa3/+SWdoG8ZNml1
VnBXDDzw+GrF2g4qQXxb13KSDV3P0VaBcjiLUGAyAKwxFzjM/j9pw/1nsDwE
AA==

-->

</rfc>
