<?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.35 (Ruby 3.4.9) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-irtf-cfrg-vdaf-19" category="info" submissionType="IRTF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.32.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-19"/>
    <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="April" 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>
    </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 284?>

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

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

    measurement
      |
      |
      V
    +----------------------------------------------+
    | shard                                        |
    +-+--------------+--------------+-----+--------+
      |              |              |     |
      |              |         ...  |    public_share
      |              |              |     |
      |    +---------|-----+--------|-----+
      |    |         |     |        |     |
      v    |         v     |        v     |
     input_share_0  input_share_1  input_share_[SHARES-1]
      |    |         |     |        |     |
      |    |         |     |   ...  |     |
      v    v         v     v        v     v
    Aggregator 0   Aggregator 1    Aggregator SHARES-1
]]></artwork>
          </artset>
        </figure>
        <t>The sharding algorithm run by each Client is defined as follows:</t>
        <ul spacing="normal">
          <li>
            <t><tt>daf.shard(ctx: bytes, measurement: Measurement, nonce: bytes, rand: bytes)
-&gt; tuple[PublicShare, list[InputShare]]</tt> consumes the "application context"
(defined below), a measurement, and a nonce and produces the public share,
distributed to each of the Aggregators, and the input shares, one for each
Aggregator.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>nonce</tt> <bcp14>MUST</bcp14> have length equal to <tt>daf.NONCE_SIZE</tt> and <bcp14>MUST</bcp14> be generated
using a cryptographically secure random number generator (CSPRNG).</t>
              </li>
              <li>
                <t><tt>rand</tt> consists of the random bytes consumed by the algorithm. It <bcp14>MUST</bcp14> have
length equal to <tt>daf.RAND_SIZE</tt> and <bcp14>MUST</bcp14> be generated using a CSPRNG.</t>
              </li>
            </ul>
            <t>
Post-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t>The number of input shares <bcp14>MUST</bcp14> equal <tt>daf.SHARES</tt>.</t>
              </li>
            </ul>
          </li>
        </ul>
        <t>Sharding is bound to a specific "application context". The application context
is a string intended to uniquely identify an instance of the higher level
protocol that uses the DAF. The goal of binding the application to DAF
execution is to ensure that aggregation succeeds only if the Clients and
Aggregators agree on the application context. (Preparation binds the
application context, too; see <xref target="sec-daf-prepare"/>.) Note that, unlike VDAFs
(<xref target="vdaf"/>), there is no explicit signal of disagreement; it may only manifest
as a garbled aggregate result.</t>
        <t>The nonce is a public random value associated with the report. It is referred
to as a nonce because normally it will also be used as a unique identifier for
that report in the context of some application. The randomness requirement is
especially important for VDAFs, where it may be used by the Aggregators to
derive per-report randomness for verification of the computation. See
<xref target="nonce-requirements"/> for details.</t>
      </section>
      <section anchor="sec-daf-prepare">
        <name>Preparation</name>
        <figure anchor="daf-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[
def run_daf(
        daf: Daf[
            Measurement,
            AggParam,
            PublicShare,
            InputShare,
            OutShare,
            AggShare,
            AggResult,
        ],
        ctx: bytes,
        agg_param: AggParam,
        measurements: list[Measurement]) -> AggResult:
    agg_shares: list[AggShare]
    agg_shares = [daf.agg_init(agg_param)
                  for _ in range(daf.SHARES)]
    for measurement in measurements:
        # Sharding
        nonce = gen_rand(daf.NONCE_SIZE)
        rand = gen_rand(daf.RAND_SIZE)
        (public_share, input_shares) = \
            daf.shard(ctx, measurement, nonce, rand)

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

    # Unsharding
    num_measurements = len(measurements)
    agg_result = daf.unshard(agg_param, agg_shares,
                             num_measurements)
    return agg_result
]]></sourcecode>
        <t>The inputs to this procedure include the parameters of the aggregation function
computed by the DAF: an aggregation parameter and a sequence of measurements.
They also include the application context. The procedure prescribes how a DAF is
executed in a "benign" environment in which there is no adversary and the
messages are passed among the protocol participants over secure point-to-point
channels. In reality, these channels need to be instantiated by some "wrapper
protocol", such as <xref target="DAP"/>, that realizes these channels using suitable
cryptographic mechanisms. Moreover, some fraction of the Aggregators (or
Clients) may be malicious and diverge from their prescribed behaviors.
<xref target="security"/> describes the execution of the DAF in various adversarial
environments and what properties the wrapper protocol needs to provide in each.</t>
      </section>
    </section>
    <section anchor="vdaf">
      <name>Definition of VDAFs</name>
      <t>VDAFs are identical to DAFs except that 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[
def domain_separation_tag(self, usage: int, ctx: bytes) -> bytes:
    """
    Format domain separation tag for this VDAF with the given
    application context and usage.

    Pre-conditions:

        - `usage` in the range `[0, 2**16)`
    """
    return format_dst(0, self.ID, usage) + ctx
]]></sourcecode>
      <t>The output, called the "domain separation tag", is used in the constructions
for domain separation. Function <tt>format_dst()</tt> is defined in <xref target="dst-binder"/>.</t>
      <section anchor="sec-vdaf-shard">
        <name>Sharding</name>
        <t>Sharding is as described for DAFs in <xref target="sec-daf-shard"/>. The public share and
input shares encode additional information used during verification to validate
the output shares before they are aggregated (e.g., the "proof shares" in
<xref target="prio3"/>).</t>
        <t>Like DAFs, sharding is bound to the application context via the application
context string. Again, this is intended to ensure that aggregation succeeds
only if the Clients and Aggregators agree on the application context. Unlike
DAFs, however, disagreement on the context should manifest as a 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 for 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[
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
]]></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 400,40 L 400,120" fill="none" stroke="black"/>
                <path d="M 16,32 L 40,32" fill="none" stroke="black"/>
                <path d="M 128,32 L 152,32" fill="none" stroke="black"/>
                <path d="M 184,32 L 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="408,120 396,114.4 396,125.6" fill="black" transform="rotate(90,400,120)"/>
                <polygon class="arrowhead" points="408,40 396,34.4 396,45.6" fill="black" transform="rotate(270,400,40)"/>
                <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="348" 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="RFC8446"/>. Each message is structured as follows:</t>
          <sourcecode type="tls-presentation"><![CDATA[
enum {
  initialize(0),
  continue(1),
  finish(2),
  (255)
} MessageType;

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

    try:
        (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()
]]></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[
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
]]></sourcecode>
          <t>The output is the <tt>State</tt> to which the Helper has transitioned. If the Helper's
state is <tt>Finished</tt> or <tt>Rejected</tt>, then processing halts. Otherwise, if the
state is <tt>Continued</tt> or <tt>FinishedWithOutbound</tt>, then the state include an
outbound message and processing continues.</t>
          <t>To continue processing, the Helper sends the outbound message to the Leader.
The Leader computes its next state transition using the following method on
class <tt>Vdaf</tt>:</t>
          <sourcecode type="python"><![CDATA[
def ping_pong_leader_continued(
    self,
    ctx: bytes,
    agg_param: bytes,
    state: Continued,
    inbound: bytes,  # encoded ping pong Message
) -> State:
    """
    Called by the Leader to start the next step of ping-ponging.
    """
    return self.ping_pong_continued(
        True, ctx, agg_param, state, inbound)

def ping_pong_continued(
    self,
    is_leader: bool,
    ctx: bytes,
    agg_param: bytes,
    state: Continued,
    inbound: bytes,  # encoded ping pong Message
) -> State:
    try:
        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()
]]></sourcecode>
          <t>If the Leader's state is <tt>Finished</tt> or <tt>Rejected</tt>, then processing halts.
Otherwise, if the Leader's state is <tt>Continued</tt> or <tt>FinishedWithOutbound</tt>, the
Leader sends the outbound message to the Helper. The Helper computes its next
state transition using the following method on class <tt>Vdaf</tt>:</t>
          <sourcecode type="python"><![CDATA[
def ping_pong_helper_continued(
    self,
    ctx: bytes,
    agg_param: bytes,
    state: Continued,
    inbound: bytes,  # encoded ping pong Message
) -> State:
    """Called by the Helper to continue ping-ponging."""
    return self.ping_pong_continued(
        False, ctx, agg_param, state, inbound)
]]></sourcecode>
          <t>They continue in this way until processing halts. Note that, depending on the
number of rounds of verification that are required, when one party reaches the
<tt>Finished</tt> state, there may be one more message to send before the peer can
also finish processing (i.e., the outbound message is not <tt>None</tt>).</t>
        </section>
        <section anchor="star-topo">
          <name>The Star Topology (Any Number of Aggregators)</name>
          <t>The ping-pong topology of the previous section is only suitable for applications
of VDAFs involving exactly two Aggregators. In applications with more than two
Aggregators, the star topology described in this section can
be used instead.</t>
          <t>Again, one Aggregator initiates the computation. This Aggregator is called the
Leader and all other Aggregators are called Helpers.</t>
          <t>At the start of each round, the Leader requests from each Helper its 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[
def encode_vec(cls, vec: list[Self]) -> bytes:
    """
    Encode a vector of field elements `vec` as a byte string.
    """
    encoded = bytes()
    for x in vec:
        encoded += to_le_bytes(x.int(), cls.ENCODED_SIZE)
    return encoded

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

    vec = []
    while len(encoded) > 0:
        (encoded_x, encoded) = front(cls.ENCODED_SIZE, encoded)
        x = from_le_bytes(encoded_x)
        if x >= cls.MODULUS:
            raise ValueError('modulus overflow')
        vec.append(cls(x))
    return vec
]]></sourcecode>
          <t>Finally, the following functions define arithmetic on vectors over a finite
field. Note that an exception is raised by each function if the operands are
not the same length.</t>
          <sourcecode type="python"><![CDATA[
def vec_sub(left: list[F], right: list[F]) -> list[F]:
    """
    Subtract the right operand from the left and return the result.
    """
    if len(left) != len(right):
        raise ValueError("mismatched vector sizes")
    return list(map(lambda x: x[0] - x[1], zip(left, right)))

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

def vec_neg(vec: list[F]) -> list[F]:
    """Negate the input vector."""
    return list(map(lambda x: -x, vec))
]]></sourcecode>
        </section>
        <section anchor="field-ntt-friendly">
          <name>NTT-Friendly Fields</name>
          <t>Some VDAFs, including Prio3, require fields that are suitable for efficient
computation of the number theoretic transform (NTT) <xref target="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 lesser 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[
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]
]]></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[
def derive_seed(cls,
                seed: bytes,
                dst: bytes,
                binder: bytes) -> bytes:
    """
    Derive a new seed.

    Pre-conditions:

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

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

    Pre-conditions:

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

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

    Pre-conditions:

        - `field` is sub-class of `Field`
        - `len(seed) == cls.SEED_SIZE`
        - `length > 0`
    """
    xof = cls(seed, dst, binder)
    return xof.next_vec(field, length)
]]></sourcecode>
        <section anchor="xof-turboshake128">
          <name>XofTurboShake128</name>
          <t>This section describes XofTurboShake128, an XOF based on the TurboSHAKE128
function specified in <xref target="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</bcp14> not exceed 255. Otherwise initialization will raise an exception.</t>
            </li>
            <li>
              <t>The length of the domain separation string <tt>dst</tt> passed to XofTurboShake128
<bcp14>MUST NOT</bcp14> exceed 65535 bytes. Otherwise initialization will raise an
exception.</t>
            </li>
          </ul>
          <sourcecode type="python"><![CDATA[
class XofTurboShake128(Xof):
    """XOF wrapper for TurboSHAKE128."""

    # Associated parameters
    SEED_SIZE = 32

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

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

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

    # Associated parameters
    SEED_SIZE = 16

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

        self.length_consumed = 0

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

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

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

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

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

    Pre-conditions:

        - `algo_class` in the range `[0, 2**8)`
        - `algo` in the range `[0, 2**32)`
        - `usage` in the range `[0, 2**16)`
    """
    return concat([
        to_be_bytes(VERSION, 1),
        to_be_bytes(algo_class, 1),
        to_be_bytes(algo, 4),
        to_be_bytes(usage, 2),
    ])
]]></sourcecode>
          <t>It is also sometimes necessary to bind the output to some ephemeral value that
multiple parties need to agree on. This input is called the "binder string".</t>
        </section>
      </section>
    </section>
    <section anchor="prio3">
      <name>Prio3</name>
      <t>This section describes Prio3, a VDAF for general-purpose aggregation. Prio3 is
suitable for a wide variety of aggregation functions, including (but not
limited to) sum, mean, standard deviation, histograms, and linear regression.
It is compatible with any aggregation function that has the following
structure:</t>
      <ul spacing="normal">
        <li>
          <t>Each measurement is encoded as a vector over some finite field.</t>
        </li>
        <li>
          <t>Measurement validity is determined by an "arithmetic circuit" evaluated over
the encoded measurement. An arithmetic circuit is a function comprised of
arithmetic operations in the field. (These are specified in full detail in
<xref target="flp-bbcggi19-valid"/>.)</t>
        </li>
        <li>
          <t>The aggregate result is obtained by summing up the encoded measurements and
computing some function of the sum.</t>
        </li>
      </ul>
      <t>Clients protect the privacy of their measurements by secret sharing them and
distributing the shares among the Aggregators. To ensure each measurement is
valid, the Aggregators run a multi-party computation on their shares, the
result of which is the output of the arithmetic circuit. This involves
verification of a "Fully Linear Proof (FLP)" (<xref target="flp"/>) generated by the Client.
FLPs are the core component of Prio3, as they specify the types of
measurements and how they are encoded, verified, and aggregated. In fact Prio3
can be thought of as a transformation of an FLP into a VDAF.</t>
      <t>Prio3 does not have an aggregation parameter. Instead, each output share is
derived from each input share by applying a fixed map. See <xref target="poplar1"/> for an
example of a VDAF that makes meaningful use of the aggregation parameter.</t>
      <t>The remainder of this section is structured as follows. The interface of FLPs is
described in <xref target="flp"/>. The generic transformation of an FLP into Prio3 is
specified in <xref target="prio3-construction"/>. Next, a concrete FLP suitable for any
validity circuit is specified in <xref target="flp-bbcggi19"/>. Finally, variants of Prio3
for various types of aggregation tasks are specified in
<xref target="prio3-instantiations"/>. Test vectors for each variant can be found in
<xref target="test-vectors"/>.</t>
      <section anchor="flp">
        <name>Fully Linear Proofs (FLPs)</name>
        <t>Conceptually, an FLP is a two-party protocol executed by a prover and a
verifier. The verifier is restricted to only access the messages it receives
from the prover via linear queries. In actual use in Prio3, however, the
prover's computation is carried out by the Client, and the verifier's
computation is distributed among the Aggregators. The Client generates a
"proof" of its measurement's validity and distributes shares of the proof to
the Aggregators. During 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[
def run_flp(
        flp: Flp[Measurement, AggResult, F],
        meas: list[F],
        num_shares: int) -> bool:
    """Run the FLP on an encoded measurement."""

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

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

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

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

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

    # Verifier decides if the measurement is valid.
    return flp.decide(verifier)
]]></sourcecode>
        <t>The proof system is designed so that, if <tt>meas</tt> is valid, then <tt>run_flp(flp,
meas, num_shares)</tt> always returns <tt>True</tt>. On the other hand, if <tt>meas</tt> is
invalid, then as long as <tt>joint_rand</tt> and <tt>query_rand</tt> are generated uniform
randomly, the output is <tt>False</tt> with high probability. False positives are
possible: there is a small probability that a verifier accepts an invalid input
as valid. An FLP is said to be "sound" if this probability is sufficiently
small. The soundness of the FLP depends on a variety of parameters, like the
length of the input and the size of the field. See <xref target="flp-bbcggi19"/> for
details.</t>
        <t>Note that soundness of an FLP system is not the same as verifiability for the
VDAF that uses it. In particular, soundness of the FLP is necessary, but
insufficient for verifiability of Prio3 (<xref target="prio3"/>). See
<xref target="security-multiproof"/> for details.</t>
        <t>In addition, note that <xref target="BBCGGI19"/> defines a larger class of fully linear
proof systems than is considered here. In particular, what is called an "FLP"
here is called a 1.5-round, public-coin, interactive oracle proof system in
their paper.</t>
        <table anchor="flp-param">
          <name>FLP parameters.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>PROVE_RAND_LEN: int</tt></td>
              <td align="left">Length of the prover randomness, the number of random field elements consumed by the prover when generating a proof.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>QUERY_RAND_LEN: int</tt></td>
              <td align="left">Length of the query randomness, the number of random field elements consumed by the verifier.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>JOINT_RAND_LEN: int</tt></td>
              <td align="left">Length of the joint randomness, the number of random field elements shared by the prover and verifier.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>MEAS_LEN: int</tt></td>
              <td align="left">Length of the encoded measurement (<xref target="flp-encode"/>).</td>
            </tr>
            <tr>
              <td align="left">
                <tt>OUTPUT_LEN: int</tt></td>
              <td align="left">Length of the aggregatable output (<xref target="flp-encode"/>).</td>
            </tr>
            <tr>
              <td align="left">
                <tt>PROOF_LEN: int</tt></td>
              <td align="left">Length of the proof.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VERIFIER_LEN: int</tt></td>
              <td align="left">Length of the verifier message generated by querying the measurement and proof.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">Type of the measurement.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">Type of the aggregate result.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>field: type[F]</tt></td>
              <td align="left">Class object for the field (<xref target="field"/>).</td>
            </tr>
          </tbody>
        </table>
        <section anchor="flp-encode">
          <name>Encoding the Input</name>
          <t>The type of measurement being aggregated is defined by the FLP. Hence, the FLP
also specifies a method of encoding raw measurements as a vector of field
elements:</t>
          <ul spacing="normal">
            <li>
              <t><tt>flp.encode(measurement: Measurement) -&gt; list[F]</tt> encodes a raw measurement
as a vector of field elements.  </t>
              <t>
Post-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The encoded measurement <bcp14>MUST</bcp14> have length <tt>flp.MEAS_LEN</tt>.</t>
                </li>
              </ul>
            </li>
          </ul>
          <t>For some FLPs, the encoded measurement also includes redundant field elements
that are useful for checking the proof, but which are not needed after the
proof has been checked. An example is the <tt>Sum</tt> type defined in <xref target="prio3sum"/>
for which each measurement is an integer in the range <tt>[0, max_measurement]</tt>.
The range check requires encoding the measurement with several field elements,
though just one is needed for aggregation. Thus the FLP defines an algorithm
for truncating the encoded measurement to the length of the aggregatable output:</t>
          <ul spacing="normal">
            <li>
              <t><tt>flp.truncate(meas: list[F]) -&gt; list[F]</tt> maps an encoded measurement (e.g.,
the bit-encoding of the measurement) to an aggregatable output (e.g., the
singleton vector containing the measurement).  </t>
              <t>
Pre-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The length of the input <bcp14>MUST</bcp14> be <tt>flp.MEAS_LEN</tt></t>
                </li>
              </ul>
              <t>
Post-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The length of the output <bcp14>MUST</bcp14> be <tt>flp.OUTPUT_LEN</tt>.</t>
                </li>
              </ul>
            </li>
          </ul>
          <t>Once the aggregate shares have been transmitted to the Collector, their sum can
be converted into the aggregate result. This could be a projection from the
FLP's field to the integers, or it could include additional post-processing.
Either way, this functionality is implemented by the following method:</t>
          <ul spacing="normal">
            <li>
              <t><tt>flp.decode(output: list[F], num_measurements: int) -&gt; AggResult</tt> maps a sum
of aggregate shares to an aggregate result.  </t>
              <t>
Pre-conditions:  </t>
              <ul spacing="normal">
                <li>
                  <t>The length of the output <bcp14>MUST</bcp14> be <tt>OUTPUT_LEN</tt>.</t>
                </li>
                <li>
                  <t><tt>num_measurements</tt> <bcp14>MUST</bcp14> equal the number of measurements that were
aggregated.</t>
                </li>
              </ul>
            </li>
          </ul>
          <t>Taken together, these three functionalities correspond to the notion of
"Affine-aggregatable encodings (AFEs)" from <xref target="CGB17"/>.</t>
        </section>
        <section anchor="multiproofs">
          <name>Multiple Proofs</name>
          <t>It is sometimes desirable to generate and verify multiple independent proofs
for the same input. First, this improves the soundness of the proof system
without having to change any of its parameters. Second, it allows a smaller
field to be used (e.g., replace Field128 with Field64)
without sacrificing soundness. This is useful because it reduces the overall
communication of the protocol. (This is a trade-off, of course, since
generating and verifying more proofs requires more time.) Given these benefits,
this feature is implemented by Prio3 (<xref target="prio3"/>).</t>
          <t>To generate these proofs for a specific measurement, the prover calls
<tt>flp.prove()</tt> multiple times, each time using fresh prover and joint
randomness. The verifier checks each proof independently, each time with fresh
query randomness. It accepts the measurement only if the decision algorithm
accepts on each proof.</t>
          <t>See <xref target="security-multiproof"/> for guidance on choosing the field size and number
of proofs.</t>
        </section>
      </section>
      <section anchor="prio3-construction">
        <name>Specification</name>
        <t>This section specifies <tt>Prio3</tt>, an implementation of the <tt>Vdaf</tt> interface
defined in <xref target="vdaf"/>. The parameters and types required by the <tt>Vdaf</tt> interface
are defined in <xref target="prio3-param"/>. The methods required for sharding,
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[
def shard(
        self,
        ctx: bytes,
        measurement: Measurement,
        nonce: bytes,
        rand: bytes) -> tuple[
            Optional[list[bytes]],
            list[Prio3InputShare]]:
    if len(nonce) != self.NONCE_SIZE:
        raise ValueError("incorrect nonce size")
    if len(rand) != self.RAND_SIZE:
        raise ValueError("incorrect size of random bytes argument")

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

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

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

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

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

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

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

    # Each Aggregator's input share contains its measurement share,
    # share of proof(s), and blind. The public share contains the
    # Aggregators' joint randomness parts.
    input_shares: list[Prio3InputShare[F]] = []
    input_shares.append((
        leader_meas_share,
        leader_proofs_share,
        leader_blind,
    ))
    for j in range(self.SHARES - 1):
        input_shares.append((
            helper_shares[j],
            helper_blinds[j],
        ))
    return (joint_rand_parts, input_shares)
]]></sourcecode>
          </section>
        </section>
        <section anchor="prio3-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[
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
]]></sourcecode>
        </section>
        <section anchor="validity-of-aggregation-parameters">
          <name>Validity of Aggregation Parameters</name>
          <t><tt>Prio3</tt> only permits a report to be aggregated once.</t>
          <sourcecode type="python"><![CDATA[
def is_valid(
        self,
        _agg_param: None,
        previous_agg_params: list[None]) -> bool:
    return len(previous_agg_params) == 0
]]></sourcecode>
        </section>
        <section anchor="aggregation">
          <name>Aggregation</name>
          <t>Aggregating a set of output shares is simply a matter of adding up the vectors
element-wise.</t>
          <sourcecode type="python"><![CDATA[
def agg_init(self, _agg_param: None) -> list[F]:
    return self.flp.field.zeros(self.flp.OUTPUT_LEN)

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

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

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

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

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

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

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

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

def joint_rands(self,
                ctx: bytes,
                joint_rand_seed: bytes) -> list[F]:
    """Derive the joint randomness from its seed."""
    return self.xof.expand_into_vec(
        self.flp.field,
        joint_rand_seed,
        self.domain_separation_tag(USAGE_JOINT_RANDOMNESS, ctx),
        byte(self.PROOFS),
        self.flp.JOINT_RAND_LEN * self.PROOFS,
    )
]]></sourcecode>
        </section>
        <section anchor="prio3-encode">
          <name>Message Serialization</name>
          <t>This section defines serialization formats for messages exchanged over the
network while executing Prio3. Messages are defined in the presentation
language of TLS as defined in <xref section="3" sectionFormat="of" target="RFC8446"/>.</t>
          <t>Let <tt>prio3</tt> denote an instance of <tt>Prio3</tt>. In the remainder, let <tt>S</tt> be an
alias for <tt>prio3.xof.SEED_SIZE</tt> and <tt>F</tt> as an alias for
<tt>prio3.field.ENCODED_SIZE</tt>. XOF seeds are represented as follows:</t>
          <sourcecode type="tls-presentation"><![CDATA[
opaque Prio3Seed[S];
]]></sourcecode>
          <t>Field elements are encoded in little-endian byte order (as defined in
<xref target="field"/>) and represented as follows:</t>
          <sourcecode type="tls-presentation"><![CDATA[
opaque Prio3Field[F];
]]></sourcecode>
          <section anchor="public-share">
            <name>Public Share</name>
            <t>The contents of the public share depend on whether joint randomness is
required for the underlying FLP (i.e., <tt>prio3.flp.JOINT_RAND_LEN &gt; 0</tt>). If
joint randomness is not used, then the public share is the empty string.
Otherwise, if joint randomness is used, then the public share encodes the joint
randomness parts as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Seed joint_rand_parts[S * prio3.SHARES];
} Prio3PublicShareWithJointRand;
]]></sourcecode>
          </section>
          <section anchor="input-share">
            <name>Input Share</name>
            <t>Just as for the public share, the content of the input shares depends on
whether joint randomness is used. If so, then each input share includes the
Aggregator's blind for generating its joint randomness part.</t>
            <t>In addition, the encoding of the input shares depends on which aggregator is
receiving the message. If the aggregator ID is <tt>0</tt>, then the input share
includes the full measurement share and proofs(s) share(s). Otherwise, if the
aggregator ID is greater than <tt>0</tt>, then the measurement and shares of proof(s)
are represented by an XOF seed. Just as in <xref target="star-topo"/>, the former is called
the Leader and the latter the Helpers.</t>
            <t>In total there are four variants of the input share. When joint randomness is
not used, the Leader's share is structured as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Field meas_share[F * prio3.flp.MEAS_LEN];
    Prio3Field proofs_share[F * prio3.flp.PROOF_LEN * prio3.PROOFS];
} Prio3LeaderShare;
]]></sourcecode>
            <t>When joint randomness is not used, the Helpers' shares are structured
as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Seed share;
} Prio3HelperShare;
]]></sourcecode>
            <t>When joint randomness is used, the Leader's input share is structured as
follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3LeaderShare inner;
    Prio3Seed blind;
} Prio3LeaderShareWithJointRand;
]]></sourcecode>
            <t>Finally, when joint randomness is used, the Helpers' shares are structured as
follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3HelperShare inner;
    Prio3Seed blind;
} Prio3HelperShareWithJointRand;
]]></sourcecode>
          </section>
          <section anchor="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[
struct {
    Prio3Field verifiers_share[F * V];
} Prio3VerifierShare;
]]></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[
struct {
    Prio3Field verifiers_share[F * V];
    Prio3Seed joint_rand_part;
} Prio3VerifierhareWithJointRand;
]]></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[
struct {
    Prio3Seed joint_rand;
} Prio3VerifierMessageWithJointRand;
]]></sourcecode>
          </section>
          <section anchor="aggregation-1">
            <name>Aggregation</name>
            <t>Aggregate shares are structured as follows:</t>
            <sourcecode type="tls-presentation"><![CDATA[
struct {
    Prio3Field agg_share[F * prio3.flp.OUTPUT_LEN];
} Prio3AggShare;
]]></sourcecode>
          </section>
        </section>
      </section>
      <section anchor="flp-bbcggi19">
        <name>FLP Specification</name>
        <t>This section specifies an implementation of the <tt>Flp</tt> interface (<xref target="flp"/>) based
on the construction from <xref target="BBCGGI19"/>, Section 4.2. The types and parameters
required by this interface are listed in the table below.</t>
        <t><xref target="flp-bbcggi19-overview"/> provides an overview of the proof system and some
extensions to it. <xref target="flp-bbcggi19-valid"/> defines validity circuits, the core
component of the proof system that determines measurement validity and how
measurements are aggregated. The proof-generation algorithm, query algorithm,
and decision algorithm are defined in <xref target="flp-bbcggi19-construction-prove"/>,
<xref target="flp-bbcggi19-construction-query"/>, and <xref target="flp-bbcggi19-construction-decide"/>
respectively.</t>
        <table anchor="flp-bbcggi19-param">
          <name>FLP parameters for a validity circuit.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>valid</tt></td>
              <td align="left">An instance of <tt>Valid</tt> (<xref target="flp-bbcggi19-valid"/>).</td>
            </tr>
            <tr>
              <td align="left">
                <tt>field</tt></td>
              <td align="left">
                <tt>valid.field</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PROVE_RAND_LEN</tt></td>
              <td align="left">
                <tt>valid.prove_rand_len()</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>QUERY_RAND_LEN</tt></td>
              <td align="left">
                <tt>valid.query_rand_len()</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>JOINT_RAND_LEN</tt></td>
              <td align="left">
                <tt>valid.JOINT_RAND_LEN</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>MEAS_LEN</tt></td>
              <td align="left">
                <tt>valid.MEAS_LEN</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>OUTPUT_LEN</tt></td>
              <td align="left">
                <tt>valid.OUTPUT_LEN</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PROOF_LEN</tt></td>
              <td align="left">
                <tt>valid.proof_len()</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>VERIFIER_LEN</tt></td>
              <td align="left">
                <tt>valid.verifier_len()</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">As defined by <tt>valid</tt>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">As defined by <tt>valid</tt>.</td>
            </tr>
          </tbody>
        </table>
        <section anchor="flp-bbcggi19-overview">
          <name>Overview</name>
          <t>An FLP is a type of "zero-knowledge proof". A conventional zero-knowledge proof
system involves two parties:</t>
          <ul spacing="normal">
            <li>
              <t>The prover, who holds a measurement and generates a proof of the
measurement's validity</t>
            </li>
            <li>
              <t>The verifier who holds an encryption of, or commitment to, the measurement
and checks the proof</t>
            </li>
          </ul>
          <t>The proof system here is much the same, except the verifier is split across
multiple Aggregators, each of which has a secret share of the measurement
rather than a commitment to it.</t>
          <t>Validity is defined in terms of an arithmetic circuit evaluated over the
measurement. The inputs to this circuit are elements of a finite field that
comprise the encoded measurement; the gates of the circuit are multiplication,
addition, and subtraction operations; and the output of the circuit is a single
field element. If the value is zero, then the measurement is deemed valid;
otherwise, if the output is non-zero, then the measurement is deemed invalid.</t>
          <t>For example, the simplest circuit specified in this document is the following
(<xref target="prio3count"/>):</t>
          <artwork><![CDATA[
C(x) = x * (x-1)
]]></artwork>
          <t>This circuit contains one subtraction gate (<tt>x-1</tt>) and one multiplication gate
(<tt>x * (x-1)</tt>). Observe that <tt>C(x) = 0</tt> if and only if <tt>x</tt> is in the range
<tt>[0, 2)</tt>.</t>
          <t>The goal of the proof system is to allow each Aggregator to privately and
correctly compute a share of <tt>C(x)</tt> from its share of <tt>x</tt>. Then all they need
to do to determine validity is to broadcast their shares of <tt>C(x)</tt>.</t>
          <t>Suppose for a moment that <tt>C</tt> is an affine arithmetic circuit, meaning its only
operations are addition, subtraction, and multiplication-by-constant. (The
circuit above is non-affine because it contains a multiplication gate with two
non-constant inputs.) Then each Aggregator can compute its share locally, since</t>
          <artwork><![CDATA[
C(x_shares[0] + ... + x_shares[SHARES-1]) =
    C(x_shares[0]) + ... + C(x_shares[SHARES-1])
]]></artwork>
          <t>(Note that, for this equality to hold, it is necessary to scale any addition of
a constant in the circuit by <tt>1/SHARES</tt>.) However, this is not the case if <tt>C</tt>
contains multiplication gates with two non-constant inputs. Thus the goal is to
transform these multiplication gates into computations on secret shared data
that each Aggregator can perform locally.</t>
          <t>The key idea is to have the prover construct a polynomial <tt>p</tt> such that <tt>p(j)</tt>
is equal to the output of the <tt>j</tt>-th multiplication gate. Polynomial evaluation
is fully linear, which means the 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[
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
]]></sourcecode>
        </section>
        <section anchor="flp-bbcggi19-construction-prove">
          <name>Generating the Proof</name>
          <figure>
            <name>Components of the proof generation algorithm.</name>
            <artset>
              <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="240" width="296" viewBox="0 0 296 240" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                  <path d="M 8,32 L 8,192" fill="none" stroke="black"/>
                  <path d="M 24,192 L 24,224" fill="none" stroke="black"/>
                  <path d="M 32,64 L 32,160" fill="none" stroke="black"/>
                  <path d="M 56,96 L 56,128" fill="none" stroke="black"/>
                  <path d="M 128,96 L 128,128" fill="none" stroke="black"/>
                  <path d="M 152,64 L 152,160" fill="none" stroke="black"/>
                  <path d="M 176,32 L 176,72" fill="none" stroke="black"/>
                  <path d="M 176,104 L 176,192" fill="none" stroke="black"/>
                  <path d="M 8,32 L 176,32" fill="none" stroke="black"/>
                  <path d="M 32,64 L 152,64" fill="none" stroke="black"/>
                  <path d="M 160,80 L 200,80" fill="none" stroke="black"/>
                  <path d="M 56,96 L 128,96" fill="none" stroke="black"/>
                  <path d="M 160,96 L 200,96" fill="none" stroke="black"/>
                  <path d="M 184,112 L 200,112" fill="none" stroke="black"/>
                  <path d="M 56,128 L 128,128" fill="none" stroke="black"/>
                  <path d="M 32,160 L 152,160" fill="none" stroke="black"/>
                  <path d="M 8,192 L 176,192" fill="none" stroke="black"/>
                  <polygon class="arrowhead" points="192,112 180,106.4 180,117.6" fill="black" transform="rotate(180,184,112)"/>
                  <polygon class="arrowhead" points="168,96 156,90.4 156,101.6" fill="black" transform="rotate(180,160,96)"/>
                  <polygon class="arrowhead" points="168,80 156,74.4 156,85.6" fill="black" transform="rotate(180,160,80)"/>
                  <polygon class="arrowhead" points="32,224 20,218.4 20,229.6" fill="black" transform="rotate(90,24,224)"/>
                  <g class="text">
                    <text x="48" y="52">prove()</text>
                    <text x="64" y="84">Valid</text>
                    <text x="228" y="84">meas</text>
                    <text x="232" y="100">joint</text>
                    <text x="276" y="100">rand</text>
                    <text x="92" y="116">Gadget</text>
                    <text x="232" y="116">prove</text>
                    <text x="276" y="116">rand</text>
                    <text x="56" y="228">proof</text>
                  </g>
                </svg>
              </artwork>
              <artwork type="ascii-art"><![CDATA[
+--------------------+
| prove()            |
|  +--------------+  |
|  | Valid        |<----- meas
|  |  +--------+  |<----- joint rand
|  |  | Gadget |  |  |<-- prove rand
|  |  +--------+  |  |
|  |              |  |
|  +--------------+  |
|                    |
+-+------------------+
  |
  v proof
]]></artwork>
            </artset>
          </figure>
          <t>The proof generation algorithm invokes the validity circuit on the encoded
measurement and joint randomness. The validity circuit in turn invokes the
gadgets defined by the circuit. The prover records the values on input wires of
gadget instances during circuit evaluation, and constructs gadget polynomials
that the verifier will use to compute the outputs of each gadget. Additionally,
the prove randomness is used as a blinding factor when constructing gadget
polynomials.</t>
          <t>To generate the gadget polynomials, the prover evaluates the validity circuit,
and records the values on each input wire of each call to each gadget. This is
accomplished by "wrapping" each gadget in a class <tt>ProveGadget</tt> that records
the wire inputs. This class is listed in <xref target="gadget-wrappers"/>. Denote the value
of the <tt>j</tt>-th wire for the <tt>k</tt>-th invocation of gadget <tt>g</tt> as <tt>g.wires[j][k]</tt>.</t>
          <t>Next, the prover computes each of the "wire polynomials" for each gadget. For
each wire polynomial, take one prove randomness value and designate it the
"wire seed" for that polynomial. The <tt>j</tt>-th wire polynomial is the lowest
degree polynomial that evaluates to the "wire seed" at one point and
<tt>g.wires[j][k]</tt> at a sequence of other points. The gadget polynomial is
obtained by evaluating the gadget on the wire polynomials.</t>
          <sourcecode type="python"><![CDATA[
def prove(self,
          meas: list[F],
          prove_rand: list[F],
          joint_rand: list[F]) -> list[F]:
    # Evaluate the validity circuit, recording the value of each
    # input wire for each evaluation of each gadget.
    valid = ProveGadget.wrap(self.valid, prove_rand)
    valid.eval(meas, joint_rand, 1)

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

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

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

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

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

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

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

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

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

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

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

                r_power *= r

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

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

        return [range_check, sum_check]

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

    def decode(
            self,
            output: list[F],
            _num_measurements: int) -> list[int]:
        return [bucket_count.int()
                for bucket_count in output]
]]></sourcecode>
        </section>
        <section anchor="prio3multihotcountvec">
          <name>Prio3MultihotCountVec</name>
          <table>
            <name>Parameters for Prio3MultihotCountVec.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Valid</tt></td>
                <td align="left">
                  <tt>MultihotCountVec(field, length, max_weight, chunk_length)</tt> (this section)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOFS</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
            </tbody>
          </table>
          <t>For this instance of Prio3, each measurement is a vector of Boolean
values, where the number of <tt>True</tt> values is bounded. This provides a
functionality similar to Prio3Histogram except that more than one entry (or none
at all) may be non-zero. This allows Prio3MultihotCountVec to be composed with a
randomized response mechanism, like <xref target="EPK14"/>, for providing differential
privacy. (For example, each Client would set each entry with some small
probability.)</t>
          <t>The validity circuit is denoted <tt>MultihotCountVec</tt> and has three parameters:
<tt>length</tt>, the number of entries in the count vector; <tt>max_weight</tt>, the maximum
number of <tt>True</tt> entries (i.e., the weight must be at most <tt>max_weight</tt>); and
<tt>chunk_length</tt>, used the same way as in <xref target="prio3sumvec"/> and <xref target="prio3histogram"/>.</t>
          <t>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[
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]
]]></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
vector of inner node field elements or leaf node field elements.) The scheme is
comprised of the following algorithms:</t>
        <ul spacing="normal">
          <li>
            <t><tt>idpf.gen(alpha: tuple[bool, ...], beta_inner: list[list[FieldInner]], beta_leaf:
list[FieldLeaf], ctx: bytes, nonce: bytes, rand: bytes) -&gt; tuple[PublicShare,
list[bytes]]</tt> is the IDPF-key generation algorithm. Its inputs are the index
<tt>alpha</tt>, the values <tt>beta</tt>, the application context, and the report nonce.  </t>
            <t>
The output is a public part (of type <tt>PublicShare</tt>) that is sent to each
Aggregator and a vector of private IDPF keys, one for each Aggregator. The
nonce and application context are used to derive the fixed AES key for
XofFixedKeyAes128 (<xref target="xof-fixed-key-aes128"/>). Looking ahead, this key is used
for extending a node's seed into the seeds for the child nodes at each level
of the tree; see <xref target="idpf-bbcggi21"/>.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>alpha</tt> <bcp14>MUST</bcp14> have length <tt>BITS</tt>.</t>
              </li>
              <li>
                <t><tt>beta_inner</tt> <bcp14>MUST</bcp14> have length <tt>BITS - 1</tt>.</t>
              </li>
              <li>
                <t><tt>beta_inner[level]</tt> <bcp14>MUST</bcp14> have length <tt>VALUE_LEN</tt> for each <tt>level</tt> in
 the range <tt>[0, BITS - 1)</tt>.</t>
              </li>
              <li>
                <t><tt>beta_leaf</tt> <bcp14>MUST</bcp14> have length <tt>VALUE_LEN</tt>.</t>
              </li>
              <li>
                <t><tt>rand</tt> <bcp14>MUST</bcp14> be generated by a CSPRNG and have length <tt>RAND_SIZE</tt>.</t>
              </li>
              <li>
                <t><tt>nonce</tt> <bcp14>MUST</bcp14> be generated by a CSPRNG (see <xref target="nonce-requirements"/> for
details) and have length <tt>idpf.NONCE_SIZE</tt>.</t>
              </li>
            </ul>
            <t>
Post-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t>The number of IDPF keys <bcp14>MUST</bcp14> be <tt>idpf.SHARES</tt>.</t>
              </li>
            </ul>
          </li>
          <li>
            <t><tt>idpf.eval(agg_id: int, public_share: PublicShare, key: bytes, level: int,
prefixes: Sequence[tuple[bool, ...]], ctx: bytes, nonce: bytes) -&gt; Output</tt> is
the IDPF-key evaluation algorithm run by each Aggregator. Its inputs are the
Aggregator's unique identifier, the public share distributed to all of the
Aggregators, the Aggregator's IDPF key, the "level" at which to evaluate the
IDPF, the sequence of candidate prefixes, the application context, and the
report nonce. It returns the share of the value corresponding to each
candidate prefix.  </t>
            <t>
Pre-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t><tt>agg_id</tt> <bcp14>MUST</bcp14> be in the range <tt>[0, idpf.SHARES)</tt> and match the index of
<tt>key</tt> in the sequence of IDPF keys output by the Client.</t>
              </li>
              <li>
                <t><tt>level</tt> <bcp14>MUST</bcp14> be in the range <tt>[0, BITS)</tt>.</t>
              </li>
              <li>
                <t>Each prefix <bcp14>MUST</bcp14> be distinct and have length <tt>level + 1</tt>.</t>
              </li>
              <li>
                <t>The length of the nonce <bcp14>MUST</bcp14> be <tt>idpf.NONCE_SIZE</tt>.</t>
              </li>
            </ul>
            <t>
Post-conditions:  </t>
            <ul spacing="normal">
              <li>
                <t>The length of the output <bcp14>MUST</bcp14> be <tt>len(prefixes)</tt></t>
              </li>
              <li>
                <t>The length of each element of the output <bcp14>MUST</bcp14> be <tt>idpf.VALUE_LEN</tt></t>
              </li>
              <li>
                <t>If <tt>level == idpf.BITS - 1</tt>, then the output field <bcp14>MUST</bcp14> be <tt>FieldLeaf</tt> and
 <tt>FieldInner</tt> otherwise</t>
              </li>
            </ul>
          </li>
        </ul>
        <t>In addition, the IDPF provides the following method:</t>
        <sourcecode type="python"><![CDATA[
def current_field(
        self,
        level: int) -> type[FieldInner] | type[FieldLeaf]:
    if level < self.BITS - 1:
        return self.field_inner
    return self.field_leaf
]]></sourcecode>
        <t>Finally, an implementation note. The interface for IDPFs specified here is
stateless, in the sense that there is no state carried between IDPF evaluations.
This is to align the IDPF syntax with the VDAF abstraction boundary, which does
not include shared state across VDAF evaluations. In practice, of course, it
will often be beneficial to expose a stateful API for IDPFs and carry the state
across evaluations. See <xref target="idpf-bbcggi21"/> for details.</t>
        <table anchor="idpf-param">
          <name>Constants and types defined by a concrete IDPF.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>SHARES: int</tt></td>
              <td align="left">Number of IDPF keys output by IDPF-key generator.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>BITS: int</tt></td>
              <td align="left">Length in bits of each input string.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VALUE_LEN: int</tt></td>
              <td align="left">Number of field elements of each output value.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>RAND_SIZE: int</tt></td>
              <td align="left">Size of the random string consumed by the IDPF-key generator.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>NONCE_SIZE: int</tt></td>
              <td align="left">Size of the random nonce generated by the Client.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>KEY_SIZE: int</tt></td>
              <td align="left">Size in bytes of each IDPF key.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>FieldInner</tt></td>
              <td align="left">Implementation of <tt>Field</tt> (<xref target="field"/>) used for values of inner nodes.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>FieldLeaf</tt></td>
              <td align="left">Implementation of <tt>Field</tt> used for values of leaf nodes.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>PublicShare</tt></td>
              <td align="left">Type of public share for this IDPF.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>Output</tt></td>
              <td align="left">Alias of <tt>list[list[FieldInner]] | list[list[FieldLeaf]]</tt>.</td>
            </tr>
            <tr>
              <td align="left">
                <tt>FieldVec</tt></td>
              <td align="left">Alias of <tt>list[FieldInner] | list[FieldLeaf].</tt></td>
            </tr>
          </tbody>
        </table>
        <section anchor="poplar1-idpf-index-encoding">
          <name>Encoding Inputs as Indices</name>
          <t>How data are represented as IDPF indices is up to the application. When the
inputs are fixed-length byte strings, the most natural choice of representation
is as a bit string formed from all the bits of the byte string, first ordered by
byte position, then ordered from most significant bit to least significant bit
within each byte. This ensures that, when a byte string is a prefix of another,
so too is its corresponding index. (Index prefixes are defined in <xref target="idpf"/>.) For
example,</t>
          <artwork><![CDATA[
Byte string: 01 02
Bit string: 00000001 00000010
]]></artwork>
          <t>is a prefix of</t>
          <artwork><![CDATA[
Byte string: 01 02 03
Bit string: 00000001 00000010 00000011
]]></artwork>
          <t>Additionally, lexicographic ordering is preserved by this mapping from a byte
string to a bit string.</t>
          <t>When the inputs are variable length, it is necessary to pad each input to some
fixed length. Further, the padding scheme must be non-ambiguous. For example,
each input could be padded with <tt>b"\x01"</tt> followed by as many <tt>b"\x00"</tt> bytes
as needed.</t>
        </section>
      </section>
      <section anchor="poplar1-construction">
        <name>Specification</name>
        <t>This section specifies <tt>Poplar1</tt>, an implementation of the <tt>Vdaf</tt> interface
(<xref target="vdaf"/>). It is defined in terms of the <tt>Idpf</tt> implementation of
<xref target="idpf-bbcggi21"/> with <tt>SHARES == 2</tt> and <tt>VALUE_LEN == 2</tt> and
<tt>XofTurboShake128</tt> as specified in <xref target="xof-turboshake128"/>. The associated
constants and types required by the <tt>Vdaf</tt> interface are defined in
<xref target="poplar1-param"/>. The methods required for sharding, 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[
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)
]]></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[
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')
]]></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[
def is_valid(
        self,
        agg_param: Poplar1AggParam,
        previous_agg_params: list[Poplar1AggParam]) -> bool:
    """
    Checks that candidate prefixes are unique and lexicographically
    sorted, checks that levels are increasing between calls, and also
    enforces that the prefixes at each level are suffixes of the
    previous level's prefixes.
    """
    (level, prefixes) = agg_param

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

    if len(previous_agg_params) < 1:
        return True

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

def current_xof(self,
                level: int,
                seed: bytes,
                dst: bytes,
                nonce: bytes) -> Xof:
    if level < self.BITS-1:
        return XofFixedKeyAes128(seed, dst, nonce)
    return XofTurboShake128(seed, dst, nonce)
]]></sourcecode>
        </section>
      </section>
    </section>
    <section anchor="security">
      <name>Security Considerations</name>
      <t>VDAFs (<xref target="vdaf"/>) have two essential security goals:</t>
      <ol spacing="normal" type="1"><li>
          <t>Privacy: an attacker that controls the Collector and a subset of Clients and
a subset of Aggregators learns nothing about the measurements of honest
Clients beyond what it can deduce from the aggregate result. It is assumed
that the attacker controls the entire network except for channels between
honest Clients and honest Aggregators. In particular, it cannot forge or
prevent transmission of messages on these channels.</t>
        </li>
        <li>
          <t>Verifiability: an attacker that controls a subset of Clients cannot cause
the Collector to compute anything other than the aggregate of the
measurements of honest Clients, plus valid measurements from some of the
attacker-controlled Clients. It is assumed that the attacker eavesdrops on
the network but does not control transmission of messages between honest
parties.</t>
        </li>
      </ol>
      <t>Formal definitions of privacy and verifiability (i.e., robustness) can be found
in <xref target="DPRS23"/>. A VDAF is the core cryptographic primitive of a protocol that
achieves the above privacy and verifiability goals. It is not sufficient on its
own, however. The application will need to assure a few security properties,
for example:</t>
      <ul spacing="normal">
        <li>
          <t>Securely distributing the long-lived parameters, in particular the
verification key.</t>
        </li>
        <li>
          <t>Establishing secure channels:  </t>
          <ul spacing="normal">
            <li>
              <t>Confidential and authentic channels among Aggregators, and between the
Aggregators and the Collector; and</t>
            </li>
            <li>
              <t>Confidential and Aggregator-authenticated channels between Clients and
Aggregators.</t>
            </li>
          </ul>
        </li>
        <li>
          <t>Enforcing the non-collusion properties required of the specific VDAF in use.</t>
        </li>
      </ul>
      <t>In such an environment, a VDAF provides the high-level privacy property
described above: the Collector learns only the aggregate result, and nothing
about individual measurements aside from what can be inferred from the
aggregate result.  The Aggregators learn neither individual measurements nor
the aggregate result.  The Collector is assured that the aggregate statistic
accurately reflects the inputs as long as the Aggregators correctly executed
their role in the VDAF.</t>
      <t>On their own, VDAFs do not provide:</t>
      <ol spacing="normal" type="1"><li>
          <t>Mitigation of Sybil attacks <xref target="Dou02"/>. In this attack, the adversary
observes a subset of input shares transmitted by a Client it is interested
in. It allows the input shares to be processed, but corrupts and picks bogus
measurements for the remaining Clients.  Applications can guard against
these risks by adding additional controls on report submission, such as
Client authentication and rate limits.</t>
        </li>
        <li>
          <t>Differential privacy <xref target="Dwo06"/>. Depending on the distribution of the
measurements, the aggregate result itself can still leak a significant
amount of information about an individual measurement or the person that
generated it.</t>
        </li>
        <li>
          <t>Verifiability in the presence of a malicious Aggregator. An Aggregator can,
without detection, manipulate the aggregate result by modifying its own
aggregate share.</t>
        </li>
        <li>
          <t>Guaranteed output delivery <xref target="GSZ20"/>. An attacker that controls transmission
of messages between honest parties can prevent computation of the aggregate
result by dropping messages.</t>
        </li>
        <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. This is
required in order to leverage security analysis for the privacy definition of
<xref target="DPRS23"/>, which assumes the nonce is chosen at random prior to generating the
report. Uniqueness of the nonce is not sufficient because the verification key
is controlled by the attacker.</t>
        <t>Applications will need to protect against replay attacks to prevent disallowed
re-use of reports (see <xref target="agg-param-security"/>). Furthermore, in applications
that aim to achieve differential privacy, it is necessary to limit how much
each party contributes to a single batch or multiple batches. It is <bcp14>RECOMMENDED</bcp14>
that the nonce generated by the Client be used by the Aggregators for replay
protection.</t>
      </section>
      <section anchor="the-public-share">
        <name>The Public Share</name>
        <t>The Aggregators <bcp14>MUST</bcp14> ensure they have both received the same public share from
the Client. It is sufficient, for example, to exchange a hash of the public
share over a secure channel.</t>
      </section>
      <section anchor="agg-param-security">
        <name>The Aggregation Parameter</name>
        <t>As described in <xref target="sec-daf-validity-scopes"/> and <xref target="sec-vdaf-validity-scopes"/>
respectively, DAFs and VDAFs may impose restrictions on the re-use of reports.
For Prio3, reports should only be aggregated once; for Poplar1, reports may be
aggregated multiple times, but never twice at the same level of the tree.
Otherwise, one risks re-using correlated randomness, which might compromise
confidentiality of the Client's measurement.</t>
        <t>Higher level applications that use DAFs or VDAFs <bcp14>MUST</bcp14> enforce aggregation
parameter validity. In particular, prior to beginning 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 "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="RFC8446">
          <front>
            <title>The Transport Layer Security (TLS) Protocol Version 1.3</title>
            <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
            <date month="August" year="2018"/>
            <abstract>
              <t>This document specifies version 1.3 of the Transport Layer Security (TLS) protocol. TLS allows client/server applications to communicate over the Internet in a way that is designed to prevent eavesdropping, tampering, and message forgery.</t>
              <t>This document updates RFCs 5705 and 6066, and obsoletes RFCs 5077, 5246, and 6961. This document also specifies new requirements for TLS 1.2 implementations.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8446"/>
          <seriesInfo name="DOI" value="10.17487/RFC8446"/>
        </reference>
        <reference anchor="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="2024" month="December"/>
          </front>
          <refcontent>commit hash 5b7df1d</refcontent>
        </reference>
        <reference anchor="DAP">
          <front>
            <title>Distributed Aggregation Protocol for Privacy Preserving Measurement</title>
            <author fullname="Tim Geoghegan" initials="T." surname="Geoghegan">
              <organization>ISRG</organization>
            </author>
            <author fullname="Christopher Patton" initials="C." surname="Patton">
              <organization>Cloudflare</organization>
            </author>
            <author fullname="Brandon Pitman" initials="B." surname="Pitman">
              <organization>ISRG</organization>
            </author>
            <author fullname="Eric Rescorla" initials="E." surname="Rescorla">
              <organization>Independent</organization>
            </author>
            <author fullname="Christopher A. Wood" initials="C. A." surname="Wood">
              <organization>Cloudflare</organization>
            </author>
            <date day="30" month="January" 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-17"/>
        </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 6370?>

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

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

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

    def __init__(self, p: list[int], 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]
]]></sourcecode>
      </section>
      <section anchor="gadget-parallel-sum">
        <name>Parallel Sum</name>
        <t>The parallel-sum gadget applies a subcircuit to multiple inputs in parallel,
then returns the sum of the results. The arity of the gadget is equal to <tt>count</tt>
times the arity of the subcircuit, where <tt>count</tt> denotes the number of times the
subcircuit is called. The degree of the gadget is equal to the degree of the
subcircuit.</t>
        <sourcecode type="python"><![CDATA[
class ParallelSum(Gadget[F]):
    subcircuit: Gadget[F]
    count: int

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

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

    def eval_poly(self,
                  field: type[F],
                  inp_poly: list[list[F]]) -> list[F]:
        output_poly_length = 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
]]></sourcecode>
      </section>
      <section anchor="gadget-wrappers">
        <name>Shims for Generating and Querying Proofs</name>
        <t>This section specifies two "shim" gadgets, one for generating an FLP as
specified in <xref target="flp-bbcggi19-construction-prove"/> and another for querying an FLP
as specified in <xref target="flp-bbcggi19-construction-query"/>.</t>
        <sourcecode type="python"><![CDATA[
class ProveGadget(Gadget[F]):
    """
    Gadget wrapper that records the input wires for each evaluation.
    """

    def __init__(self,
                 field: type[F],
                 wire_seeds: list[F],
                 g: Gadget[F],
                 g_calls: int):
        p = 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
]]></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[
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
]]></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:
H4sIAAAAAAAAA9S96XrbxpYo+h9PgVa+e0LZJDV4SCJvp1uWZUc7HnQtxdm7
3W4RJEEJMQkwACiJkd0Pcn7dZ7n3xe6aqmpVAdTg7O4+rS9fLJFADatWrXno
9XpRndXTdCdee5+W2SRLhtM0fp5VdZkNF3U6jndPT8v0NKmzIo9fLPIR/lKt
RclwWKbn+Nrz3Rdr0bgY5ckMhhmXyaTuZWU96Y0m5WnvfJxMels/RKOkTk+L
crkTZ/mkiKJsXu7Edbmo6u3NzR82t6OkTJOd+ODd8YuoWgxnWVXBRPVynsqH
F0X56bQsFvOdeO/Fu5fRp3QJH43h27xOyzyte89x6iiq6iQfnyTTIodXl2kV
VbOkrE9+XxR1Wu3EeRHNs534Q12MunFVlHWZTir4bTnDXz5GUbKoz4pyJ4p7
UQw/vK132egsKcfxq378LIHZKvquKE+TPPuDgAPLyqpRQZ+nsySb7sTldPgv
2fy8X136gz1PzrNxvFcUn1pGOTiCzalBxtl5Wp6meT1OztN/OcUP+6Ni5o+4
d1bCkRXzs7SMD5O6LvK29U2LxXgyBUDr8Uf46pzeuZ+l9WTVFIdn2XSazefx
0eismM9nSd42x8uiOJ1641f28X85pS9p6Cgvyhm8c57uRPD07v7RDr1kkHF3
fJ7kI0C//XxULueEfUd4sHgIHXh8fY2et4dFPz1Z6+uihE3Ff+3HzxFtsjz4
fn+aZHmKJ/kpLYPv/gr/r+J3/fhNOjo7T+pk2vrAi6LOgi9eJRdlCouO9xFJ
quosmYXz9uN3xTAZfWofEpZbJsv4r2Vfvo/hsgDK/tV9EX8TX86m2+VkFPMN
zOBeVfEajrMWJ/DbX2mcPj7MIBrDEzsx3LIthnAC2FTvxGd1Pa92NjYuLi76
OSBP/7Q435gvhtNsRGdZbSRyBr3UnkGvkjPoJXAFIrzK3jG+/Ovbw+0t/ygP
y6y4D/hTZufJaAn/plVanmf5qSUtKR5tDWvIRlUMO4qfFcU0TeDE4c6l1XUn
fbQol0m8Ox4n+afwPH4G6OTxy6Qcpo3zzwDmk0n4+btkAjgbvwXqV5xXn5bB
17t5nZ0WeRYfFtMl3Bv4NRkXCw/K29v0J9CSEZAvuLYAgaN0tCizehkD7OI9
BGVxWibzs2UM4AM8qxFJq7hztPdG0Do8pCzpj8oNGH1r49F3jxHUz57tvXx5
sPWDD+t/Tcui93NeXEzT8WkKsC6KSRXj3UlHJZBIAugYCFCdEKBfLKbTZfwK
LkMChGPv8FpYP4cTeQZU9awBzbSGM3xWLKchQH9K83IJlA6uI1CJ3stsOKyC
R95k5/HLbDoskuCLvy/Ok2l8ANco8yAMzKQBYQbq9bDb+mFj6/vvHexCPH2V
nZ7VFyn+Pz6Gu59nvy/gauEREe7CFn9Kk/Nl/FMG2y3/J4Bqe6sJqoP9/f3Y
YuT/sveyc/S/Dm/Gvs2t7xQEHwREG4Y8m6VwjeOjT2k9OoNL/j8BSg++DqG2
H2xsbW5tEzzgKj7ygWFkJbl6RMtugMc1+777LXnU3NT+oiyIkrfvCzlBlozK
PrD0jaSE4ztPN1LzDg658cPmo8ebDzY37S/9+XiCANh7+Wzruybd3zFXp4uM
D4S9LtHAo1EyJUFzr5jNFzULl8WklSF8DQKtxBILne+a0PnlaP/Nwd/io+Vs
XlTZYoZkU2gzkMyjZVWnsyp+nlbZaU67OJjNp+kMXub1d94cPT9YcYPG034y
mhFgx0UGaNN/BD8bD7YePXz8YLNP/z4iTHpeLDa3fUAenwE8lkNgTLt1DcLD
dRD5a3GWo/ACw4zg6HwBoIU1sfBMGwA0+hX5EIhruPXDNC17ddHDf+3uOweH
x4dHqzZZZLRD2N3W5uZ3Gw96jx5u9h4++u7h973vT7Yf0vYO3x2FZONuikfb
3klK+glEzOSMhOvK/2aFdGy/f519SgE/q8U0/eR/s0rovY50GIK6n5+B+IRy
DnGTYlqcZsBPHH51DvePV8FS05gHmwS5i2LzsQ+45xmIMCBy1hmcnUx7DYD2
lnl9BkyfZGIfMx7fhBl7xXRa/L6Qa7G7qAsQ+5IuyLz56SI5TSu+2CBwgGQz
m+GuOwd7u69WsZRpln/qV3OkiGmJGsEG6FdzmNFiz9bWd99/Bys72cLd7x/+
vPXQ3/273cPDt+9QaMvHxSz7Q6EM4ZIApKcEzrflOMPdvEurOSBTet1N+v/+
93QCQtF+CUs9raoi1CHeJ9USoJ6dLUINYhfQqIJFlUn8c1HCuZ8nPvF52IT2
7t5rgHFOxwkaBMCYSSNgLAmNxWy2yI1k7th3Z29v5W1skJytrYePNrYfP97c
fvxdH/998JDEof03h7s+aPcvAUUXZRq/AS1nItNagM6VBA/QXJLY3sFR1uNf
zzKg3ofJPC197WO7XfsYFaAKb/2AegUM0x+N814yn7OSuIG/WW1EntyAnSPK
b/AbGwjCZFT36jLBu7YB/GgDl3JCKzmhlRgm9SL5Y/sRcI23B32DZT98933v
QW/zwXZv8/F3jx4Cndoi8Rr4+cPwsjnSdFhkee2IEh0RUOmsjHfVkq/Drrvz
8xakuYGf33zHePePH273Hj3a3t7sPTp58Ih2f/Sv25v+9l8ukjKBiWH3bxc1
YCZwwimaJpDPkvZapinQmfgn4MdVHb9OfisIRV8f7l0HiPfZfDGNXxbLhp79
92yCKmCRnwZf7J2l+R9nWfyvZ4HqtXk3Oe628AE5p/fo8fffb/a2TraJSb/8
+ddf/x5C6BkKb2UMc6O8l8aVuaSoQZwl00nvlHT1U1BIp0QgAVo18PbZYlpn
PSDRNarb8F5dw9fXGjj2zhag2S6KBvcHgg1cJ/45qf8IvvtblhTxr0krND8l
Wfxr2vjq7wv4778exN8LiBsQ3p8ALcpgVhYiEb5p/BqhN0/KeulJk5OymMUv
sst03Ps5XcbPpsXoU7yXoQxw7cX8B0L2duD7Cn0sRYDWTlYn3XbzOxKwXh8+
PzreDnSR1wmK0lYYh7NGLReuMim0PVFoCaogYjKV6z1LKnjidQp/3yCFZ7Os
Rnvb6wI2Eapj1whfIqy3yW1icyzhMD/FR0n5KQm57Jv0E8AlK6r4ZQpAwF+O
q2JRV4Uv6m+3KEL/EBGteQrbDze2t7f4FN693wxsMwo7gcLfXnbj7R5MlwkI
qmWRF+fBV29nn4AyA3DzcRqarN7OAOzvUthiMR0H3x0lU9Ap3idjAIIvDt7R
wnIXRrP54MGjx8Bm6ZK/fvfTZsBmD/KxgwzoPHApunGG51Fl/CesCyT1msxa
ZTpeMA9m+VNLDHFdEHktST6MCxAQQCqcpQDdMZ70teD+BZgb8DAgMCHevUuB
EhT4T974bo/0wQp44BT+qdMsgGsLDwexoQAeCsqvZxjsHO/t3VLNYtiiqrUN
yuT3SEERtm9B983y4xSXVJdLH8r8ZWy/DWS1zXb7QDrsi1mAFgB/I9Jvb8Ed
2/ru4ebDxxvm0UkGmywue3Ahy1HaGxejqj8r/gBlKqFX66KYfspqkN7gZHOA
RLVRm7XAh9NpSqe6UdA6+2f1bIp7Otx9s/+q92J///mz3b2fA3UgPc/SCwRk
uwvq0bVq82IKitFPaVWlbcQjhAR6Ngwk0GdiLSYbs+p0AyfdeDsbn5UPy7db
82lykk9/W2xPv3v71/2Xvx6+3sCtHL1+tR2g/i4xsCnKDs9S2DbgF3CibJwa
TH6zmA3hM0IZsrIdA25XaIKPO2+Oj6+VGHZB9QEqUcCtB1qdXCQhGX6XwuEA
ysPIoUwKFPqsiF+lAWxasJmY2e5oBIDsxufFtB9vbd2Bej76nsTPw2L63ZaS
03/Y3DjahLPoPfpuC/D7h++2UGDY+uHx4x6pxscgcL4HjCnKKrCcoCR6zt8Y
Q27xgDXVAg6mDBa3ZlZ3mtVniyGTMjzNNpRaa24fngdWCMJedRY/Gn43nmyN
9c16no5SOkECXnT+QFw5uOgqm6Lmh7/24hfFAgWc9y/jC1gI/G8M/0cpkq3T
1TwdgVqWjqOo1+vFybBC7aeOouMz4MJw2RZolYrHaTUCXg4M7S4WlriDHt1q
HQhqNElm2ZSIE8uoLGbNy6Iu4JIySEfE1pCHJtZ6Vzl3TgEqQrwAfTGapQnq
lLi0qo9IXKVqKMA7XHB2msPCAE2BfqJ0BzIX2gyreFrgDPBcHU9hoDoCsmFn
xA2gSgpTpZcgSqGYjRfGDB+fkVIyRVYC/AUUyQVwXb0gdD/HeYojVGmax0N0
1izNoCKoA/9Iyj6ISPRXBXcDMG2WdmOCWJxMp8UFfhXxa8SBxnCdR3WcTeIk
ngHDHWXFosKznKG3OJ9kpwv0yIymJNeS57vGswFRM8tBFczGGnAAt4vCqRgy
LyzdokQ3RsDgwZymQECSaW++KIF7ppEGVocuwjrzzLyoUTgjNYUcHGciD3bk
kqz3GdFm2Xg8TaPoG/S5l4Ww3ijqvHuxF+8/PzhGcwwsFM4cwACoCPiSEEPr
r+OBx8wOaCb6nq4VLQKhBldJzB+Zb1kdATCG+BreiqSO7nJL+3gr0ngxzH5f
oPAAuIyHZ4IG4Ew+AbJkNQF8nAJawJZroqm4TAV7eDWaIqHoVaMEbhJItDlo
vnnSjS/OUgIhu08RilO4sDVsZkxnjTMO0zOQcOEPWMFIbDtRJXZVwGoalO4F
HCfABlABFUKSD/ESTZN5F/D4AnG0C6PVF4in1gML54B3Bd8ErFnQXQf0k/UT
jNWzdK/oWlaITRXsHFbP2gFA7EWBFynBU+i67wFCSr7iIeCGwW0CCMqevTkK
nqFPJ1DMARtr3n8w0oyo2gUKsfDOpxxu0cVZNjpD/EE5j44sKyP9DiL9AhWU
WVHh0QAFJjqRwDhLHOaUOOdkUS+Ispyn02Iux0jYpgbrx0d8fUa84G9jjIcA
/KC5F1VyCmAApro4PUNwLKZjwPJzxJUKyFSG7m8APpoJgRaDCoLjz7pwgrAF
WBLvhYGNy0bzGUkPSNHiU3g7F/BFAOtxRkuKogMADNGgrF4kIuOSuUChpIhK
ANUM5WGg1RkiNtC6FM/bkeTIkeRunPZP+10D4qJkst88FlwrQZfgDHNcwIlH
E2Q14q+Zp0AgUuB3cOHTSzjgLKWgDbOrcQY7rQirgegZZNeIE7UyDVjalKk3
yoEAphVUmyjDmO1QdKiI+qm5496TjSHNSbPq1RfmCQ/AzZkROBGnkAgA70sE
ngDbGYFqrNW3uVHZnx+uR1dXZKn/8gVjPQBj4EyAOCefYE5AUJQEEp9vEVRi
c3n1wNNlJHdS2KHADjc3Tk/R4AaIzueImNIOJbyTABU4mCrCNz0YOfCzVmVo
7byEC1GlsHiUbkpEs3E/9ugCKDfmRKfkQCF7fHx1Rbb6L18AzxLBe+SV8E4V
5wUMyrYZuKggcfbwtufR2EglhHdI5cdjosos+WY+IR6CboE8j5klHiY/FjXl
ASKobXICPJ7zLIs5QQKXtvRwphvhSobpKIE94GJwrSxYeOul7fApmIFSoEKV
7BpYckZwjeBaZjOENT5WlwvcwoxFvBLmLXKi2slotCgZJffxEl3gSnlQwA9Y
MgtIIYZ3DTEgeJwhDiupBe4/KF9CtpBKoqRFpn20ps2AsxJhDMg3vW5ITD9+
ywOCgBGdAWi6gIRzYHE4YcFfrfFQazgWLzkxog3BGsbM4DKqdSNwohmQbEQ6
UvKnLCDAi4uShCVH5JChAb+G7xS8ThegbRiqrkb+tmIYE767xROj5uUTCBGT
eKkMrIzIBay2S7dlioOXQGJorgsE4pAfZUSCWeyxhnfKp3sg30yXCKuqmOLF
QkyPnx8CMEawnKyagZANxBYRi7aIdA2jJuNhMiXDsOH5Qm4IOwED0SYCuLIr
YhyyPxIxchhpweiQmHe070bfKCFCWSVMO9Ly/kiZVTuvD/fW+VKdFiiZTITN
6SGQRuUFcW+Qd+eAYpHgohXIqzNio4iaeOGXNXND4p4k+rZSsmG6BAYZXRCt
rIX6gxgqJCUAPiwVLtNZBjhfsbxJSwbR3l3f/DRiJPfiEHzKCCoqICarQMju
mtSkYqkbBEQmA8RIgJ7O+KoCwrACAsjeT4H1wlHFIMuytwCpq52UHPxAtqLX
gJcFiXq4DaHKZC5BZkw04zzh+6FxqPJ0J81e4d6lU2BcBZFh0qI+wcNwo/D8
9MU3p7CUTYUXqwIazwZOYHKrlc4aNZVpUlUp3U7chlX3hDckGXmK6bpHlvOh
BwTfwNOqWBBKbtRbgfnuvujCykDm//JlXSYwahUINTXykyryGSMSFHOsFcfp
VBRz6NQoXqibMTKMhXSvMgW1AmENm4XdgQhUZ6mhRnpIuvgjIMuAmC+yEnEB
6SgeLLBac1npLcIMJhUe8qMoCAxlicSJJJg5qpzmgHjd/bhzvJwD3cC4PloC
fUyynDGEkEpegeoST7Ic3bWgN07HoKId4UKA7rHwhmMDvBUSWNhkJKoYqyxr
Gq1XGRfWvh1lATBAw2njkihxQRxqRsdSlxg6Tm40Iw4hDMyJMLfzWOFO49AM
1zcMP8QEgdK0YMCJgMHcUmYAGQS5tXBFEuMsY3oSsTgBEGt+ieYgsgQUwr9F
4qiI/dNXp2nt05yIpTFzuywMsopoAOyJuVHNgp/e6cRcCCLDTDhgOCL8OVkW
WITBzSD1RjwA4bBgNt6UnPvx/qVIb1k+mi7G6U4E786ScqlFdqPswFddfD9n
g7yJF0YNLKMFPjH8kmlt9PsCldxpavUSIJpZAo+dodsIo0mqJyBgUoRqiUIv
JQY8icn0BLIGLhsBHvENWpRupGfTArjCJJuiNaMf/2SUZyR/eFYTa/OaZEIN
kE1E5WJYZiNSJxnT+X5izDjRc1mNYhpyqRB2BMt07Ju7iIhNQHHqiuFDyCVI
D6BPzVKMyAHUmCGVIrpCR1tNUTEGfEQhJTKrTdgn0rS76dO3JAjJehT9x3/8
R/SiAw+eoEmGT6g62erG/X5f/ni9Hj8lW+XL5nPr8X18Ev7f/PL1Oo0OnA8N
F4OWgQdEfZry6uDlgG6EkfuWUV7kPQGu2Qij0cDOal7B31P0t9M+AdMt3o/O
gEWiBS9q3kWkOmKXGmensAVSP/Cg7esBzb66othOUGcisu+x0ZOkxqqYnxH2
k3bIih3Gw1QoAyXVp8qZAChxhSkguVNxdUa1M/KxcbwyeyUv7pcvsWdh9c1z
sDQJZEY+3EGJwcjhU7Jf0Crg+sOy++tsB6uIxDNfJg3eGmDH6YTwmyQ1zdHx
8JAswnfOjhzd1o6MLPmceXI/PiCVKzPqxRD9kgYOXWXNPHf2ahEcJxh/dkFM
FKQb4KHPlmIuRqWazywyZ4amjJhsp76mwVQhiXP2oxh5eotQbGsT+FoVoeRZ
IbAXGQxHyghrqwFesLlETLSt00QyDdkMkTbA81ubgoFIIUVSdrteTNFiK/yU
RcGKpo+c5dgqKHDAs7lRfmHN5WJex6EsizKD05JbDMpAFh3Ytf3dGrNjZcwm
4xJQMSZPKL8Y4zEcU1GiQOtM3ghUawxGbueJkHDqpNBpnV1gYzGPDMLix2Xb
DIoKS7xQBkNY+wGhBx+A4wOJsTDYWlLEcY4KXJbLhERor64oXBlNFFdXHJEK
NwhuyC5pCwgqb3zQiIyYMXJO2mwU1y5NwMi99gJFahskI16ndTNY6cQEKRXk
WdSMilCBpTNDkmnfP4dbNCNTE1sAAOCZOZP5tFg+IYEOvlrC6ogN8qAg2xAZ
pDNH+kbbX5pNE9Yo43noyYHNigZfg2pbmntLooX2yLMByQQ6ddEp4nRuYIVV
MakvMD0NzlL8OGzF5ERB+IM/RTil+TkGQxgTQiwLUHYBROIKdbDIKKRCafH6
mfsk7gEAMOHre/pF/GlExZCdg8BVVURSyixlMKA2o06fqVQEyIJGboBN08F1
jgJTZsFN1nAOBSE5SQKAIkEWYZEIQnQx0Qxwk2vYFx4hCiTwoNgfQeWvgruD
vK9kKZbET1BPUFwv0aPAihUmbG31MWIX7bDAVE7hjd4UDeVaTyPT3tXVPz/f
PXx60HveFx9LWk968/msN07meI2QHrDzWcT2LmgxGXlRCDlB9BGrDvmGEbGu
t0jQYKwvwSLUVYIF4hZWwS/24Qdf8Uhk3186Qa5mPl4lk5QN/JS/FiNEXrLf
zPMBjPz4W7i69mqwDp6wagUUtpieE9aKD50vMttGOkK8u+0mBPGDKc1BVDsZ
KbTVrj8xS95L5kyqRPfUrsZRgQKjMdgnrGqF3ANYz6mdp2kLkIuj7/0TC1uc
37gthKWxMxVPGpHe9+bGTV4G5BBokZl+VJRtvKzv46sixMgjiCEx/4Kv8Bpm
iedoIEMkCpZMCS2OlQWI3cmcsCFPL5TdTIToW1nOqoYdhBiR8cqKMUS7bR1y
k646pGA7MgmayxdZm5YiK1F0j4xv6L81aGXZWawkVLa2NZYeGLow0kNRtTZn
DGkawywnTYOEt/OGYSPBkDvHAQFpzo12qsybFC1wlo4+tfEVhAIM4lkIrq6Q
aQNvVoAkxzUKcQRElvwL3rZ1yqMuBqCA4ZRyxd9zQBGH3BUW1F0iqqDeFiXQ
SIrSdcQ9whvB7m5mR0bu3voBVkYrEN8J0mjF4IFE0UVC2+0p0JzKnR751Z01
VEvyaB4+J2HB+KKsjiKSMiyIFIGeKAIkV9fKe+Ubv86K6RiHG2Z1D2V28kMJ
qUFOAMMFJk9FlcQkLA5rkUpIaOGh5MIX6LNA13zM0Rnx4HgQM+MiMouSQH0G
YMLF4JdsQh4hf4JdzRirLHe0VyBmba9F9galEWPwrdp2dYUh+wC+zjgFYgIn
heolYeI6rRHGShSeOKHW2ZTInoA+dna8Flo8qb61Ox5icBYMJwjO1jK4Y5Ps
Mu54mmouDqHaElNYDeE1B1Z8+RLFCrcFqUV8leAL8QyaiIjKnDRNZywgiOra
PEAHbC4k7YgNGeTJlWX5yqQBuQhEJWbvk4WaoKApG7pGOeefjUly/XZgW0Dh
zlEmAdIJJzEFAgJicEpWRpsnoZ7xlhPMmNoJn8DAeKMxvA8AhuAmdAaqNYnN
F/gS6zEixYmz3DA8xZiJpSo66G6Dlh2YIYBwjdx4wSYnMS6LqiyItMzr5DLC
p3HWJ1bdbXmKxnxvHpujV2mmHhRZwjP0ZKliqSiFaMec5lSr1Pcn0Uoq+kQj
ov6SPyMOD48Y0Qpgn4JKmzJ9tAKXCQ8R0cgAwh0ELklikWyoTyMOL9gN6mvk
PVrAl4CS33wT7wEXOU3jV8XpNQFHFceNoi7X+bd76zFGE49ovcD+eQCC5hD0
hE8oNTBUyaDKqh5damaeoAmilEISL6wBc+2Bfu8DxwIuApvhATnuAr//nr5/
8eoQgynF3spUNhmjhXdeTJd5McvQAStI/wrDo3BVwP9RgcWg4WTs5D44bnqB
vxcZX8jYgjVj8odipYYapFgijWJhQXBPTwvKyc5GSEpnKAsJenv66tUVpUZh
zAKCDbdBJ3SExlzz2/t0JH9QysVZUe8h9YGPd+JfcpSuKcwpQx8QO6poGTCx
uea81TkVJWAGgBKX5bRafElKGKhE6bFkIIvFYYoB7oNRmk070+J0uzNLLk+U
zLC+PmBvRpxOVaShO0w3mVx2lGHriwxYdFIR2TcgwHRmgAOGe89EZINRkLIb
8xV9xoaCkRFR78W/zMfGxe8C2nBLx4tyWBz9tPvz/tb29/j+1dU/AR7/8P1j
st8ZmO/Eu6NPtoJDAmIayOkzKbDCXA8lRZJX1MHBgh/TgnenKANbak1wo1io
KREZXMnu0d7BQY90HxDzQQzFTDpAF8uoyOYUw+hHfJ/iB/0H/a3+Y0Svf1Za
oI20U9L4sieUhGHS29yW3e2Ox2i8jydpOsYaKGxY46j3WKK3D5M8RXHID/Tm
7T2i7R0hJzTIhibV3hx1sd3DA9rato1RdUc1xLCO8tRInQC6IUYSkrRZoe5n
TP8s9sITw99g33LbKMVAyLhY9FAhTCr5jLg1JgKImwctM9M0RIXaRSLHrF1Z
N2CalyZ0RD9F+kGCFrIYY6sIdDlJZ+fyIK2hb7x2jr75/pyCs/XEw0XDwewy
oRL42X0IcH5IcBa6vBP/ip4tvNE0YJJ7UqI1w3edJ5S4Lnsoh+hnA7lrgsZo
kklFbmGnOClk6RgnfUCTdt6vw50i8jlFi4FEm/RAbKy9efG4RfwCrpEm5EaG
D/vxPusRxiRN9qYMrSQgrlR6jC6HAC3ojMg3HEKD1RoffgkJrKwLMGlhPS7U
9xJJNJEgUsI+hHwYQ6AAr2D+GhmagGpB5IqsmMgvycpKmhxqUmwejgeI7ie4
0Q4QQDrjQVadkH4Fn/iD/1Kl8WBYFFN8MraeQRuKMCRXueNEgxdIULcHjkQ1
6f+ewz2tHGP5LlkhCoMf4J59NOujD3AZH3nko3aBAqPmUbKBcyhJhUALQgHU
jBULMgXA5Eg2jMWcDRNWVrFyoHPLwzE5qYpCHK1hqS6crE2xq7C0A2ac9l2X
Ei2Kq+QVoACXsKd+yk4Eo9YGAc0I1fd4OAP2br0kAYEUhsliOu3H/AGjGw5l
7KDAL/E+zSns6tKKOzcuEj8EwcRYDNQCJSqnmPRYRqOrAXMAzpXLrugRo6wi
/cWIE5VbKV6BixJXVIqcE66aJRnk9LJcq26abVC0Or9rOAUrffS03HM0UIp5
Ugv9ONDB88MXngBJo9AlIs1TRsKFIeHfiUlgdMxDHNVoKJ+bHECKWohi3/Ln
bIJGkteM5gmPi3AmiMZ3guhiTpEWtEMZycSVNkXsKG4nw+EwOBkN5QydCDQC
GBM2fAOpnHkHifG2R4zpNPzIYMp4uaxFI1bOWLg9SM+EVeA1VPBhZJkVNerb
JGaYPABhXZkwUCBxuUnVIcNJTTaKCUow5pb3Y/J3imKBmR02Nj6rjSTJBkEX
emNgx1FaaGhER5VzKjhPDQbXcrR4bnA13D0WadsdwSC4W1zAsKjPmhlGHB09
RJ8O0C3K0WBXGsVSGE0OByRDk6i+qAsD3jpxMzm1xOZvb1+QPmuC1z2RfccS
ggpxPXexkWRjFMwUOmAtzlk5WmRMIPHGiFUwIfn5pQGximMmZz9GPFyAsEH5
Bhgnh7yK3qtTpeywWSgxeZgkwXbxxRE5UJnPqEGIR7YMA2uDQ6VLycHPjZ1r
seEsnc4pOlPzI9yvAIAYfAWiaGUFCTxG3Dp+2lSEdrQ4JwAjfF/M0a+CC1cI
KboOMWkOaD4vsjHpQoiOv5HxiiGCRxRM95MJfVmpcL02pH5C1kybB+tUR/K7
UCxNndq7jmqDMWvxFtzMSBT4tq9AeHPdMUcjXSrqRhuUE5Q/YQHDDHNOTAg3
LPQSQwX2j/DlcFaUSf5WTFhFOgOVFlUkJA8o7JwbPgXiIoYVj9kdZv3NKtwx
9thATH5E8uWhRzCc1FclOHWH8cLIz+6NcHFW5BkcgZJycnTwr/sDlnS2HgN7
JQtyET/YppBlkD9POT6YSBjeBhFVCkPnnK/ai5Loik+WEVXnHQAw8tP6DJ2m
qMGiMCNXCk8ryxephPI24Ur4jiBYvb0ufkLVE35Ol7tpRTs+QPdFIoHSPL0R
UsXjgFezlXQRZJDHDMkdhN4QApLoWEz4kxEZuMwlY0GnQXXtmt/BWtjfAxhB
VEVMB9OpL49Vmhy791cKnL74UaD2M8Ggk16W92Am2LXQlIqsLxRqFLcQfma+
JWULjBZVpfxpZ0VBdIBkBcu8kfduEe8Vmdfop6wxOseOnaFNBuDaZMjhGaeR
oiFW9x3mv1O6Gj05ZMsrBaAPU0es8yIf8YvvG4rZvEoX4wKBL8akuRbuWLpi
ckFC1dI4iQ+XoBgxzaioSqDRvK38taQZWfgga0b7Pkm9SZyMiEvsM2bwKge/
5PDlh91u/AzVDlRG6MHBbvw5fjboK/vOixfHcWftBbouXmAVC0yzNsnVa+v8
2ptjfCZMwsb8Y/ckHuGmPsJW+t2VYIKE4z8YdQh3VVQrWtIkZNc4G8hugeHf
lAfct+bGXRusI9qqT+NF3U5kOBOCZDIfTRQv0hHgZ5+yeYM/MR1mWGc5YzWb
HzzVUnIsJmjYiEnWZg+qJQZdMY/EgzdADQaUsJfHaVkWVPP2UMx0FLtMUVKM
/5hMQ/xsjv7TMef5MQXqPTAGE5jpj7QsKm1KYx2gTRtiK6F1seJFtO5IBTam
QyTpcwA9jb4H2zWMA2hSynqjSwEyYfxGpxbrERcTJN5llVky8oI6y5fbSPwU
O+VYAs+JFXFBvLchB7gvp9TiReyKWAnoswN4TFiRXrKmhyI02bV6BabpIRjn
qlqbp9nIFeVjnhaYB/aEM2/ISgUXCe1dRHFTDBYYpchfnzhBBynOmOP1CM/h
2wBV+GKjiJLljjw4T+gDsRo6qQSNmIkxploLF7IR65kjNBlnI5ps8wffkPUa
12/sT5Q7VyboA8Q0TgzKRJIyNAEkRncnccPcHxQvzrLpmB2Q/A0xXsTHKZzm
eBmfg2JXs23IU2wQfXNJ3SJIZjXZDEmI4XwnFxihrFd4I2sswehWWxcX8BoS
BfRPOVdwEJrgXQQEIB1neoksFZDbA6dlSO5qVNkfmmUIObPiVGbdjCO5DJ1F
vu6rmZ4IypAnCW1BeoWnO2FYPMmYJMwRQmqBjFg0wCEfkfxgo6XigHnjsX/v
H/uzzHr3SE4nlmaEUqyVgc7IEcFaCIm5FmS+qFm8SgOB6WA8n/AUSGTGuP8B
UQK0t1HYZS2pA+yKd7Y1pjlsGCUNFEsRjjmy1eKNuGoqL4aAkBPkfHNOzhoN
UjWOBpIPvcGaPE/0ALe6bdztVS0OdYosV2qDyRWUEBVS3JkUEc9pqFqIT0bz
ccUGatH7VfygtXiy2weXF4Z50I5TCtqrKNYvGac9kJVtLKRvg6FdEIFE3/eM
SmZkE8ZumcQkh4uNF/Y7Iyu9oLZkUy1MJhU5U2bzZCR0UgvjTtpkmcI6cIhc
eT4d8/Cm5zk6fPcSjwCV9s5a+jdEEQpPlCp6Jl4aRAf/RpTyenkKQvkD5s0g
lFspnsttnvpCujzkf9iP12ARa3zys6zCqgUllRxBrLpAc0P+bY0hbAtOGyIj
KzFg5hjMb1neE8FQzpvM6+SgEHNi5UqdcyS8J5CNfOiZv3CzPWsipYSOhhbh
NAwQpevCOsREJ2W12kQfljbVSlPhhB1Q7LfBY045VsIPsDD5HBO1WjJoohjE
HniHFUIVyTBLUkLXRm9orynNIJYB8kOYbznTiekOx+FQak0+VsTbGgN8C4RR
eggRFpU1c+P0U87uUY5DP4hpuNTrYzcApVFaazCTf7fPZNKN34+TyY5BaxfW
yY6OihkbivNw+YcZu9XYmiUOdBrGcH6W2GFEKrXC7qLEEecBmRGRlpKBHEVI
48jgZfyEVjXf76GDlFgExa9F+Qn4sRhIDEeutCnAbQ09hzacGj7HC4uLo2lz
oPc4LYcuFnP2uWume4Rph84gyl5GUH2TxSWwT3Ru23Qdl29oHxd1qSGK65ot
Qr2ulTaElzDCj03IPOkOIAkNF6c2GsFZxB0IUHdFeztK3eTG8+5phue6yY5n
Phd7I4xTwI//9VzoUvKgAlk7MWnffDXX7FLWnP6Y5UbEBhg6EQltPLJz0Rck
GyuhLWMIX71RSsVfFfJHkc0/HR8fSgAQibcLFIHFIMzHzj4AGzSJPGcqqGC1
hzkKaJnNBh23Xt6X9v63+8mqIrbVHWzum0ngi02xExThkgqrMnHIKxwPxZQy
xaxar6zyzt2oSVuPhA0uYRhI1J8NpFAuhzIhXKQEl4QcP5SQkYqFzhgE7Asc
1ZeVxufW99fbJeGKRQy3xMG73TfGzkZgUrG1WhbCM2cWxVY4lA8pD3vIl7t0
1aLdVjuO3FD8UjLh8CVYDVqhkAIB9TZf4/JQ0d/kiAQtChpGJ1ybz6jBpVH9
J3NoD+2oqP6JXwLkuB7yGxUN7NkzCeGurqT8LIbrrL73LuDHEyKN98eZa/tY
5Tl1uIesDIWWjPPEze3EEEOxrvk5HVokNsYzsSc5gzEODJvtXWM0tq4wtAQY
syBhPQZpTuGAJZqS4ml5HHeuexzsKlPB+vkO0muCECOgpIgtJZZlCSg9gKUN
M2gtpjgQu5kS2qAMaVkCO8uU88vilrHGwUAhALxnTPxEKIjUhc1eUHZXQnSH
z7yQQILk0AYTMS0KERM7h7OWbct4ePoWLLfhKzGxB9H4MC4FnUdstuIgmIoC
2Otp2kNvL5IzuJi9wiq+XrxWi+ndj4ogGCRUJwN4OwoqbENUmKRCIgyP5pAD
+ojjLU7q4sQJFZsPVejUqshGGxnYkHFxGSqRzDHDQ8wbckhrgowaSKJeeaeJ
qTXreXW3ClbXUzUyY0VXKjGtijnA50nkcnivUQsrOI3wSukxteZ3akSaNUwR
kdu95uQaV81zhwZcaxPV17pa9iIfTyjsP7GOyTWPkKx1LT0YilbvAnTQETRH
oR+9b1TzxWQvWTBhRndVjDKiG3SczvUryRB8jz2lBfYtypWh5kjau5T+2Qpi
eELLkEjLycOO+k7vQdcT2CksQiKIpLRQOkkw9T/UBmkxxs/ACyJzslkVfEp/
25vuLVpffhA0qOYZrsZG2CeTlMxAmQhqnKVXZ6LT+1V0TfEwP6KcWKW7EWzV
9q+Gb0bouru9zz48MpY437aG6KIi6wBn547qFYpgl2sQnJ5yCTRgDnp2w1VC
Y1yr34qj00qyIZSpqb4hZo2mnrvKGb3WEODJcLoWV1yCxOzZBpnxifFrVpqh
FymIyb0Yui2DgEXPaoIICGT6DH3tVFDKNyBJdBsI0uRohMvc2A/Z0Swda2yK
1tYOYdG7ySVc1mfjZKn9nypLVwe3BifXYAbIVpwzlK+cQRtjSy+UsYxMbVzH
za1aZBoutYtXQ3mYdWxRTdEGbXszONGgt1XLmp+TncWQLhTtx9nY2UZTW7Ka
g4phTTpCwKQ4x61cWMl4XSl2h9KbNWtZjFWEJbbGzXZOZgq9eKl8WFwQreXW
CcnmXqx0YBzReWGMrZkKqhTthTgboRHG30n2jMR1BSDH/EbScy+yCom3Qxpj
nAwKh5HvnE2bJm3FLFeCsGpTXjMvpJTaEAQyLP8BL+DJKHnVnQrQ5yrFrKy2
QxVztXZyYdGjspYQQxCYW06aTJQU2ikaBmrLiUuk72NMvQn8VKolXShysaDX
LE/ZW1amv0nlN87ow5oEfARP2C1oo0ZtAqwqKZjqIFMOWbFqp+AV5l6b7gvT
ZQsYvOCAWXKZzRazxr4lw0poV1B1ZlVMW8tk1qbvyVWtV1x5LlddIZMh2nDz
Aw2y7gicQNscGOLWksjYPlGLsoW22Ch2YdQrUVSIb2p7T8s2nZsx8esD+dq7
hSNs7u3h8cHbN7uvGsFpogyElXV9EZfjI2Oqd9bTNa9ijozvh/ouanu3GnII
J8IVTyWgjiU0tnnqyOPGFH78uQmXU4HKDT5o7p8hR+SzBJyfmpB05wPOqR4c
hp2VlH5CHmRrx3+gHflBlAkLipUW5mbt0iwu0QaHoAAXBqIYlwppHw3Gqo1P
UiryPEPkmWNrIy8Z1SrOxhwmgUfkZGfq6XPcFqGFokUpME/57tAcECpYFM6q
F+o0W1yHGZjsAS4jqd3r+OLFcW+CXukx0DLSB8mTx3Gotig+a+wUzN/06Ruo
UooWOeKsTs65dyrmMonXNL6sGRXCNyXwaY1VnRsui2KwR1GDlWFMayr8DCvB
I2sjN7Ul5+RutxhxlKZeMnA3Nhk4D/sPJCCuBkyu2Ga2aqNOcVzkVtskhdkY
9Uhnw5UuckPEnDToFWpx/FvDloPJaT5tv1dJD96VbZSZ5aI61lSAs7blbaF6
JGPWHK4SrNsz/K10fntBRK7UbXizmEbqzfWt4st2LbU/IogT6p+rnZ+rN8QW
d/hIx19h+rr3GFEiHpYF+bGpRmcA2vA+IZB4EM7UePQIL8+WOCHVTJyOaVT+
CmskTI365Gf/u5wUmeMW5Z6oa0Aj+Ia9SVagZenirhYa5YXlwHi+vX7Im6jI
XkaeeoSjfNG34D3wKV2u0etrKuji4PkaJp1iXQubq3z1jc5u5ixpNN9iE/oq
Xnv9y9HxWpf/jd+8pd/f7f/fvxy823+Ov4O2/eqV/SWSJ45+evvLq+fuN/fm
3tvXr/ffPOeX4dPY+yhae7379zVW59cMz19rr93FwSt++FTkpX8+2zv8f/+f
rYeSkLi9RYUN+I/vt77DpHpUGXk2KjLOf9ZYR8iJrSzozrM6wboxqIafYd0C
FLgRKz4gZD7uxH8ZjuZbD3+UD3DD3ocGZt6HBLPmJ42XGYgtH7VMY6HpfR5A
2l/v7t+9vw3c1Yd/+WfKUehtff/PP0ZRtOslzDSP5qLE7HuWEDjkqhOWd5TP
H/S3tqMCi4nBMWKoQDzB1vQcOse5QRK2Ene4/hh2Ml/w8cMlqFJdzNVWTXBO
mXU25nAEAAfpkfkE5KZKEv/QOjCX9JoDs2I46RJ706Od7pLZDKVacaDl5sCU
Qxtcftj8OODywMY9KzSPChnD99M071yu97bcY2ToxWSpS6ABB6xOYp6drjtK
EztXHDCnSBg0eqLU9I2BjclZJogigfXCpHZWy9kQg/cG92Ebgx7+795AChJu
UPAiaIyoFpveBsC1fhXjSkSfYf8HPGi8fadU5KemslBkpyX+XEmN45yMVwxi
Fjuzc84RMu2u6JAn04IZDfv+mfv1DZaIgMOVxmbYo4g807w4BEK8sREvB8p8
B3dUIngGMHRRduCReCmedtoLgIZ3vOQ6jjrgjoa8DyPGXHSDwJZxD0RA1FzU
YSp6jOSdP+9cdnEKhJ+pWsA1CqPohSpIC7PZduLUAKNIxpXAzwL8CUZNAa2i
N8j2jr1L85Qtl5wCYAqCADbDcu/dw/XaGwdvPMtqNDAg8LHSwzmqy833/j18
7RidthwEaZtRUKU1Yphs0COKKfZpeLzaMRVgyONrQiPjwYuBtqViVDuV+2Hv
D5WU4X409JrxmyMzqxZDW8uREzUHcceCg9nxgDyhUjhTHR9/CRvgr3KDpfw5
uauzkbcwnkpX9ECru0QUTrEiIwYDBrsTJe+UxzMloXmS3Xxp7yQmD0k45oLq
/M2tnVkqo7LOyKUXGRY8yluJvfhwzDeckJoq5BFiH8efYwo3RhoioxjLkcQh
U5VeipGgpWOBGhr5KJ1OBi5HtrL6Z8IFkSzs2aNPwqEDj4tYoGBPZpWVGfl3
6slg1pxm5Pdh/zn1jFlg1BzKTnbXam1h0W2uIFKlVPmIPWzifCWLD2dy0X1G
BlOSAsnFrXL27lJNAFQcUV0xlGrpcSm4r4YbeTNweSqgk8x5osHwW0q7NDML
un07QHTcjU+nxRCrZ5hvB+/33x0BIx24LRqcFPJg0cCxU5KSyzSNJMkl4WQ/
jL1Qh8xSAh7z1vdtUDOlytXAlK/dXvy+UhEoQOBNaZna1tt2FvdUIlBMzDfB
njPmkpgrHtdLtUMuUWjSL2rMJ5A+UDZzhpeD2g/H/gSVhKngPG8nSlTxlMDK
BrPY6ZMmPTjic6MyM0EZGiJdA1MB7IRLMrGs3rncIbT98OJjF1mSSPA7MWX6
TVjnwZOFB9bj3o9wF+hxeQdzM0i5s8oT8pyGAiVCPofoDNw0A+dwphxBdpAP
WJoYcAleYwdacvyC1OAuVFiXpEbAWDoaIlOFgSUegmhhzgXyztPpsiHZOZqL
cAEQ4JZjocFm/RKQzGTF83UJESYYWL8aZxMOPmx24+1Hj5l3mozFHh1hg66P
QMTpANAF8sdwNLAcDuikFR37qxEw0L2BLZMFaaxDMUjyt2VtqLgmkiquVE3N
uD03AvntmFyg6YxGwstNGiCX7IOjAN5WlMa0MwFpFpkoPmahYVclHT65pCe7
LYS18qLPxIHKHgXHHUToIAeV4CkdxsdV5+JJL95C0IXliT/czmFAY4N8a8tk
8weIgvQbCbW8GrzPJ8P0hObtSLHwHV4GLYhoH+n6XOYqO9VxE8bNiSZsmts/
Qoc6E+rXhLRqAIq0nRBEL1yVzLu+Hj/Fot/yp17i9PZLbEZ3fOUqp3dcZV53
4DEhM4YGgUjBJ0sM9IP9rOu+BoIjHSFgDewM4AAGISOS36w0lXPbZGuWjFNK
sp+or5HY4ECWVLFKYcMYpOp283UuekZpAsruRR4KTXfQiANILhdv0Ln8sAN/
4I1GHNv5KPI6BqmdoNJhwdKG4omxeJfJ0q2DwiTTsZBPNODSptb9SKvEL4DM
WeHch9sLDxernI0Sx/H2jg7fvXkpIimafU7mmM59UkxOtjWlJOzSCMPB+1Vt
MAcGO8UQdRMmg+lAvy8oMYagbuVjVBWxUOCFRCFeFDw5uwduM/0A6yP1qdwU
/UY1p3KsMpVNDPJIBXsuYagnY4YF+jMb4K367HyavBwi7h3skc2rIHHUfgr0
QzDcPvGhS8Zc+v3juhWg6Q2NOVYpFjpsmzFMsyHW1mIbKxbYScpTliKoZK8C
vrjKUHfl4dBBgp3rRVVa52BtWBnoHVaBkg5BAIOemNEx2S2YxjTMREmpzKyp
mHZs8ZID91GLsk8J7SdztskQASZPdYXPfZ4gsrZHAAWYbTeEDHxlrXUhQqgL
7CjAI0rsaq5Wx1z53r3O9/dg0HWyZa4k3IGEMrALnP6XL3Al2XZrRJ3drfKy
KIGwTGphBUDV0dOuGUMLMx2Kcv23t++IKuIAAxNUSwOAWrarbwc6uxNSUDLF
eiupdq56r0qAGq2NMj+vJ3u5I3kcGhzSPhRL+WiE9nE1KW0nIl8G27sqCokG
SJLLkEoUvtbF1N5IMTW2FKv+BWJUsjYDzKdtq8IGY37mUm2gMi3nZx2A8ef4
uUq1/oy+MVra5+jzTs//8T9wf8GjIKD04OVd04qBgsIWQ1P0HNVlDgPiKl1G
UcNkqz4G3rBenax6vUVyr6jZH/7LnAHYHK7jHkz1mhPEjD3+dnPP/JfuMCNO
GZiIbjdl6r90+yk30Oj22dnzqACQ+YOkZ7K83XIZ9s3mAjooa4WgGaKCgnYV
INWrVvhvn//tMyGTlns/uzkbArGfdIvu/cxo+TTk1U78jcbpnrXX9eDpnrkC
1Kb76Zp3bd6aJ2ncI35y7Qt6Y95K2SdqZxMnSXWOvCD4ue/fgvtR+N2Pn3V6
7SZ/KI+xtvG5dSD87LPq0ERl5Tls7rO3gn9Xv3+WRyLvs3jFX59XP/b++sda
F+s/dj/c+lb8GZ8MHvvcOhp8HtlP7+NbrRvGWX7Ub98H7BJ3+n2zrsb+7vOp
7Nmy97hUBWlv4lU/4cT4GVvOVwIVVbXrgNr2c81j/5CTDEDPG/kcIrF/kG96
dJQ+rsfto1GvJryeUiO9N6FIAb6Ib/kzbmVEX1Ciu8REr7HTs0ylnROl0KNR
m54y/Q+wVd/ui14s9dF6nMpieh3pDg9cg2pH8APECRVQ4Woy7+nWTba0u11d
7bcmRCfYSCLmMqzbXJemdS8XkTZb5mhgliKZFydVZCpZR9EWfFtI65zV/Sgx
j0ewm6IsqrC5qckfx4B5V0RyTTpWUHNw6yrg2F+0p6PM4WARNvaA0VxXkKBD
TiVGZU6+V2UrTWtYMlglRrKXxX9bxWscwbYmiVsSzyaGblRwJhiIgZaajBr+
5sCpbPDciCNpxQZuN/9EfDXSWUhXG6YC2RjCsoV9WUcUcKQQukxB4zpPRcx1
wCEFhMDDC6f4VFlAapfgbZzjRcRCJKm5MOpaEOugjySrLXh83AvLg4al6ZsN
YHGQditfEKpi4OBhPFm0BBZjXXk1bcDDAa/LvgZp2iDBq7EtcKuDYG5al8ll
NoBdCyNo1qRVvCm3zgW4C6qmCMqZ1FyXVgZ0LeUE1lS07JpvVffQgL0ajQB5
PtQgRi3Yjywdz1pXcF0TMtIo6lqLb2QoVdQb8KJnIxvW0KAo2GVjTh5IJ53Q
otlMfbIp4oX8ucX8R3/04XVv62PU4D4tzAgZwrn/0XnzqXPDOQ3XDP7UHwGf
pmRpM1nwp/4IRr3vj3q/OaqVqv5xmyk0KCntx4GSgVn854Py5h8EpcOaa38+
N0ddNU2Tt/tSgVlm8AE2o2DEbeP7hLKG+YcFzkMWQlfCuzcUt6FDkhvVps1F
DW4RthSV7l4YYo3paprfvdbRBKvCEql3oA5ORPHkQKqYYBw6vMDxbh3bgFBo
lJYRpPykoUs6NGyN9meJmG2yJqn57IAgp60XCXpQs2cD42/EgrGiBS4vgIL1
u44IjkwQvUuh4Fhz4gFjKjcgcR62d0ZImNHPqmLVSbzh7kbGX03yWkzh8lRP
vKCyKyZKt6XBkfT3FGHNiEbekUjXXvRJxaZJMlJb9iJjVybS8DDVmUqlco4F
J3K09E62JUq7ZpveuZKDOgpb04WQwBImNTVu5bWsnjAyE5IsiLsi7PRagEjj
r4agGgIbh0NTgWvfIWkUOtMept1r9tWiZS4qC2jqfOedJtnAChLpMJi54/zP
We1nilD6SS0debBbo66KXklPchNBA/fMhvzDNHRdcG9WHGlbC62DquhivOrC
b/IOWPhrht2g2RCIeQD2dH2weo1XSOdgJ54ENtuOgRHv0IZ/mXqIZA5M2atN
yeLJ0ks2AmwoMDuI+g+m3M6Y8ccJWyNqSM8+Ayl5k3tyVTqZWBHaNYQkCqBg
glY6vAiLU47yo84dI2ki1JM21F6znfaQBHZEqtgDl4gjYepO5aJ2k4y+JkzO
ubdbG/uZsiaLygqtAmvsyFmy3dhA1yKUbgzHVirsKsHFQWzOFF4rt7ZIfWi0
E8rSkmo4JsWM3boGZzGSNOi4V2LPnnySjaXnIRXXXEjFIlXGi6JFDHl2RmUa
V+5UpFqiegRMYoISQM7ljJtDfsMB0LaBHnGUq2+Qn0TRsyW2XhSExcQoEk0p
7dDA6L0vG9PHKu7E1isiwoyBi6ZQtXCkW8ddx7/klOwsE1LHUOnxafKb/J6m
tmyg67BniQ4FotS2g+QwjUwDTr8XWFaGaqbQgn78LB0lFrswjEKaX5PROyKQ
0dWu4iDkVvorY40vr8wEp0a4ZkTER1RmiSuySlFGrsWeLiNh1u5FyKxpGcY4
z9ZMBE+V1lEofHg+UQFaHzCF6tm7HKe2cUOyM6NsxSqdcstcfzE2PHdNrMag
586ynBK5bHnKIA8Fee8MI3xGlQW+i4LPKps6EwcqDvoq3Cq5IZ4tZ63ah3lN
I9i7Tb6RNcwIytC8YTrPR8OUHd4mscY1thSeQKlxAXT7TSrdnve2ckE2ydIk
h9HfPdsszW+VhlKrzR8yaGQsFfo+S3iprhhAaHZGTdAWpc1NRx/mqURMHUn6
zQ77koTjGwSq/PtjSgOGRcu9PCRR6V0PUl/89FtshwaRrtg2RuE6GjlRY5P3
iChDqUPiVldYKHVmViRFUSaIVSgEAEoEsd7MlQq+1iakDpOOjV91x0zZEpXf
Y8X4+rpEU82XaFHtiId8wrV8TOh0TCa6XjJCQBHtNgiIkSbxTHctSpQ00gkb
1FijVYutwhy/s2JhNRabD7ZDtELLP85g1EgFajGIRLFTNgySS4F9p0SS7Y8S
D3BrKAR4lR81R0M0V9lq7k0mw62kIu5I1Ufsp5Fimis9jWcMH0nZMg+aHIJq
O7ESl/AKSbmiPEb80Wgkdk9TtaGYRGzj5AvP5NeW/ujaCPLB82Qy6Kp4T+ug
D9ssRqalS1AF3l+ybi2oSprYUF+2nqNt3rXss3M6VzRXxUc386HFbWcq0Z7m
r/1p8Uv3Qtf01/6g53Jw8HyHI3bcum3STczCIuWd2VYjVKOxNTziwTZmmtl1
x4Ojn3bf7R+p8T/Hb6wxomkbYfWd8CJQ8gmpSQO1Y795+2Zvn8qZyfif4yOs
DOfUo5F3tFytBsdms0A/bv2hsW2lNLN0NzaP4OqjxSpIXFdJaylRxGO/djsz
MDmWcM1w5yuWuHrdh8R/kJakrWP7tU7uNvYBHpcaOhxbHeed1w1U7JAbvppP
7dghh1K85nZjv/VX3Vi3x27uvu5rx25Y7e429jviDmbwdphYg9Wtx0YbJmhf
PYKksV3uNQmfSy1a2hLMloAaX6Y8aiK4uQqlJPDoyCObxVOJDmiLnia1bdvK
PKBVr6Kwev7CxGmxD03UaJNhIRK9LhRvmpyMQCtfUmWcxugHulmqUaiVRsXJ
BXb/qrKTFLrFEYlFOd5ls4QTFzVoMgkiwxm9G9v1LllXXQvJmHPoRlDnkCkr
OVx9A5yvhydLtOcLuVF0lAdLzvTrU/qJ6HftUTY44v/7nv69tf1e29s5fGN8
S+SUGe+HRvzWP11Qg1luMFbbn59vepZCGuhPJpYnRnT+qhncwj/7a/7cXPnn
cKD2cc/9Z8/9Z8/1s9c7zzzHGXNqdvncdUUrn3Ww9Ffv3EPnsfe3/EnPeiFG
sR924/9t1k74TuSNcM4LzDgwoQzKU9vCog1Va6lCibZZQwlFB1XSqOriTdGU
cA37XBF1VF/acE911Xbi1zoMgsQVFxaa5DZdAIBhQ/EVtZBgfEcwMCZfhJBK
nM3N3j9YQaPjpYyijTqIyECflJGfuN2X69/qVYlpFvcQmT5UZF0wiq9Jm4rN
adhytI+kCVTfHvrCOVFyBz/CuHdc2CCm1HdKApaIUxfAjrB30iHnENDjQ1X1
lHDM1DxfGZK/Ihhfh+LTovC5gemx4OJiryujq+TCg9pth9bVuiVVvrd1R3Y3
vDYGYVHVTRgee05BTw6nUXlempTv1kBrqID15IkQb5WxhbWim4R9NL+JOPSD
ZWddSorraKErhlWPZSw97kztXWeR55pnkbXIE5O2qecopNDspwW3vrO1yYIV
waTwbOQKWXIRGtsTLfEb51KgPPUSw2wuCbA2Zl9UwT1XFnbZu64DYtxRBh5a
IhtYWp7twqoK42syrJ5NBSnGArm0uy5A0ZmyI99966q32UYmlC1NMILrbBs3
PkE5CA01tNFZkmcTrE1LeXOnSTmkQKCm2/TYKl+c18EEQ64CRxGFWpnz1Rrn
C0VlYWtxypKz5GgoJnFKHhR/HbmKyelkGlLQC4xHgQLLcpxxC9uGHdQ2peDG
jfqUGH9UgSblZcMiaCkhPy9khmMmnJhhXAjs8BUomtXJ9fd9gBHVWCP7Tk+W
p6adUGeVstGByZeQ0zS6uiI49bQ3kO38tuoRyYwa55zYaHApjA6+gRPLTxtD
xs+fqp/mn+bnafOHpdPrZRjzc7Ms436aISwsp2gJxf20hLI4GSWIl22Ez/KP
H87LS6C4EbOc4E+3UPVxQzC+3/jTzXc/mO8/EwbXBxWZn6LteIy4hsjH/W6u
ldl0I1wU1FriHr14v1BeIbbJFe8sx2OHGubSRRxxV3FIJt2EUGLxG8ypcohc
sQzoRnVm+LC4bZUh1/B7JyBScSYtH2KwUTaW9CX8g3T0ndgogoGcGPlKyk7s
yYfqTmBxSSMnUmaPM4pokdGOp+Dlat74gsKK8vHGO9LOvzy6923VJNLdhj8t
Vl4D9vGpKY3p3cmXXosqne6eUAFfz7XQLmKSPMcHMbBCVtPc6YQj6bDCRSoZ
TlhPh+qp4c9AHYRJSF8dZzxXHWYcWPt2ZavE31DqFU6s2Qy940kkzI6vtbJF
b2tbPrbN7mR4m/iF0Ubu4lnCc2Lu815FHGn/hTWhV4opmfCkXjUq5mnFIWpB
6MMce+C5ekZuicrpwYhRuW5aFP7dj34yPa/52p9zCDxHOJ1nxZRtPBwOQHtF
Tg8iyCgtMSpKV8dFkTBaCclqNfr243d6FLQ3gGxGnZacurC67QiC0jjuHHHJ
qhP6ttNKR0wXkhP7rcnsN8+YOhPDopiqdN7jcpFy7q59k4vfoPILy5XaAQrF
I65KF043EJJu2lUCCU3ndTpeAT0sLlVm3M6PH5WaWu2AsYm7zj1HWVbpaZZj
tnjkVRsOIsD5pkigGQlwJlpJVbNgXNb465DWYmDTCKdm+a0hH0VNQ9v95ici
QhCNymFxNqMFP5EqtZ//Ah9p3rx65Kaw0PLTEirriwHNn5ZFt4x73aK3Vo/8
5xe98juQhFZ/+d8DCBOMvWL0/6wTdMHPJ78545pF7muFtUBMWhmFnOk4Fr9k
2OuVUl4xHVdhdAMxg2TM6SfG49/IPjCGd5pP5LcK2/XNdDA00RIV42zqM1ty
HDkX8DzJaFeuApKjweaKttFgksOcRV8lWaezOdYWUmEC4j1i3Vji2qhwH5Xy
Rc9kEES+wtvf91bGyNbOH+zJ79g1dh1CYsPIt1qedPsA2rwAHmtqJusTWhXM
LrnsOufd1JENHWjE/WdYu6zK6oWpKSWW2CorExEBqDhJW8JPQpW5rRQAQn9B
nXdMCrD0u5ylZdDuy8Zx1MVpiiJR/BvXmsL4vggbcSU2onUk9ZYb628GlLBc
MUlGGFLInQmzKrJWEYdm7C5zqEUrvOHsFEtnE7F/VlHM+wyDZ9pDV2xgevNM
vgkY4VtyuV0hpeAuRV84y4liEm3NbxeDjlgyEgefRmTTPyvNpTaIePfYpWfj
/ZupSCqpQTp1p0le+bY8s7vI9DIVlMN1IlTENsX5CS0goQp60mgANhfZEGvS
Eik8n2uWd66u5vjLly/rXnN7/Jx/NZY5defNZvIg+oYHtsUvKWyb6/y5uskY
wEOmLAq7BVpFSe6qpqG0mdaQNsFdFE1ry1GbomAG5/smQaQol10gw0Z0JjuX
if0l764YwVR5ItEKXMOgSKxUVUP88mT4MJTL7ZuBT2KYC8pSUpjEQl0rg20G
f1ujxS3NWa32rJXGLMdPNwP+utXCc28yZLUmWa8w4bTacJpGrNv8GPlTwLtC
dGhfV8Oze6u51K4sGCUznR3bhpz6J+REFlnqtQKLi5wjsWN3wtWRfBWaLp6j
LhS3uVKcEb2CwgujFmGkwQ3QYlygo9GU82xxQ9aFCcxrVccdg5C378oi0KiE
lQH1rlxFGBWU4vkaG0Q1broOW3wFKw0wKDDaPn2savLAziQzcK4pfmcQLnug
vVn17URQJictIcqUsdCzxAsw5IhdhGnzWU1NURSybeGd0IjC5Rhf5+DMHNkH
j2fqXbIVfk51p6JxOkG8OIE1dKywzt1ik8kHT3zXbmXvC3v63qfaZOh94SyG
/udvWz+1QmL4KaOL+/ij+1VZPu1nbdhqv/RxkvBW7fajj6E7PsVtIHrwdfw0
/tAusq+3aEfI1k4QcbjGmDIG8riUgeFVMfAXb4d08Tv2I7ZdPo1tKTrfsueW
g1+Gz1knsXuso23Enlm4WofX/83bnhe30PUDA6QDIM61HqkdHGpTim+7ddD6
rRVaO97kVr+AZWn7eDf+TZnDzUJW67PmZ/XGP/z20T9WhwjwlUzfpiPdYtYV
g97pTQsJAbSWcOiDkNbBkrHeo/5oPeCVsqsGX9Dc4IZFhrPyFKy4aa6MfDc6
duF/prqGI3umkQx5SZyJtMUUbextkbUwi0UUKO3OagMgR7FotcZXhI+5lG1V
eEtpddEfcwKerNxVCUYB2CZhSfwAB4kn8dowzbPTfC1O8/OsLHJDBWyZBtVD
jWp2l0vjw4hsD268CfOErMAuV8WGO3DEYjanqE0W+qWOJBa279VFj36JsBBt
nk45s6VMKWXHVNE33+lQShfdyLAmVWJNmpHbaIu1LtcFTqr46uqfn+8eYqsd
ca+TSaIKp2Abqm2G7MXcwOHgc1k1g2W+Bo26IMWCtRhVFS2Uxzog80nsxbpR
QGYJRjVgh22pE0a6vDEIZ6U7QbQHg0SXUaqNlxnnZ5F6LF5QDw9T4lbtEWbJ
NFLnzQugtmUqVxrfN53d7Vnmpm6ZyTSU/IiW/Mn3kkB5zhmU/CdZV8acwDmV
iJZKkjdj15e6yHs2Cf/cd0+aKjQUfEFtYLhcaR77b/hVSLxsf4vfSGsjnUNF
dUhECgozHptVEUJHYRXRPWUPcewKUaMZUDr1ee9jTRVp3WGiVirJRnbprFIg
cbjUHk5VxdylmUQ69RQu0cQfyBVblHwvDZPmVkgkLbkJj3JYWn8F2+2kTAG2
HENroK8RZ7XnlUsUxktgIpo0OFLGd4F4+ZvwFqdDRy2S+XFbao3Kv3XZM+/5
MjQydrDnA7ZKHhCtxZ2Y5DuUw0x24LmNRIdbRxlLq4LO33NX4bZMG/r50+k2
7Zk29POn023aM21k3den27y/Kd+mPdNGxv6T6TacDfP2lzfPrx27tJUJvKTz
thvh8hTas3hkbD/dRjn1b5fn0J7F0zr2Nak8snxrF1Bjv99/d/Di7yc/7/99
dQpS2CWL479uhkkjQ0jW/SfThNozhNrGvnuaUHuGUNvYd08Tas8QCsb+yjSh
9gyhtnXfPU2oPUOobezQon77sf0MoWDsr0wTYvwmZnuELgk1erBuD8G5vemt
xwYad23qlO13d2uIe2O/Zhl6cP3YImnfPDpnTTlm9VVpU+9N3pRKZtL5U6mk
TyVDFA5WJjfFLrkpulVyU5jNFHvZTNGKbCbi3a3pTNKlB6GZuw6V0a1zmdyl
6IbIQIFcUfMUTb4TpX+/l7IXlltKYX2JJnuw3RtmttS9SiE+eI79iyyLrSKT
esAjmizmsc1m8zrNqbzjqyvXylbKYEahp87WVoClKWeQcgDtNCx83Pj2xDW+
PamT006VTidd7hEukYHOcObKdLMlZW1tjf59QVVmWjrpwoC+aOEisClyh20G
TS1YuvTiZWGLRKvhFn968WDBh9Yqs2w9Xh94SxXrAdfFORlXdQcexD33D57L
ttfj+7hnZ1ZgYty1rnDMdmnd61pXN9+ScG9g81yOgjGg8WLf1oaJB2pZ64Mg
/fzqCj7uDUlEpsoWzWy8c52OpzMouNuSaKETqQDJg/pZfFJlNYzLjDxxjvt6
6C7ButDQKrED6YYJcorqs9DVJk1Ta1N+TLk9pEEiwZ3bk/I7qAJGzt0JIHmF
aQjs6K3OWhJIVhhd4vMsCb+LzHfSowfUKjg3qQyUVV4WyU3JG9GK5A2/DtmN
yRtcMSji/Vl3qE6iMK/btZ9RkSyjl3Kugj6USLpOdkmBM54DkYCZHdhidnh1
keRTNkajUXBkOP7xChhzI0g2OFRsa2k0cE8QxlUdcdiEtVdwK2zbO3CcSuFO
jO7UGKZuAavvNzpj23yx8X9VdsGq/IK7pBfcNbj+DikGjSQDFfYffCw+WgY6
hwl+bvnALNj7uJlq0Eg20PN6Hzdg8nnFBzo5lD5uQOfzig8aHzfg9Lmhfq/Q
yhF+vX4UDm5mFilEtVMWgdE991ktIEz2bX7Q8vF9me/d10PO/fO2AcTzFR+s
+PhzfBn/8mfwzqzkjY+AmGDhIaD5wEzb+Bj/9/zPYKIZ5OhPA/bPAbX3rchG
XrH8xp/2w+grycotnuePv4oMBVk+q/J8VqX5cBjGLXJ8tLGZxFPPToLKk8df
sFFeeQrM9A9TcjpRXn42S4Xhp2KsGlOtOZQErBlzpyViCzOKuPwlSiwr47e4
dx61x9IiRJlSkgDx1mmBtnlSk9u6LjkbmrflyKQYmZRIbhwY9GCnUde6tv20
ajg6kKtFjwxI4qXurrDS5ywTsh0Mp29Gwg/LIhljI8SKFD+mfqYKvFlEWnK8
WssCBj4RHfBh+Mp9S/nwyA85DCYmuTNU4mFybPpl55OPecYofDq21c1Mh1CR
sLXgLA45qeH4evfvWMdRuyEpBNC5D9TJiwm9bdqg+tuqnHkW9k6lgSURRjoj
6vWkTwif0T3BGVNJrQuS3SQBLpJXODppMWQnqfciiayLkuqxNRHNeipN+kaL
RQVbyIo+IZoXdQznOTLu8+AFB5NS472kAYMFylLSHuSeZE5wtkaiKPrrgmVq
0ag8D5crpr/CZ4yJ0o286nX0QoKOmFYt9MhrahCWVox0xn/jXlnlyju10ILO
AZeuilljCWpXppGCTxk+pcu1+AwDQIfLaAWqSZAsmqhVRUjxt4X1ofl8TIAq
aYdyJdor58ZB3VztBDemnMjMGRbOteUllPO1YVafS15QJDmJroweOSsJaTj7
q70GqsqNDplLM/Jf9yHjqp1h4D9qO30lUHfkd1iqTfS8RdJnpCK2gvIgX5H0
GakqIsq22409+9tH2wlxjEgMRArrcY5aSEAUu+yDIL/Vq5TisIywwwsapFVi
IY7wRLurNO6VKaS4nNVJpOpajrDPX96SQOq07Cg2kU51YHjpfk1GLKoXB7Uf
CuntQOC4is7CfWNrieW1sSV3aIbja2Uqdyi7h2cyatCiFoZDTVNtFIFLbja3
xStAL3EIJgZEhKJrk2rdPWjLX6VrE7jVBv1VCbkMfe7f2LQznnvZudwZHP3q
to1YrdJ075igK/xJ8oB4OHfS1+fonjeTdD2C0apsNjLEW+Ijg7cl1tG/22Qr
bljWM5P53XbjleACDLGnCKpfvUZXPlWrWZXT7CGdLTDMkoQICFIsVQ9mhcBr
2Cqm/lD3U/aTWJmpQZjxOw+wWkreiT0SGYqUSJoDOK7firqCSuZ8jdcC3qMC
khR4GwILw/HTLXSmZeSOrxys6zwsGCrNKPkFpTKC5QoK5R+35d0O/CCYUyPr
ibXV+vJgtyENohqlg2wktKstaKfSYTuru4BEhnKM0TBLXUkocshE2pgmWGMS
6ieLspZ8FyMBSPnaAtHjOBRDTFyUqgNB6mBcJ9UnuI4Ssr+MGrWJbeCPR2Rw
VUTL2aor8VthRd5IqU+0GxFIh5XtJEqsA4MLUfEokwvURcUs7mkRaA83iQUt
iXsTSUiwTViowR25QwiaDMuOaZXRjbhpnejWPhpm6YWT6pl7raNSw5lW2A4A
bjGulbAlsju4IMv5kNImbAKUr2xzXkQAYBSvOa0vaoSQKci5QgCIoxfSy4JM
FbhSaphh6v5Hs6xyxvndwwNASdATkqWKf+bsdINmfviAi3DMchtRiYFRn1Iy
QdwHGXX35V/fHm5vgYhqYVkAQ2cqCeebV5PU1qrMU0Q/gJJNcA00SWNX8Spi
GoCZNZP3OWhQRL0k7li34by9cMNuq0Sm+rlc4xeLnGoWDvzFeoKuT+OnInPt
UqEtGdNSNmBoOjhI5QDfWyPaMopbrmRGe2GA87AygH7EurNd/KYnwXpw8cDh
RkRAVKy/s0dK192WG/deDywhyHVkrDZhpmV8p0xLrkDlkj6/rMjNO/eT89T3
bVDQWVA+EJSv1Iz2pTV/5z0n8JyHGTzHnjpnm777wb9aEPTayTAVRdkatNYM
FBl0xYmblWa0UzU9/ZjLc+4l85xTNg8GXfyPSufBHy3xNL8w0k/7VyI/teYH
NfXm26UJteUVfUXqkAlQkE5r7voYEsulTvx+j2H6i6MxHVUwBYtutjhkOwNY
+oC7RkUWAtrU0dFK1HrfW6efy3T+1clMWnn66mwm6Y1wY2tXuJ1W6zZjSBlN
agMzcSUEnQkzaWpn6nUTBG4+aeRTBVrY6oSq839ERtX516RUHbjKDhoHmv0v
bKNXbm9h3pd4AQZZJ7RjtBVCWyfep4ZwFgx+3K7I1yT64XUlvYBQ0FUsMTaM
k0BP9Z8K0sQ0Hvp5Yp2KtStZ+NP4GpMb2dowgewu6VexojB3ffG2yWnej4dQ
d3z32rw271D6mHUCeE1/+c+tOiH7ikpGw59vQELiIhcBgh4HsqekRSknkxoj
cHbF2F1oaqImyabc0EVAxtF4Tuql+DNALYRJQYkwgnnDzZSPxVSh8y0J1VWD
36Yvg5IhaCbqFHOBniopWWyGsGVnG+YKbgxJclWhQjgpjgkjZj30zwL059D7
uBdvBVcgtEl4l6DdjNRAK7oYKg1wFQ6sR7dCFf8ymx3d6kLLsMFNNjaaW18I
D9nvknIZQrPJJTELj1qJmjIfnQIDEMnk03y601hJYKFDolUorqWAcO01DEaJ
fOL7J/DhK3DB03GanMnYodqqMLkhrJvSt/6YB26NQTp1uIFD7Zh/zRm1ooGg
ABqLfDQwckALMoRpxVYq+1N5xX8isfjazOKwoZUVLvxMAmW5kiFCg4MjtNe2
T+dcMxzi69KZz/9sPvPdEpob3Qk5NcvP91MKQFfgQOBUVkytL/rlKM3AVN5G
y7jGf0nu4DkZ91Bu9NVMCS6w9fil1pWEt3YbBfkj3ZgWldn0EpNwT228RRV3
sn7a73riZNUN+SoPFuLHuiltETdKWzQiUoNumXXyKY24GLeLaMbyvJVnvuJR
p0srY6h0RLYdqmTcG12/35BIo5LXDjH5EguSkbfLj2pVEa09dNiLMYGiiqmL
jcnUVacjydFS88gGOvG5eUYliUPQYbNf1glqKLtzK2obznSRLKWLcIGX2NYQ
UxM84cxSjDemWKv0dGnCn+JpUp4iDAXz3Lg6aVXQYKDo72DdVM9r9GRFu7fM
k5kuD1IpHeO02EQJz4QUIxETsGmTaFLFuexyvmxfHN8JJ16GQmXTLIixSWkz
fIRQCpAusjFPJne9K+YvdlzkylewUmh0/Y0j0bwG17BiLCFsvTtUp9Quodmi
dKWTy+t24OXrclVrScznfObGJiViid06MwBZlruMKQU9Sg8tLnJuH9L3isXf
7/V+jN+Z8PS/cDxo2LwHPnqB3q6zdNxR3Kg9gPGauuX/frtXdFjj5+iIAEcL
+RHuO3YzXaRjT16zkoH4powo1LbEG34+3/2V86hRkOtHCy9sBv5WlqMlD7dE
G2ppaYdcgx7trWcOVsIvj8LTbo+55MecGsO2X2pMS8pQbRGHaqFTM5J5kTf9
vd9WEYdBur5gG0Xp+A01oB0uSSIcFb0gRim1sRJmsmhAByphhexHNV/TInfi
gcFHbB8J7Htk6jFZpxrxthFcggJD49o9gU/iQQvStg+pm8RLQXpx24V+tYEd
avCEM99ufdIrduNPHa2cmmUTE9xKPUBtoInSXLF2GZc3NDUtsSGFqR7iwOyn
RdXFvGB8q8gij2dj2r15BnyPSAXD4GFSOGwxTzCtDw26Eaf+ADLs6la2kqtI
7h6Tpmjmoxw/k6aojWAgG/rNiBpSTUjTpY1RqwupariKae2NpD9epKnMYBdm
epbrHESTSNXj7C6sjwDj2KBj93FJfUjQbTNdSjVOhPghDNw7xLIxx3Ae0wKY
fuctCijHPu9dB3lmjs/CjT3t4dlJuU6O8CENzfaHbTDuFtEgfvo03h5wSUuV
F7k2pyOASdaCMgFzlrRiU4mzQm+SFLv1GxZHeCVRhgJZZgP3DXAWwkS32PhS
XXGan46PD03ZSodsXXG5Z5T2CsvyGZyKM36VJmMpJ1RTU1ycc3ztKz+l0zkm
nh9LBGSPIyCzcZqwCCFkQg3Nr3AvG5R+Yy6FWy5yUzbFc+YRDYXDYHsZG8B1
gZuUe3uLsMlVY/FEk3irx0IS0XlJ42MkpZtrwt67eu/cHxlJchiCZsxZvHwu
X2gNd61ikay86x5jw7VPm0jKcm2ZW21qdn19TziPYidjU4VeF7wPtGNuI++b
Z2vOzQFruw1Yco8ZXEH91hBgsBgKP5BxmvJmCDwsvYNFglwBYPd6WyyUMeQD
WgNWtk5DZZ+cpMh3B/VitWB9GNeNdcvj85tqt48XHKWBPcmGPIX72F8fyp5B
rNC9Zt9x2aip7lWp7X5bhdsSjx7MHsShiXzSioS2u7XEydMbT6KYK90aMoE7
kQUJtQq7xK0aGEfSQwd4unIXftxbaI8n6UZxX0v5yQWeVGfODp9w13peZqTp
D+aoIunXAoiVpCgV1wVXScaryltdBxU+8oPYK1czG3g7EkGs7VRbhXcwSrNp
R9vE72+tb2yvDyI5ZxYdqUmExJl7VdSC3H6u4maDuqZJfroQpf341RFltQL3
PRLB5AF+/k/vXux9//DhY4yy2OcCLDajgxPKF2XYBxI1o3pa9fRk1E48vtLx
02lnc71LeMPqSGeL/pyQKNjZpj86248erUdfYvGXYzmLJ1HEE9No6guqloCI
yA1H4o5818fP1+npmMPj3BKMNVWELV9X/ctmv/9w+4eHPzz+bvuHRz8+cQOY
Ja96XYDUOsCdJ2OA3H2qL08c4ABoG/coio/5sHsUD3I7vncvfrCN/pb43oat
N1ApixgwkVMMOsbKv1ohyrQWZBQqEuJuUMWwbp4UajMX2JIpOZ/ITcRShX3A
Kl3uJE0fSCSVnq5leEqzVAWGIEyTqhJBuhmugkTiBInEyZRmZierta1ShQov
kuXkmtiNG8q+Bt+EDa/4x8+ACL70ciBcmQyr7YNObnRCG+mxx+KbKKzCFv0W
C5pS9k3QRV0unSOizYzguXyorIX2UzciBRTgfNt1ww+26f9JQ49TVAlckx0V
9+E/3eKk1gNo8HrBDuur31FQxwoe6k/1knIfsfoSOpgMkPjb4MsAXIEvzHwu
1ntn3FnpEO+GQORZcfntqwMxL/5G4YTaF73O13jfhC3vhGsyaNdZD2uZmKDo
gZRcsuXZFDpSiqmlBKQjTTx6EVlyoI0e2mSJl/4smWImlKogKOG9zqhiYdfy
uiH5lQiWpPuY7mASFK7KqlaRR9FCIwPTMxt6N2C4D3QemhQ3QcoVvm0MswSZ
M5cnWku1p4E7qgGIK169IBxPDMqDTYylio4Luzm9YSfatAj59Vm74QRH13qg
ldmMBUvFBOhUVBdVbKl0ZGvPXkeYz2gCRVUcUb6OIIfEuJ0QN4nwSgLcJL7m
c4KRzbeAeyR3LLZ2AcOkowa9bjOLtZFx+ten5aJCcKs2sRcU7WwWXzZ4aUf8
bybzW/8Hk/mtW5D5jhz8CXcpMX9ldTqjYDke1jzlqHg2ifWb8T89jTd3VlBf
/GlS2Js5jbeYD5sueKUlsmUlQK5jUXYsiyyr+Mo1nE3Fxob8hNbhaICjKS3B
HXfDnAAC3ZBv/gmG50ppD+Tw1weCBpWY5XxyGjSHirSqgyWYsetyR5P6LuiL
QjwGXBWAVQdJcGK7SjqlaguR4hthqe9BK2gxozD55Ir2WaOYAdWKyIdQzzfh
AcpcRn1oW7KsTL9nJGzldVygDQN86fzOTRduk1rYiNluSaMLHymZHZjOIjdR
e0atljAnR2xvCHMKQ5wakU2ttCKYKJRLG7O0xxBxcJvmCza4LV7BTbz3s4kH
tvtbaGOn4aQ4b3jxWv1IYcSUIUed7RbCZOZfR6I7QaOcIbk38j90K7vJbkyL
JK/WCvDfRSloUwhWKwOrXb73Fc8VAG2tBlAjxGgFiV+X0HZax53Ef5FgVor/
RrZU4r85/gFRv69QBtRYThmgwdowywystAhpqpDkDaE9rM3gFIpVIrhnC75R
7jZugchZSnwDsgu+1VJ4i+Tt7CPRHe0jIx/fHAm+nbwt5NNC/mtFaMKm64Rj
Z+gIIkqM5dczengDtYsgo+ZFw47B3Qb1lXtn5b4AjisBmFUC4x3qTPzfDFVP
L9A0BEkWhXfrD//xUvHTf6BU7DjdzXJxwBVDUbg1xNiDR9XMFruZwDo4rOCn
LVJvc9JrwnybbPYvmssS5fq3kN43TmRrxyP1+tE7sk7zcxcWuhKc7VpP0Ff4
Js2HDvIO2o8d824aUHMp/vf+ovFWWLJwwzhVH5u8lxVoHW035ZYaFf58hVbV
spxW+c/in1tjOr1JBrwldm7viEAHXLwNAjrMSU9fpTs3kBZ67q4aYWDCjL9a
homaBs2WQW8tzES3NfPFTTNfU9yI7iZu3NodI1a//yPFjVYzXK0FvDaHyq3F
ihfJtLqFXGEE7aWb17i+sdQEe7qbAvEb4yHsSqS0C/uPGqUkwzQ2mxluAnC6
HCaJoSjYtQtDmJLRmdTLUYgui691P10bnxeE5ekSchTwMwJZmyzvfLf1piRI
qxWLpcny4A1MRGZwEz+GkZUqdGw3X6qOL0H8GEqPJnSMbCjmaOPaDOAK+XGA
hYpN5rB5L9rbJQdUkW16xbXuqGTlZTKqm9Fo5JLQ77LTc8ZwSnJ8XodSW6dF
6da5OkARASzhaZjTUAOBoHKfVHsCj0lHhHFomdh1vH4MFDW/KnhMB4Whi5kj
4r1I+dLWweQ7hXrTbm13UrvWNhy/rOR8GyxBwWL0kDGP6+guk2hJLXBdSqWu
G9YIlmyLJqpN4cpGiEsH67vfWPhqXQx2rghplNU+2cVQ0FoiWQqqoBfGq1M7
3Wbtp/VBZKLo0MfElY5sQZQgThcLxAFPITxqv/ORf91Nly0Eq2ksvqpgkrQU
45M29TEjN5bVrOWoJLaoMoBwkfwGujapTtkTVZHMm0KCHF2UwKUVVYEKbjMe
qSihuBElRB3sDksQXzA0u8Tgtqtv5vQ30Yr2DBIiFPBGLelnptJGMZu5JFqp
QKdDZr22HZzU84KaoMM/ZPC9+oYsvzD1s9amHBSay33TnY2Y1pLaZu/q2yid
SsIan79E+piOJMLGae6BCuqzHB++LkbUaTFyocRcRvL12+e/vPrFtN3KHFCQ
HYwX04XARfdiozVxsbP9N3tvn+97/a9kDMe+iLGHftaER4llZ1HMPQpUgyyY
YM/0tGEYwe0gBlMthrTllKAm++66KprB7unZSCK1edf0Sv+PtCyqDlfNcyZi
MjwfgWDwcWD9Aa7r/SSmt0y4WmyIHWyOB7q2NiE/4uoLwu1IuAE4Yn0pTaQH
m9xu+rCo6pvbVtfOvGebVss8fbVZLP4A2tDozvuV1mWMiHHsUFEi+2uTSYi1
+9jq5q/bVMr1oL5ORRet/MMkwTroRVognMm5UDKGndvwJ76MI1NzKLJF5Pim
wWSuUuSuj2mUO0LZgpRZy7U/bPMkQSYg96YYbgTYZuqcdU0ipU36GmfnWUW/
5V46JsgQcMVcvgH1BupGOoa+Gw8u4/vxckC/9Mwv98wvG/xL75LbFcFHfRiV
AIcXw4xP6/d3iPVOcoxKqKWXjGuViGMgV+rH2DKF1JjIbx9lyIi9TRXDh4MA
C24ZOKL5XfUxUyETZ468xaj71pHnGPUcsg3k84FH2YgceENxie0YS20tTNyF
vGgQ36/R2ekxxgmN68ben+sDjNrjYztPeVSpEU63kpZgTrUSiXV3cZlNM6wT
Z5r3VGGBJ6bGJjEEo00Eojh0SAWxdSyp9XLhyFfo7ZqujyKLVVNRsw6LUWc0
JVV/tKOu9aruTfuGEru7Hsw8gG8GLYRZj2KUtac8hSjoiCSXeBy4ltAYGN9/
CjA4maYn/IogJcgzwMg1R/GcK/Iym3CtXUi2LF/qQDwHAH/bh0lZXbtrklol
RGg88HcL4hlmjMuX6/H/1VgzhxA4ewTWksSadot0vyyL0jfwfMu5QULMKT95
SE1TTb620PdK+j3CZfvWH8CA1NvDt2KAhS26chkXZ9k09Vf/o16p+fjk0oIT
TYUADTiccJfuEfv+JT88c+dqB/RMn5fxj08Jakb08O09Iby+NWIISofY0+Fb
Nxrsz5SsgAE7l+sewsC3rJd7sf7NSmym2xZcUMyMTbE+apG7C0miukhrfDeV
4r6qS68pnOpYmnBqkK0TFKuxQAXyOMs+rfgQ3G5YxwnwIODbk1qu9YuP3bjM
Ts/c3w7jXwTofiTsiwkjvmTW4MoQ4tAq/kFi0VzdhAD78fF1xHP8g4Zcvwbh
12ZZxWWRx+bOITpXa95h4do7s2TemSaz4TiJL3fiyw+bH4EvXn7Ygu3+kc1p
Xtn4+rr4chA6yXj8FdABDt8CExH6r4HIfyMw7t8CGMCxOo4BrNj7Gy6hwGEw
SIF4LaF5rGUdPQolGK2LyQt54pvj494LULnyMUhovgLUy+u6N5HvTEvK91w2
kn23eBFJaOsavdYoRFYd80w26QTkPqw0EbWUnRSdA34FFRqvMRcwBQEy7sAq
1+Orq8Ni+t0WBsOT5IqyIKVRULWACeWpO9HKJHHNi+kyL2YYT2klFJEK4nfY
LwWx5urq6PWr7YdfvkRcR4DoBlWhRQ2YK0vCGvrRkRFeiSQZGQcV1CQzrTjX
EKYGbmuAalRxWPc6R+XDdc0M6lWy8vmFyrbazms+8bPvaoXoFFCYTazANgfc
/EKLM7EUl7BBUqYaPfPRhMs8AAYBvToti4XV17XYfI5qD3wH4hztVW9VjIel
6gauRzNiXgJHciGPUDMc2MHL/Tcnb98933/nq6FqrMYy7Li6pj7Mp6ExcAXq
iVLP0CYGaAI6DpcwNcIvnjoFUwQDYK4H/2lXiP4Rloi31j0dLa/PTsqiqDu5
U89eDDyAg2qej7I5aon5oFej+a2oWQVa5Fg115S14I4F06Ut/M0C7eDXPJbZ
3fo6bmkbG3FOrTNde0NCFaKPXJnYV9xgGUpw0efCybH80Fb8l6dxjv+zU7Xu
/IQGqDQAhHZp5RQ/AuGUbR1RLEYJ7G+Cq+EhnCW4HWAMLmmbUKUk7X7IsHoS
QAhgkg26egMKbO6UwtOrO3PFg3JptgGDn1QcR4BjoEOhdWNoA/G3RhtIUTNx
ud6JJkeDOR5Vh0uEcjUDSyBBCk4MQLCFLG71VzTyDWhBT2khA6IR3vbnHQEA
qGgdXUn9VXJKihUZPbzMNgNqu7CudGzET3r48Jcv66htFcp51pi2At3Xzr0+
6NLNv+kARDeuml9uw3DBCYH+fIKndN44pXZMY1Ojgyjfs/AE9CrPB6bLVHhu
+KBUT7CoCoPdCVnjjqZFs4LX8HXn0V+XSiyqlbwliONsxEUXzooLJurBgJVk
0VM3gLa+z4liDeh64IYohNRMkk0R93iwfe/eNlm8UJg4dKB952/q6hu3elg6
Vf9JsGb7OOTKZEtVS2UTjHDIfvQrKUJc0ZwLrk9T8RiiUcOy/WDUqOOcqcCz
XCkdUFzD2bDVL7Zkc5mgs6KqI4tJ4YFhQX8WEUT+rBHmIpVy/VOEzjfxaznz
+FlSZWJ6MHiAFdwVpzLAQTs71/biGcloo3EjuiBHIKkrxoQkCEHUyCUakzPA
9UTISu92RBUcNu84qUbizByn3N4Wz7wbCXPqsgsJv3d9wNxIzsrPPcOpSEf/
mkLaaN+q9K10d0/gH+nhfeDDwD24nfDyCb7WIeFph5J7iEBokg4C8IsWroz2
Rzdj4/bR3e9YRNCnxTT6kqwMuL3BhG1FusMXw4LEsGKI4QliTR2wpdE2ABdG
mPmtJBixJYXXt3QAPeFqZSIvIkkgLDOU3mCZpPbbj2npTaxvmO8IfYBmeqSQ
1WnpamVYk3ho6E5OssvUKmIr2Hp0E1s/KqiuTnAIxcQg5BRr74jhHUenOhb+
8iPLi5F8wzNiItTkvsEyzW26RmCgczawHMjJGv+KvfECKQ1jQWX/GLiEiTPW
tsV6oM3Q4DjIwNLrXSP276364sBKzFxvjfiVXQ+FG5Rai5RGUvhriBtZGwoZ
rJfUYRIjVScjpQOyY4Srcgeyv3d5mzvTV1bwkKqyuQWiwK4uqL9Ec0FxA1M4
IfThZ7NU5MbkvMjGldYZBW0DmpyE1cz0ok+GbBAwi4fPTf6D7EJvwx6N3QxR
n7T0kF32IuZFxGNNZ7SrhRzXqPma24DhD58Qd9wKB0EBSRhkmGLj8JR7jpKG
MEvH6GLEqIHRYpq4Al7kxh3zptNL7J5+wjcJnfB0mCfF5GS75exy4ypgI1+l
ZSpWUdoJbW8+Bc12XdzLvjdS0yIM1cot7RXMNV20Vuo1vJNxsQC54UQN19jA
teoLiZIg++SDmyR86QAwyJ+iiWm+7r1gFu/7A/ncVy5/1/d/1W0EKcj2Jz4N
2KG1deMIpjI2trAgMPrsnBfX5XaybB55kfyx/QgLdQk3sUSqC5ssC2B6XpIS
d/Mikm5ryFe+dZQXahb+4cVO/KauieR+7IgRDq1iJ5QdeXIi5+PzdzojDEpy
RjsKCmNO+VTcnnasO5NQN+za2tprvkUcUNSk7CF1NNY4/MmlVu3cWb+5UrC+
QXn4pbyCBgf87Xf3/fxkO7dx1U1UVtP8fv2TvzdS4j/Ms3u/ZySkzDOAC1Ub
R5Mlztml8dY/BiC9kXh7cNwX0udflXk7GJHyXXqw9IL/GlT4wxwnXodv5iaQ
3VvmV5Hr9uWTyN2k2jetX53tlRwwARvfp+V8oRPfaiIPfvlh8+MNOOTeo2TJ
p+pGNA01bqxP3pMdFVW8QC/UHC3Y/jpdfDVeNZpNbP72i6Bc/RYwhaAm96f4
3tN47H3kRsv80fAHQ/o/oW1AHvC+pErgXV4iltAhsyDDraWY/ALLbTdmxx+M
FY//Itev+aJ9GT2hsJY5rsPtOSHHgAfN3tb6vXudHP6Bx9Xn+TpHBawCGK5g
sR4sYYFwgXXzROG9WDik/yp23aSoGnl3m6y8hZHPW9m4Q8xV7FzCL/KVvK9t
SXcgpGjF9Dye118N++gF3gB1bJvrH+/l153ZPDyzcTaZwCCdS8FpxJ6gbr28
x8j3T0/j3/zcgwtRVoCxdnA00cKfendWrRlH/xSO3rx/weI/taD7heCbXfun
j36zh+UJnGgX/gFd3sf7zfXuCqJi5+7G58F1bVkCzQBD87/3eEn3ZcZ7WA+3
8QJ985SejFYcxadVR/H/s/fuzW0c177o//MpJnSdI0ACEJGyFW86ShUtkY52
ZElHlJ3k8rCIITAkYYEACwNIYiTdz357PXv1Y0BQlpPsW0HtHYvATD9Wd69e
z996041p/2YT2ttXrsS13ceX7+rQcWR06s39dEt5NH84X7GM6m78dUIpOo5n
ek/18Z7yUR7+TWtCF/GV3Eo3n8rbSjz1W9w7V/rFfDyOD+iyY/4UazC8CNu6
B9wD0ghTiYalmWqyEFmGXnJddP0BgN+PvV/UFywsCraxNJ8+qaYfhn9yuDc7
msF+aHxgNtb0o28XRviRbAwPv473L/+wvfNt/Ev0xM433+BfxcfdAA86+nOD
H1qecC2XHOshHe/cvfsA7PMGF+1euU0/PHwIPzzc3n747cP7299+vfOHB9/+
4dv/+oN/AkbcL7f/C8ZcBrE3H8uW2X4stx+20UGecCPyf7mWf1ADNv78h7t3
zXDNe/BDZrjmidnvq7BldbcZamRGRNRYN+awZYDkFu85IW+bopkC+9a27+w2
AzRuLHAI1z/63l+QcqxRb2Xnby8OMCnj/fzMPS2pE5zLEARogp2g/tuNTTFg
f3G1WlzNG4hWK7YHMAaMvgT44gtER7pq6tV4zmGpHBQnuQpbTV2Pmy3iUICK
666F5WJ+BcZR1iG51auKDNT4AoUuTuegjAbNk02gMaHIMFYTaqzR13+bnw3Z
2Z6mXEXe9sP9bMg0umLADMVBbMh2YXzkw3I9dOAvTZUaN0v99ykyDIl/G3qb
bxLtSnKUm4aP/yEDA7TNJjY3dceB3DdghyYzcnVOSRLEmIjsjiEXZQjK7cbU
p2cAwjK1TGAnBEB8fUVBEE5MA1OIEmXoZgPR/2BZQmpDilKzukLYTzVEYUMY
O0Pd4N8cIOCa8y59qd8h0ePk+OF4YRM8jdR+fPjy1fMfIIC4KgxMK9jERoF1
3w2MVsVt/wGmeti46tCFiMkpo4vV7E0Ur62rYS0tsDJJyGWGktRgJuQ7dJNI
ICpY4jgWhEreQt7PyO5qBklDg7sP/eDAeY1cRfMOxu8v6uaCyI4bCQPhpKDi
rJZVgThwirkudBdGTUoaS1hwMfZVQHOOuSyotSKNS9FIlwr67ztusfQHj4KH
9NTTuQojljkGKgnAoxmfwAsYbJqIivZQJj+aQ5r8Fh7aljDdJ0LwWf1OuAF8
n80xgE8fNwOyCrQDQKylP1xB227zlvgAPo0cRVhJEJCmmzxoi6PO4AeMxM3Z
13plNt8gjlLkO0FPi2ZKRLvg5qmzAw0Lu5z22W2mWSIRkeA4/am8HxIF1ASc
k5Ezz4LIcZA+8FEbaJeLtIVIOTIDAAkCxTEMlUWxFClMPQVR0DbG9n8/Kn35
TIym/WMZDC4u4KcRsqRlZGJkKYYcj8YJHAiNqs6aLaLlzT6z9kDAZ92hgE9w
MPKPbLSt6Jo3JvEhDG3I596EgP+T9tvaQ+kfy27L255VXEYcnZxBE7PpZInX
q8Xp/PCielODjoByXH8J3zX8XXviXPw2GF3w3tIa8kBxeuTPe3/Zd48U6nAK
QLI/fADE6//69uE2iQuuO2gniiiR6woESUABpXBNlDgrBs5vEJQ7WiZKlXLb
u4JKbsjxmbrg+XmwM7Siw97fyfdYoX5fIyI6PU3yyASS1PC6hbBtiPl2bzlV
xMAa+XucZAWUcygG2IaJD2Rk4YWeCl0sZQ3dUkNIQMP3ZUx+GdfzF69lXA+/
+ebBN3R8Nh1fUQYjTPwsca8d90VXjxus2rsFsBoKhQwWf6AIl1+Ve5qLaMqa
4G96HNw2f7DjLRuR/2ZDETjy50Do3f3wq8ukiLJNSoHT6lrv9sqdrlM93T9v
eBiPdq/chqdxR92LXqDx+Xkhu6c5xczMiAFmBvce8YO2OuaBgtoGJO/82Cuf
9MpnXQrjbYyUbl4W7PmdwTbswiM+i8feIvOVeTqsPIPw5rtu+7AgXUHEVF/k
biPmmhYaSK3ilHDwJJdDzpJmOP/5G+BsECsVhbHYqtMAn2+nStvYXWBzOmdb
1WkzX5z23Qhm/cYJlPU/6q1y7+VT0wYFFmDoN2VMn62m7vjPxlOuB04hVDBa
Twse/aOwe7q7L93Ks6VymtiP6MWjPi/zccCHDyDc5S/19V7deEaMMTD9N/V1
v8KvGfAAeaOWFggRDkxZm7KpziD0F+MzKN6GuerMbcxcDnP5ZyfrvIX6IEut
hoAKWDNZihWQoj1C0o8wVQ7kcXfwIdAe5fvT+XLp5lqP3rA+iSntPgALBpMZ
rkc7aL93QmqZknmiTIRZwE+fvDwAZAfJu+58+DAZX531T09H5+eTnW2seEg1
gIB7BmGMcy6gxHcSlwcsKIOejRRS7xHW7G3TX8y54CNPmeo+uoGNJ81o1TTE
WtNF17rOe/uHffjidDofvRlNrqCrDx/ct9wuHo20VAYvG4CgVBi7UY3fVjOp
EAkNQ/HSdxiIk5aPwjB726OG3bxz+pRbmOqtmwXYbgY6wIk3HVWl7lbIGYcu
Cw1joqKQ8BNmooIq46ixWpBVJLiNKLwyvDhaL/WMVUFV4e2Hwy9wxYZL9E+7
Y8Nuw0sW/xvIWU5Jnywg3GaBFWAxF7nvFPMJBU5eVI1JQdNSun693HJGGNSb
3tDbD7/cDc2pVCQc/45t9t5IFtyiaUrVZIYRqqOltwltGTcW8WTcBgDw0ziG
N0ZhwFwHPzUxY7OWDiCU2soCA5hpAlN5c2azQZDljkccWxzPa8xyN20Ad+YM
oDeAb+U4oLtBxLxyTag+hlcj3A8cQ9OGBOoA53NPKFyIHTx1UUlqP+J33+LK
JxMvwHEwEx9VmNDGlYDdBjUtWD8SweTATLyIjfZX37nbLid8Zh+1ymPh2uJu
Bozz5GYOvXa+ZRLn7jE5Qv1yJwJGf5gDBsR+cbc9wgl8jlA3PzuDgNdH+Q36
v+CAyaOz+p0nSvbxeyIZyivIzk8ojOQROyWDiWWb+f3vgwlHfeOv4IZpo0h6
yvzb/rgBU3ILhiNsAT2HR+iBznt3xJXcvWBLTJzM9bDbzbiE4VoyFNAHEmhz
MIBWy04wpO4RLc0u/ecejd9ELJnR0Urjv1vMePCxbs3XkofWV3Po8l1dvUHX
iGHmjqNREKUTKk4pMNYg6SlPB6n9h7/89a9/37l/DOHc9O3Xg50uW0yh7RIl
t4nEqtMHDgwyJTeK68YH24uyDfdM5ARecq6ytkFFv0k/piPdaPoEFwQf+IX3
qorjgXA+oS4BEa+rTpCMBJT3D0/nvfJiArgD8OTR7rfH3NbRt7t+nZvJ+WVF
iwXWE1ruowu3dWBjwX+n8+5xIrHDjzzIkMf0bIvd8C8v1gPln9BlcOgvg9fs
Q/meuPAhiR4fvjI+EyccgsfDQkVcVldirkajFfvv6K7plVQvMDDHo/xJtq0i
Z0jXzL7kvuqZ6E1YEMJwk4rVY7LurxBGru2ye50Vs8B9RHAAtAm9f4Jii8jX
R++SSlJKRDWhyg1/3n91+PTF82H3O3lyC2WmLdmYPgLV5+mwn4WLKj7ZO6Bi
9ojWDxckObBCDxboB5iutg31XymNstSiLgv1o/r+uPkhND14+sQNEavsuvcP
KTp67KFqMKPKDE3kaG6DisW7JZAZXNYVLBVjJDEOGgyUkG58Lc3E8ePHN9k0
vKA0de8L1OaWLWKzW88Uh4TeOHHbuQOdn+D6UBJkbMKF3/O/rABbLHtpyuE/
oIEBf8rvwZuNtn54wwgz5uh+D9zu33aH8fMtTz7YCR/F8bc8626r0KYb3kL+
InS33KnccrzxwbLUyz7gJ7P+mV75dcuvKyoUscM/HwtoKvkBAewRzj+G/rsb
HeAeAQEHpMgJW9d5NzOnKOsrKDS8qKYM1gP3TKGuWxBjJ3Wj4m5FKWICWkiW
+rDY7VYgdm8x3BuegK/oBLQaDRhdoKL6qnDAuIRnn3V4W2p5IGVqmyJEikRV
GOuA1EvMp7P1mRVJxKIadOBSBPkeMOmWONNu2UCYmzvTs55P0BvXbyfMfd0M
lvNzp3NxEWjOOFlAzhJbD7IFi1E7yI2IbniB6fLFnrSWJCrUXGlSOQ06yBlY
prJoYGBLwgW2QSQD18KP5mUsygmp6Kjxa/I5QNWBcc6DrKC0M1luaSrLGHso
KI9NBmDG5RjyrEwbIG+1Thlos0AQFkrXNaguPrmKzyfDuXReY/nFpIbn2coJ
QmTEIcPphw9n0yu2Hm3/Vx+niolzZG2QJRCwEIQdPeVM0FOIYri8hL2xumqb
Ino0ipJ94higgvQ28h5l6kJCJItYWI+6ZoiXK7i/RwKEOlmEjcMYSKmEm4Qv
mUvsE253d2JWWmiV75rqcs5fBBCoXoqo091TIGF68VuQbCToRn2CqA1QPGY8
ZIP2WTAh3XTU1JdEUGT2hPISwHKtm7DcDYZ6bB2sIPjkGR2xl4u5+7Zz8Oxl
dwushG6Z3aUaIENgT0TyQeEebDTVezQn1Mir+YzTV4Xp4GCvtVw8PAyeU8wk
j1ddRINrynijvaHo7eOwLDwW5phhBDd1VrAu7m7jFQLanNHRVQgUP/VZ6UYv
PlAUWsDMBmxPbBLsCZvlq9BDz2ipZRjUAK7TLb6Y+Tz8K7F0egD4wNXV9JrC
MCjZ08m4YknVYtdscC3q99UlQ2ExD0eedonFkYCVuobAeg/GWtkO2VGTgJRK
PwYiOFtid8A5ihJJ4t7D1ceZhrgrsGnocdw4FoEmS35/2YROUbzS+hrD5d6E
dp/X75c9i1YI7YTX1Oy6UPZruGPUvOVh0LACZHGdq0a3MDpa4VvwNMjODei7
rJo3afXjQuZASu6SLrgGqQPwKQKuhVE5sEOkwhbv4jMCqIV2nICy7PPzkD6G
aKvJ0W3w7GJAIqwCBezVV8sVw+ww0fFEvJsz87mSKs71+3q0UjxVCCQScGTF
taVlVZRbzBcGhjmiq53QpasRCEcsuHMp3wkknI9qgJgt1IrIXQA+Md/xTssA
2FrClh7BuHFHi6TfA+6gHpqC3r/TBPwTRabFAlYAKlcEHKunNclkCneaInpZ
bwDY/i1cXxtU1gjOn60rWIMtSdYznA3qh8uGRBOp9tHIBaPYF8CBneKRdPqE
3AWWhacAzOx/aui+NDMr5rN4UMyJuEKQ6zUqOw+eQwMHzVoTXeizwoJYC7Yy
7g2Z59idg4Zpik1dVuNaioEO1yJRW63ywwfHmfq+rvM1aXl7oM2tANNjGbAl
dewoLLBlEyiLWcjxGmjlbiFAqiJUgaE7OJjrjjUchgfwFxmI+GBzlCpl7mtc
4SxwE0TdYhoOB+YxA/YP+3jEdLy4HhPE1VWWhW8CC9krQhYYjC+jATdG7GfQ
UobHvubKp8BAAGtblpCwC9FJZQmH6dt+QHRHu2WhsF731QAPZgf2mkmMwi/B
FDk2X/4C0Afhl6DxOtlPU4YVjtmNTzzrCBeimwQEKj7nxBLAmynZsogx2CpM
0/7ZYk5EroBZDQaVoR/v0PONLRxwUYaP+lkMta5h2J6aH5BDBoMFdfOUw/6w
oeg1yhyHd07nDBNieLNyZiU+8NDrDPHnZzZPFx5asxh+AXqQZ6YFCROUIF4d
w7+vsytT+GosEhqVWQ7PjYiOXu6FF6h1MoXxkloJ2CT0d2PNOUbF36IrxmPJ
cXvZsfRKBsmTaVFNykq0dD82v3KuvaEn8lA3ULLC6eYBDk6Xq+4Y2CLXwcU1
KId+XYbR6feZgXy7dNARP6fEBGgMjnDX7xlg1uO6I42HyVKA2aULLbosWEFH
yuSLMn8c/Widxp6hWlKsgPQ+TjiA8G/Xd42x+2Q+BF50lqwUShSsGS3Ld64L
VVkKKGNGLE1CKkzRCvELNt4zyffE1hlKV7SvtxRzu4aaxiaK6MOH779//MMP
T0mE3MOkLszUcJvP3XjLJXkoBdv7CiHkwCpwSXgiE+qZvJgFUA792Qz6n840
2JN1ct6UcEXQQloTAnwh1dmSg/+3wpt8q+uk4dUCnPmwb3qFVal1Ctw23j3X
7o66ZFXY0DLut4BAHEj1hwoMeAWdznkn2EnOfTAV3mUE3AqgSUuzmK9hDlCW
pUd+atjBsDmq2IjTooZTTMKK4GRiQqoUVL8fXaD5MqnCwaVnyXbgRiAFLaC5
fP1Z7syLRtofSwXxKKSuO+wqzXcLzn1GNKHDX/jDv24bUQPvwDOmR0aKXcJO
r5aVgvQam4nWyjCDwWx7QYoMoJscGwPd1K1VgTj208k/uBglqkVoh0qNFyDE
0vASKRe3oOOKipVRBYPT5BBqyEnfdC5Euw41PxwXmbcaggVhFmD1oZZb1yjI
qSfALfeJ68p7nN0fu6WTKI9+tAKIm9grvOZ6pQ0lDy9w7wXPXMbAJNU78Io3
GUwCttgsa0PUSBd/+0A4vrsKzsJCCfDVf794+vz1yau9509Onu0/Jzehl47a
33v56sXP+9F7/k5sf+///LT/6u/mPQ7JeUn09yqXioUDGRJGh4cSqBU8rYij
zUJVv3H2hETtw8++Vh/JDpgSAzsvLsqHXWdWrWd3A02evur6OWzcCd0Et+uF
Zy01DUXlVgKoxTPUCzk6ZV3NQi98Bu4sT7bQzWWmGv7gt0j4vV+7KDgjM+0Q
CsIMwXYracxmYYPfuU71sdDssef48XVQJqXHQ3oFm11LrnQicgIqiS8dEFWT
xDoCYX1wnaTpRrDA5auk8mWyA+jqbHKClb9t4R121GUExrDkPOwZkghIb5yc
g7TE3ByrOw2hk2F4ObvLRDim+/9eQYfXLy7aBd5BlIbWzIA8dXfjvCCOR2LD
BZ5z20cxmdle3BaHHFfEATayN0GoBiK7vRTBBw6CeUGiu6I0qwN7SFCy5InC
pFtHiVNBCybEWwVMJq1UcDchmIxjUyoCV7bvlgwl6u+cEdj0OKUVZ0YSdVHJ
apX+ErN42g3YE7donUkY1T4wc0dCk93NiqPgxBB4C1UVI/FRob6GpFXjEPR2
jZ67u97gWSlysFzCXy3yKvuhNrikfTBhMDo2cPrNF9QWqMRiJZPmIIbC29Mx
BBn8Jk9n5KDFQKRengYT4wfG6B/I7VQimiMs/Yk9GaxaGrEA0y3QyrVyItB1
nxzEcIjY+u9nbTTWHkYh0qCtDqLACgxDvig1GcsqNIU9pQ2J2hMKf3LHGswN
sCETMrxjWG3WrMGT6QixVcjule/L7cE3fS6Jd7U6ddpWfzSHOB001FVY+6ec
u39MY34BIfng/LqqrtCmEQE96Odj+QTtUVRxYt0ngXS4BYSDBW8YhtIMJ61/
LJ8Fmzsx/PQihdwWkvLVVjRYMBQ1MbTVWuzENoIDCsWklgHFdonPG4/X47Hn
UCBs6Tm2dGzWs7d2tRm6aAg/7u8dms5lV4RDyFmYOpHVktt78dPrlz+9jlqM
2xOXD7qaJKwq357bLS8O4gFmdgusZn7XlhDt9fTg6f6roJm4jUS3D7y1uPyZ
MCpraCN6+t+GfhTla7CCpwpkMmZsQzWZof0laCOODRjEbYSZtUq3xzHyr94X
uAAE3Yu0R/gPsZMLAgiwa381MbLHV1T8SajzFO8l9JzJapJEs+TxW/Kd1nge
1Q9Nks6ZhDjwFTEo/wyJ/D35m2rGenW90jLEXL8KGl1U76JYiLAU3VlQDNEb
3WnMHfPqro1IiXBTOQyxirsrymx/YTLwupp8uTOHSSMG05YGLEcY8lQOuMAl
OpV77eZhoJ9aRRyjcFcMhusGYyw0dcdbHsrRRT16I2vNJjQwu5PZEB4GYYFT
w9Q0xhclxA6dQjwvtlKThCU+ebaMDg9Xl0PaLEEoJd70jptyURTqLxMuEhaR
I3ebD5y7rN6fmOePhwNy5OMTOCpvy6zttradoGzagAMV8KsCmoGRD2Imyl/A
WQXw5j5RDp3qNjzs9cWqMaIgSxzGnoUzXTpxnm22beuphYZu4LJ+l3OjkXcp
wmuurpoWwweHmLK1/3Sy7CuxUi7X5SKCWbZPoark2YBQ22m91HpZWP+6mswy
a9BtK42Zy9QiUVlTuoJD03YON6mMCQ35Cw/O3wsMwQ8YNCu2eGxx72MUx+Vk
ufTA5I/nTuCDGSMlIGhpdSm1m7mSgACM5Lk/GgtH89V0zDiFi/kvtU/UQvq6
TXan4e3KDfE5aTCGebLkFpgxqJAMEIpAIV+de1DsE+SN0yN7ocuoEj0ociGH
3lTi17vWcQJMl3dp6DOzTNwb68wlSfsUaAY+j7OU9uH28+XINt9B8coHq47V
WOORch1JwhoPJbbgVlLDMfJ+E5HlLs3qDWyX+XkNtO6xLXl5AQGultxwBfq6
CrK2jg1TkFCxtXcGrKUfnD85r03Z2TvYb7oMc/Xhw+Mfvt/+A8fGfFX+KHG2
HBjz4SuvWDWfJKzXR/SCmWJRcREMzd/2LnKPuQRxU6D8Ajeh5goRSFDNxEML
4USLZsl7zG0pEGQ5dCDWJa0GVACLBp+IO3ZcCYP9DxDcypElRpKB5PU5Gjw0
k5tNCPWi0CMjKcbMtBY1Yop6bDy8FxhCr6tDaKoRxppQ/CUP2leC4rtVMNAx
wme8GvEs53jJTMFEf7maTULcKAk5MrVcMEZvXPfnAAvpHnMnegEVctypHdVF
W9QCJRhz6ILef1SDHgDqu+UPiOpFO/DUtXI2obsOTn5dLVekuEZnPtXS3aY2
24Ka424pMlrA3tLgAtZhQDduChMe0Y0B5XsGEoCyNyidxShBFH3gdaooHgvl
gIYRlXFXmc2K3iztAJcc2y9iFRGdtWJkSnxzEL/AlsLUj1XIa+5LPwpHPbLp
tBs5zleTMWGzgYw1n2vyCu1htBIhpq06t4j6FAl3GCDtcTB8GDkYRcZ7GXyI
i40hHnHVEEGF/3lcnQ19kFERiHcQmiTxjiaqB+1bGCoo1eXlMkmao8o8scTo
A31eXwhYmGkMiAa3BLDCXhDY27OyGjkeVzN5NCwDFCbDYEj86pRJRHursV0z
ir332ynabBqxiYw4Z735SGnLa202iW6ZsdRsbr0JrDgY3hW0XkaFACjmS6Of
U/Uc23kPSIdhO8MYHAZbSRGFPnVNO2gnOBzadvYcpx8SJGKoBmz3yp1vHkI1
vnQ8aCv4+8lf9v9OYEoljdHAK21C53KIRh37fNyOkxkO/7z3av8QuEDqHQQv
8H2nVbiNA9im+VeH1NfzF88f79vOPiJswY0DTcb84qfnT0IaDrdv1Qy1I4Mz
7bSuxc6atUhsKR8hMsSYB3AXZu0+QTtOVMTzoyMCmjnV7BZToz2GJljwc9Yy
nuGLK5LCCK4fM6COxdzS1g5aSEwz0M5y5Vjmkcq9+g9tn5t2z9KjjIIQ/85b
4kXYAXahet0tpuxI96XaCU1an7mU6Gy7PgSQnWEL6VKKtLXjrnqd3K9s50cy
Gg6DLUEv3kQnMrWZu6oFbhfvVzS5AetfTFDIzrfIV0O7yT5m/jiXnw73ftg/
QcUYT3BkEt72s6YnyTSbPPqx3Imf9KztxY/P9w8P1dL9INMmOweiJ7+On/RW
++jJb9p7PwEWKmP9WD5c8+TLvVev/ZN/SFYKL2dZqcd6k3P1NLNYoEQdstRQ
FK9qkF9F1cKbMQyZa66d1PSepFxc9q3Y/r/lbfuFkYspnJOsCRhT302C9O0z
JoLLXc0IelegiWLGpVZJfTTZOb5lBjNpsu4JmpvTDorALAf+TSgeaLGy4kgy
Dv6S+nKTpdouJouCoydE0xnXFeaUW4zAg0m17DtaX04W5UXtJGSMreS6dlZY
KwTa4OFgZ/AAhJUg/lCKWaqsZwLJKAMssmYAfIkgTKOtzBDrTpgsUNn8GW/h
LnYGLQE0nFllwWyT5IOmeDAQaNf2NYlbNgEqCNpSfD0QmPLaKNQ+AV5SseLm
i2/s4EVhSoZto2Aw8yBKeLKGhU+q850ar6/x1FtTOzkRxnUNnjb6mTN/xhDu
U/GZbFd+WX3k2H1MRxSIaNBw0Uz1dEYoNQ96iuUDRebcSUmoXYXKisqmbOW4
C8VIa8TKcO197X9PtFfKxhXYgITsxRPUSQkjWXZSLx0PQF6DUf5U8XvGGZd0
PSOtOiOHDsPTL3l94/YdV3QOkViCJJA7S8FJgEDqNPQPX/NhUAiQon+Nlu8T
UNc2r40J7oKtnrxHEfwec4VkgSA8KivphRFU+Auyfi/iHTOKLMNSYfcel8qL
7rtmLO2gVPi6oFKZZjEST1tV5WOzRiV2hD3JODWn4J4jjIOgX00FLShQRQpa
FkC9f1QeQQNHk90JIAgdx7Vc7veiwTkpV0p3YcCclNfI+uB0tvpMtE//VN43
szVFuXAPncBROvFhSh23eXolh0bN0beIs6BuQO26qbH5atnSHjckqAdYm4WS
pa8cI1M/js1OAWZJ2FUY4A/hChbgJLpAoLKo5BDpDYI8jcQGKar7bi5Ghx4H
GhGrgKqiaL3PpcnEZhZ0v1rTSWRmgfEZa4cWpcTar5ja+le2g/439vbK9yYG
JiRqn4nax0H1YVCf8vDzmtEBGwx7QKFiPEemJAhlSdhEQcIPxoK0MjqkP4bv
NEs1LGcven/h5dxjtKJ01W2ba5VtnbBWOGvJaA6eZhki8W36REMfkR7YKMnP
YfKjwSE1vcYNgfVmIuFBgxc6jutR6x2b7fPMCX71ggVOt6XhAUm2bQHVp+BB
SZexjf25nl65xliQ6yZFfhmwk6EdAJCFQLo0U59QxcUPxuPIYhKZ3QoAUWSZ
TOFw0iCjIpWPekkEb3wCxF5Xrd47SaVaXKPNLneT5RjHLS+3TCg7Mg7+nq6l
L3yFQRVCvsUucBE1yFc4v5MvZ1wOiY1afUKwVZbaoehxXNJu/KJ/NIklv+Fw
UUDtFPfpiY8/di3DHxoCbIppRYM0wJG5ViAK2HG3MBI7eTAkIYHOEaH8M3RD
/AKId72QjEe/HHdtxDXT4AfrPDPMwhx2SwMfna83qfmKevdr0LV0I6akc+bC
A0C3k4huJKkamtmcgHAEtLIpYdKEhuDNbrwcweDuGRmhLTXh6Lj7WeseUWHd
yttH29fePhU2Ax9YkORL2h7J1/F2CZ/IbZ79MNXnTmNvBQmraPKp7NwE6s0S
SRj4WN1tQXsO29Q0mjbW4beUfV4qSXTaz19v3RL5H8GUy1kZt1z59eO5mfK+
Z9M7i4sd/DHowmP6GckoEYtuJfS0SjtcnwjCvekCzYk8f0KJ579jKdDC9onB
o5oVJhxEbmcPuWHSygKkrelkNt6iK9nCKNxsSHmsdXwSCxgqrlsGESYvJGHf
NzUFs9jy9pFsV41tJG9fETIQc/ZIl1HLsEGiztmhilEdfbQIcJhNkPSxVIAk
tRYmgwC9HBMMp4DSGVt7OCokyNzE0jKA/Q54hBgXDUmFI8RnIWWfQUaqS3cK
4Am0SGR7Dy18GMuQWPgKEFDRs91iyiHTCxXOwLh3CmGwoQ+CCAp6h53MtFpy
jIzYKYwG1bKuCn+Pjp2C4Tc6jB2EQp31CEeJBI7Z7oEtV0vPWVxEv6enXMbq
Zqmxxf6R6K6/XmTMG0H+FYIkdBmLgwnHLu+WO4E0GbDlIHnOtmvrMafGiJZe
diRZzbSGnOSz+tnerJ8OX3DYUSCnxbTZ+WxRmQwEnovx+/mTsYFc7TfkCR2m
QHLc6P5NhGSRXFPpOdhba0XpjeT5G0T4tk8yLt9bTA6RJ3A+0Y83zoY2XCJv
JN2z8Yolj2QITsSrXW9ieWsdBY7gfq8Md2FKI+0tVlHM3ee1lQlvvzT79XN0
FT94fcd8Fc0lni6V20M6RzTq/g/QhEzCbkSGdU2Hsl7w5m2VrKCDMCM7mnrw
fS7R+D+62a/SzXrchiplopD1vMjLMXQo08SNer5vZKc7ay+Bfw8lL2BN/xJl
r501R4pfzGLalEDOHI+iLQOBsxWHmHXxEYc/M2YKmvcNfqZx/FJmszjRYYNA
bnV/6mT/qXrTsyghVMNV4A1ix75Xt0JDMvyjFQLPgt4V8jhnSatlWx7osK0Y
G2GwGJMLoe0I7p173JeXRTAbcXeo9hHnAMeKEQLNAU29yoch6ckx4XCPwmgd
yzC+2VtMwOMqeOhl9XY+GVMdv+XC6zphmHegzWi21m3VGdxB7viAtj2/qvkR
TJk3efGmp9FFzWmP7iKtrnsQlj8Sm3kUrwER68lgsMHTSdXUBluEgqoL3LTj
lVQEA4VxQpCKZ44mC1QAL92ynBP9Jk26Opi8Rq3J0K8ZYxarEOOijdesGlou
ThHziDcExOZQ4k1wfHA0Y4Ah71EvimK05OzqhfcSxTHlbjRzozErEnG0t2Ev
5uviyN4eSXEpIIlGgoUbwg6bqIKwTOjxn9YcJDOKWmTo72m9pBT1qEYbJkNc
VteQhOSB2iVHw3AINE5w2MuES+CBn5IdySAQLoHWE0w5LRyfdKzE6f6ksyNW
+wHXCREAP2I6vg+ptC1QDwgO75a8gJYhWxfcq+6fuWw9YlG2tGCIMbzEO4MK
txVUKOUtVZCr37vz0mCMw5zdTzzF2rKg9JZGZlVIjl3LiJBTLJPlG/z2ZgUK
fcE6W23GBH7kTX2dmAlydobq/PxkMo6KMJzAtxjSuBuZSvP2B+JbdE/u3mRj
MHfqbpkKJG2WC3zSRJEmZYf9AxIeCuLNbpvKa8dMqnwCkqN/oejQDQqF4tbT
csk6I9JViKiB+ECSxlz+tDETQUZnhFGzzng5iKaWqUHNgSL1+CTSqRJ9yr1D
dm/4XxIHNwzZgGp57n2kkUCOaCPmgWQNcs+mo9pQDReSswqc6r6t+r7rA+iW
SH/tbxxRZ0Dn6Cd/1NoIn5kR6rgZw8IG41mvUWtTraPRffZ/MAUqZndZ6ZC2
nccJ0jGYrzqeC/VoCGYR5A79bHVdUbPKSL28QWEnPIrwLU9Vg7oVzW5dsyEG
SfCmb3rToxQu7gY2g2AoG9kNYuJbm8G/ArvMqH2Jxs2biMSSR2VHuefaHW1n
qTujE807OV6hJmh7zuCH6VWcB/AuZGI0o/jazd+uMbSZUdiTS61X4C0Z5Svs
8ln+aWaCDhinO4vWRpD7EXxKCNsWBPdZ8LbwIoRfLVhLebe0p3cDs/PNC7QR
/luTAYBrevGu/7yTmb/HstdYbr5iukg2Hi8byTZGled4kaZ8V0+nfQRFHpNz
X0ojGWi6jXhnCokXxQDF62geDGhGaKj8QgyFd0Ol1js0rzBn1ymRUCH5TjcH
NdiiNKvCqADbkXnMC/pOxGpRJzWdm1+3Mvu0aijWO5a05Ca/tay0oTCw5v5n
DhW9UVjtAIuPRjzoJGZClsPttgvXeuCYO+zGTKcw8nqulRaxvPwowmoioDNh
4p5JRt/oCpC3eXqypZ6epVsAoLJhyXu8DT1yMyZimS3GjSQWp2rp3mzMO4zU
nRYL4o0ST/V3j9qnsiYM/E4yl9xB4u2iZDM2TCly4M7ins+X9gnLTVFIACbm
vF8B7Dliki9qyrCg+sEeAooKCMc666Q5QT7VprC2K5tS3N4/IdciPHccQf/y
VCGoPvNiF8OE/fTNlAsNR6BQCr4yQ3ss2A4gO/4aYy2WSwIEAUukL+Qlka0c
0NqHQuApPVB5AAWeqsbG07dIPsHEstewfulxTVg+gWZXV2PQK0N630h2ue7c
76ylJ2EI/Jl7RT6DQxSMXi5lbbXn3+YRX9aL83Sw68apjcm+4J4zw3CPCrfV
BUBy6+2pjWFEjG/ZmkqMdOH+6vnHAubsvvUb7SeFHkAIDUYi8Nssxrxh27Hg
CrFBzfXYrNtmbKonNB7iRkkVOnUpAEZRNXJMZ8wIK0sCGUqh/JLNy8O//Vlu
XaoQvfkGyKBkLWnPkOXCd9HNnhuGKsKFi/syzp09McBppWKf8OCNc4mDR1BH
PVqQPmxMgoghAXl1ejsA8EQR1agROzEb4Wv3OAbZCTBFsixrwi5uDjXKmgD5
WPvEqlaWBGlFaghzWhCAmKfagYHg1uZ74WNUxvXEl3E9WVbnnTi5Ge0JxjsL
I+zQFLq9tF+BC1P0b0OuvC/5/x8EMzneWYpZBaG8dxMV1XgSKnYBUTPG0F9L
0880FWevq+yXMVSAZvzRcLKGThAwrGEXBIsdfagTm4zNo/rQJnFTgVUz0loj
s1drfERbG2Ga3Jp5PfDz2sA6Hk9VrCk3vUr7xwYSkWhk9omJKvrtzpjJdLnV
QQuAD248bfnjZYKJ1pwxa2JtOVy39P9Yh85vQFJjB96cpDFCxCYMjHJB0/GE
9tk1pG11MXwm78KtnQ3rbZWqk7UwZc/jlaAU7sh3YIJsNiJ0BJux7moVErv/
RooISYu4HYwDq422OOCsQtJKXvuJjSJp0HNYKn4dtgLlQTDoBQdORSXZ15Pb
qGBBbnV8xDdcAng/XgKuCZ/YglrI27SQdh1ZY5NDGy+4gZpKSLSqtdHx1gwk
9lt+DmU/nzFHtrws91DFgaGEykNHJSjxFIaHGUTtjN7QBO9QpeCGS7dwBVkJ
YaHy6Kizzerlu/niDeeDULkmUBQIxEYGlMv8Ljl9lwwgU9fuCobutJbXzw4h
BCSITBDUFURc+d2rg8fffv31Q0yWfeaU2OEVWYnGNZZkqCI0ObIhYZzK8sJU
XoY4Zffy4RCtSKADTSqaMjU4iNDbwPI9PBgiOjcgLvLTBT9NzGj/+eMXT+SV
gaY7NUnSclK3ajlt+gFR5lcVgHfg8A9dG0eHx9/RYh+EiP2Vr9MN5AKogGnd
h6R9wDJxu4yjxzoBWQuP2k610T57cDgcd0y/M1lqhHiGOQY15aVBJGk981FP
QZgpgQxAzvUahIEiwF6ENlawjlTDG80HlLomC5JPW4N4urMiB2AATgWyxaIt
Ixkkw4zXl1dLiBlaIJzxCxgtWUAmGfvupFnbZJJpVCRehpvXglGPPiA/0O2S
Rg0cOv5BpCF/p1uwT/S8waeDzELM64O8QruihM7PC/rfEOfIpyWeFBmQeLlD
IG22ZfraNWsBJYBwWAqPo+hmaRV3G8pmkrruNBwOEhXchesh68zJxXXGuOQt
UxD8eh/VhjsVSm37mDLybHJZP/vs0ydYuoiBcmZxR0UQqwcFZNYVkG6CMIky
3JpAoaRj92e1lOC2cBRxHIaPQZSIjCLmaSEAw6CUXYI8HNBM+sv51VwgmnyV
Vcr7xFhYAo5QALIpWbrhn4QCwVV4lvMlgWPD9BdYqH0RlI2P6Dgo/wrzyjGV
4NRz/3caf+TpdK0WG7HF9CgSr/aC6dGBnkJrHnJnMXrFKqrRS9YaQt+SROAP
NE0DDyuf4bb5h1xPqHzHIlZ4ChSfzYwaGgoPj3rZaHiZpQkYQLRAxa2HZ0jl
Wnas4rto6MhJcpTNscqDyYwi19/dPKH1tP6syRjCbjIZ83gr39cqdcz6N9xI
YcDHFztIUSAFHoyf/b4P/Lw8i3fIJYY/Q8ylHqEoWMSeouEaZtE+P8ung4so
e98wtmDxm9JkrTiQkGyzTcAi/e23gRRHWi9E5d+JYZXymrT4ygt2bBgv+WdL
TgmVeP6thMq6devWE/65S66upuhm8F5YfyYEiVeHibJyjNgeVPtrxWpvh2hH
zO6JQKp79G4C2iwYZtAiwguWqcfP7JWi6H092KGsHkJwRwnHxwWESGOTxvQL
FAargVc0qWiFgIuFZQ37oMm+ndTvPn1C4ytW4YQwf/46VyCChKH5ZV3U75cQ
5A9uteUcixZGrWPYgSkJ+FZCHqTAsojKjq/C7p3PjMQc9Ek4ZVz5vQ7T+7RV
GNjF/J3NsqItZ2qDUIYfNN0XudiWD+jFFbB7BbSa1hlIsweCmdt17qNZ261u
TPzgIewXtgD0t+5Bivb69KmAqiX1iFIu8lD3t0e6zyMf3x7pnnCRcWWGpvEE
6f5neqKT3zhSyg719KAdanoQ/7B2XnEBxaFvx7s+TsAL021vMlP30LTj3QMb
tRNq56ad+Icb5qUlmWL6xD/c0I6pzRO2E/9wQzsqnw+j8VDU8g2k8e1YIWVo
29HYtBubysLhJxDqtFHXgahnsdg/qx0pD6ibfU2dQC7tEvNNhcd+IXw6vL88
W7fV5CutI7gFhvP+m9n8nVM7z5kfbg3KPSqZNWOsotxThdZJFRiid3OCw60J
7fe1wgOCDjB3DHk6pjqDoTrti6hzTVHm+0UARXvHXxrSuEpHpnUE/VxcX/GN
jEW5ICF0smQEn16s0rtuYBRcr0bvm0wFaSkti4jFkhrZA2swoPEE8hoC806h
ENJoMW+aQqvrGFGMUYpd+2Q3ucBih1RdPUQMs6O1OXhVODW4eItCowkngekY
LkwpTFzhxVUDsjfvI4FbsibtEFNIrAgNRSmBrYJfReudWGChg/IMYrqkXg5c
2HinL0SqzYCsfIc/nOMu4Enb5pl8ktNbePMUiiCr0yVW8oUlv+KbvPlOTScc
Phi1SxWusVpeEaBfqnGKg0gb3P4t9iAksgfN/q6Yx6YmU5d75i7tjdpiWCcu
RsnFHWnnYuhj3Sx1Hh4AGsU8aGQ+WkmDQcJjIWWkRvPVbOluVRK2i8ed9xA0
8N4J0J33/W2toG4WWdEPAAfVEhyF+s7QvTYk6zk8EK4XPlO4Z6R9sDy/OG0c
Z2IsriGP4P4QIz6wFartNHyPpdltxZMCi1DudIeMi30+dxwqJypOqGodTD7J
yEdMFUBogyxV12HBgb/ur5FCnekhxPENjWNNf3g/xLMxw8xbzG+GQpUA0jWe
U/o8S6qeddOwNJU/SWymzqBQFeCnNzWz/ss5HXOi15CrdFZYli5zojHxbiam
XiBn4c8GycJ6iMx60okK169/et2XQktYPMDJ6HI4Tx27kK3NYzFV2HTXVLkt
wXnd7+YFvC09MJsZdImuKTLeTFfIL4XCJFCNNtnVgkNx/7i8Vw4GA/e/+h1Z
/vvbx27joVIZPN/VF8zX/hU6IR2t/d5j+z9A7EK1QsQEoEtJ0q59+jfkXbvh
Uh09WQVALqhKQ4SAWYFIsf17LgrkSPPn+bv6LWG1TdTWgC9UQHnYRMNCqZ+h
faPEL3PE92VV8XThli2w6CbYquGHJnvKOdHDwBSiY8Beak6HqpZVkcXJgMV1
mxT74CXlQ/7GnSyF2JgTVMFSBQyvTYMMMZ9ez+aXEzfuodPEG7qt4dRcdX7p
DgtZI4HzC6+H4S/DviNMZm6D8qVv2cMTFli409ezF7RlOH4sT/jXuKYC0aNg
emQLe2QYVo4x4ZTQ+QqbyQ1eSqWhIcDdJRMfdtxg93j1YE1UhgFRPEI6v4Xh
JYZjzPVODARQYqRzKLZIdw1YfZmkkIV/dTXlmt9ScYSpLhWLpR1gachNCLry
tWZr9MpzrJsYY/k41tvz606UdpSDq3FcO7Jh4Fu0F3zRY0e4+3DjNOzNvups
B1fgEO3WYC1tiNVCa2RnI8sxTIoEhKDIuckyQU4ZP0wnqcQItyUUDqBN7G6i
0XWuuHlXwewb9LKZa+I9Dh3aMl+6SUo6IbdmJM4BlVeJdhYfNNleZGOKkGbs
hmPiOCpC3/Y0hU/KNfZ0Vp65y0Urj6NwPJ2cX8Bli/UxiYJTEmphpzjxYFbj
bpX6oCiQtl0hsPXNBeSus75eUG4uFWxCFdhxFw5CwSoqjt3Lb3WF4/QCle0q
rKDJotUrkFh2IvkK/n337k7ZL9/zRSKlR3WQYSngKL+u/fAMusWf0RN47hg/
imIjLuW9cEdBcDSCY7L2jDC/9NJwyCWxEJNb+CFNUyvTJWoqbroioaiP1beE
pKthNqquHNeiS2VpJYw8h+L0QduQOlRxUFvnlVNel1sD45tKZEZQwlCCRbCV
S8iugmtRbZKMceJBVJD1Jpivli1WJXUcE5ogZrBaNKeFTGYFS5pUjkeXXeuM
wJiv5hBOMMEzSy+ilDczeLABvBS1RSA9aPecC15tmQcHkhu4KrR2EFaBWsKm
Wc7j/Lx0dpDKp5zZScOumSuITuEl4oXA9rZ6qqZ5WKOzubnROXSg8O330sqh
hCe7oflVKmvse6t1i9Wk7w3bXEiDqswHNZcCf8GnEl8ZN+nWcgJeq4mfZICz
+h3IAQ3uUC7ZnOFDk4wHQb1u1czUHO/xlVWQo7izNGwmUxRNilOtK3Xl9ij6
Ur4DV1NYZ1Xq237q8kKzKIPLyWOfXznuyMF1hHJVYLFlKRVtSlLXkFwpJY0v
3EF0ch7V8C0D5o0+MQyVKAIOAuBj57PJP6TWNSV5UU3y/vD5UMtweI6H9yab
AcApWVOFdiwGs0AzAJjGRKejU+E1ZK4cb3a+agUa19dDeKaJHHw2nrkZTqvF
eVDgPLjsGsMtCuUW+hqTBVGXYa7jSTNaNQ1tjBbH0jdu1wHzYijmLswMLVsB
rUViTSdlgZRoEzlSj2UJvGXB7UG48Bbu8pPLMNCvFnfvPre/Pc/pV6rncHVr
FKWbOi471wO50XHuS5gdqEkowaEJAWNqzOLTiUDZb0ESnoh3kTHotWdxPLfC
X3d8lNAu0Ue+uGUZoecUeDsLovzQSAWFSAJDNrIZHMGesYAgF5AGcJ8O3x/9
cszWkUKtI6VYR4yRSbYo4pmJpQ84OezoEvj+Yjz1VeALveodab6jDXtGyGa+
T1A4ozq0Sb+kBhQCoybmLxLaADvRFqeTKmdYRL5UxhvXQxch0tQ/zOgkovt6
oUzuHPCiSgVEljsl1heurWZ1fl6z0zRi16/qy2rxxnHrb9A2AUKAOko9rP/Z
tH4vqICEdA7w8yAriqsTg8O0MgGPr9ciwDYRs4Pl8efO2jLhO0hTv8W5e2Z/
e4amkHsGWAs+7qnOs3sIuI1PPoAnW07vg/D0sv4kP7HU+8Dt9Qe45++VO7Tp
rZlRrPCVxbAbPhsWbHzmpOB025lAOXjjef/ZsGx5hwyID7p84lDe1gEQu6vf
Q/ABAFBQ6caK7a4L3kduudxb0+tIJ+kp+J4XzIiNvpPbAQAN6wVu9sli3Asw
9VAcxneUhbjRi1EGCkk73rHj/sfRvgcyeE+I/IvyIpbM4WIZBXEJMnAc3XxO
tvrVjPdpQdTGiArXIAWc2kvcl7B8/vq18X5j2Qa3bUdO7B25Q2xZdtIRNH3l
tulC7QmsPPNFD7vbNd8/W7jWxk6+pRF1SNTAP/qz5VJ/p8ToQJpvk5aAZ0AR
RwK5BIVRr1piU03ZccIIAD0u4cLvGp8HaqzVZMw4C1RyYXIWqNnSCLsLQMwu
sArDqduY7ybj5YVXgJfVm9pcOGQ3YoNMsGbcKMZpr+nMsNxFDTrHWIxawnrh
KeXkAJWSNpRxTrQ0lvLxIuTjAajFY2F7kYxNnn10S9pAgJwVP+vGyrB9kCb1
uuDjwHEFPi4m9ZdwcA9HhHiXKwT5rYugycRZeO9u+QTvfnJEbvpZX236M4Iv
JP7ih70nP+y/PuQcrR+QFWBV7Y9O6oPvgKTEIZq1FcR1nNLmyeO9Z8+kYUdl
qJ5ePtezhbYQOih8A6tSni1Xz2EKQd1souczlN1yNrIbxhmGUJiW4zYTVMf2
Nvd/3nt24mMhfKNxm6r3kEV03ThzzWXHKUFMuBlbG87GO5g2X3MIwObUbKtD
n28zBr1YO3dk7bsonR0d2HLvH8vH7kJ3J/70F7CWqupB90LLnUCxFRxH8XPM
JvwJx+iJ16FPGC7ON9YqHleRwtgGjj4BWboT1ofJoYASyIVgbgiUBv84dPKW
yOQMF5K65yHgLAmcSPfra4ya8A7nSs92WN9xF2+vtxDf5rVdteO6JmxUVed+
Vpkwd+IWGZe24r0EgbehPxwuXtMjKBFqPb65z6IMel3UsCeSXgeAt4SiC5f9
GmGSWoN3N9sDkZ43hFqgWVjs3ORXW4pRry1SQx0fZWn3FYKhk88FPLpYkoll
ffKaYRwMK5lQf7bn1C2VoorSBAI7EUbsb+L9utOYuiFRQAfcPiS6kZRRlAJD
PxAaVWJdAPOL0UJiC0TkkoQ5udZOa2uqxZvSTmRQ7rFu1FAdKvIzNkoSqMNb
TQXXa4kil5sT6fZDf26GSNSXixpsTdziLnxFsUBT5ZBDWMJh+eNPh6+h/Tj+
bZB9xx/a5M0oAo/ftyPTN2D0Xqy0+6PxI8OQJCfKu+OAmhaPl09D4CmlKc+b
5U1zNm7MaPTRRQXDR/+PrCIFHUUSQI8TSMcqOOBhrJasShGHdAtm2aCoU2lE
EWvtvC2aC1GF/F4jIzAMHYDSPf8Te4c/N1iKN7aO9crWgKACz9cgDjcd4aUy
JEFoiFQIeb3Ki8Tu9149ff13vpZZ0fILTTrCuwmi3ScBO+FQ3eIxHYY/rqZO
S78mvfiaBgFTxwnuDLDfJ/s/vNrfDzs21wN7cAINz/tcxKnE4jMcr7ls0/BN
Y7Ki0nPiCtRm6veQdoDnnaI7oqvADyoiAUyT5sZd8sxosLR1wtsfwbpDGLOD
YXRF8lSB+zHXYCcxa/yQ8IhZyHFfJzDVXIf4wxrsMiG/6w4NBm5CwRy6QwkE
NHu/CWVAjqwz5HatLUxiJY1ZFw7QRn1U6Y2EDzI3xc+eHO2skuzzGi7m79wl
M7su1kjuZScQ/ofd8OTPMM0bg58oOGlWYNq1mSgVWcfaCKAKi8tabBRy+cGN
xCGlTp7EDTvDwH5wNo/BC3Z2jXb+xRhFtgW7KakGPN75fmbLhGXygO804h/x
8dPdXub5JNumEwduUw2hYk1Xwqc7sQ4xBFPGXro00SysfgqRWlyjG2jOpnl0
z2iCqyi2Ta2GHXTVi5rMV65ox+rREuS5QNzF7zpGRtotjYYRHhfCm4Dbhfws
4P8qhSomUF3TZrl6phFygXagUQRqzMAMKMDrzyIfZsfBowA518azByPp+Cib
LjrVMkqXGYlHtIuk/htg9Mz44G5IkAKVBP4NMZn6GCuUCj1wAHGp1L5lkl8i
o5m/92DGhF+lW0u3DIluGFBkdiH7DFrTntLSGVGOBQB5IFHcy4pvEmq8SZX5
BNVkddk5H+AtTZnusJERIYQFmAS1adOuKQso03PYFJQu4AZ9l/CY4BFHp738
U7ntcb+itgQJPnrHTjh8Q2G7OKdiM5LOz3QyfCwBlxX+RBjw8155foKMGgG/
/zG5CqbXs/Sli8DWBnBtAT/GaxXHJG3pI9ynm6ys3D2+AMxLA5KAeuVVgCTJ
BziEf99w5gnMekKEbSVCso921w5/u22MESlolkgPzxPsiCkgtZqOOAAmFDhH
cwQM5XhLujrx8jNyHNj0oRGJPhkETfMQAZ/6BA3yJ27n7HS2/RLwYuHok1Wh
v0mgi8C27EdnTWOCd7/AdDPxNNnJBaOE0KvMcKiYLCycYgf94EEyYBgvUbOO
bNeZqBLiclXVvD0v7uXssPeKj8THOt3Y/FVGL9zjrz+SFV0f/SP+SuVj8Wf/
4j3/s5dS+KGPJek5Jf/pnqOR2IeClrT/0FK3frTp56OjRIYW9wr4qSzfcqYN
kN7b6x5LqFUTsKoyl6SpBrz2R1hdbfEUczIuZ6QUG1nY8i4m2HGmq4LlbZsU
ZuRAzT7Faw0FWBNlhzHTRqsE0UlkcFZiXcOrhXUBe3tPj6sUa2RsclyawoOr
aw4VOHdQv/CBxtZDND+zIro366AQUeglnYF4QJgoHwcLsaAYcIOlCE2QF7Vs
4rwgDup1VAownUvPSgih4hUvFKXw5sltAHWQlcp8JcQxmLwUKgDoZidIT5oL
WuGtd4vq6spNZitUnDBVi0wOL2GgYnfQOCU3HqQhdu1j8EHMw9eg/KB6oj58
oHb72JuTwT59GpRPCPJLJyUePvYHY8NiPR++yfiIxSxxPiTddoBb7+iX46M3
xyB0P3d3RUBrNRJYz+RWdA81W+QhttQ7cFdT7s7qoWMUo62SvUQhKZSBDQEV
FaZ/4EmjLgH4YItnWAV3Ax41SwZzS05s3HiRBsRSKKrfVHMzSeqxWtKAkVMA
O40oBw+ArdgJbGx7Qos4vdAE4UXBuIr5KQSw0L6Sw813klg/iHnFFE8xqena
ifEIW+ra21rE2Z8zDo4UovCrcl/jjHInkXe9zEgjjmBfcAPmMOoWMlbtiCHh
S+SZf1SaQzaAQ0KCK4dQ+el1/UvelWM9OD0nHfgyKJJioneSpHrEqBy6PRqJ
0Hfvp4scH4yCie9aCQryeEFc5HAasgri9s9EEgeAdgjk7xiioHZ6zlOj4T0h
W01mQ6nOfoWcAZ7AUE2IBkbZ0bQCBHiHJWLnl5fzMddxcBzU+gTKq+mKoqzF
HWBaAAe/MioEz9pEpzANZG9os28k5pxObSIvUyNtt4FdKXryQBYRn4OYHL5X
8ZYzzGDoDQ9AStOEY0Knq8l0GaCg+J/7ATO+T5ZIiGZlbkTgqXCl8gjKDgTw
mhbK0Fnk2Wp3EPQDpGtWp8SsIAR/ifWKK6ocDOjUjvNSqutKCiPrgZWuzEqH
rb+sxpY06GBF3FaYyAJp6MkziFY0z7hnVryCGBO/zgEJy3KoG6dTTa8uqrt3
34DhPeTV5o0zLqbqrkrNBMIXOVbUDRHuE4hv0vAmP2btDEtr+U7iStusOXaP
wzeJdQRvQgrjjS8T77j3yLRiT4atYJlyo7Zrxp7ulgun/P46jEZ/V0uGXmXf
HxpF0i+DD10jsUSMa/KeeQlXzJvxCRwWUWoNybspPUwTR7vrbAzHQa0er56g
ZoiVGTfXCwnHBS9jUQztsDoRknxJ+pKP2wk0RyoI2LU6WaCLfcxrjvy01Ry1
Y6P3vf0MDdIbxv6VGqTqLzKr//cmbTKC9VEVMvr+NnpjHJmRYKqiOyLrwbKR
ntIaq4q0+3heNqEoME1bPUNigV5bxU4IY4WUoIXcBL2fAkTupEPRRiGDJxBh
4QvK/Vld1nn7aZi0b4eP+UWU31vPgJ7sm0D9k8vEWwVkOS/W64ZUEixpBdoX
4dT4SYsxiASuC/Q4cXpVnIaU6QQoZDgnuGzc/zF8Lcn5u6Tu5t+fNMZXzmo5
uhjxVQr5Zm+A953LQ6QiA6Lo0hvGgJA9jp0eBWJrx0cjuD+7CSsvfmGgUkPm
8WTMGAcks3t6yt4qM7qmuAVyqqahQ0bVLPcgedGntlslGxDtqpL1XnUXDpEz
s1Ldu0lTptB/utvQuXbDwYzldDsZSLJERGm3F20aND2pp4jpZ+0qMeU16apQ
fya7MsOQ6iZ8y8S2P6vOKST+tHIH3XuzKO7gNLyifdpdhhG5A9DYNDCOx0XU
SwTum1xOptUCkmoBEuBysjQxsmuHMSiMeZVc1W/rNFImSOIHXHUOTnM9ns5x
O6G15HJujmCmb4A7ce30YQwUKk5GjNHFHHA1NACblPfh0knO8dRj9tXt6XbJ
2jDgAA9hExqu0Mad6NFBkYUVaCGnY1NnTplzO84tqI/J99eW+/rDh4PqHzvf
fPqEMrbbgeBMnC+Ihc0Ly3o0MRjXBhizQAUQojHvREnrjeEor6qGGeoSY0oI
G68wIHokOsOvwt0hxQGOMl8EyRJgANPzFxjEhIl3Ehrxvh5b+pABRTh6MW7V
X5sA/zk7D/CfKteHHIA3bdd7alwhyew2xpX5WfYX79Lb1Oxif14TYfovssiU
PzV253MbLQLPEOkyjK3PgWDThEYew/SzRh4nrODzcAAerbfyeOKpuedVrczc
KiTizs1G14VO3Q617Ze1u6aAeba9m+t5m2riWh6a42f1F3TmLqjII8TeqjeX
xue+juoEvwWVCfLG5A38NaxUdfT22HXoHsibx+IT1mYp4wwTbiMMlicWGsmH
tArTCqxawhqNHhjWHAcV+q0pbH3ujr/OHm1ieELMRsIyiIE9zRYjCT9mYUO/
NymVJNPcPw6MU3unUK4Vsjopns8wuEhCjWUF04g9QiZMOGVr43ndzO5APTFi
aKaNSGNw6kmzgiwuMnJThLEfZiWGDtMCmjxkXSGcaILxgvQ42gUx5pWMJl6b
B1C08u5dIFSwYbdvLFa9JIPjZLYMhkQDuRPaAOcMVnDh897ewW7rrxXBxFjL
u5GK+DIWAciUs9G1zwtI73NOB7VtBArLAPORcSQqGSSiT3aZIm0jecl6YNZs
FknKi65ciQ8LmjVNSN6XIgYhxtNVTmppWKhBfcc0ERe9B+kibK5K4zJCEyDX
ohhyjfPu0ABG4AgFtmI2n2msu66lBaQSaZGwiuziUvppZMfjnNRHwHUGaDVC
C9Qplpse60nfZXvcMTCZ2HhFeylqokP/xuc9HxcqiBmPuk9+lxr2toOw0rQ8
6Q1YT4B0cMFrTsw6+xXDC9vABrDgaLNuLLlIB7BWYUcWbThrx/FWHClMfWMo
QAq/PNgq2YCTgWZmQ0STj/spO/t5nKTCQCEZLcUmeiS8tjqT8hxS8prq1SOM
XXEjkLukWmauQMNs0LxCKj+J0cn92MsqHWKuMufUcot1ul888l2poNJi+0qD
ZOVGC2w1nLBCukEhEdWo1Jn2xL6wtl0qbGi8csUyBCCITA7CzgIQuFCMNVJr
oC1lKfKdzXGC2dh0WZPhlL0zTL9tqAiRvsH8j+pyylhCT6yvxO7kMk0WComR
QDTh8x0nL/lWvcC6bb4UOfht+btI5PQ3OLOgA7ejai8hQsyxW/9EpuNBMl5q
tEtbtQe6Q5h5L4l80buJeUtv5ayro7npoCSDGGQiBQPp0agDhpvnSMzXR0xo
WhXL5TdbIF4kcpeknhIaRxeW0LYdyWDJKvI3rxerWmso/CzFhqS+ng8UVuCk
bAmF8DkgNFXbBnJCBSPgoSaMvVxWDVzOyLS5whGltzDEKpVdinJDP32CmPxk
uxdtQPM9Ybk+/pDqDwUsDB4ivjMo96ZTjfYKiy6I+ZHMjiCQWsghDi9CvIkz
QD0iyBE4EX1+TrCqiDCPAbU3n3Z+K3z/fJb5rbLLs2D8gMqORTkefj1U+jeQ
j9syCs3OD5rAaVKKjhPyOjZFv5tpgkvVBE1sD8sNPzZT+GWItu5prj4iMqnL
3tMNOxF4dgIJKRFeGZgyLnEE8UyYUoXBlNJbPon+F0TA1WUmPxW9Sk0Kqqcw
hQleouadDQMUhELN5O4NQLohnY5QKiCcw2RVSZvUxWWY+ANlfLRdREkIg/8p
lo3WF1f+aEJptu5/3NVFzCcHVQBqOSjzkDLH/m4b7QI/bdPXkleiUdxR3UOJ
cDdGG3kyNubA93J1teag8wUQ5JPRW3BXn5wAEvrJCd/W4WPmuvTsGRg6/Ne3
wUk31EKQepM188GHufSRuZzNi10zQLwcEmtUaPFoNWXeaJMsy5MbzZLYpxOQ
AAj3URBqf3T/OLm8WkwxyecIBu0aIIq5fxx3U+pwr319xtNFE4s82dcEu5lW
MTZbm+GsIGqE5C+THnTSnh+kwfGmaXofqOJ+7Zhqt1SuaXX5Ba6GL3I5fJHr
Yc0F4abaYVnmsnpvKZjeF1/girj5knAD0isCUirSG6IBKHeoYepY+SXnQYLz
5RzawfBgpzX2vSRToGGTsXqjC4QBXc+hzESChBUR5NhDREW/DDUQDlpAGMGG
KyhF/o7X2gObBUOXLErTUiA0VuCqMO+OWJsWi0CRnRwNeA/OEWqxZyC7q/Jd
DUjBUDdRL8FG47ZBekJo+9McKlhCC0iwBN2PMboQKUzEe+yG65KtRgDVDjq/
Aat6N+9RBU90PQJS0+La/WeJhxzS0yehXxVbp2Yxc/Zi3gCKs07NX+wFBJrJ
ACyecrJmg/KvbH5sdMhsrg5rXWH0VYheieVZBLU29MpiaV0RTd14QrCQ1mXC
yn2zZMvgsoDeewq+bK2JyjspEVcs5Bt5lGbLhWJhA4F5/xBUgfilCjMUtF+r
2OPVs77RrkX6AWcrOMLaRCB0GMN7FCoQBx0OrxTJjlAb1QJu1+3+sLi5joVC
17EQJeqxBViRIRYiTflYALxbGJvORJdvOYo1W2xTNZyCYB4QaEwxk3sirnHx
BH3CQpGpwVtrBPDGoyIBPR1IkXHju8H0fUFuGgoZazlYImv/ni8m52ib5VcG
GSkSLoFWGXJzoe+zJLeEtdDFvVaek59gedyXUQMD9/UJRb92umEz/AL8J/wh
aiJtNHw8Fpi18ePcc/iInJUObNT+dq/cPu75QXWjF43orc+ET6QStn/wC8i7
9OYJHi4yZ9Tjk0nW3ZqRJi3yT/pCRFrrgf03E6bJ3X3kFwfElFPgPNh30KJ7
VvwIN0ne5dHpcdf4KbxQ+gWk5qNgVCQ137SO69ZSKJ1+u34x4eOP3/E/SZCn
JNubd2/EhLxLCK7EKA03y6CSJZCM2X3sO5Qs3f2h4LmhQNCLMBuwiVhOo8h+
LggFSXpSickChi4ZkBUaICvbgGiewXmiTx8BF5wE8CeoFmW/jtnhn6Lf6bU/
Jlwy9xDr9j++ePLTs58O13aTfVboClZyGm2yIH5TxI7urUjeX87nJJ9v8fHb
9ApxS7Q8cUQ/gRU4oYE8KnfA+97BNjD5uc83IcirJyyvJo27pzKtiXnkaVgI
FxIRdyl8U9fQXeY+eJWLehDInsR+iHQBuDO28IwJsWQvGcYzgBPt7aSCx0H2
oEYAB94JlE78rMU2r0vgVj4zBXs4G44TWnn/ORIF9r3c4xJYE0bD2HcdqQwp
17QkqWUiHwU5X1Of56FL5fvjV4R3U3sdHMWf3BHvlv/bPd4tMo/qMAI4Bcl/
LgrP7D6HE3E7mfurlR8dhJzoSU2cKGQ55I5MNEmvorA4SWIWhJO1ctPukFkM
od9V1woNCGViJuRSTCVZpZFwSJoalhvTqBeWnqV2S4hK8G92ammRx/G+xjip
aQ9Gi5FStbva0OXR4fkf7cogrAFTWrunm7v84x9hI96FlorsI2bo8Jy0r83b
Dcovpzavn+vRFzF7tX6+iD3sMw1l2zvfbmQpWzP2VguaI5wY0Wj7JUoNxEmv
Zm94d/5GprU1Y7/R5uamwGa3iTgTSQdusbl5C4fa3tByQOh/UDHMwxrtlkOa
N0CuxxIDmT6GljzDrK2usCyLTERva2/4Q9Wacx6DaATp2+MscQUl4YepN+j2
lkHHB5+BRWQDxsRJrd4liu8w5him68DxLG6yJFLppFf7j1/8+OP+8yf7T4jX
LiNSlqHpAnkqWsvQYK+hiEwkYjGAq8kw8UCz6bSe9t2697HhPj1JKQChw8oj
XdKGyq+jMv/Qnpk1lFUWVzQcIhl6opdopTSchhtXCbu8nI/ZoRbbGpPQP6v7
Uzt3GiO1e5Qv3GNuwkOT76U2XA2r03KxWBSti5V2QL2bYabScn5eg32xza6n
9rjhS14Q7NBDYniTm1kw8HibBB2+lJuoanGzOjX1B1VNYT+la1ua5Fgg13DD
YVaY3QBO+7mbqtq2fIMUwmOHZOAP9ThCqRuMNtBtajBT0f3r9iMZ1yBjtBBU
RcZDhxBbLhhrukZmRF5Xqu3D0I3G/YoJFwgVAtFZi/nq/MJDs4188WRDIOYE
GGKFgjR2I6hzGH3l3cvmPY25NzZHtGa2r+mS9GMYKJaHQd6rhC0ww2I0uRIg
J2jo4NnLOw3F6fj8A4a2sZA2klXugzULUhipOwonwz3IL0CBsxKyX87jFS59
5RbMHMnOpSJuGio2kuYm8C2KdsdnQHjIeiN3S2aJDQmE6ABacFSjB+UrUyVE
QECNKduH+dkKVtZfQac9TfqYEKRQXY3pwHJ0gBILk6hsdEAXMXS2ztx1ueWV
tijUAKsuChDpuUCnNBN4rJrV81UzvS6CQEXcntbLZMzu6bR8IMI1nsLClyd+
4SPqweMRz0d5hDHXB6CTesVqpAOHFWlIu4nZt2XP4e84RpG5sHcKEfZLXIEW
J2+3go5hMiOkDA7RLtLlwerrmj6KI81taD8Ek+AFddShxM0VZdUBN+RjmT8T
sKoY5joRv+Bap0V7CAjLn2S/18oRvdL8U235ubAM+J6uVlQk8e+chok/WNnC
f7uZ4T+NN2hTffVjOsr8mhtl5rFkzEbXEoUSPk8NJufSciBZD5CXA9+cmlzg
o3KmFxIY+WQD6TE3njWOD/xJIRYVgZU+/zKviCU0AOWYP9vdIv5sdDAiKdKU
sg4V73gJVrsTSIjlvaAlUvV///v8sNrdL0Gb4VPBQcrNM3GdJXM4un+8ibdG
z3Le8p9YveBDkZ9TcVYktlL74r1HGzp8wn2ZHjbX4a/zE8RGNKXNb+wPuoU7
KJ8ZSC87ikXJgyYdcuB+7IS5hBNvmsztjTiPyzXtZ3I0OQ5/JfRRqFMXfE+3
NM/7xRVZkCEKMPMUbKHn7o48BozPHfc/ycEOQFZiGJ306d1kN0xm4/q962eS
a90d2l/SN874pT9iOiAsc6Zd+MBPYhjGQDR87zh5NrQ4t7UQLnRmIkCxo1/c
PHYgolLof9c3svYdgEo95oFSl32zi9L+tH1Y4Nj1qDjHsdvxVsfX53Eykr8b
bDc+qonD0XX/q8L95I0MA4vPR3ZX6ftimE/mtbkX9CYKwYd2lmxfuBd2OxNY
za79LifPlJswQ6Jy/i8muc448arewCJjd2vw4xrXq15Aqbv5PXlecbneo4cJ
+zhW+/JX5aHb3SPR+kJx+DEcfqnJ9eGrdnsTa4WhcUttCKZ8aIk1kPvzszMn
My/f1Zy+pNVAQEvPiuSdFiNKt0zTGNj0oNi0thLba03JYp4G1sTm+vJqOV9S
dBDoIhMs8euxbHBihX+jxVJH4XABBncWWeHPjlW8BUsKqSmEStFcTK6UKD8/
2TuIKyBEwy4oMhF3Wq+k+spo8nLKIKSHoq62gHQL960ppuOrgzE0LF8uYF1x
/6GqorklAOr0QIfCwlmlJwyPyRQcCuoa4hgazmqUYixxwlIvym5ZcnZwvKpV
Ga8pD4n2AMSkqv7qKEHa26J2BGFIDKzLDdmwF/MJGdGjbUsJDmABXIC+F1QG
d7uCivy+rRbXop5TeSdKbFFT1UIBk8DVPXCnbIkxBGFnRagdp5vJ8czF/GqB
ao8dCe8CHItWyWZDEdPjm/v/i2zUbE2xk+f1cdOxaTd/dnxkfu723Bd2NH1h
z9IXdiW1+o6UHLH76J/qLbrJPaSj9B6iJCjblKevG9gBmg44dm8vJqcr4f9Y
+9ptQ6dpL68JSgkShG1l4PJCe8x4EODUsKVoZh4tTlfuWl9iSBEFTHKVekK7
oV+hXPX3+C8SKaHX0/p8wsn294eDLkEq26pT/Krj2uAZpqH/o2bO6rY6MRC2
nsZpSgVVK17U4D8zzXn75Wi+cOfrak6Q3qMpxPIAsqhruk9NC35VccbAtcs5
XTNJkhOay2PM/8BmwTUOmFptDgfrzNHlH3oPH8Q/5/x7RdizLo7Q8LuMt89E
/QowXVWo5RzYiRQV9yXgqWxsuaETrNjICeYtOOD8KjZyfq1zbbnd2b+YLxMv
lByMU9mH7rLjLLGoxTOq+mevVDZ+n1GwNrRP8PAzXBPIkm96eKjgOeppMzN5
GZrJaTOfXhdpQ+ziAJ9L5HjL9mGLYYr1FQ7fxMlrK7wlcUZodZ4sQ6j8qOIT
5BxoX+0OAuNqc7RHb9tSEw7BcSJi4KZ+tnbJUDKv54UgZhi7ewMb23Ezd9wm
9VtmcIj2vLDXI2Gq2w5FqNzQixCAMFZ2BMVNln/HTKersQVnmAuOR8YXMSh+
rUdAei9aPQIQHRQ65hOwgsgRUPwqR0AA0oY2/OIzbfiJZd7f7ia4fjOz/E7O
rg5fxab31CD/z7K+f45ZvUrrk5vrRY+huJK1DSpIqPw5EzHyRS3o/1bW7A3M
2DckD+QGnWYO/KYG7FaTqjFdB+a2YzGlRMOSyDbrPykj8Kv/GcZkDyciyVoi
EDSlSWj3O9tYr/5jhf6PFTqg2L+DFdruz3+BNTo4T1ZtA3nVyQTb/iS5b/Qc
9c1k5fc1WT7+VTfF09QWbojQ8w//Ztnw/3xzL1H1BBVNzrmJ1w3JZx7LGYXJ
bPAjSIFOh0EYi988/Bjb+k1DkH8D21F+DnlzUkzOXFAyBYn/a+ORaRLrjU7x
XND2dIBwIbkI5V4WH8aGDH8/n0/ralZQurtFU/b2iiGAMQ0lIx5qyYDJtZYy
0t7JUEheQgXAYgLiDWwmtJhJHWtkSpdz7BDz7GtOze64wc3cnwVVaO5iFgXX
c8frn3pm81qWMlyJXOu6U+QsY+ajk4HMSw2oQ5DQM2kuQQ95AwG++y//sv01
4NQA4Wl+GDU4OTtz5AGxfVo4ZfptNboelJ2gGjkS/DGaq0oycoHlxaSd40DQ
3Idab2Gh2LobGJ7iiZLgrxHm1gJV+AjzcEWl7g7rccSPaFN8R8HodCD4RffF
5HJ1WSRbQtrpTAb1oGdgDtQ6jwsMjg3TaPc7KmMW2bsIbU901HeQN9NQFG9g
t8Dp8ndqSUMYKyDdYzEUZo0uotejIhvPXDVnnoJYWcwjpBt7yAVj2QozGQsf
7uQh1En3bg225ulqLGWxLnK6DCOnxWIpwIHrIQ9aDFKYTM9rWYTQDnDouj0m
IJqH11HQj5dNSmTnhVOIpKMwZCquBCORyOngIcKhXZ0uFxWUmJxQilYxhELM
2OmJ67Trayfpd1rtJ105Bb0ibIcIQSE3iNh+4gSVWmfxmgw+xW2Mda1IDFxn
inAYcoaT5B4zwY2Ax7hxdGPWjPLPMpB4PvAbm1AoOzSynZDNRJuIMnCU6eVM
KfpSa+YwfPqakRFkB/NP952aZDqifvwXkEEqxvnozUARC5q+wbRjNQGDTB0l
2mDmq+SDWFoMwrbh4RN3KYYJgXweglhK0++PUHMTq+2EtipLifEcYMQBw/oM
UriXAUY1zchxztV0ZWstAM41SAaQCoD+otFyKp6zOmqD7fOW5THTkkustdxt
AC3uSSwJ2X7VbsIX93EMmnGtWG93siqvfu6MVosFej+QFmAiv9O9eVzmtN0w
NrMLv9z4bmFYNP3bYf8662MW4i+YyE22Sc+fPs9KmT01GeNl8Prt43EtffOd
/ksNnf6OyivzkzO1HgnOmkL/bna0BCWKJe80ZONOUsLTeL4mgt8tahHjaxqg
dhUvIqMsKPvvuybQy9pg4y4bqPY1DvqMRSN9g/4+0d8fAQsLSORbz4Y6mzBm
HXzux18HahMNswXYhvVr/fF/rDWa5GgW06laDe+a/xio/2Og/o+BuvzVBmqT
KypcONHCQgiVr6CE/eTSV2+kSyDPu3Fld83NYirjivgRqJi9cCm70eOWQW8W
UL0OHuzIXnnHt2amPCRhNjyhfjzUGwz0tpUvZaOPSP7vaLEPCnTLZ73Fvnw5
v3Ji8jbEaNO/2rHo+VHAQMQgYwV59jnzVfOGQ/toBxcX8+mY7TJ9iBcki4rU
sP7+6evDodpcHrt26Cai4oNNCNtYDJ8N+2DfoXbU1Dt8BnoCNkW2iWm1XFLg
yKI+qxcLwl+g0hnF1sh1BxnQWIQEYgibLS7POuea2XO2u2hCOh9mmlJzhzlC
gQGGXFOBceqDlgdMydCmrKadBdt2ZyYm5qKu3l6XF1AscoF26eV8NIcisMWH
D99///iHH57ubAvoppSHXbIJmx6VCXhFGauV2yT5C9CqIToHq16BafP1UCaH
i4q2XbDFNrB88DOF5HG1X9kythR7sR2sO3LycUPp7bTsiJYWggbBwq+upnMI
JwfJg6rHUIy4xWwwZWcG2NPrYLdcTcB2hQaUCRi2JUA0XWnHCZ2yPbzP6vv2
EM8hlYviQPNL4dDZTs2XpWMmSgoyW9rMblOTQSK0fOUqYmON9gzfTxYm7JMJ
xEPRqeZmv5oxrZeZwNG2mnIXE44phdHYQgvhBi4P5Cf6Akq6Sw0WbiDYRUjO
8ChX4zEgwpYfP5ZCdvxjexhE3nPVCIolhlbSxcOXHeXqys3jcFlflTuOHn/F
UDxZB3QhLesZY66c1kmtuPCEsRhcnc7f1oWcIcz4Z3+NogG7JgBUgNOFKTQN
gTdGHh74XT2dDkpJ0ShGsJvFjQCYFTNTthlBjldY54iYrfsSYv3BeeNWESMS
L/v4veManz4V5DSYjK/O+o5gYFL+9AnHMq6X1QSg3ApDBa1SJXWK3PHYeioh
1u6MPJHwbffAS4zEO2A2VXaePnl50N3qFYC4PbkkQB4TowvVUz0zIrmH1m86
+QebwmdziQuvinVdQU+uuR+egrdqUH6/mNRnBLPrftHQYUc2DTcnCB1TrIyC
wreoVJvw2i1oQv5g7ceXMJ4zSPOsgJW6ZjWIfXoIqe32AnhlLitYe2p7y1u+
pWcwepvJTWYFLmuFvh/sdDZHzgb68nX5ZgbOPvZLwCxozG4N38Gzk3CMEBU7
K2EtIuq6XnlEFId5VUHS0AwnDNDdBLu9BFealqiCWGgIlzbADO7Uvq0bCbb2
+AjIwcot1B22IhhLKCToLmQ3rXFdiJnadeRaOeN1H9ekSNIEmYz1GEfZI58J
Cg2yNjpljOZWBylJyKZuVEye0rhRaavDsWKHajUrkHBUER6cu0GndBMvnGwx
AelABBlkA3qV7hq2UQRMkxJ9ZqSW9UqsB66Busgu+QbCMchlx95ifKlg9A9M
uPHBqm7JoUboZMz7w13dfVzH9DiX9k4XkYiuHsdrFlAOKrjB4dh65xcEeUOs
NsDhrOHnRN7Ck1dTp3B4W3wrLBHoRNDIsZ58nJ6AMl40rAHUoLSSiuuxj/y5
L/xZVgYb7cX3Mjph/VUjxdx9g2Z8vPWYdWaELfTN+XOhkhVt76C+uG0XgTYb
igGYzCBUnIWAU4D9xUWkpJBZpk+QN5yu4Lr7rmxaWT8BVLgOCsdsRqumQYu+
cnsOEEAJCDecuoosGpTTAWhZLO/uuQsHD0Tx9WBnUHaAv11VUDZ+hBkpSADH
W+l64kYca5XqABBEsZheo+hfjy6IN7yrmsKJ4FB7XtkWl3rinh9QAR0Q3icm
Ha/cSgbsWt4adNEzzDOg61Mcw75CWXwgGJZy5n8g1lVkBAsJFYfqZAaYndgQ
W1Qhs2+LUzO2JFS9oKgBDUehA97Qm3i10Cz5ZkGT10wjCvBiYNf5oPjRLfBc
UzsJ01J4hjrYPT4sxLlz3Yn6sgKmstAtK6qb5YxjI67TRdZcO0HgvbApLJvO
HlxaLBA1RNeQvYZ6n3f1cnAD/RhUxnS7FlCVak4mrWgvuHWFvgblXqmo+hY1
CrdvtEehO4oTxxIEKABRRTJWheKaYXouwrJhZbZsWLmZTNSQUNQ4WeUrpIu/
mw01YPncVMdzWJCS80DK4c7du6idqsJKai8eLQVlKp4yO0Y9SYmBLAbkSKP4
uoP6dOa1cROvc6dBKFHRuBq9pIS9yFIhFfGXvkQ6RNJkt/TBKIW3AUiDUrSY
bxzvd+AYq+Gpa8fNGPa46hdbU3cmplugyGfgc4AqUujhTX1tVQJfrVSqy5HC
CCQqttzDW74Tfz8Myr8iy1fJBq82N4ISBkBpMjgVYgRDIiUJDjAAwX/LFjjF
CR49Ox5i5QpuQZR7tlQUfE/4Gs+k8SmPISlUJBy3IW2xVSs7wWYUosYBcBZg
CzV3KHvqRBZypQI5F7SFILMHgh4aBQdudnWBJrMZpNBhLEuHQ7UKim18Cj8N
uz1BKifw5bo6k8fpsWfum2GXb5GgbiGodHIqO238okspyaBkVU5rcnTgFGTy
x4Z9FnihRuNmYZAsIKxm6UECoZkvf5Dpt4Adei5WhLfikxppCEPfFqVsjebV
ddzAp31jd7ZwENGcoAk1IFJBgw23pZsfONNTPh3C2nvl8AXa7YaqE7nxu9tg
AYTwEix0VQzRaEiWRl2/4+PyYxn9ACt2fDzEJQOquZc5Sk+1lKrwG82TOsbn
tGsT/caMpBk5UacW7IHFBGbA+9ybD/WYg0HpbjkEmgzcie/g4XHy+OpqWqMX
tlcOBoPjHoAeVCc4rt14cjxrfgaGBybUaPK9crR8v+tk4yUYh5zuMar1L3K9
4R9oiqXeX65Onc5/CEe4J+3hM8fHevxhB/TbWBhWJFS8St6ipBSUwiaMDOBZ
KUp03uIAG27p9qNFrcNcZJwFRvu89jFcVHEex07O2w5QHxZ8aGY07KoIg3E0
cI6AJZaGqyYcH8NIZd+7WTcR17cM+TXav3CE1E46H6SJav1OZnjLuhume+/t
HyJvJkv33+ZnB/D1X+rrvbrZ3vkW2Mv7+VkfH4Yl6Ff4PQQYls/mc8x4rZwQ
Pu6RqARt8Ykq2BL2HuxHJFLCfr4DtJAK7CTP12OvmTgZdTpmRiguVrxkXHNG
QZYLOBZfYJmy4Vh39cr48afD11SsKjCbD+QxfwbanoX4jNzzRzjQ49xrP+89
+2kfYiaGfiGH+Dhc3eJkyNzgGAsSdQaHb30n+jwcOn7UyW5y23My6ePDl6+e
/8DRwqYdjO84fPr/7Pt2cIvd1BCDIeOzfbYGINMi/s6zZC7fTftF/vT8xfPH
+9I7rKYT7XPL+TqIWdPDokOk1g7/vPdqHxZX+R+6L51aeDIZU7whH2Nyq++W
liFBi8q/cLU0RFGUnV13nZFL5Shmp2u4ITJAfwMVZcjnTA0xL6qBfRzq3sU8
IGV/AX9x542NTJMxmJ0gGpiYH7MvEsGs3Y3qpnj7ujERxDYD17qQnn5imRTO
Lifrz4Py8K45eKHHR98XEct5F25i0UUZMukIZdhLl14FDFEkPEPOOJuynAT4
CG4efxhS0dtsvS7JqJdoxdGriY3y5dDRTWV3Sw2/n/nCSRzZd5V/tI+DVQB8
et+4HeQNWPSJ08jSo0hy/T3mc3TaQjglunTC07bJ2c21xXPUxiAuQ3ZBd5h5
yWbotzWCI/IsEVt5eiZTe/SIVkn5ubGlckskeGl7XihHOxmsnhHnvdpRgLQp
IAE9LzFrVkwopDn59WI+DhFrwQ/O4ZMnFGYQhOF5b7fnSSRSYQi2l9aciOq/
QgGN3N4YXQdU+CPFEAgREqe4j0ygG67I/wYXEjnAD6CGHjocEiRrkIMF1YIx
rPEuJGuJR/AlOxZYSd1pnNZN0/MHZNZ4qyGZT2eA5gHHdlQtFgQATLhdSHPP
SBvGeCdtpppOzmd+adh0o4Y+NMtUpw0qJzB2zG9CoCliauO505kQb5wSSIjT
jHko1WgxbxpqxY6gdBvjCpscubuFggoXTQ3+McKymp85WQk226m7X6FcFQW4
1O/BIAmWN2j+bDUt914+NbSD0wvTJxaBDxU8hqD7w5zIFPm88omFT9BbhcFe
cTzELT7/hLomxHTxRAx57M8zQoJnqrFuATdqy9hJ+DNtQ+sMyed2KIbNC2+y
boR8g2nryqukCzv2WEOUKgw0EbzbWvvB1lWo860fgjmNuSelwUlwAZgSViZ+
ah2VsHXP+bn5bOt0ZwTCo7nU2sf+l/2/B0OX1oHq18vak0NWeAOS+9YtF+dV
fZqA8NNTPicVDCyoVTF+8KpuQp3enTffOl0bN7eeadEbaQaZsVtlk1t/DVoo
6JFWvDuTjFCyF29IGZFQ/bfl3nRSNYQCdVurSJbumK/Y1np4lUVNDoZlywdz
Zr/yFiDJn33MxmF2n6EZSWxWqMcENifMpIUU7H3JXXvKUrajIhuXNcorawEu
AF6ydEJlhZK5KUyMbaAZTazUjcFONCIv21xB1jUyPqnjLA7BCfAxXPA+ekNm
lbulA3TFsABzgXCbnOLHxx7cbeoR5Vohwtbw376rHrsHsbwH0q/AX31RahSn
5GdsEsfVuJsXHRVOcjulYirkH41+KBhWiCA/rkl2wAxL77DqES5oZQfGphm1
FFczlMx6RTPHJJYJRVGFegAuHPoBQDj3ETKgGGV8OCH4HYpuxfd+CLvl/e3y
/k7xvVLWfUOfbf7H9n2Sl8LBtrVU3n+wvjH5xza1uqcQVSCKTev3kxHYvq+c
7EIrwnTC/bB4K5wYi9NdXeFOIKc40FXcHxhO4DcLxgrVJuydyIWIhxDkIcn0
5JGc1VDeHOMoABJvbG9JiGObX4KBHSxSjGBaHqwWuG6kqoI87cbAZk8JAoLg
hurydHK+mkMamE27LkwHI3HyXVHxCZTzhqdb//f9/e2tIcvizAMaClGkX+9v
DemCKSopPUVersPA2+a5QGCCbw38HLLxfpgTkwXv6ecxXBkqKkNhpLfuK7S8
PV1GTkN1DOKrT90uHabtpt4+pgQJTaAS7XBImYoi/sti+Lf52evV4nTubps3
NQI0VE1Q0bwkY+ESHmr4IfF4Vk0zH00Qi3mUYcMaO8IiQTz96CgW3ushNn7s
hZSpJgxFwXg+ZFk2rLBXmJhCsihw6B/aKhc2RGti3Qe4DyEGdMRi9WsskyJd
X0JuI3hdUL6XmbY7eNFo+avhPL6AaI138gS3jm243EsWOfEZB9e62wLhzey+
S7dOJ7tXGFHj5/1XTw/+fiJiH0iT0OzgcH+fDZM30MLaMP0ogibKu+WD8h4Z
AdKHQ5l2qE1sP1zbdTKKFz89fxJBg+xs2kJpNJpf1cSPpo6gNBEbK9tbxCb2
zs9xh+pj2gSaUNttoNhwm6i6F8hftPlahFNsAgUw04KZCNlYxVQbCY+9WHZ0
oxIB1zbn8WesWHojZb5AE68wZEae/8jyLyQq3NgGnRjgbNeHoPoPs5TBZZJx
xY36Jib1Qmdz+4lIEz/CXX9e47n1KWItnZsmQGwP+LpI7jEIu4lLQTEdeCXL
HVGbzETz/DFgkjCDnw73fnBH3h25J5jligontLKtk6RHHr949erk6fPn+6/0
kZ3cI8/29w74CffIg+gR5nO+p4/l1xlS4D2RKjGCAmwJgWUE+BKL8E/Swp2i
gUDQpaLJiMf03QXYnNClCU8X1jqNOkGGhXQON4uKKc5Xk3E9RY/+XCJg5BHB
vDHxGjhQVonhZr6qJosmYxUZdrZ75ZvukAODyMv2Bj0sI5gOxoqRLYK1CTZM
kG/AhAIY+Ns07A9oa3JJohDAPSyu4eT5x4OvB+UeAp+awLolpiZoUAwFrxQY
WEdhWZs4RWzQptTmy4xtOSeR51qNptclBrCuDcuLAJmrZSFDI6OxDS7DaM7A
4s0xwrh0CLP/ZhjFYJHNqucdobbZQoNLJfXFhyjxYvnlhn06PFV4DhJeOWC1
IWUKTtMe4Nft3K3cdf8Gv/jefVHdvQs5k6dlv3yDP41Id/LZK2GQEpkltEfX
m/ufPZaXvx+KK0mmYdNdSEKEPKGrZPXCioQUk0m4E4WVViE+dUV1CzAOElTj
c62H2lNv1ziI+7BaQtUUEq6Y+BrwTfIxeP+C8V3i30H+fhI6go8EAR/kK/BB
H73Chn0QiwicrXjl8Q/+pj+2PotZB7vwWADG7mjyqyMsgK3JjMFA2AIJcYRb
XdssjNO36m2lGzXasKWT9yeZJKvF+QpotcWprVNJAQ6kUPoNFMrpZGlNpaS5
6sEJvhXLPzAQft9HxvTItDFFA6tHg+5pqBzy2F839zt+7gts1oOPAM/HfHIK
+AHUmcV8tqRc7lDYpie6vO0gCOQR5p2Ojya7UCdoehwntd/vuSv0bun23JQx
gmEYJ/ByT5ug/nb4C2q+gxOnB7vxo9v6KD7r1scslfG8+SYCb9yA4lPdLyCg
wBKcLKvzTixKYDCAyXrGnUh/dmUXPBbzgWeWfOtleaVlwdQAOnm3wOK45e+0
7e8wSjrwSMa8ld+vZKNtVSuw30EhHsempDGROGImxmVovlrDzQLdW9JM6IGJ
9C5RSnpn1QF4P03aXZ7s9CC2TFP3QTgB9MqR33bGi9nZdnvgTVhB6w3QCI4m
pM9Blncn+2q+WJX/+Jc0eAffOPajRIP+o3Ro8L0b2bHb+f9Xe1k7InijBz0w
/X7g1fR7A5xdRKCOjXLBwJamK9tc4wK122zRLU/j6Dsch8+tX77P7nL4eO4Q
bnwdeZZ3fd6+w+jx3IYBP+i40bg4bkJLypvrHi1Rncrple70OrFyuQBAPwgY
B0H3SKS+HjdhJb/jQdczqPnZWVMraAYqQgDV4Nb0xB3L0LmP90P9/srNHpAC
5rjyadr/+o2pbPHofg4zYB3H8ppNzLFwvd3d1rnfdXs0Wln4AG/uZE6AASbo
/ZZz3f4N5rr9a+eabgMA1fhCSx+evC+x8qCw3n7hv+AKr5vS5y3w2im1rm9m
IfmYH6y/i3sJA9nrld93h/w26a7VQjJfxTmGwa+BU8pwHuFRyH8o0tfez3w9
O1Vr4HdbPoz74deEeXZ03CuPGLSHcgFgLiH0ju5sg48jWIKI6eKDi457ZiHD
0CVs2aCkAA5JEjPrljaJSgoOlrkT4QOQO/7ycW/rr0q0XnjoHgV/Hu0+OA4f
OHqw6xtBjZGGvwPVKr3qCB9UH8u7BLoDCqT7w00LVEi7Z7fdY8H9zTDTO93g
sft8EzSr084RbBUe2HaA5tdOmd30sBBl7x8j0pcH3+H1p+bvd9ve2177nhlW
inuErYiAk4hKUZM733yjY1kLGhQ+vB09fCznct8E3lzQAQtRGrJhqyL5YhR+
EDCalUVYc4JeGIgL4AtdL51/TK46FK5vlBJP1p4nDh8GjqOLJDPbdNfjwP9s
ETG8w9FK1Vz700Jl+MKfJNtEEDAZ+xIHHFQzY8FwIx3Vk7eSruYJrIyL1Al0
9nKZuNNra/SCmuA+eVsRPOLue9ATyG2ULjAERYZIwXYW4Hr8RSEqUYokwhax
ptZUDllKyvnEVeNwTC1xyRpRajILCBYMyVgkU1tRcaNlDQAJzKgx0NSkWeUQ
OygjXwK6OeMDyrRNZkXGzS+ZSBg24eg18r7MsU/JgmlNmhOES+y4u4bwhrvl
T9gL1U2LPPhmmAu2L1nzskH/blaXAmwQSOFdwhYpzyB7PKGMR3TtsTgfWMO4
xOBZNZm6Y1V5QO1QOcCKn7N6vmqmkH34S41dUcR4IYk5rv8VFpvF+dvMdCKZ
NI0EpYhTCoFAaFmlSq+gJG6wuM1rRqLnhUISEnyKKa2KKe71GYR5OppNr1Oz
HG1ERF9uCwDmR0yegtXDku9s3kPwJTKKXXEliLcv0uOS5qLMidSm528wz9X0
QW/jM4bBgLXzg8a5FbJ+dSnRLUSiRk/PCyi4Ojl6AvMUbuTPgCfoB0wyEss9
66UcvYqsPqq2fuYnYuZfUrYX8118k+Q420uItkfrF6as9Cj5Ipo7CrycdGLU
7GUknOb1bWStgctCNFx7gwaXJZ1SY1e8WVxBerdZ2/SB0OAmJ+DXqnVEyIzs
76UbJ+g7EaTvaPGuWtA18rcXBxzizWZZwTjG6Q6SmSWiH1ovaafAc6EA9dvS
Y60WdAM5OpVstVP5B2++rsjV2dl2b7MdOnvS9vembZACg/EaE0pGTSQJdkfI
vAv/6mgyS/c4nlm4Au1DsL0aRpE97zceEvYHCWv5KsCAuazcU2NBkkUJY8uY
miIjE3ENugTgALfuH39R3MJ6bfzTWfO1o6lT6U/rE7wXhP3uBJYPM7hkPbNr
Gc0m2VVBclDQFZGXVm6zvo5aN/axbXguV4HHUwYW2Zk4gbULUoxmn3fM6I3W
7KVGGdcBTQYX+GhyDOi8nsurlNv29LZ52s6adT7T3V0D3xs8uZ15EnXa/OM7
+LgZmW1Y6TOocHd2fLN8RJgsl4iEexQfsx5dr8KGwAQ+D25fUZX8SQ152B01
ANOg74SsgTZmyC2UrD8DoqsfX95aGT1uSePNQ0Zmg00bO1RPYomMn8UbZbdV
2JESLm5wGFWzW6YhNRnXqm3HC0rlR/037U53kt6esMU8x+vi3sWftqyvVOYw
xENbhp9VIRcAPA+xpOlKBZjvdjROkgbs6Jtw3uv3VzXieOHh6JXnc/Ty2mII
9ZQ9naZ5dHg+uBlEXn28NCiFjpd39vIHVSkSHOzvb3rYnms6DO3P7phng+Nl
nrE2rYg7hpI2d+YuS0Mj4CYBRwg/fbtc1gS37jE7avjcUwreLcOuo8e+N+wA
Pv53Zg6pqLDBeQiZQgprnX4Dn9M7bqRQ0j7LbeST4Try8UuU/p6xhdmli3Gz
/b9YoAlOWzjOW541oqvZW05UeWGV+DWWwPaCDFqSijmK1GG46Q1W/ZGv3LHc
FrgTI507aYRbbVOYEyYMn0004Kgr68uDjUQZ/QljDmJXoiaQBe1sFmbhkQ6U
fNQIsyKRvU5SnXdDzdXvs5xncs3FQOMAPte7xePbx4HoxhQS3vwo4M32gMd3
cNfv+qiB7WC3y9S4CtIAbHNNZztC/gf8Mrb0YAGk8WqEfprL1Uyh1dxMCPBk
6rTpIRybYdQGxVKCqXU1AvMQZOxy/2FMV+a0QXu3OlaZhtEwVo/v5FSc29xx
3vgs5Qfd/tsz5mVfkNKbMgOzs+QEwSlGkE+FnvNG5AmkN1qrdeGt1pqRjZXy
SI+DwoankOG90iqO+oRt97R2PdYDUwaPqXPlWmDkgucvMLcfoDVs1UnOTJfR
ug0AILA4thAREU2wpPyXATZ5UG8vb8ktjBU3sN2iNbKh4ilBO9gRkXQCiYoV
2j054b1AiEkK86qmzVwsvk0ZwWzGwDrYXrM6o584fBEuh8l81dAjdxpjp4qt
lGo6buG4mzBX6e5EHxYGG71CfBbiDmlLS62zxzeSu1xHbuJ+tyV5GZGcjtuv
IbulRYb0dsbrjZ1ilxA7fTtZWv0J1ELOq6AKsAnN244V81jWwK+PJmDzOS7/
9Mh8dZwVOw4cRb3+INJ7tEm65R8zqBVQirRgIrk744Qphf+25Mo0eNRnOTZ4
+ASMtXCDLjthIxq45yuWiCMdNwvkC+oM0AT2qPRDSgZu5hy0GSxYtGewvZa9
QsVqMbl0MvOQRd4m4ifjpndeL0+gXmKzdNeCOOT8aEN3tHmTcDBSisVX62M2
lprXKp4NJrq3zyNLpmTBgRkFc/ADhgSDtqBlJESEoxI9GPKaP9dTgPT1aOhz
79YxB578atDzEGLo4U1G7AkPMs8BnzzaVVulqQFurtbwnoUKEoB2DIWVr9yl
wVmyDIIdhUnGfBtVPnAtUfWWdjaNJAmtBjd7Wm4hdTIBrFwWspJCx7u6Gmu9
mVhL2uSeMY+yL0rlyfiZufdXyTMZQlRZo4m2z+bD7EPaQUCFxC5FgnjlnhdC
XNaL85QGm01fR5ZXYH7DVXYvZsnQvuxd5WE6agxk9lOwMobRWtxfvbWrso7i
7ikj+f6kKcEG2wgjHjYrGII55cGp1CeKtoPJDf4aeap9mY0mvHGVJKIuVZvC
vadDMERtAqIevfcllKgKonvQsDTOECwPnWAOiOZxXAuFq8Qp9IIC2wRvEUg8
eS1Z+28AIvwCBJOxxgEXMye1zRdvAMJpChji9WiF7k1Nxx/IsBLkB+bqHjxj
6tpewQQck3/97DBEvy0/fGAc+PIBPPC7VwePv/3664eY6v0MtEae5hALooeV
is1oYtRa0jgPJvxaUSFaCkxbGkxCZQf7zx+/eCJZ0z339hTT9gGDWd4ucm+D
eyt+WVKd1r/PaJrFvsEqIpCImaIPA3ml4CSIDpPlclr3wa9VEaQPK+EdT9cC
6arYOyirpqAqvoASHKrltOkHyza/qkDQZRL7DGF3Po6/o935bPKmpsCTOpoA
xrXdavxFJ94XX378kM98dDCV4X8Fp4tCMDARtOZkSgsGZCNWBUg4k9cfxM/5
uDFQgbfYZABb3J2pMdT82iujL1FTh+oUpjAXl7ZSZ3rNuMWInItWueF3xc6A
YxNm/1913/7dNnKk+zv+Cqzm3IR0SMXy5HU1cc56/Bpnx2Nf2dnZvb5eERIh
CTFJcAlSMuOZ//1WfVXVXQ2AlJzJJrs+OScjAuhndb266qv1qp5FBBq85HUz
FJCdfAV4ii8PFSlkywWw4vtJCOMkFlkDeg0QvcZ0DjGJgOuXhh3Gj6Ci8qta
KiBUtQeMC8PFcVySRQzEMh+8fqtVwbGBWrogGIc6yQyTlNxWLhKI8mrc2AyY
JFY2SWLdjPKSTU2KE2S3k5ImGn0SDUXoSvo+1TGd8pje6W8kmonE3LsIyE4O
vsE13Pta3+wcM9sdvaZ/Vt1LGgioI/cGX4+Phj2tMLGHRmZC+TvaoK9/7AlJ
0mPyDQoHxLmRfBs8uPc1Kd6/HXK15d8F8OkUqVJ3x5PmYYahhdb86k0k9E62
K7iqIvij2RAp/GO7oQ3CaVme3h9yKdU4bARBViPA8iTX0H4Qaop3WyVrnKf6
Pv/hIVr4/e/zQZX/r/x3w84QKkRQyzV/tyFVmF6sQ5gp/ByXq5qUHsZmQ7ge
GkFGowALAdfx2zdfswH1kv4PLHMUsH4MySprAUOlhi+YLVYWKmReuEjFkZY4
i4CwwDPCUTzMn5R6eMmYYxXCqi+TusDoLUvNpzzmoFauNoZwRYWaQhNSdMi5
5nlwaZ8FVKn4TPHukcYb1wSlcgLOFfQN+nrH8iDfcl0LTFOB7HIZNx3KhqWI
jCfTPkMlqThu8GVoHeb4NawmJibWPyXfSrYLqlNYauFRbLrzciPglzi8lIhC
uOUqJeUWAb17n7X8RklhX/+2hRIwj3f3/n0sysj4D38w+h3mP8uP5HphmM3K
izUrgTaIvibGR/K52T1aPZiYATXH5ng2zGhpkifcKV/hwGrptjnk5YxZC+ko
6LP7xzuuvViMzOBmpDedG/4LAaAzsd4Jd99VnuZzJAAS9D6U237OnkqAmJdj
LyepzTuFgAvUelahdPG9nBh+vpvjh4ArYveoj+x4e4wi9RqQIZGExTJJbWDQ
yS0a6WhLpPxrmbUVatzUFxFT4ZgPRtAbMrxgJbBQoEyuTqS1qPek+BRfWSNa
9V1ayfa0AuB/38ahFqrnnyyCGac1zkCLbvWlJjkgJ82m7E0WGLmaeplX200N
Coow6UHPEoVKVk5qwYTv7kSAXTpJ4o9AKV/6jU/wak6431eLEl8qIewaWRz+
Zw8M1JiOa3ancfGHrWF5IvgvWLG9I3p7U/etVGdIf8ulum1AbonSI6xGuTfN
MFivXidnWp0ASfWq9IRn4WC7yQpF5/9lBL2HhnWKf38q3kO/rTG57UmK9zVl
dLoAQj5cxoYNarRYdDt2Ac6D1tzUshJKHMt0Oxurqnk5X663AWTZMl3OSs4I
Kd02h5KRKB2n4WKMOrmZW8XP1bo639DsDTWhJ2MlC1fZX/mL/eRqGTWyo0Ef
NH4/0lEWa3CKX6k+L6cb+AJCgSyoUod6Eh4Fp6Kz6MuWRGsVO/YEf3NVGjtX
KrYCQ6CfTGVIrHwTVdq+BLGv62APNQbMGLJazrbZbsES3F9oS2qoTyxc4vaO
7Sj8dEYZvJZyJv14/FEwbLe+8/hTz58bwuwOQ2hzx94wjH0JgM4Q/UzVcEM2
29FvTvVy7qvw25cPThGYFC79Eu1QOwsP34WrQXEl/Nj2Xuvsgn6jxkfQanPc
xegV2ijfo+UoGngWxpVP/DD140hr4XrV1SoRp9KkPYtJt3BJ+Do6BIOJa5jE
9UVmlTX8MkwOk7IcjMgr/oVuE6PITNgsyIqGzWJxK5J1OF7X429TI3Ft6Lwe
IDoCyWifzE8Y9pqmvCiELwqmlGiayc3zHkdGYGItT4abLLtYXCqGs6HupaED
WXvR1fMA43UwzPbdavOz86vNAnAuFdH9mszH5hD1bstpuNX+nQtP4KZPidNT
L/fDjwjvp4U+jXjW9Fcr1h8dtSLIQmvOp/LbfJz7tlxkcmumwejVVtT4C66K
cOH7WasvhjeMeGRqnHKOCabbNo39/pDhmyFuwb/yBzNbeYF4ToLdF8z539FU
ky/StW4NgdboiFcoNJT1vPQfD/MHv/51Bnjx5nRJ7YaIhX56ym4hgvaiK2yo
a3oYwjbRDLwDP2uPKyzFHaz4SKgW7Rrm4PJJEreIzatFqLLeD3PxecRntIIC
ZEDPmN7Mkede4AWT+cSW4PWIH8NvAueED83ickhGmHQI3PgjxcItr+draP7A
bgGY493KgdVSafpZeyalW1VD8QzYMPQd9xZdIUXA1ogs9fZl9P9jLR51Xogp
YDVT5GaQv9D+GX5UC9zNiy3fvrXrU0sBTZFVlhkMuHDUfAnqJRxm2gQiX84t
6Zx48HW5lfIymc0o5NeHmLAwNqnuaQp3tZLCeSvEVmIZ7d4y41QU1Y5vAIQO
HMK9sa1aypcFahvpPL0j2glx3qqlQJOtUCdUa4yGYqa06gZfimKGhpgdoMFd
onoPSrginSco4buKG8dqoNAxMCxtECo330dJLZxVdR2yvr0FMGLN6aakdUfh
BIa6L9db9rRCo895mzmfXV0yGBZCBoQclfJw0cvBYTQjJar6DLnpVZPFpaEG
JK/9c4oyCvAp7WIWb4wEk5U/uG7IoNKKP1YOXS75purs7qkAdBsMeQdZ9zbQ
8Q5IuOCDp3Oc7JtkBxf7NkjsULzHXvohf7TYaq2KaylIdVm2a9q4mo13+yDi
lXfhxtvD61SesT9/86tYZKbh2XY+0GIy9icJx94vXBWU9AjsLoeSHLZQkbO3
KMorIrLrqrzJskccxndVXV5ZOlhQxufFks9JUjfo51qskNGNGGlY68keIdBu
lOEPKVtHlquWnFgAdYLZv9Qr4Oe/OJpocO7Io/2W00viALWVsMhg2zOLRSld
tMfqiZYZpaM3K85Kzr2d3NcABzSzwuUMGovvZJMjKae9sDBeK9EbcZuadpkM
KeHj6ozacOVa5Yyji9XrvCzopcDyV3UNwTD5OMG9SFFZrY0psafpptDbR0ZB
kLikjEN5pXKqvos1g4zgeA2zGDRRLmjx8okbRNYdhNZOpbaA5egq6drW5WHr
JhYRPRO+mEkH/ltebs+Hfd0MGs9NflZXM0bSuEF4JTErosAxc2FjzIa9oiHV
3IXgjLBXiqfNl3WLiK+R3/CdnwP3+Mg1dqo1kEHU9rW2+fssiIbJq4FWnCea
bMhAY0wSSf8PVM3uCr4U+zMXJlFcr4AJk0XIhUoEG+MLcwNzwxHgUuKquwAw
+AUthxbVLd0DCH0a2dhwOx2aQ1yQppyJi0s3NlbNVYlSsKzLhMFyPRHZiLOi
4QjvM64IE7xZcsdwQftBxOIG0vL0cRjHpJl4OzcwQ7smAQgc4q2aiR+IaDJI
WdCYOSv3R01n+KwBZugLC8PxF/LcQHhHCi0LxT6450ZQIfxdblpY9QLabnHJ
Z0ogdm9qBYWdkK3KcVLN6Qojl8B5fRfFclj48/rhfSapm1HOnNCoR9rBSydj
t/UiMhiK/6JvJbO4khoagsPndi9WqKxWupxsr9MTIQwEwgGpPZwWfc6t4Hpc
a7EA8iY9dLIJrm6QVI7PJlBMV+sBEX+IeJbUGuW4tvhWGxFcXxbB4IszMhJW
9XLFao2pVII7YDWDUzF1hQjrsfXHQm0UII4Xl8TVF+WNrJVJKdZyI4hd8Ksy
YBeou17y0rHdxuylVdOe+UFrR6bVxUUJyaH7KSKkEdygWVUmXDuyyJGGFyq3
S44ImGxgi1rULZSlnPJln5yLph4rJEQ30Kqt3ydRQJLt1P5G0QYXbnOlEJJy
Hz5DsSIiH/XMM6Nc2tTPrT4nIsI8oZE0GhmSRcEDDyEyB6NMSAN2DaDcvUva
QFQgSqtmx8Kyz5pY7GH+Sm44+fGoGydGE9NKahOurzQvCxTsqRc0aV7gMLFA
8dm6u2T8PbcWV4b6vbjIY8d6Q8qZ5jyy1qJhGD3taviGL3yuh93RLyll28AR
UGaLqxYgCNTqlyLGlj8bMDUvm3IzrQW/ZxhKB/auYhYQxYn2YEpBiBuWWbxF
ATUSNQi18RIeuALKmFEWCLJDh8YLQHhSeaHZoAAy6kKXi9xV4uKp+imE6xpZ
mUk1WYuA33nk1lzYIOy8k7danN10jegxE4Yv3CUUehLfhIHniwbslFfJuCAu
SDJYCqbKBU1OVoshGCNF4+2VFY9a+pJe7SKaaXnvOUKMtHBUsflYzSpSe7PA
A/MJUQh7WrSitGfMSWGs21hpN+A8gX5uBZvzCu/LnIlInr1Qoz1I0T4iHaiO
MWu4JzW7H3jMlRVwCTto93Ggz++JPK30D15tlRLA3CLwPYq77nboObx/fKh6
SFpGIK5G2m6ruPKeth2QeV8HP6lOQcDqT9v8W5ZUwBdM4x5gApj+xx0b34UK
pTv7bs+rx/quon5CB3iIkq/n9ZJvB4SQVlxu4R0SxUZIDxMvq8dNS32vffi3
LehbcaFi8xW1Njz6UDLgAus70UPK/2ZcQ4ed3GO8ksU4tuY+sa37AYJdz7Za
0IbfnGC4xU/J4lof7fv0aMen/PD0/Aa4tCsawjseH0P3Hsl/OWBaWkF5swWp
cZ9BQf6D+pf/H7DVw1MetV870tfw/6wbhBeGcRm+aNfCDT7iJtFYWJcO4dn6
JdwIY7nmZvVBYhvNddpcWdFHMu9mxbkKG/e9uRrH6wr6GRtN6qiXEt383y0s
APc5sbIPHItwXRU5tQC1rWJfwBWZguXMZS7yNQItJy1YelX08X7cCKaO9yPb
oBY0r3xML6/1RVpR3SD5O94ndQAD0Il1cEuznREftUd8ZCM+un3ER2j66PNH
zJ1YB7c06w6FHZmbeKhMQurR+Hh/14GyM3NztPPbox5ARV2qBNyuH5X5rDf1
rYOCvQ9aeU8TAkWXjIhEUeTosbB40mKHqbdTIPODaGtzR1J3dc7XaNEHY2Iq
+dgt0I2wEcvNM6TrM+wUlvx2blA1CTNY2N1ROOSuieS4yz2E3Ci4Yy5ovMkT
18J8M1tXoQLzLRzB8wHXxt04Qvt8dWOjB7x8w9Ydsy3ru4rPwlj/My65l3J2
PzfQgzqyczjKpWmftdctEuJSIVnLVZzDW7XcMrz330PDTVFUu/mUHUzcFNm2
V7F0wr8LvhsTyhOQC4lU2FMu8+7KcEzUbIH7dwqws5IdNV9F+tKkfaftyIXK
cN+ddhEhwakJjnKQqleXofqTccNu8y1lqtu43vjuaHQxYPSFmBwcAu/tl31N
h0AIKxwtgBd2F78D3nEfckKEpOD7bhmM3tjfHVNOOwh4O45/8OFKcET9RaTF
Pwr/RXKemMcXngMlIVEJ9LDBEKAX/pLat2pRiYKk9Sn4tnVVcF6MubRggbvS
rXB1WMSea0KjnSzOSTw87m6iFS/JydLQKFwTgwn/MNGMSe/soUfMyybDQ3ey
zRxINFkOIOI0EsWXDM+2Mbc/ifyxJPaWUdAXlMH/xDBg5V+m+y75/r3bWJlS
v5TbLhX6x/vELBOh1UIPlove7bPvEuhIuMbW4iKtr9tJ6k3cai3WFeIN0H8L
heOLpNC6uHMiBLvQXB1uQa7K4nrb+v6qWq/hCi/slkyqjV5VKNa+WCNNspwK
Jm7rY6Fhzq9oUMtS6QkpSrJcN6b6dz+O0BxSHFTp0xpJll3KPLUacEi8luP9
68Oj94dDydZmTaVgm9MVEG0Pgc+O261itiqL6VZ2Tc+Z4caEr1ptnJRjWV9e
O7nmKWa127jZNjaFHht/tqWRG1qx8mIzO2wRZIMbj3LGKoxgGleN+OvaVFjz
dx85ioBOrkXRyHC0BMBkoDjrdAqHbZw0lMIZOtdzIDsAK8HFx5Jb0FSHk3RN
XMujfBvN4fBBR2fqQmfzPzTQ+dUrAK3z3NOEf959nFi/sduP3R97ChElir1h
gj70sWf8r4PA2zUVtsN95kWnAVbUSdHub6gLoBE1nzurJHGeofMESrdnJ1PN
TRAsaVO7hQn4CW/sMRi/06qCEnfK3uvjPNXq9itwtI+tX+6kpKUVyqHrtfAh
A4qZ8sxwIeAFphPmOOpODlv0PRqBEG0LCJX1sc0mDdrPJzQ58aRnOtWQ8iws
M61NpZcI7tbCXVRGfKPgoxMjsLX6BvIanU3tFxSMS23IfiR2/76hyw44smqH
hyxQTW+JhDv6o0J6cPRK/RSP1F/njTLbU5vY74kyxFecinigxAMEnw7cJx1/
TiMeF3njqO+NNVyBD4ODx0H3ruH+i4+O1EoFprtqZut3RGxWzRUG36lKhH5X
TIP3u64ctKkKYNqQjWi7g4aSdw2C+a7OiFD3OnVG7HZE+B3etcGhibaLYf8G
h2V19dq6LoVt25+wZUfCLx7miSPBXAJhWUex+VEbNGk7dI6CR2ba58+Cad8K
HO0a7V2TXQ7tDtbfx557JcFncGh3UWS3RowvojzaFVYwcZ8UWGjJ/lTXkDjh
02mDasP36X8cr76rUqqC8SZ3KDEBwmoiiFltQS5D54G/67vvlcz+pJloRGcN
V7NuwS1o8p63vCLftdqnIeMERa9Yemws6vgSpcPKiwv+ghZpmx89+K0hOejn
Fo5KAnKzVrpvWmk6j56+UcVQYqtZbB398kuhfuYW2C/wMeZIP+NqnLn+dBR+
kkmHl0iT+vjsqf521PnNToHQxUBgjnP7g3jFexY0oq8Yn/o7kqwqFS114m9L
qke3k6pnvTtITrwqHi5uJ1LczY66iakvO3VcOi7VYk03Bpvnl6IXQLB3h/bu
lP2jxdr5rLNz/1ZfuGvo1tXBuItm2rkMVcOHOk3kX3z97WZ1Vr+5Kj6U/W8L
p2b7VULAHych4MSr7TQSV+bUh4bDi6+nBQcLarwaxys2iJlkdHlr6LIuZorw
9HpVXRfn22NEnq7XnNa20nA64SNyuiOMnhZg3JxpYSypxxfUK//IV3kjnsUp
syScJYXjrN6Iq8sj2/FHJFfKBjCc1vJZueVs9xuEOEqY31QEboh/bXtKyFSW
onFNs5mLvh2QnMIskwnyEjFiimLPKfyTZCiJ9A4AztSYDNLP3X5yc+7LKdH4
U2qXMelQmYW1PSSXkORv5lXTqJM+ZGtLNE3j9QjeOcn/Ls5Ihq/37l/fbuk4
kIEtq+P32LmFisVWdqzWOLBi0Vrx6Dzp30rrkzT62aZRkPHkVWxjU899WzaX
sU6Do9W0odbm9uxsSbTfTFf1EjgbOj3b2jMENZZSINCE5c7FNwjpSJbYUeBB
PmMWPEuC8ZFnihMForj2e2S+llV9tmnWXMBtCGI+44CnzUKR8568Pnnz4Msf
f2SgNj7U5kQ+50jO89V2uQ4oz9TTXPIc4Fterup1fc6ToQXJ2MtTWgoiHbfr
cs/IwBBsXVE4MSY98dXausnqm8WIVuGGs1Y0PHUZL98QpMfiHnH1DeI1i/wC
0Z/KdDiytMTSjaQmqDgmiQ3dExbHGse0Ykfj2SbEeLMJPZ7BQxrR6gG55MAA
hGaSDH+ONOGWnzacz1Q1oGGMJZ6jY9ag7zFbvaimyiOTms3x7BdzNuXd4ZYI
QaMOM8c9x7MUuHCsJFW5v8v44dhVjGYEsxb3afPbhOFgwkk1TJIkdIJmdPCQ
wxe2IKZoWckzzR9TmgNqP7X3QgMC2dG4uK5W9WKOArKFvKfFWYXIOLdkLJLS
KE073GYWujcVUjxuMRyVDoj+7OPnstoqPDIRHi7BIuEmBWwu8JQbCws/QxJg
uVq5Kt5ZV2h0KtRiXETXEkS6q8eFwmPsaDBOU5nWKmFaEQ+CDdiGNp7OLtEp
/YSkhwtxMUhOCfFkKPrwLKnC7wesCj99KBmIJcJmqxUxnVnwUPHW0d6+shh1
HG1RIKY1jr/uq6gIL4nH6EU+EcubLfEMZbUN86t6c/8Bsyvzq8sjCfktpuza
5ttjolRJWShTgeSAsRrjwutwx6TFfqu1VKGlsw/sNG6tWoBfoX6rW53QFMq4
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

-->

</rfc>
