<?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-22" 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-22"/>
    <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="14"/>
    <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>Concretely, the problem addressed by this document is the following. Each of a
large number of clients holds a single measurement, and a data collector wants
to learn some aggregate of those measurements, such as their sum. Building such
a system means addressing two distinct risks. The first is the risk of exposing
an individual measurement to the data collector: a client that uploads its
measurement in the clear must trust the data collector to use it only for the
intended purpose. The second is the risk of the aggregate result itself
revealing too much about the clients that contributed to it. For example, the
sum of a batch of measurements containing one measurement reveals the value of
that measurement completely.</t>
      <t>The protocols in this document address the first risk using techniques from
secure 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. To accomplish this,
the computation of the aggregate is distributed across multiple aggregation
servers, one of which is presumed to be honest, i.e., not under control of the
attacker. If this trust model holds, then no server sees ever observes any one
measurement in the clear, and the exact aggregate result is revealed only to
the data collector.</t>
      <t>The second risk is the subject 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. This is arranged by adding noise
sampled from a well-known distribution, either by each client before submitting
its measurement, as in systems like RAPPOR <xref target="EPK14"/>, or once over the course
of aggregation. The price of the guarantee is utility: the data collector
learns an estimate rather than the aggregate itself, and the stronger the
guarantee, the less accurate that estimate.</t>
      <t>MPC and DP are therefore complementary, and an end-to-end private measurement
system typically requires both. MPC bounds what the parties carrying out the
computation learn, but not what the aggregate result reveals; DP bounds what the
aggregate result reveals, but does not by itself prevent the party performing
the aggregation from seeing each measurement. Indeed, a client that adds noise
locally must add enough of it to protect itself from the data collector, which
costs significantly more utility than is needed to protect the aggregate.
Composing DP with MPC <xref target="MPRV09"/> allows the parties to achieve similar privacy
guarantees with less noise, which improves the utility of the data analysis.</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>22:</t>
        <ul spacing="normal">
          <li>
            <t>Shepherd feedback: Avoid framing (V)DAFs as an alternative to DP in the
introduction.</t>
          </li>
          <li>
            <t>Shepherd feedback: Don't use the normative "<bcp14>NOT RECOMMENDED</bcp14>" to discourage
use of DAFs.</t>
          </li>
        </ul>
        <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 not recommended 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 6559?>

<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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
Mj0i8gVkA1q+A3AZWVCIR+zRbOyvzOMY5idwGhs2bE3gx+Zgp6SpkUmBSwfr
JGOQDGUNbkbbAqT2WAtROOO2+YH/GFWxPXVVbE+X5UUvTNBGu4XyD8MIezSF
/iDuVyDPLMS5Wq60N/v/Hwum8tSTK6YVkfzeplW0RhpfgfQWNWF0/bVr+okm
6SSLS34Zwh3YPEUaTtKgCuKKNiCDmLJnH+qFpmn1qH1om8gtz3oaaMeBea0z
QqOrDT+5b828Hrh5bWGFD6cqVptNr9L50aFMJE6pc6Limn67O6aycG510Tzw
ho23LX29VDjTmjumTbkdl+uWfibtOPoNllTZm7df0hDlYhsCRhms8Xh8O/Ca
pe10ZXwi7cKjnQws7pTEo71QVd/DnaA09MBHocJ8tlroAPpjHWuVJTb/DZQX
kirxOChHWdfa4oCTSkzn8upPaHyJw67Vmu3s7KzDh6C8DAbu4NCtoCL9+uVW
apuXER5e8S23AN4PtwCKOpYJH1jH8rYdS7tuWUPTRhct2LCadiHRete1jrcm
IKF/9FNW9tMJc2AzTFKPpErB0Ej5kVkxqHDlB6gphPCERtF671Ch5JZr1XAB
XQmioerwqOfNquV1s7jkXBWqVgUqBIHyyIBS+eo5Jx2TOWVq2l3B0I0+8/rZ
EQSheLERgiKDCDJ/ePXk0X998+XXmOL7zCi+xZysUZMKS0yUAToe2aowUmb5
RhWehqhp8/JRgdYq0I7qkqZMDY4CNDqwthdPCkQbBwRJfjrjp4kwHT6HneFX
RjYVq41SraOyXctpO/QWxde4mnkJ0CQ4mSPT4vHRybfxMXji1yYoXQFzWEiA
PphWQwAhANQWcxY5sq3nLXjm8OmpaNxnGjYOzlztxLgx645Q3zBLoqI8O4iF
rWYuVssLlCU4BcguX4OlkHn4k9DGCvaeyp6jmYJS8WQT02l4EAV4nqWgGsD5
QTZjtJlEg2So9epqvoRIpwVCOr+A0ZKlpU7Yoet2bZNR5lQWeUNuu0uMA/Ue
qYs9YnGsw5GhRrRQ5KU1W/mRnleIfZA3iVmLkDXZtddUu4C3+r8hbpPvXjhd
MmHxQfBhxtnO6ir7rAXVgCXFuoIcFTgT3AcVUqZC81T62p2WA1qC6sXAeJLu
qFScaoja3jEFQfd3UXp4hqFuuYuRI98s10jUzz59jIWdGEZoFnaUebGHUF5n
XTXu1gv0yP1DCysUdWz+LJcSrOePIowkcTGVElOShRTSB6EY5XJKkCMAostw
2cwbAbByJWspwxVjewk8w8KzTckKD/8kJAyuUbRslgQdDtNfYNX7BdaIKhXt
Ues4yv8G80qRG48ecP93WkcM6KatFp9ASuNLStTeCcDHT+z91GYoc0uDV7RC
HLykrS70LUke7qrTpPDqJm5318r4lFLW/47G83Brk30mAtbSIHng1OetB57Y
To9oBJua/cqBq+U1/Rhi820wKaRFqd3YRHif1DOK67/ePNX1+/MZpqk2Y5tp
qse34i+2mCCzmC2PpR8a8xtd2CAABS/gz+5+ef7xxPyukU4VP0Pcqr22QcCN
vrnFGnLVPXPNKTxWmOR4jP2Y/QtXa62oEi3m7Q8OKy+3PzpS1mq96Jd+J4S9
StsPJBIhY+eOikH4TPJetH68GlstYdJRXnVSks9zTKyLLuBnzq/tbphgLScn
gFpBiM/v1XbsRObvBuRHhPZaAPQdVjvBqmYMKqnx/wW51qGlDnJRg78c7VHW
FeH1o8TmojN89Li6Vf3C2oN9xanhVKJEAOP8IpZD0PPf1tX1x49opsairJCG
wV+nyoGQcNdcVVn1bglJGOCOXDZYojJoHcM9VAHItxJ4ItW3RfQ39BtOfDNT
GoDXJ2HPweyvsCUtbNpWYWBvmmudBUeHUVWCoWxMaHoocr4uFjEIy6MPMmg1
rioRZ3d4M9f7PEQHgNndcPG9h7BfOALQ37oHKf7u48cMatRUY0qJSRc2uH1d
gzTO9e3rGhAKNu5MoRqP6hr8TE/00gdHCheircJrh5oehT+snVdYLrNw7Tgn
0Sn4q/rdTSaqXKp2nCNlq3Z8O4RqJ/xhw7xsAa5wfcIfNrSjKjH57YQ/bGjH
ahhFMB6KI9+wNK4dLfIUuh0bLbixqWTxgwgwnw7qOsj8JPL+J7UjxSDtYV9T
FZIL+YR004KhvxA67fMvR9YNd7Zll0tbNXIHXAzDy1lzbdToC6aHO6P8gAqk
zRhlKvVUZqviCoDUdUPgxxVhO7+2kI+ghTSGIE8nVFXSNw9IKm4rFWSZ7mce
1PAdxzSkcStRqdYRyHVxM2eOjCXYIGG3XjL20iA0UZhuYBRcncjym0QRcSkk
jPjUkro6AFs54Ch5Mh7CME+h7NV40bRtZmspKfGNMalN+2QHeoOlLVsA1xZ9
M676l+kcydKfGjDeLLMxnbVnWAeGKWWoS2RcFeC48zkSoCxt8PfRoMQq0lLc
F9he+FW0U4oVGjrIzyFiTqojAcNGnr4QSTgBiPMt/nCBp4AnrZvn5ZOc68yZ
21AEWZ0tsW4zbPmcOXn7rTUFcahm0C7VM8faiJmHaGqNbRzW2+Lx77Bv4SI7
iPRvsyY0nakq7DPDtLdqiwG5uPQol/Kkk4thplW7tPNwcN8o5kEjzXglDXoJ
qZkUDRs3q9nScFUSw7NHvXcQXvHOCNO9d8PdPonHr/UmW6QKwLbVC47ifq8w
rxXkQYAH/P3CZzLzjLQPNvYXZ62hTIyiVvAI7hcYG4OtUCWv4l2BJdBUfZsM
S47u9QtGQb9oDIVKiYo11SiEyUeICYh/A9h6kEVsOsw4FNv8NbYgdfYS4vgK
5YK0P7wr8G7MMDMa88+hLCnAq00agjdgSdWRbhqWhVqIEs+pMyhLBmj5bcWk
/6qha07rVXBN1hKLECZuNKZCzsR0DcuZubtBsrC9RGo/6Ub5+zc8uxlKWS0s
FWFkdLmcZ4ZcyNHmsaiae/bUlKkjwXn3100Gb0sPTGZGfVrXGNNwZnfIbYWF
saCKfHKqBTPk/kl+Lx+NRuZ/7Xfk1RjunpiDhwqm93zfvqC+dq/QDek9lzL3
A/ZnAGwy1KZEzAZiSpIW79LzIS/eDJeqJsouALJEmatF8IgViBS7f+QSUGZp
fmiuq7eEsldb+wS+UMLKwyEqMrv6ibVv7eLnqcV3RXTxduGRzbDEKtje4Yc2
ecs59UYBTKKjQzM1o0OVyzJL4pjA5ppDin3wlvIlvzQ3y0KgNAQlsbQChtOm
QYZopjez5qo24y6MJt4St4ZbM+/90i8y2SMBYvTZQ/FLMTQLk5jbKH/pWnbA
khmWaTUjNdr2rKKqDzVBYc5YnnCvcQUNWo+M1yNZxiVBsFKECaeErmk4TGbw
UhgPDQGGl9QukLvF7pH1YAVchmmxSJJ0fzNFSxTFaCxP9ARQIqQNlNYkXgN2
Z15SQEmYz6dc4V3qy/CqS31qaQdIGlITAh19bfNnBvkFVskMcZcM6R24faeV
NisHrHFSmWXDEMHgLLgS12bh7gPHadnXP+/teiywQMs52F5bIrXQGtnmyFoN
kyIBwStpr/J+kFKGD9NNyjEWcAmFIegQG040vkmVsu/bAgUteg0Vm3iHQ4e2
1JdmkpLgya0piXNExXSCk8UXTY4X2ZgCJCB94HhxzCpC3/o2+U8KG3s6y88N
c7F15lE4ntYXb4DZYjVUWsEpCbVwUox4MKvwtEo1WBRIu1gIHH3FgAw7G1oG
ZeZSwiG0AjuewpEvWAWl0Afpo26BVJ1Apbvy66WyaPUKJJa9QL6Cf9+9u5cP
83fMSKTQrB2kX/g5yHjsvjyjfvYDejYvDOFHUWzMhdsX5ioIzol3TdbeEaaX
Thr2qSSW3TIbX9A0bR3CSE3FQ5dFK+pyHPRCEmuYjcu5oVrEVJZawkhTKE7o
1A1ZBzEOaueiNMrrcmekvGORzAhKGEqwCIZzBTluwBatTZIxaBzIDZLeCK1X
k8Uyp47DhSYIIKwNzok29SxjSZOKL9ltt3VkYMzzBsIjaryz9CJKeTOF5OvB
f1FbBKKEds9GkIbzNHiTcOAys5WisObXEg7NsgkzJuPZQXKlpcxGGjbNzCEO
h7eINwLb2xlYNc3BTp03iqNzKETm2h/EdWIJCXhL86tUSzl0VusOq8nQGba5
OArQr6DClucv+JjjK5M2PlpGwOs08ZMMcF5dgxzQ4gnlAt0JOlQnPAjWh1fO
VIX5AbOsjJzYvaUiM4kSeFKKbF1hM3NG0a/yLbin/Kq6Us34Y583mkUZ3E4e
ezM31JFDDwmFLMPS2lIYXBUgryDdVQpYvzEX0ch5VLE594g3+tEw9CPzKAiA
w13M6n9KZXNKm6MK9MPieWFLqziKh3yTzQDg4qxqNLZggZ8FmgHANCY6Hd0K
pyHDTT6r9Mm3WoGNehwgfFYtF5+NZ2aG03Jx4ZWz95hdq6hFZqmFfY2XBfGy
Ya6Tuh2v2pYORodj6Stz6oB4MYh2H2aGli1vrUVijSelga7oEJmlnsgWOMuC
OYPA8BaG+Qkz9PSrxd27z/Vvz1P6ldVzuJY5itJtFRYZHIDcaCj3FcwO1CSU
4NCEgDFCavPpRqDstyAJT8S7wBj02pE4nlvm2B1fJbRLDJEu7mhC6CgFcmep
BVAoqSATSaBgI5vCeRwoCwhSAWkAz2nx7viXE7aOZNY6kot1RBmZ5Igi3pxY
+oCSw4nOge4vJlOGqQRSa1m9WZpv6cCeE/Kc6xMUzqDqcNQvqQGZwNyJ+YuE
NsC21KUIpaYd1Kqc5JbwOi9rUH7LVbtM6CSi+zqhTHgOeFGl3iXLnRIJDWyr
XV1cVOw0Dcj1q+qqXFwaav0V2iZACLCOUleQ4XxavRPURsKoh8IBICuKqxOD
3WxNCRlfWn5tA1oHu+OunTZlwneAG3CLa/dM//YMLSH3FNIZfMxTvWf3EBsd
n3wAT3Zc3gf+5WX1SX5iofeBOeoP8Mjfy/fozGsroxjhSw0xWDwrMrY9c8Z1
fOpU3B+88Xz4rMg73iH74YM+XzgUt+0AiNpV7yAqARBBqE5nyWbXBR+jQT4z
b01vApVkYLERnVxGVPRamAPgTVYLPOv1YjLwIA9RGsZ3LAUxoxebDFQNN6Rj
z/yPWfsBiOADWeRfLCliwRz4ytgLS5CB4+iahkz1qxkf04xWG4MrTIMUP6t5
uKtX+vz1a+X8xnob5tiOjdQ7NndYU+yoI2h6bo7pwpoTWHdmPg+n2zQ/PF+Y
1iZGvKUR9UjSwD+Gs+XS/k6Z5p4w3yUsAcmAip2EQQr6ouW0RKXavGdkEcDh
XAK/7yuXByqsZT1hsAuqlVGfe1q2NMLeApCyMyyfcWYO5nU9Wb5x+u+yvKwU
vyGzEdtjvD3jRjEgfU1niuIuKlA5JmLTEsoLT1lCDtg1cUMJ30RHYzEZz3wy
7iGLPBKqF4jY5NhHr6SOA0gZ8ZNerATVB2HScgu+DhxW4MJiYncJx/ZwQIjz
uEIs4boAmkSYhXPu5o+R9ZMfctvP+tLinxB7IeEX3x88/v7w9REns32PpABL
qH8wQh98B0tKFKJdWy7ejlPaPH108OyZNGxW+QRiF57bu4WmELoozICtTj5K
tClRCl6RdFrPZyi6pUxkG8bpR1ColsM2I5jN7jYPfz54dupCIVyjYZtW7SGD
6LpxpppLjlNimPAwdjacDHdQbb7mCIDtV7Mj9KGjzRBFZO3ckbTvo3B2/OSk
0G0+Mgzd3PizX8BYajUP4gsdPIFCKziM4ueQTLgbjsETr32XMDDOS20UD8t/
YWgDB5+AKN3zS/mkYFkJJ0RgSwSNhH8sjLwlIjnjr8TeeYg3i+Im4vP6GoMm
nL+5tHfbL9m5j9zrLYS3OWXXmnFNEzqoqnc/qUsonrhDtqWd8CxB3K7vDgfG
q3oEHcIajzf3meVer4sKzkTU6wgAsFB04XptY8zga5F3szkQ13NDpAVahcXM
TW61pdj0ugI1rN8jz/W5Qqx6crmAQxdrabGsT04zDINhHRNKCg+MtmWlqCxX
scNGhBHzmzi/7rSqxEsQzwHch0Q3kjKyXKoEjGSNSjEugPVFaSGhASLwSMKc
TGtnlbbUIqfUExnlB6watVRAjNyMrV0SKK1cTgVobYkil5kTqfaFuzcFLurL
RQWmJm5xH76iUKCppZAFbGGR//jT0WtoPwx/GyXfcZc2ejMIwOP39cjsGzB6
J1bq89G6kWFEkhHlzXVATYvHy7fBc5TSlJt2uWnOyosZjD5gVDB8dP/ILlLM
USABDDi7dmIFB7yM5ZJVKaKQZsM0GRR1Kg4oYqWdj0X7RlQhd9bIBgxDBxx7
R//E3OHuDVZXDo1jg7wzHijD+zUKo03HyFQKEoQKXAWf1lt5kcj9waunr//B
bJkVLbfRpCNc11iMIIrX8YdqNo/XofhxNTVa+g3pxTc0CJg6TnBvhP0+Pvz+
1eGh37FiD+zA8TQ853IRnxKLz3C9Gjmm/pvKYkU1A8UTaJup3kGmAt53Cu4I
WIEbVLAEME2aG3fJM6PB0tHxuT+ip/sYcU+KgEXyVIH6MdVgHzFr/JC/iSna
YV+nMNVUh/jDGmA4WX7THRoMzIS8OfQLiQNUZ7/1ZUAOrFPLbVpbqDxRGrPd
OIB/dUGlGxfeS0QVN3t0tZNKsktreNNcGyYzu8nWSO55zxP+i75/82eYA4+x
TxSbNMsw81xNFHkDla4AVVg81mKjEOYHHIkjSo08iQd2hnH94GuegBPs/AbN
/IsJimwL9lK26KVDnu9mtoxIJg/4TivuERc+3R8kno8SdHph3DaVe8rWdCV0
uhfqEAWYMg7irQlmofVTCNTisuuw5myZR++MzdcVxbatrGEHPfWiJjPLFe3Y
OrQEys8Td/G7npKR9nOlYfjXhYA5gLuQmwXcX7msiopTt1nAXPZUCbmwdqBR
eGrMSA3IK6CQhJVMjoNHAXKuDmf3RtJzQTZ99KkllC41EgcKGEj9G5AI1fiA
N0TQi3YJ3BtiMnUhVigVOoQEolKxfUvlvgRGM8f3YMYE9GWPlj0yJLphPJE6
hewy6Mx62lTZJEi4APwTXCLTlIWF8fVfDvlSik8IBrO66l2MkGdTGj8cawRW
YXEmArvatmtKCUr07DcFlSW4QdclPCZw0cHdz/+S7zq4tKAtAeoP3tET9t+w
aGecYLHdkjbndjJ8SQEcF/5ElPaLQX5ximQb8dj/Wc+96Q30+hJb0KUbTFtA
nZHJ4pikLfsI92kmKzt3j9mBemlE8tAgn3vQnHydfXT+LWceoeBHi7BrFyE6
R/trh7/bNcZgKWiWuB6OQugRU3RqOR1zNIwvfo4bxGPl4EtipMgKlVQHFn5o
REJRRl7TPESADz9F8/ypOTl7vV23BbxZOPpoV+hvEu8CjDL9sbOmMcG7n2G6
ieCa5OS8UUIcVmI4VAUYNi4JufS9QwOBIb1EnTuwaifCTYj+lWX79iK7l7LQ
3ss+EE3r9UPDWB68cI+//kD2dfvon/FXqgGMP7sX77mfnfzCD33ISQPK+U/z
HI1EP+S1ZPv3bXjrRxt/PpiVSKzFvQx+yvO3nIIDS+8seY8kBqv1yFaeyt60
pr3uR1iR7XAhc5Yup6pkW9ne0s4nOH2qq4wlcZ0tpiREm5aKLA5FWxV+h8HU
St8EoUqkc1ZvTcOrhXYOO0vQgEtN25DZ6Oq0mcPBt8lV4PZBzcNFIGvfUXOu
hXdn8EHxIrMMO4E+gehaLkAWgkQxEgdrSKroL2pZBYBBgNTroIZjPJeBlhZ8
lSzcKMrtTS+3Qg5CsirzldhHb/JSUwJQso2IXbdvaId3rhflfG4ms+OrVJjD
RcaIlzBQsUjYACYzHlxD7NoF54MAiK9B3Ujro3r/ntodYm9GOvv4cZQ/JqQ0
Oynx/bGnGBsWu3pxmfAei8HioiCtd4RH7/iXk+PLExDHnxu+4a21NR9on+VO
wJPaHfId69V7YthUin8N0GWKYVjRWaJYFUrNhkiLEvNC8KZRl4CisMMzLD0+
gVdNL4PimLUOKM/iSFmKUXWHqlGTpB7LJQ0YKQWQ02Dl4AGwIhvhja1SaCun
F1ov7sgbV9acQWQLnSu53MyTxC5CxCtc8U0g38SEQoBH37+hfnCSe/LnhCMk
xnz8Ij+04Uipe8l3QOZnA5PglHAD6mraA6Ws3wF5wpfIg/8wV1duBFeGRFqO
tHLT67uXnMtHe3oGRm5w9WskE8VyKMkICQE/7GFpJZDfvB9veXhNMl5804pX
ScmJ6CKh05CtiK7/jGR0wMKHeP+eWhTUYi94ajS8x2TTSRwvq9vPkU7AExjR
CUHDKFWqVmABrrHSb3N11Uy4tIahp9p3kM+nKwrGFreBagECASzZQsywbbQN
1UCSX6tzI6HpdIcjSZoa6eINeqfoySeyifgcxO4wl0Wep0hD4QwUsJSqCUOS
zlb1dOnBqLifhx5pvk8WSwh6ZdpEaLTAYHkEeQ/ifFULue9UckS2P/L6gaVr
V2dEuiBSf4llp0sqAA1w34YOU0bsSupb2wsrXamd9lt/WU700qAjFoFwYSIL
XEO3PKNgR9NkfKaFLYhFcfvsLWGeF/bg9Mrp/E159+4lGOh9yq3eOOeauIZx
2oQhfJFDSs0QgbtAHJQNg3Jjtp1hTTTXSVg8nXXK/on/JpEO703IdNz4MtGO
ew9VK/pm6NKjMTXqYjr6dnewn/y7Gz9o/bqSRL5Sv18oFdNtgwtxIyFFjHDy
nnoJd8yZ+wltF2F/1ZL34/VQTRzvr7M+nHhFlkhZSeqMWF5ze42RoF+QTYvK
qIfYC2D6c9KkXKyPp1NSVce+1tY8Le1DWqfkp7VOaTtWGuHbT9Atnfns99Qt
rWYjs/p/N+mZARKQVS6D72+jUYbRHBHgLLowkl4vHR0qrbESSSeR56VzkDxz
ttZAJH7otVb5ZGG0wOK1kJqg822AMB51KHoqJP14wi18QelCq6sqbWX18/z1
8DEliVKCqxmsJ/szUDNFHdOtDLrfmmy91kh13aJWoH0RVJVvNZuAeGC6QC8V
Z2SFmUuJTmCFFBUFN4/5P8b2JQ1gnxTh9Pt1q/zrrLCjWxJfpTBx9iA4f7s8
RMozgKounfkMFnLA8dZjT4TtuQgG82c/IuvZL4zVqpZ5Uk8YFoHkd7eecrby
hBYqroSUEqrWIaGE5geQ7+iy4bX6DcB5Zc4asXUxFkiZWd0ebNKhKVuA+Bw6
5DZczFBm15OBvEwE4jZnUWdO05P2FvH6aYtLuPI2TyuzPlB2f/ph2K3/loqH
f1ZeUBj9WWkuuvOAUazCmc+uXaZeghCZC9DqzDGO4UVATkQBrK/qabmAPFxA
Ebiqlyqudu0wRpkyvJJ7+20VR9d4ef8AVM8BbabHswaPE9pRrhp1BRN9A0KK
aWcIY6DwcjJvjN80AMVhg7ZJrS+WRooOpx6Sr/7AHpekdQMucAGHUFGFLupE
j46yJBJBx3IaMnVuFDtz4syGujh+x7bM1+/fPyn/uffVx48ob5sTCA7IZkEk
rMk06bG5xLg3QJgFXYBAnfkkSiZwiHo5L1smqEuMQyE4vUzh7pEYDb8KdYe0
CLjKzAiiLcCgp+cvMPAJc/UknOJdNdHrQ6YVoejZpFOXbT0I7OQ8wOdqqT7k
DVx2sfdNZheS025jdmnOk784N+C2Bhn985oY1d/JVpP/1Op7wG10iD8FrksR
Wqk9Maf1zT+KBSTNP0Z0wefhOjxcb/9xi2cNQa8qS9q1qiIu4GR8nu8I7lHb
blv7a2rSJ9vbXKJdFYi3Fb85Atf+gg7gBdXghOhd6wGm8Zmvg9LPb0GZgswz
eQN/9YuCHb89MR2aB9KGs/C+ddnQOEeF2/DD7YmgBtIi7cK0BHuXEEqlIfpl
5EG5fqtqlV8YYmBnj9YyvCHqIGEtSs/Spuu++B+1sb6vnNRNknDun3hmq4Mz
qLoLaaEUEajIXSCvhpKDakRfIRVoHBO5SVO1sztQuo3Im2oj0B+MstKuIA+M
jOEUo+yGWYoJRLWAxhDZVwhIqjHikB5HiyFGzZI5xen5gKqW370LC+Ud2N2N
9ceXZIqsZ0tvSDSQO751sGG0gzcuc+4aTttwrUAmZlw+jVSXmcEMQMKcjW9c
ZkHM3TmfVLfhqS8jTGjGkVg5IRKEktsU6B7RS9pTs+awSFpfwIAlwsxrVjUh
mWMWcghBouYpGaZlEQe1H9WED1lOsobfXBnHcvjGQS7OUXDZ+n6hECdwhIJ7
MWtmNlre7qVGtBLZkcCO9OZSAmtg4eOs1odAdUZoT0Lb1BlWEJ/Ym77PlroT
IDKhWYvOUtBEj/6Nzzs6LqsgBj7qPvp9BOrNbNLTHfjFw+XJtGnrMSwjMHub
YbPOssVYxToYAmw7tgszrlR0BNixsCMNXZy08Dj7jlQX3xg+EGM5j3ZyNu0k
cJ7ZRNGm44by3mEadClTuEpKf9FpIxHdLc+ldonULTf6ejUnTLxsI5K8JG4m
2KEiPGh4IWMACdgRrxwk1RExZKk7qynHOq0wHPm+lJfpsIrFIbfC3TwrDqe/
kNaQSXw2qnuqPbE8rG2X6kkq31229NEMAmOEkDYPUc4XaZUE6+lRyRX5VmdM
wWx08q3Kl0ryD9VvF8TCWk2EKSMVR5WR+d7bs6aZijrwyCYi+UsToT/h8z0j
SblWnSi7q74UCflt/odAGHW8nYnTE3O+Kic7QjyzOQ2RtMeDZCjW4Mx26hXE
XZisL2kxg3cjM5jl10n3SLvp2kSDGCXiDj25UikKis6nlpgZS7jQtCua/m+3
QbxJ5GKJvSs0jj5soW47kM6iXeRvXi9WVbJUw89So0mKHLqAZIvPlKzU4D8H
i07F0GFpofATUFcVLp8vyxZYOJJzLgxFaTSM5ErVqoIc1I8fIfY/OvpZF579
QIixi2ykQk0ecYOHiCKN8oPp1MaO+bUdxGRJpkoQWzWyEQcrIa7FOYArEbIJ
3I4hPyeQWLQwjwAcOJ3efqsyAuls9ltlsScx/wH8HeuAfP1lYde/hbzfjlFY
FACvCZwmpQIZUbCnoQD6iSa4vo7XxG6Rb/nRGckvfVB3t+bWr0RmeDl79sDW
ggJPYCQ5ojgDgcYtDpCkCboqU9BVlv9HWQYCPLi6SuTBoieqjbH7LBpiBMto
89sKD20hs6Z18wYA6pDmR2gYEA6isrekTeriyk8wgtpDtl1EY1iXZEBxcrTb
eA6Oa0ruNf9jmBqRpRRAAqjyYACARD32nuvYGfhpl76WbBYbLR6UlZRIemXo
kSdDAxB8L0ytM/OdWYOXxUZvARc/PQX49dNT5uP+Y4qROsINpB7+69rgVB9q
wUv4SZoG4cP0+1ixbfViXw0Q2UZkwfKtJJ3mz412zDw/3WjKxD6NIAXouw+9
kP7j+ycRW+sw30SfYxi0aYBWzPzjpB+vDvc6tM+4dbHpTG7Z14TOqVYx7ts2
w7lI1AhJZiop6bQ7K8kG4aum6X1YFfNrr6MYMVWVWl19BqbxWdjGZ2Eca1iH
mWqPJZ6r8p1ezZiTfAbmsZl9mAFZ5gFpHDHvaAFLHsrFGiJ/xZmY4Mq5gHYw
DNlomkMn42RoGGWw4IC1MKLsBdS5iLC4ggU5cSBVwS+FDbGDFhDHsOUSToH3
5LXtgc2KvoMXZW6puBoqfaWf+UdkzlarQMGeHBXIIRvEehwozPAyv64AqhgK
TFr22Nr4cJCrEFv/LIVLFq0FpHiCvsgoYYhVJkoAdsMl01ZjwIoHO4GCy7pu
BlQSFR2ZgBW1uDH/WeKFhwT52vfSYuvULObuvmlagJG2U3MsP4MQNhmABnSO
9myU/43Nl60dMpu7/WJbGNflw2difRiBzfV9vFjFWIRWMx4frqRzm7AQ4Sw6
MrgtoCufgWfcFpnlkxQJMhp0jjxSs+XCgnHDAvP5IbAE8Wtlaiho/7YCkVPi
hkojF7kIXLfgSOsSjtD9DO9R4EEYzljMLZYewUZaC7ret/tFtrmQhgXPY/FK
lGgN8SJDzETOcpEFyGcYHU9Fse+YFWt32CarKAUBTSDUmQVtHoggx9Ub7BMa
DM0azG2RAj54VKVgYAeSJYICzGCGrio6DYWMvRx6kbSfN4v6Am27/Mo6wwnJ
l8ASOqXL7cXBT5LpIkJDLH2tpCc/wWaZL4MGRubrU4qy7fX9ZvgF+I//Q9BE
3Kj/eChK28ZPUs/hI3JzenBsh7uDfPdk4AbVD15UQrl9xn8ilr3dg59BEqY3
T/GqkQmkmpzWSedtQs7USETxC8HSan/uv5mYTc7zY7c5ILScAR3Cvr0WzbPi
ldgkk+fHZyd95fVw4upnkKePvVGRPL1pH9ftpax0/O36zYSPu34n/yIRn9J8
N5/egAg5BxMwyCAROEmgoi2QnN1D7NuXMw03sVi5vngwCDAksIlQaqMMAq5P
BamBUhhKA5guGSAWGiBr3IjWPIE7RZ8hAkAYeeAvULxKfx2Sw78Ev9Nrf46o
ZOoh1vp/fPH4p2c/Ha3tJvmsrCtY1mm00Ya4QxG6zXcC6X/ZNCSt7/D125aF
mC1anppFP4UdOKWBPMz3wJffwzYw/XrInBCk11OWXqPGzVOJ1sRw8tSvywvp
j/sUGmr30LB2FxjLNUYI9E8iSUTWABwcXQdHhW+ynw2jI8AN97Yu4XGQRKgR
gKU34qURRiux59stMDufmIK+nC1HHa2cNx4XBc698HEJ0/Fja/S7ZqnUUq5p
SVLYRFrycsumLp/EbpXrj18R2k3t9XAUfzFXvJ//b/N4P0s8aofhATpI1nWW
OWL3KZSI20nwr0569MSnRI8rokQ+ySGHZqRXOoWFhUsSsyA4rZOa9gsmMYTG
V95YqEKoWlOTUzKWa+0aCYWkqWH1MxtDw7K0lJLxcRH+zW4tbfIkPNcYdTUd
wGgx7qoyrA1dIz2e//G+DEKbNqW1e/Zw53/+MxzEu9BSlnxEDR2ek/Zt8/qA
8svrrWE/V+PPYhDr/HwWS9knmtB2977Zyoa2ZuydtjWzcGJeo6MYKTgQj72a
XfJJ/Y2MbmvGvtEaZ6bABrlaHJCkHXdY45ztw1rl0KZAyIRQzMxBLu3nBc0b
4OBD6YGMIoVeniJpxcs0+SLj0dvKmQRR6eY8Sy+2Qfp2GFBc3EloY+xBur3N
0NDEZ2Ar2YJIcSKtc6PiO4yHhmlBcFWzTTZGqur06vDRix9/NPf58DHR3WWw
lLlv1ED6inY0NOvbIEdeJCI3bSEI9rBk02k1HZptH2K7Q3qQMg18H5cD4aTz
lN5Gywd8Q2fSglZqyFN/hGQBCl6ijbKxOdy4Fbbzq2bCPrjQCBnFFGozALVz
p1UCvAMgwyNmJlyotDJr3LXxeraQLZZr62MNIND0ZpgQtWwuKjA8dhn8rKGu
eMkbgh06TA5ni1MbBk5ylQfE/LkN6im3qzNVGdFqLOzaNG1LkxxYZBpuOWYL
kyjAz9+YqVqjl2uQ4oH0kBQyo72NUIQHAxTsKVVwrugxNjeGrG6QmJoJ4CND
tUPsLpeyVV0jLSJHLVUdYlRJ5bHFvA7EKoFQr0WzunjjUOPGrqyzWiAmBBiv
hTI1diOAeBjK5TzS6j0bzK+MkWjm7N7TJanKMFAsXIOk1y5shokc43ouqFLQ
0JNnL++0FObjEhsYW0dj6kgiu4sCzUh3pO4oNg3PIL8ApddySLK5CHc4dzVl
MEElOZeSiKmv40g2neDHWCA+vgNCQ9ZbvzsSWHR8IQQU0IajRj3KX6kCJoJP
qmzcLmZQ19bSjgy67XE2SU2YRlU5oQvLAQV2sTBXSwcU9BHEZ+fccMsdp78F
0QlYD1IwUi8Eu6Wt4bFyVjWrdnqTeVGPeDy1+0nZ4+NpudiFG7yFmSuc/MKF
6oMrJJyPpRHKju/hYVoOa4MjOBLJxsqrZABdkB3+DgMemQo7bxGBz4S1cXHy
+ijYMdQzAufg2O8s3h6sC2+zVHGkqQPthqDyyKDCO1TfmVPyHlBDvpbpOwG7
ijGztTgM13ozto0aYWGUDPu2xMUgV/+0Rv5UJAd8T4wWNUz8O6V64g9a0HDf
bucRiEMUunRi+1EdJX5NjTLxWDRmpYSJpgmfpwo8dKnpkewOCM+eC8/aYuBj
hU4nMjD0yhaiZGo8azwi+JNFf7RQsfT53dwleqEBqUf92e0vcTelh0FMgdqU
9LQ4j4y32z1PXszveS2RDeCPf0wPq9sv47XpP+VdpNQ8I59aNIfj+yfbuHHs
XU67BCJzGHwodHQqXozIiKpfvPdwS0+Qfy7jy2Y6/HUOhNC6ZtfmN3YU3cJP
lE5ApJfNigU5iirrcmR+7Pkpi7WzWabORpguZpp2MzmuT/xfCRgVCup53xPP
5nm/mJNpGQIHE0/BEXpuOOYJwI/umf+JLraH7BLi+MRP70enoZ5NqnemnzrV
urm0v8RvnPNLf8asQ9jmRLvwgZ/EYoyxa/jeSfSsb4ruasHf6MREYMWOfzHz
2IMgTFn/u66Rte8AiusJD5S6HKpTFPdn24cNDn2SFoI59Efe6vq6dFEuOWAG
2w+vauSJNN3/qghBeSNBwML7kTxV9n2x2Efz2t49ummF4EMnS44v8IX9Xg27
2dffpeSZfBtiSKuc/ouX3M44crduIJGhH9b7cY1P1jKg2A/9jlyyuF3v0PWE
fZwkDc9f5EfmpI9FH/QF5UdACKSQ2Psvui1RrC/6Vi9rXVAlT3Os2zxszs+N
NL28rjhLypYwAf09Kaz3Oswr/TzOiWCjhIXN1eXjXtvML6ZvYGZsb67my2ZJ
AUWgpdRYltiB6eDEMvdGhwmPIug8qPAktMMPhmy8BRsLKTAEi9G+qed2UX5+
fPAkLNsQDDujYEY8dYOcakKjMcyoiZCRilrcAnI3zLeqApAracaotcxowO5i
/kOlUFNbAKszAO0Kq33lbmF4TKpKkleMEcfQcvKkVJAJM6EGQarMkhOSw10t
83BPeUh0BiCM1Wq2ZiVIr1tUZkEYkwNriUMC7pumJut6cGwpWwJsgwvQBL1q
5uZUUGHit+XiRhR3qklFWTLWiLWwiE3gDx+ZW7bEQAO/s8zXm+PDZOjnopkv
UAXSI+FTgGOxlb3ZhMTr8dX9/0XGa7az6Mnz/pjp6ByeHwxNaS7MmfvMHqjP
7HL6zD6mTqeSXY7Qr/QvdSNt8hvZUTrXURTHzeV4MWqlhRNg8wwn5u1FfbYS
+o/1us0xNFr38oawnCAPWZczzt/YHhO+Bbg1bEOaqUezs5Vh8UuMO6IYS3CT
oA8c4HboVyix/R3+i8RL6PWsuqg5v/9+MeoT2rMulcWvGqoN7mMa+j8rpqzm
qBMBYbtqmPOUUYnlRQWONdWcs2yOm4W5X/OG0MbHUwj4AZhT0/SQmhYAreyc
UXSXDbGZKGMKDelhaQLPfsGlGHi1ulwR2s1jt79wrj8ImU45/jK/Z7s5sobf
JtyAKlBYkPHKzNrUgZxIIXRXtp5q3eZbeseyrbxjzpoDbrFsK7fYOqeXOZ3D
N80y8k/JxTiTc2iYHaecBS2eU6lCzVLZLH5O8d3QPiHXz3BPIBm/HeClgueo
p+0M6LlvQKfDfHaTxQ2x8wO8MYFLLtmHruApdlm4fLWR11bIJXFGaI+ulz6K
f1CmCtIUbF/drgPlhDNrj364pc1eBJeKiIHbeuC6JUNJ6W4yAelQFvkWDrah
Zua61dVbJnAIPb3Q7JHg3nWHIlRu6V/wUCBLPYJsk0/AENPpaqIxIBqBDkl4
KUbZr/UVSO9Zp68AQoh8j32EiRC4CLJf5SLwUOLQup99onV/g83e8XoVj7+d
wX4vZXGHr0KjfGyq/1fZ5T/F4F7GJdYVs7GXUlzOtg2qqWipdSKw5LPa1v+t
7NxbGLg35BukBh0nG/ympu1OY6syanuGuBMxsgTDkmA47VnJA/St/xlmZoda
ItleIh60ucqVdydb2bX+Y5/+j33aW7F/B/u0Pp+/g53au09aiQPp1UgIu+4m
mW/sPRqqycrvaxKD3KtmimexlVwtwsA9/Jul1v/rDcG0qqeodnKaTrhvuHzq
sU3mYjIo/AjyodFuEB/jN49YxrZ+06jl38CqlJ5D2tAULmcqjplizH/fEGaa
xHpzVDgXtEo9QRySVFDzIAlDo6OMv2uaaVXOMsqd10DPzpJRAP5TIen1UPIG
jLGVVMV27odM0hpKQDYTfHEgOb4tTcpyI4G6arBDTNqvOM+7ZwY3M39mVHC6
j0kYXJ4eRQHqmQ1vyZXhwuq2TD1F2zKcP7ofyPDUgqIE+UB1ewU6ySUEBR++
/OvulwCHAwtP88NIw/r83CwPiPDTzKjZb8vxzSjvecXVccEfoSErJ/MX2GRU
DjsOBA2BqA9nGguuv4VJKpwoKQE2KF3bpjIXlO7vqJQHYg2PaBMdim8pfp0u
BL9ovqivVldZdCSknV49qkYDhZlg7fa4weDyUI32v6Xaa4EljOD+RHu9hrSb
liJ/PYsGTpe/szY2RMuCpXskJsSkOUY0flRxw5lbnZqnIPYX9QhpzQ6/Qdm8
/ETIzAVFOXR30so7A7R5ujb+MlsXbZ370dZiyxTkwvX4CR2mKszM573MfJwI
uHT9AS8gGo7XraAbLxubyAIMtxCXjkKXqQYUjESirb2HCBR3dbZclFAXs6YM
r6yAStLY6anptO9KPNnvbFGieOcsthYBRQRwDKlBhJYVI7RUdhavyRSU3caM
1wnrwOWwCNRhs0kl4moqIBIAIbeOiEwaWP5VphNHFX5j4wqlmgZWFbKm2CaC
FB5LAlNGFvtSZxoyfIY2p8NLNeaf7hsFSnVE/bgvIB1VjPjBm56K5jW9weij
dQQFmh1k6mAarWSU6LUY+W3Dw6eGRfrZhXw7vPhL1e+PUDYUywL5Viy9EpMG
EM4BXvsc8sGXHnw2zcjQ0dV0pYtCAAQ3yAmQTIB+pfFyKh62KmiD7fiaADIJ
E5bmV+xVr7o8Aw//3C225Hm7/dsEgu4iH2witwWXu5NUi+3nzni1WKC/BFcF
jOp3+pvHpe7dhrGp8/j5xncL46PqXw/711kok5iC3kQ22S8dpfo0S2by/iQM
nN7rt4/m1eub7vR3NYY6bpVW+Otza2ESMDeLQrzd1RIoKpbI4yCPO1EFUuUr
qwVYXNQlhvdUaPJW7AgMt2AQeNdXYWLaTht22UKBsonXZygy2Tfo71P7+0Mg
Zt4SudaTgdIqCNoOPvXjr8PKCYbZgZfDerf98X+sxZrkaxbfqaQOn5r/GLH/
Y8T+jxE7/9VGbJV3KlQ40s58ZJYvcqMq1Veu4CQxgTTtxp3dV5xFFfYV8cNT
PQf+VvaDxzWB3i4cex3q2LFmeSe3JqY8JCE2PKFhONQNRnzdyuey4wdL/u9o
1ffqi8tne6t+/rKZG5F5FyK86V/dsPj8KIAuYoiyRZh2ufhle8mBgXSaszfN
dMK2myFEG5LVRcpxf/f09VFh7TKPTDvElah2YuvjRGbFs2IINiBqx5qDi2eg
M2BTZL+YlsslhZ0sqvNqsSBYB6rvke2MTXeQWY2VUiACsd3h6rINl/9u2DZj
E935YtOU2jtMHTIMT+RSDwyZ77U84pX07c7W/LNg++9MRdS8qcq3N/kbqHW5
QNv1shk3UMM2e//+u+8eff/9071dQfmU6rZLNnPTozIBpz5j4XWdfP8GdG2I
7cEyXWD+fF3I5HBT0f4L9toWtg9+poA+LlYsR0ZXlc92vX1Hqj5pKW2eth0B
2XxcItj41XzaQDA6SCFU4oYizDUWhKqNM8KeXnunZV6DfQvNKjUYvyW8NN5p
QxWNCl7cZ6V+t8A7SfWtOEz9Sqh1slP1ZW4Ii10KMm3qjHFVHkLiu1ypLSJp
re0Zvq8XKmiUF4iHYqeamv1qxmu9TISddhXBe1NzRCqMRtd88A9w/kR+oi+g
Or0UiuEGvFOEy+lf5XIyAQja/MOHXJYd/9gtvLh9LmBBkcjQSrx5+LJZuao0
8zhaVvN8z6zH3zCQT/YB3UzLasZQLmdVVNzOv2EsEpdnzdsqkzuESALs07Hw
w6YJACvgxGMKbENAj7HDI76uptNRLgke2RhOs7gaAAtjpqpOI6ryCosxEbE1
X0KmADh4zC5iPOPVEL83VOPjx4wcC/Vkfj40CwZm548fcSyTalnWgBaXqVWw
pbSkmJK5HjtPJUDb3JHHEvxtHniJcXxPmEzlvaePXz7p7wwygPiurwjnR0X4
QvFXR4xIBqL9m9b/ZHP5rJGo8jJb1xX0ZJr7/il4tEb5d4u6OidcX/OLDTw2
y2aD1QmZR1VXo5DyHaotJ7R2B5qQP1gTchWYG0aFnmWwUzesErHfDzG8zVkA
z81VCXtPbe8467j0DIZxNbl6luG2lugfwk5nDVI20J1v8ssZOATZdwGzoDGb
PbyGZ2t/jBBTO8thL4LVNb3yiCiKc15CytEMJwxY4YTzvQR3m62jBZHUEGyt
AB/MrX1btRKq7XAXkILlO6hH7ARImVD50DBkM61JlYnx2nRkWjnnfZ9UpFTS
BHkZqwmOckB+FRQaZG/slDEW3DpRSVpWxa3C5cmVq5WOOlwrdrqWswwXjgra
gwPY65Q48cLIFjVIByLIIBmwrHRfkY3MI5qUJjQjFW2QYzlzG+aL5JI5EI5B
mB17lPGljFFFMF3HhbqaLYeipvWEz4dh3UPcx/g655qni0hErMfQmgVUqfI4
OFxb5yCDEHGI9AaYnTX0nJY3c8trE69weDvMFZYIoCLw51CkMEpuQBkvGNYI
imZqScX0OET6PBT6LDuDjQ5CvoyOWsdqpBa9a1CNj48ek86EsIX+O3cvrGRF
x9srj67bRSzPluIE6hkEmrMQcAbIwriJlFIyS/QJ8obRG0x33+ZtJ+knqAvT
QWaIzXjVtmjdt9SegwhQAsIDZx1IGmXK6AO0LZp2DwzDwQuRfTnaG+U9oG/z
EqrejzGfBRfA0FZiT9yIIa1SjgACLRbTGxT9q/Ebog3XZZsZEdw04sgWV53i
nh9QLR8Q3muVzJfvRAM2Le+M+ug95hkQ+xTnsSucFl4IRr6cuR+IdGUJwUIC
zaFomkKCJzLE1lXIC9zhxI4dCXTPKLLAhqzQBW/pTWQtNEvmLGj+mtmoA2QM
7F4fZT+aDW5sYijBZgrNsE54B0ELUfJc6KK6KoGoLOyRFdVNU8aJEteJkbU3
RhB4J2QKq76zl5c2C0QN0TXkrKHe59zBHABBP3rlO82pBbSmilNRSzoLZl+h
r1F+kFsYf41Ghcc3OKPQHcWVY80DFICoOBqrQmH5Mnsv/ApmebKCWb6dTNSS
UNQaWeULXBfHm9VqwPaZqU4a2JCcs0jyYu/uXdROrcJKai9eLQv2lD1lcox6
kl0MJDEgRyrF11zUpzOnjauYnjstopWKxtVaJiXkRbYKVxF/GUo0RCBN9nMX
sJI5G4A0KFWWmeM4HwTHYRVnph0zYzjjVr/YmZo7Md0BRT4BxAOrIpUlLqsb
rRK4kqpS6I4URliibMc8vOM6cfxhlP8NSb6VbJC1mRHkMABKssGpECEoaClJ
cIABCK5csgorTvD42UmBpTK4BVHu2VKRMZ9wRalJ47M0hqRQkXDMgdQVYbXs
BIdRFjUMktPAXai5Q21WI7KQWxWWc0FHCPKCIBSitfjD7b7doHo2gwQ8jHfp
cThXRvGPT+Gnoj8QMHTCd67Kc3mcHntmvin6zEW8Eoqg0smt7HXRiz4lNIOS
VRqtyawDJzCTb9bvM0OGGoybhUGygLCaZS8SCM3M/EGm3wFy6KhY5nPFxxWu
IQx9V5SyNZpX31ADlzSO3elKRbTmBHlogyYtLrGitsT5gTI95dshpH2QFy/Q
hldYnciM33CDBSyEk2Chq6xAAyJZHe3+nZzkH/LgB9ixk5MCtwxWzbzMkXxW
SykzQW70AGdlzUMAUL1JwW9cirgdG5mHBEkjtyxqmAofeGdHtPcdLEt38wIW
Z2Sufg9vkRHMV/Npha7ZQT4ajU4GgJ1QnuK49sNZ8vT5GRge2FWDVRjk4+W7
fSMkL8FKZJSQcWX/In8c/oH2Wer95erMKP9HcJcH0h4+c3Ji6QAchWEXLcMq
iRYQk88qaQe50AslDDiaiqKdMz3AyVuag6lh8TClGWeBwUCvXcAXEo85jp08
uj1Yfdj5Qs2o6FtZBsNs4EIBbcwVeY1IP8acygUws24D8q8p82s0hOEIqZ14
PrgmVv03wsNbVuIwa/zg8AiJNJm//96cP4Gv/1rdHFTt7t43QGfeNedDfBi2
YFji9xCNmD9rGkycLY00PhmQzARt8dXK2CT2DgxJJFvCeb4DayG140mwryZO
RTHC6nTCFFH8rshtTHNKUxZOHMoxsE3JaK27lnf8+NPRayqT5dnPR/KYuwNd
z0LQRur5YxzoSeq1nw+e/XQIgRSF28gCHwceLp6HBCvHAJGgM7h86zuxz8Ol
40eNECdsn3NSHx29fPX8ew4tVu1g0MfR0//n0LWDR2xTQ4y2jM8O2SyARIsI
Pc+SyX0/7hfp0/MXzx8dSu+wm0bGT23nay+kzV4WO0Rq7eiHg1eHsLmW/qFP
0+iHp/WEwhH5GpOvfT/XBAlatPQLd8tGMIrWs2/4GvlWjkNyuoYaIgF0rCjL
fTqnqpc5mQ0M5VBxL6QBMfnz6Iu5b2xtqidgf4LQYSJ+TL5IFtMGOKrR4gzt
ylYQGg9M67L09BMLp3B3Oee/8YrZm+bghQFffVe+LOVm2ESis9wn0gGMsRMz
nS7og1E4gpzwOiUpCdARPDzuMsQyuDp6fRJWr9CcY1kTW+fzwqybFeL1arjz
zAwn8m7ftfSjexysC+DTh8r/IG/AptdGNYuvIgn495jO0W3zUZmI6fi3bZu7
m2qL52gbg2ANOQX9IvGSTvTvagRH5EgitvL0XKb28CHtkqXnyqjKLZHgZdtz
0jkazGD3lFzv9I8MxE7BGhg40dmm0PhCmhFk3zSTdZC44CrnCMtTikTwIvWc
Q9xRKBKwMF7byW5GcnVfobhGnnEMwIM1+TOFGciSRH5zF7xA/C5L/wbsKfaR
P4G6fuiTiEC0QVQW2AyGz0YuSQYVBx5Mpi4wpJp7Oq3aduCuzqx1hkWysM4A
LgQu9LhcLAh7mIDBcDcciW0ZXp4UnnJaX8zcprF1x9oC0XJTnrWov8DYMU0K
kayI3E0ao1Yh1DnloRANmvBQyvGiaVtqRY8gN0dmjk2ODdehGMRFW4ELjcCy
mnMjRcExPDOcF4pmUTxM9Q5slmCcg+bPV9P84OVTtXZwr2H6RDzwoYzH4HV/
lBKmArdYOj/xMTq0MDYsDJ+4xedfUFGFyDHejoLH/jwhPjhyG2odwGs7xk5i
oWobWmfMP3NCMd5eqJb2NKQbjFu3VEy60GMPdUcpAEETQa7X2Q+2bsU91/oR
WNyYrlI2ncQfgLVhpcKt1q0Stu54AjefbJ24iSdWKnbXPfa/Hv7DG7q0Dqt+
s6zccsgOb7HkrnVN33lXn0b4//SUS20FGwzqWwxWvKoCbd/cN9c6MZTNrSda
dHacUWLsWg3l1l+Dfgoaphb8ziWxlEzKW66MyK7u2/xgWpctwUzd1nCSXHdM
e+xq3WdrQZOjIu/4YOrtF85IJGm4j9h+zB42tDSJWQs1HM8shQm5kMl9KClw
T1n+NqvI9mcbCJY0EmeAX5kbcbNEmV0VS8Y20NImhuxWgTMqYZjNsiAFK+mf
FHUWlOAGuDAveB8dJrPScGwPvtEvCp0hnidnCvK1B4+cdZpymRIha/hv19WA
PYhYWQTXL8NfXaFsFLTkZ2wSx9Uazou+DCPTnVEdF3KhBj9kjFtEKCI3JDtg
oqbzaQ0IeLTUA2OjjTUmlzOU2QZZ22DOS02BVr6GgBuHrgIQ210QDahMCTeP
j66HQl32nRvCfn5/N7+/l31nV9Z8Q59d/sfufZKX/MF2tZTff7C+MfnHLrV6
YDGwQBSbVu/qMZjH50Z2oR3hdcLzsHgrlBhL5M3neBLIbw7rKh4SjDhwhwXD
iSoVJU/LhZCKEAciOfnktJxVUHIdQy0Ac2+iuSSEujVXYIMHWxVDpOZPVgvc
N1JiQdI2Y2CDqMQJQfxDeXVWX6wayB/T2duZ6mAsfsA51b1AOa842/m/7+7v
7hQspTMNaCmKkX69v1MQg8lKKXpFjrAjzyHnqIBnpe+MDS3Yvl+kxGSBkPp5
AizDispQk+mt+Qptck+XgV/R+g7x1afmlBZxu7FDkFeChCZQlvY46syKIu7L
rPh7c/56tThrDLe5rBDnoWy9Kus5mRGX8FDLD4lTtGzbZlwj8PM4QYZteAmL
BOH0g6uYOceIuAGwF1KzWj9aBUP+kGTpyMNBpsIOydbA0YFoxVzoKK5aexjw
HEKY6JjF6tdYoUW6voKkSHDMoHwvM+32AaM581ejgnwG0Rp5co1HRzecH0Sb
HLmVPbZujoDPmc138dHpJc8KA3P8fPjq6ZN/nIrYB9IkNDs6Ojxkk+WGtdDW
TTcKr4n8bv4gv0fmgfhhX6YtbBO7X6/tOhrFi5+MbqxeMd/tbdtCrjSaX9XE
j6qCoTQRmjG7W8QmDi4u8ITax2wTaFztto5iw12i6oEnf9Hh6xBOsQkUwFQL
aiJkfRUjbiA8DkLZ0YxKBFzdnIOx0WLpxpX5DE28wqgaef4Dy7+Q17CxDbox
QNlujkD1L5Irg9sk4wobdU3U1cLO5vYTkSZ+BF5/UeG9dRllHZ2rJkBs9+i6
SO4hyrsKXUExHWglyx1Bm0xE0/TRI5Iwg5+ODr43V95cuceYFIsKJ7SyaydJ
jzx68erV6dPnzw9f2Uf2Uo88Ozx4wk+YRx4EjzCdcz19yL9MLAXyiViJEZhh
vRBYp4CZWACjEpcMFQ0E4jItKI34Uq/fgM0JnZ3wdKbt1qgTJEhI72i7wJns
YlVPqik6/RsJkpFHBDpHhXTgQFklBs48L+tFm7CKFL3dQX7ZLzh2iPxvl+h7
GcN0MJyMbBGsTbBhgrwGKlpA4evGkYGwtirdJIgSPMBKHkaefzT6cpQfILKq
ir1bYvaCjZuh+JYMY+8ocmsbd4mO65SygImxLRsSeW6s0fQmxxjXtZF7AeJz
ucxkaGRA1vFnGPDp2cI5jBi3DnH8L4sgTItsVgPnItXNZjb+VLJjXBQTb5bb
bjinxZnF9SDhlWNaW1Km4DYdACTe3t3SsPtL/OI780V59y6kWJ7lw/wSfxqT
7uQSXPw4JjJL2B5Nb+Z/Dlhe/q4QJ5NMQ2fEkIQIqUTzaPf8YogUtkmAFZmW
ViGEdUWFETBUElTjC1uKdWD9YBMvIkRrCWWbSUTjBi8EtkPeB+d5UD5O/NtL
/o9CTPARLzCEvAguOGSQ6fAQIhieUxYZIP/g+P6J9mbMetiFAxJQVkiVnB0A
CezUM8YUYXskBB7u9HWzME7XqrOcbtVoy3ZPPq1koCwXFytYqx3Oi51K/rAn
k9JvoF5O66U2nJIea6+R9634AYCc8PsugmZAho4pmlsd+PTAxtYhxf11c7/j
5r7AZh1yCXAATEanwCAAr1k0syUlgvuiNz3R52MHwSIPMWl1clzvQ4mi6UmY
EX9/YBjq3dycuSmDEMMwTuHlgW2C+tvjL6j5Hk6cHuyHj+7aR/FZsz9qq5RP
zjXh+elGFNBqfgFxBbbgdFle9ELBAoMGVMo0nkT6sy+n4JEYExzpZB6YpJya
IFMD6AzeAfvjjuNwu99iWLXnuQwpLb9fykHbKVdgzYO6P4ZoSWMif4Qkjave
fLGGtnmauOSl0AO19C7RTJaDVV6tAJq0YaXsAiEiTVN3wToebsuxO3bKv9nb
NWfg0i/edQlrBFcT8u0gRbyXfDVdJ8t93Es2yAffOHGjRPP+w3ho8L0Z2Yk5
+f/X9rJ2RPDGAHrg9fued9OdDXB90QL1dDQMBsC0fTnmNn7Qdpus9+XWOPgO
x+ES85fvkqccPo46+AffjjxJuz7t3GG4eerAgFd00tr4OW7ClrZXzB/tUr3S
aJnm9hohc7kAlECIMAex91hkwAE3oeXAk1HfEajm/LytLOIGqkWA82D29NRc
S9/tj/yhejc3sweYgQZ3PsYMWH8wLVk8vp8CHFhHsZyeE1Is3G/D23r3++aM
BjsLH6DNvcQNUKgGg99yrru/wVx3f+1c42MAiByfaev9m/c5dh7U19tv/Gfc
4XVT+rQNXjulzv1NbCRf8yfrefEgIiAHg/y7fsFvkyZbLiRVVlxlGCTruagU
5REahfSHIoI1f2b2bBSvkTtt6XDvr78kwLTjk0F+zIg/lDwAc/Fxe+zJVuA6
AkmIgDAu7OhkoDbSD2rClhXECoCYRLG1ZmujeCXvYimeCB/A63HMx7xtf7WL
NvAv3UPvz+P9Byf+A8cP9l0jqD/S8PegUKZTJOGDymR+lxB7QJ00f5hpgUKp
z+yueczj34xdvdf3HrvPnKBdnfWO4ajwwHY9KMDuldmPLwut7P0ThAlzyD28
/9T8/X7Xe7tr31PDikGTsBURcCJRKWhy76uv7FjWIg75D+8GD5/IvTxUYThv
6IL5sA7J8FaRfDFa3wssTcoirDlBL4ziBdiHppfeP+t5j8L6lVLilnXgFocv
A0fYBZKZbrqfBpr/WcNpOFeklrC57KjG2XA1R0nOCfBjEpYnDkUoZ8q2YUY9
ruq3kuvmFtsSMVIt0A3MFerObrQ5DEqTu8xvC/8Rdj+AnkCGoxSDApQaWha2
wAAF5C8yUY9iGBK2lbWVTf+QbaWEUdxBDuG01TVZO4qNad6CeUNStsrYipRt
tLkBmoEaNQanqhytFNwHpfNLEDhniUCFuHqWJQIAJI0JAyrMeo2dl3Pi8rlg
WnV7iriLPcN3CNC4n/+EvVDJtsC3r4a5YMuTNjwrePF2dSWoCJ5E3idgkvwc
Us+jlXEgsQMW7T07GVc3PC/rqblipUPs9hUFLDY6q5pVO4XUxV8q7IqizDNJ
5jH9r7DOLc5fp7XTkknTuKAUi0rBEYhWa1dlkFEGONjimoqh7nmjcAkJe0VV
dcX8+OocAkDNmk1vNhns6FgivHNX0DA/ojIdtIYWfaczJ7wvkWzsi8tBvIKB
hhc1F+RexNY+x9scvbMPOuufMhl6RJ8fVE4wnylY1xPxJxJCBvb2gOprJ0dP
YKbDRsoNMIVuwCQ9sUS0Xv6xTEprqtYnwNRF3AFLyhdjKoxvkoSne/FB/Gj/
/KSXAaVvBHNHUZjTVpQCvgzE1rQmjoTWc22I7qt5q8dG6c4qi+NmQQbXu8sO
Zx/wTXFyA36twkcLmdAKnNxjVAAjnAzNWlyXC2Iqf3/xhEPB2WAr0Mk43VE0
s0goRLsmnRR4zhetftv1WKsfbViOXilH7Uz+wYevLxJ3crb92xyH3oG0/Z1q
G+RDb7zKuJJQIEm23ZNl3od/9Ww6TP8knJm/A91D0L0qQpG87xsvCfuNhLR8
4cHJXJXmqYkA1KK8saOMUIH5iagGMQG4wJ3nxzGKW9i1lR87adg2a2qU/bPq
FPmCkN89zyaiBhftZ3Ivg9lEp8pLL/K6ouWlnduur+POg32iG26EFTiYZiCR
vdqIr32QaWwie0+NXunTToaUcT2hyeAGH9cnAPrrqLyVebue3lVP61mzNqi6
u6tQgb0ndxNPorabfnwPH1cj0w3b9RmVeDp7rlm+IrwsVwiwexxeswGxVyFD
YBxvPO4rSpS7qT4Nu2NNwzToOz5poIPpUwu7rD8DUKwbX9qOGTyul8YZjpTM
Boc2dLWehhIZP4scZb9T2JGKMWZwGH2zn8ehNwmnq27HCUr5B/tvOp3mJr09
ZVt6itaFvYunbVnNrcyhFg+tHG5WmTAAeB5iTuOd8qDk9WiMXA2Q1Jvg46t3
8wohwfByDPKLBv2/usZCNWUfqGoeXaEPNmPTW+8vDcoi0ss7B+mLalfEu9jf
bXpY32u6DN3P7qlnveulntHWroA6+pI2d2aYpVojoCYeRfA/Q71d2ji37jE9
avjcsyt4N/e7Dh77TpED+LjfmTjEosIW98EnCjFadvwNfM7umJFWALKaojby
SVAd+bgtin9PWMn01oVw3O5fLNB4t80f5y3vGq2rOltGVHmhVfo1NsLuOg+2
AhZTFCnvsOkNNgQgXbmjqS1QJwZQN9IIt9qlMEdEGD7baMBBV9rLBweJMAEi
wuxFtQRNIAna2y4Aw2El2OWjRpgUiex1Guu8W2qu7pylfJZrGAONA+jc4BaP
7554ohuvkNDmhx5t1hc85MF9d+qDBna90y5T4zJLI7DUtb3doKAAQKGx3Qcr
LE1WY/TgXK1mFqXNzIQgU6ZGmy7g2hRBGxRzCYbX1RiMRZDZy/37sV+J2wbt
3epaJRpGM1k1uZNScW7D49Jmaal8aM7igTI8u1qYzsjpGaQljwhuNGKHWkQ7
Z16uISVS27MzZ8+2WdxYpI90OqipeAZZ4StbQNI+ods9q0yP1UhV4OOVmpsW
GAfh+QtECgCgDl3wkrPZZbTmMAC2LI7NB1pE4ywZAnIP8twr9Ze28WbKvutZ
ddFO2VJ9Fq8d7IiWtIbkxhItopwknyFyJQWDldO2EVtwmwfonSFMD7bXrs7p
Jw55BEZRN6uWHrnTKpvVevulNTF30OJtyK50fmofFtIbvEIUGGIV6bBLmbVH
Gxc/X7f4RBdvuwF5sAF0EX/NJui1SGyEnvF6M6hYLMSe370snX4HaiHlfbCq
sQrn2w1V9lAKwa+Pa7AGneR/eai+OkkKJE/MijrNQuT64JD08z8nMDCgJmrG
i2S4ySmvFP5bL1eiweMhS7jew6dgxgXeuuz5jdhgP1ciRZzveFgg49DOAI1j
D3M3pGjgas5em96GBWcG2+s4K1Q1F9NT65mDQ3LWEjcZM72LankKpRrbpWEY
4rhzo/Vd2OpNQtKIVyxkuo/YjKpeK3k2mCrfPY/kMkUbDsTIm4MbMKQodAU6
40IEqCzBgz6t+aGaAm6wg1xvnPtHXXjyv0HPBUThw5uMBuRfZJ4DPnm8b62Y
HYXJFdP1OTCUrAB4Zaj2PDfshHNuGXU7CLNcT9FRTQR3FBWS6SbguFi+pWGz
d+YWkiovjZbl/r/qvv27jeNI9/f5K2bpsxtAARhRzsNLR3tW1svKWpauqMS7
V1dLDIkhORGAwWIAUojs//1WfVXVXT0zAOk4r9XJOTEx0z39qK5XV32VMpks
jHeznIbSN23L6i4SyL2q91dBB22/U8c7LnunZyGKXkdL6F9djr0vhQ8kq9Dx
ZYnyXtD7thDzcnXZXYO7TT+MrN/o+SvuMjXsXYbd2z4M3C2MGmHRcQpe+3CW
Dv012rsr+1ac3tqhLf8+pB47DCXET9ytdgly15PzGt7I7nZktfufooPtJgBn
V9+5lJOsu5TEAlWGIbjlbpLlfvcx1nmSUo304g42qDmK+Qmp+Qy73o6fkbCY
dhK/QdU2SStBspf7UPUrNIxjfsWKzTTEHmcL0vrq1QcGkZox0Hl5vsHFaQAE
OLRhdbAnVCpE+I4Z9b3hCZCQePvNSQrRm3/6pGD1+ef8wj+9efb4X7/45a+R
bP4N26M6zQkqu6dFlt1o2tC6Yss+q7RZVgCvhadtHXbCcw+ffsvLr/nVI2o9
A3AAA0Vb66yvNV+ctRtbstX+9or0mT11aEkCU7EIEMm8vFYhk1WPar2elWO+
MSsEVEjN+0Fc1wzrGtB/oOt2YV1ilSc+butZM062LT149bJgtVkXPGYs08l5
/2WXbr+pPpQS+lK2poYoux81s2zQppi/9sw48/rds1nfxD7jEykBIUhfLTUF
1EMY+chaA0buQSNI4vxiTBsb4QfqwOBjQedwysXMHuWtH+Er4LIbruKY1uwK
V/ul4jADCRg+wsmX2YNDjZRYrFf1LOLm4CWvD6JK7uRLgGp8fqj4Jluu7BXf
T0ItJ7F6HDB3gEM2prOLSQScwjQ8MjaCWsyvag0ES7QVpBwGueOYKYtfiPVL
eP1Wq4JjGLUmQzBIdZIZJikZuVwJEXXjuLMZkFSsHpTE4RlNJpuaVF3IfiyR
aXrUJ9GEhOJkJKc6wlMe4Tv9jVQAIj73LsLIE9ZhkBP3vtI3O0fT9kpDCJ5V
95IOAnLKvcFX46NhTy98DEInMzkTO/qg1j/0hEv1HKCvUSshzpMk5+DBva/I
DPjNkItNfxFgtlNMTt03T7SHGYYZevMrOZGAQdnI4EaLMJdm0ewDumx3u0F4
MMvt+0OuKxsngUDOagTQoeTy3A9J3QTdXt9VmPj7/PuH6OG3v80HVf7P+RfD
zhAqRIRLcEK3ox6V7cU6hM3CH3O5qkntYhQ6hB+iQ2RrCoQSECy/OfmKDb2X
9H9gwKOAamSYXVkLAis10MG6seZQaPPCRV6OtN5bBMUFchOO72H+pNQDT0Yn
qypWlprUEsapWWqu6DEH6XLpNYRfKqgWupAKTO5ygQeXfrPIDftenin4PxKW
45qgblBA9IJeQ613LA9ySde1AFIVyKOXcdPRbVgmyXgy/WYoqxXHDV4O7cZc
14ZKxYTFOq/kksl2QUULSy18jV0MvNwIYCapIPWyED662kfkLdJ69z5rebuS
+sf+bQuNYCnh4hj62JoR+L/9m1H2MP+X/EiuS4bZrLxYs+ppg+jrYnwkzc0m
0yLLxDSoO3YiZMOMFip5wh/lKylYVN0+h7y4MT8jHQU1u3+84xqPBdEMzlF6
c8e1wmcCwmdKQifIf1cVnz9fniBJ8UO57ZcTqTyJuUn2cpLevVOkuJC0ZxVq
P9/LSXzku+VHCC0j4YEC005SxHjZXZqW4bSEZTSNwEC0k7tD0hKXAETQOnUr
FAmqLyLixDEfpqCfZHjBaoihwptcGElvUb9K0Tu+tE7I1qqZs6CXbE8vKJjg
+xBFQ36yKG6c8DgDrVrWl6rlYK40u7Q3YWLkihJm3qQwdSuo4qRvPUsUN1k5
KaYT2v0ZpNmloCQGCzT0uSeJBNvnDY/i1aJEyx4S2TXmOLGfOGRQcDri2Z1G
zA33DNgTzl99lfeO9e1Nfdvqdgb711ve24a6Y1lTVqGOCW+EYhreXEh4hzpC
kjJjKSfJAgNxyyAnJ/8bHZw9Z0Un/I90Wvack9Zod2xpUpmxKaOzCmUBwpV4
2NRGK4G3o0ngdGnNWq1LoeuxLESHGNQIKefL9TbAY1sm0lnJGTulI41QDxR1
ATWAj/FCN3Mr57paV+cbWglDuOjJKMpCQMGXPtQiueBHAfTo7gi2jR/pKIsF
VsUfV5+X0w08JaH6GVTDQz09j4Kb1nk1ypa0bVWy9ofk5qo0UaOUb0WjQFmZ
yrdYzSiq6H0JfF/VwfJrDFIzZB2dbbPdQi+4DdHXKaqfTiyA5fYP2yH5SzPk
4AeWc+xH5w+JYfTddob/smfWDW52h8Ht48K9ATT7kjqdmf6TlOANWbFHvz7V
a9Uvw2+fPzhFsFm4rk30YP10ePguXOqKC+aH9h1Cz7yDJqemWdDsc9yb6UXo
KN+jzykqvFYW/DKf+AFr00i34Yrc1bIRJ92kPZ9Jt7BNaB1dr8H8N2Tq+iKz
yit+QSaHSdkWxmUWr0y3i1FkTGwkZUXDLgNx4JLlPF7X429SA3ptGM0eJjwC
COk3mTcx+DlNeVEIjxVkMdGok+iBPe6fwBD3+n/c1NlN5dJunH15Lw0Gydpb
oP4amPmDYbYvToGfnV9tFgD1qeh0rMm0bg5RJrmchjiFL1zACXd9SjKEvnI/
/IhUDlr204hxTn+18jrwoVa0YOjNeaJ+k49z35eLQm/NNDgEtJcewzg4eMIV
/k/YF3FXwBGCfJ1TzjTCQrQdCn7n/jn/IkOMin/l38zY56Xj2QrSY3CCfEGL
kLRId6E1BFq9I1670FHW89J/P8wf/OpXGcDom9Ml9RuiU/opLbuFPNrboSCz
ruthCN5FN/Cp/Et7XGEp7uD7iCRsMc9hDi6rKHEm2bxaJCzr/TAXT1F8Riso
QBf0jCnRHKPuBV4wmU/sCb6i2BjeJrh0fBgel9UykqXj4cYfaRnXIXryhn3+
1W7poOPdyolV4Wn6hUEmdYFVQ/JM26ovOI4vukqKna6ReOo9zej/x1qQ7LwQ
88Wq7ciNLrfQ7zNwrRZNnBdbvjVtFz+X6qwi3SxzHEDzqBYU1Fs4ILULRDyd
GygB8e3rciuFiTKbUcBfCLGAYWxSOtYU/molxRhXiLDFMtp9c8bJSaqd3wBC
HwiWe6OdtU40i+A2Rn56T7cTHL9VhYMmW6EIrRawDZVyadUN+BYFMg1rPYDK
OyCDHnx5xchP8OV3Vc6OpWahlWBY2iFUfr4TlCpKq+o6oAJ4C2TEWthNSeuO
khtcJKFcb9lzDYsi521mvAN1V2FYCAIRclTKwwU9BwXSjJSo6jNgF1RNFpeG
OhDcgx9T6FMgc2kXs3hrJ2i+3OC6IYNOa0Whvj0HduOidaqXBz21o24DsO9g
Mt8GV9+Blxdk+XSOk32T7CCq3wamHso+2Uvf548WW61yci2lzC7LdjUkVwf0
bg0i0n0XqL49vE7NIvvz17+M5Ykanm2ngZYhsj9JUPa2cPVz0iOwu5BOcthC
ldfecjqviMiuq/Imyx5x+OZVdXllCYJBfZ8XSz4nScWpn2kBTEbCYoxqrVF8
hADLUYY/pBQiWc5arGQBVBJm/1Lpgp///GiiQdkjjxNdTi+JA9RW/CSDb4FZ
LMozoz9WVbR0LR29WXFWcjb25L4GpqCbFS670Fl8J5scSa32hYVvW9nniPHV
tAusSPEnV7vWhivXVGccVa4e+WVBLwWWv6prCIbJxwlulorKqrRMiT1NN4Xe
8zIuhkSaZRzCLdV49V2sGWQEx9mYlaGpk0HzlyZuEFl3EFqPl/oC7qerzmxb
l4etm1gk/Ez4YiYf8G15uT0f9hVXaDw3+VldzRhp5QZhtcSsiALHzIWNMRs2
j4bS8ycEh4a9YjxtvvxcRPyV/IbvUB34y0euzlStgRyjdrT1ze2zIBomrwYP
7t1TmmzIqGPMGgGECFTN7hK+ZPwjl7RRDLiAGZRFEI5KBBsjU3MHc0OW4Dr1
qrsAavoFLYcWai7dAwh9GtnYMF4dvkdckKaciYtNNzZWYlaJUrCsy4TBciUa
2YizouHI/jOuJRS8aXL/ckH7QcTiBtLyNHIozaSZeNs4MEO7QgJgIOLkmokf
iGgySFzRKEgrFEldZ2jWAF/2hQVJ+dAH7iC8I8W7hWIf3HMjqJD2ILdQrHoB
mbm45DMlcMw3tQIIT8ii5fi25nSFkUvChL6LMkss/Hn98D6T1M0oZ05o1CP9
4KU3Y7f1IjK4iMNF30pmcSU1PAeHz+1erHparXQ52canJ0IYCGAExn84Lfqc
e0G4gVbxASRSeuhkE1zFKaBsFdkEiulqPSDiD5HukmClHNcW36pqguvLIhjU
dUYGw6perlitMZVKkCisDnUqpq4QWT+277FQGwU47MUlcfVFeSNrZVKKtdwI
eBj8ugzuBuqul7x0bMMxe5H6oaXLimnvyLS6uCghOXQ/RYQ0gis1q8qEa0cW
OdKwUOV2yREBkw1sUcsBhoKmU74IlXPR1GMFCekGu7X1+yQSS3Le2m0UmXLh
NldKaCn34TMUa2nyUc88M8qlT21ulV0RlecJjaTRyLBNCh54CEY6GGVCGrBr
UATAu8QNVgeitGp2LCz7zInFHuav5PaXH4+6sXo0Ma3BN+HKXPOyQKmnekGT
5gUOEwsUn627S8btube4MvTdi4s8flhvjxl7gEfWWjQMo6dfDYepPaNYt+mX
lLJt4Ago0Mb1LhC8a5VvESfNzQZMzcum3ExrQXQahqKTvauYBfR5oj2YUhDi
hnUXb3FAjUQNQm28hAeuKDdmlAWC7NCh8QIQntTsaDYoqo1a4+UidzXceKp+
CuG6SFZmUk3WIuB3Hrk1l8QIO+/krWgoleka0ZcmDF+4SygRJr4JK7sgGrBT
XiW7hrggyWAptSsXRDlZLYZ2jXSct1dWdmzpi8G1y6+mJePnCNnSkmPF5mM1
q0jtzQIPzCdEIex10SrlnjEnJdVuY6W3pRAkoOGt9AFe7335UxEDthektgdj
3OcYAA80ZpX3pO73A9O5ghQubQv9Pg7U+h0Rq5WQwqutIhSYWyyZgCLBu119
rlIEGqpWkhagiKuR9tsq2L2nbweB3/eBn1ThIlR5SPv8SxbjQAumeA9AgmoQ
xx2L3wVYpTv7bs+rx/qu4sVCI3iI0sHn9ZJvFISQVlyo4x3SBUdIEhT/q8fV
S72yfcjJLdBkca5i8xXvODz6UDIgB2s/0XfK/2Zci4nd32O8ksW4wOY+MbH7
AbxfT7ra04b8nWD8xaZkf62P9jU92tGUH56e3wDReEVDeMfjY9DnI/kvB2lM
KyhvtiBX7jNozH/T9+X/B2wD8ZRH7deO9DX8P2sK4YVhXIbP2jWVg8e4SfQX
1qxDwLy2hFNhLJfurExI5Kg5UpsrKx5Kxt6sOFfR49qb43G8rqCtsQmlLnwp
9c7/3cKKcM2JlX3gyIjrqsipByhxFXsGrsgwLGcuf5UvGGg5acHS66WP9+NG
MHW8H9kGtUCdpTG9vNYXaUV1g+TveAfVAZTAR+wDt3TbGfFRe8RHNuKj20d8
hK6PfvyI+SP2gVu6dYfCjsxNPFQmL/VofLy/60DZmbk52tn2qAdwU5cqAT/s
x/M+601z7OCn7wPl3tOFQBUmIyJRFDl6LFCf9Nhh6u101/wgWt78IanfO+cL
tuiRMTGVNHYLdCNsxPIwDSP9DDuFJb+dG1RNwgwWdpMUDrnrIjnucish9wvu
mAt2c/LE9TDfzNZVqOR9C0fwfMD1cTeO0D5f3VjzAS/fsHUvbcv6ruKzMNb/
jEvupZzd3A30oI7sHI5y6drnYXbLy+xIe2X9VzExb9V/y/DeP6Lum+LvdnNn
O2jKKSZyr8rp1IIubHMEHEhAUCTuYU9B1ruryTEpt1Uw4vv2r6x+R51YMeIU
1MHpQXLxMtx3D15EaHnqgmMmpJLaZagoZnyy231Lzep2rjfDOzpdDBidI6aI
hxQH+2Vf1yF4wkqTCyCK3d/vAAbdh6wRIUv4jlwGo7f8d0cj1A8EpCbHWfio
JQi0/sLS4jSFMyORUszoC8+bkmCrBLTaYCrwFW5J/VsFskR10ponfCu7Kjgf
yVxfsNRdcWC4RCyy0HWhkVQWQyWeIHeH0Yrr5DR56Bqui8GEf5ho3qt3CtEj
5nKT4aE72WYoJDouhyNxwo4ik4Zn24jwkMQRGZRBy1zoC+Tgf2IysFkg032X
tH/vNlam1C//tksFivK+M8vmaPXQg/WjMQDs4wSWFq67tWBNq3UbnqCJW60F
4EJcAr7fQmnRqjofC57GSNw+EcpfaK4OtyVXZXG9bbW/qtZruMwLu02TerZX
7M/nCEyktJZTQVNuNRYa5hyVBtVSlZ6QGibLdWNGQbdxhG6R8rNKn9ZJsuxS
OqzVgcNwthz+Xx0evT8cSjY+6zAFW6OuRG17CHx23G4Vs1VZTLeya3rODFco
tGr18aYcy/ry2sl1UDGr3cbNtrErfLHxZ1s6uaEVKy82s8MWQTa4GSlnrNwI
GnbViF+vTYU1t/vI0QZ0ci3aRoajpSQmA0Xop1M4bCPsobzS0LmoA9kBeAuu
QJbcgsM7nKRr4noe5dtoKIcGHW2qC7rO/9BB51evALTOc08X/nn3cWIXx89+
7P7YU9wqUfkNTfahj1fjfx3s5q4RsR3uMzw6HbAKTyp4f0ddGJWo+dxZJYnz
DB9PQJh7djLV3AT7lDa1W9KCn/DGHoPxO60qKHGn7OU+zlOtbr8CR/vY+uVO
SlpS6V10vRayaEC5U54ZLg68wHTCHEfdyWHLEkAnEKJtAaGyPvbZpMkF+YQm
Jx73TKcaktCFZab1zvSywd1uuAvNiH8VvHdiHrZW3+CBoxuq/YKCtal12Y/h
7983XOIBR2Dt8J0FquktrnFHT1VIy47+qp/iq/rz/FRmlWoX+31UhhWMUxEP
lPiG4O2BY6Xj6WnEFyNvHPW9sYaT8GFw/TjQ5zUcg/HRkdqvqAagmtn6HRGb
VQiG+XeqEqHfSdPg/a6TB32qAph2ZCPa7qCh5F0D776rmyJUVk/dFLtdFH6H
d21w6KLtfNi/wWFZXQ3ArrNh2/Y0bNnF8POHeeJiMGdBWNZR7H7Uhs7a9oUJ
IzXGjP78WTD6W8GmXXP+NmNejvMOodDHuHtlxI/g3e5yyW6aGCVGubcr1mGK
QFK0o6UVpFqIRBqfThvUtr5P/+Po9111eRXgObl3iYkWVmdDDG4Lkxk6r/1d
332vBPh7zaUjCmy4dnoLAEPTD71NFjmyVdoNeS4oq8ZyZWNxy5coTldeXHAL
WqRtfvTgN4atoc0toJVE52atJ6JpJQc9enqiKqNEZ7NAO/rF53IumI9gv8Dh
mFf9C9d+zfWno/CTTDq8RDrWx2dP9bejzm92PoQuBgKdndsfxEXeswgSTcY4
2N+QZFXdaCkaf1lSPbqdVD1T3kFy4m/xcII7kQRvdlTpTP3fqbPT8a8W07ox
WEW/FL0Ak707tHen7B8t1s5nnZ37z/rCXV23rhvGXRzczgWqmkT00UQyxtff
blZn9clV8aHsf7vLw9nKlYDyx0lAOXFxO5nErzmRouFg5etpwaGHGv3G0Y8N
IjC5eoF1dFkXM8Xser2qrovz7THiWNdrTqxbaXCe8BQ56RFmUUt/bs608JpU
fwxKmH/kawoS/+IEYBLhkhByVm/EIeaxDrkRSZyyAZir9XxWbhkJ4AYBkxI0
OBWxHKJp2/4UMqilRGHTbOailQdsrjDLZIK8RIxnowiECugluU8i4wMoOHUm
g/Rzt5/cnPsyVDSalfplZEJU/mGdEKkqpB8086pp1LEfcs8lNqfx2gbvnGS2
F2ck3dd7969vt3QcyCeX1fF77JxHxWIrO1ZrVFmxaK14dLH0b6V9k/T+2aZR
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
DMfvVta3TKpkPRZcbY28ZFbmeAHcl8aYJSlFnrgOzoqm8hX76EP0Fo0Ocz8k
aj9drNf9LFtGE/t6hUS53Ic1B1u8M7gX6UdFishH7YNz3PSC2vxn3giTFtey
53zzEAE/eH3vRWxiU/rxdPSuS0gyqo/S/qNkgWP47/ulV8HhkOUsZwM1Ci39
dcwmqcot95MxV1z5GGCjCzMLueyq4kiwLpqPOJR9YYJMJBB1GDwiCIhU/NiV
Qy3QL3KyzP9wnDrbUzDzJhkS5vN1u0UcUpCT0oAOF1eKaIdlhW4yN5mQBNvV
xHrHtG6/5Dq7g3jVRaK96EjY2M9xHp7hCWYF2bhToPY2HrmWTnKB1NwSPHSt
05ekENhD6SZ9ZPqAm738dK/v7SBw3Ovy20/mzzWqlMjBuh+PXKvoRpxOS4Rz
jMj6lA3Mj1xAjobfWh6ZVtKmXExDi0GFanR3asdD/fnDzotpZcwwARz3zs8s
RNyYj8NYWtKhowDTx/+OkkeucVoawi3i+44aQ1uKOY1h6L9/ymwo8OD7wj9P
I4l0hzh8/49OTqdWLa+fqmSLfwRpySL209cO8rLV+ePelexqx7oj7/6Iujdu
LvRLD+3yu73y7eSqmssNjGaVGVja/9mUco/5WiJPguy7WXFo2qrjiTCLqkHM
zkFDHR+YW0KCRvkrl/4rcHEUTdbKIE5CX70XcYwQZvVPaBwUev0fG6z0yfba
nftE2/0FeFX68MdFOnSkj9lIz9WqkjWySKLzmp1sUY26qSx+HaFXUd1q1R3r
SqouI7mV08Ak4DyfJgiBnrcuveDredxvYS475s1l27jBwZKkIjJq+qXgZet4
pkLv0mRd8ljWMJS7Db9/oN/us5rpvAdgNRI0JGvGAQNMF25tOmZUUGdh45Kd
13lDKo81UuNHdHg0TOq/pgO22oT8x083rnTCP3/oDNAWM1H23ja944iIX7yT
ft6jBOyyh4HEPTz0ujT3+3cUiv2DkyHEEeJvHea/4yDPSzri0zBuPquD81m7
vA28BMfsOqim71564MZHl5dvFFW/MwswqFMOO9t12DCX23rt9+G85DACTgBd
QomfYIgTceGAkVx67jNV7D1mPhqBh3+BTA0eaRIHPUlDWgWcwBo4suPo58C+
5Kv9/iIdyqnKAV2UwGnepweYuxxcjozbIGvpT9VygIkePn/05PnTtyej3P95
+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

-->

</rfc>
