<?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-rfc2629 version 1.6.6 (Ruby 3.0.4) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-irtf-cfrg-vdaf-00" category="info" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.12.4 -->
  <front>
    <title abbrev="VDAF">Verifiable Distributed Aggregation Functions</title>
    <seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-vdaf-00"/>
    <author initials="R. L." surname="Barnes" fullname="Richard L. Barnes">
      <organization>Cisco</organization>
      <address>
        <email>rlb@ipv.sx</email>
      </address>
    </author>
    <author initials="C." surname="Patton" fullname="Christopher Patton">
      <organization>Cloudflare, Inc.</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="2022" month="April" day="27"/>
    <area>IRTF</area>
    <workgroup>CFRG</workgroup>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <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
input that would result in an incorrect aggregate result.</t>
    </abstract>
    <note removeInRFC="true">
      <name>Discussion Venues</name>
      <t>Discussion of this document takes place on the
    Crypto Forum Research Group mailing list (cfrg@ietf.org),
    which is archived at <eref target="https://mailarchive.ietf.org/arch/search/?email_list=cfrg"/>.</t>
      <t>Source for this draft and an issue tracker can be found at
    <eref target="https://github.com/cjpatton/vdaf"/>.</t>
    </note>
  </front>
  <middle>
    <section anchor="introduction">
      <name>Introduction</name>
      <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>Most prior approaches to this problem fall under the rubric 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 input before
submitting to the aggregation server. The aggregation server then adds up the
noisy inputs, and because it knows the distribution from whence the noise was
sampled, it can estimate the true sum with reasonable precision.</t>
      <t>Differentially private systems like RAPPOR are easy to deploy and provide a
useful guarantee. On its own, however, DP falls short of the strongest privacy
property one could hope for. Specifically, depending on the "amount" of noise a
client adds to its input, it may be possible for a curious aggregator to make a
reasonable guess of the input's true value. Indeed, the more noise the clients
add, the less reliable will be the server's estimate of the output. Thus systems
employing DP techniques alone must strike a delicate balance between privacy and
utility.</t>
      <t>The ideal goal for a privacy-preserving measurement system is that of secure
multi-party computation: No participant in the protocol should learn anything
about an individual input beyond what it can deduce from the aggregate. In this
document, we describe Verifiable Distributed Aggregation Functions (VDAFs) as a
general class of protocols that achieve this goal.</t>
      <t>VDAF schemes achieve their privacy goal by distributing the computation of the
aggregate among a number of non-colluding aggregation servers. As long as a
subset of the servers executes the protocol honestly, VDAFs guarantee that no
input is ever accessible to any party besides the client that submitted it. At
the same time, VDAFs are "verifiable" in the sense that malformed inputs that
would otherwise garble the output of the computation can be detected and removed
from the set of inputs.</t>
      <t>The cost of achieving these security properties is the need for multiple servers
to participate in the protocol, and the need to ensure they do not collude to
undermine the VDAF's privacy guarantees.  Recent implementation experience has
shown that practical challenges of coordinating multiple servers can be
overcome.  The Prio system <xref target="CGB17"/> (essentially a VDAF) has been deployed in
systems supporting hundreds of millions of users: The Mozilla Origin Telemetry
project <xref target="OriginTelemetry"/> and the Exposure Notification Private Analytics
collaboration among the Internet Security Research Group (ISRG), Google, Apple,
and others <xref target="ENPA"/>.</t>
      <t>The VDAF abstraction laid out in <xref target="vdaf"/> represents a class of multi-party
protocols for privacy-preserving measurement proposed in the literature. These
protocols vary in their operational and security considerations, sometimes in
subtle but consequential ways. This document therefore has two important goals:</t>
      <ol spacing="normal" type="1"><li>
          <t>Providing applications like <xref target="I-D.draft-gpew-priv-ppm"/> with a simple,
uniform interface for accessing privacy-preserving measurement schemes, and
documenting relevant operational and security bounds for that interface:  </t>
          <ol spacing="normal" type="1"><li>General patterns of communications among the various actors involved in
the system (clients, aggregation servers, and measurement collectors);</li>
            <li>Capabilities of a malicious coalition of servers attempting to divulge
information about client inputs; and</li>
            <li>Conditions that are necessary to ensure that malicious clients cannot
corrupt the computation.</li>
          </ol>
        </li>
        <li>Providing cryptographers with design criteria that allow new constructions
to be easily used by applications.</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 aforementioned Prio system <xref target="CGB17"/> allows for the privacy-preserving
computation of a variety aggregate statistics. The basic idea underlying Prio
is fairly simple:
          </t>
          <ol spacing="normal" type="1"><li>Each client shards its input into a sequence of additive shares and
distributes the shares among the aggregation servers.</li>
            <li>Next, each server adds up its shares locally, resulting in an additive
share of the aggregate.</li>
            <li>Finally, the aggregation servers combine their additive shares to obtain
the final aggregate.</li>
          </ol>
          <t>
The difficult part of this system is ensuring that the servers hold shares of
a valid input, e.g., the input is an integer in a specific range. Thus Prio
specifies a multi-party protocol for accomplishing this task.  </t>
          <t>
In <xref target="prio3"/> we describe 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>More recently, Boneh et al. <xref target="BBCGGI21"/> described a protocol called Poplar
for solving the <tt>t</tt>-heavy-hitters problem in a privacy-preserving manner. Here
each client holds a bit-string of length <tt>n</tt>, and the goal of the aggregation
servers is to compute the set of inputs that occur at least <tt>t</tt> times. The
core primitive used in their protocol is a generalization of a Distributed
Point Function (DPF) <xref target="GI14"/> that allows the servers to "query" their DPF
shares on any bit-string of length shorter than or equal to <tt>n</tt>. As a result
of this query, each of the servers has an additive share of a bit indicating
whether the string is a prefix of the client's input. The protocol also
specifies a multi-party computation for verifying that at most one string
among a set of candidates is a prefix of the client's input.  </t>
          <t>
In <xref target="poplar1"/> we describe a VDAF called Poplar1 that implements this
functionality.</t>
        </li>
      </ul>
      <t>The remainder of this document is organized as follows: <xref target="overview"/> gives a
brief overview of VDAFs; <xref target="vdaf"/> defines the syntax for VDAFs; <xref target="prelim"/>
defines various functionalities that are common to our constructions; <xref target="prio3"/>
describes the Prio3 construction; <xref target="poplar1"/> describes the Poplar1
construction; and <xref target="security"/> enumerates the security considerations for
VDAFs.</t>
    </section>
    <section anchor="conventions-and-definitions">
      <name>Conventions and Definitions</name>
      <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>
      <t>Algorithms in this document are written in Python 3. Type hints are used to
define input and output types. 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>Some common functionalities:</t>
      <ul spacing="normal">
        <li>
          <tt>zeros(len: Unsigned) -&gt; Bytes</tt> returns an array of zero bytes. The length of
<tt>output</tt> <bcp14>MUST</bcp14> be <tt>len</tt>.</li>
        <li>
          <tt>gen_rand(len: Unsigned) -&gt; Bytes</tt> returns an array of random bytes. The
length of <tt>output</tt> <bcp14>MUST</bcp14> be <tt>len</tt>.</li>
        <li>
          <tt>byte(int: Unsigned) -&gt; Bytes</tt> returns the representation of <tt>int</tt> as a byte
string. The value of <tt>int</tt> <bcp14>MUST</bcp14> be in <tt>[0,256)</tt>.</li>
        <li>
          <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.</li>
        <li>
          <tt>I2OSP</tt> and <tt>OS2IP</tt> from <xref target="RFC8017"/>, which are used, respectively, to
convert a non-negative integer to a byte string and convert a byte string to a
non-negative integer.</li>
        <li>
          <tt>next_power_of_2(n: Unsigned) -&gt; Unsigned</tt> returns the smallest integer
greater than or equal to <tt>n</tt> that is also a power of two.</li>
      </ul>
    </section>
    <section anchor="overview">
      <name>Overview</name>
      <figure anchor="overall-flow">
        <name>Overall data flow of a VDAF</name>
        <artwork><![CDATA[
                 +--------------+
           +---->| Aggregator 0 |----+
           |     +--------------+    |
           |             ^           |
           |             |           |
           |             V           |
           |     +--------------+    |
           | +-->| Aggregator 1 |--+ |
           | |   +--------------+  | |
+--------+-+ |           ^         | +->+-----------+
| Client |---+           |         +--->| Collector |--> Aggregate
+--------+-+                         +->+-----------+
           |            ...          |
           |                         |
           |             |           |
           |             V           |
           |    +----------------+   |
           +--->| Aggregator N-1 |---+
                +----------------+

      Input shares           Aggregate shares
]]></artwork>
      </figure>
      <t>In a VDAF-based private measurement system, we distinguish three types of
actors: Clients, Aggregators, and Collectors.  The overall flow of the
measurement process is as follows:</t>
      <ul spacing="normal">
        <li>Clients are configured with public parameters for a set of Aggregators.</li>
        <li>To submit an individual measurement, the Client shards the measurement into
"input shares" and sends one input share to each Aggregator.</li>
        <li>
          <t>The Aggregators verify the validity of the input shares, producing a set of
"output shares".
          </t>
          <ul spacing="normal">
            <li>Output shares are in one-to-one correspondence with the input shares.</li>
            <li>Just as each Aggregator receives one input share of each input, at the end
of the validation process, each aggregator holds one output share.</li>
            <li>In most VDAFs, Aggregators will need to exchange information among
themselves as part of the validation process.</li>
          </ul>
        </li>
        <li>Each Aggregator combines the output shares across inputs in the batch to
compute the "aggregate share" for that batch, i.e., its share of the desired
aggregate result.</li>
        <li>The Aggregators submit their aggregate shares to the Collector, who combines
them to obtain the aggregate result over the batch.</li>
      </ul>
      <t>Aggregators are a new class of actor relative to traditional measurement systems
where clients submit measurements to a single server.  They are critical for
both the privacy properties of the system and the correctness of the
measurements obtained.  The privacy properties of the system are assured by
non-collusion among Aggregators, and Aggregators are the entities that perform
validation of client inputs.  Thus clients trust Aggregators not to collude
(typically it is required that at least one Aggregator is honest), and
Collectors trust Aggregators to properly verify Client inputs.</t>
      <t>Within the bounds of the non-collusion requirements of a given VDAF 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
Aggregators to augment a basic client-server protocol.</t>
      <t>In this document, we describe the computations performed by the actors in this
system.  It is up to applications to arrange for the required information to be
delivered to the proper actors in the proper sequence.  In general, we assume
that all communications are confidential and mutually authenticated, with the
exception that Clients submitting measurements may be anonymous.</t>
    </section>
    <section anchor="vdaf">
      <name>Definition of VDAFs</name>
      <t>A concrete VDAF specifies the algorithms involved in evaluating an aggregation
function across a batch of inputs. This section specifies the interfaces of
these algorithms as they would be exposed to applications.</t>
      <t>The overall execution of a VDAF comprises the following steps:</t>
      <ul spacing="normal">
        <li>Setup - Generating shared parameters for the Aggregators</li>
        <li>Sharding - Computing input shares from an individual measurement</li>
        <li>Preparation - Conversion and verification of input shares to output shares
compatible with the aggregation function being computed</li>
        <li>Aggregation - Combining a sequence of output shares into an aggregate share</li>
        <li>Unsharding - Combining a sequence of aggregate shares into an aggregate result</li>
      </ul>
      <t>The setup algorithm is performed once for a given collection of Aggregators.
Sharding and preparation are done once per measurement input.  Aggregation and
unsharding are done over a batch of inputs (more precisely, over the output
shares recovered from those inputs).</t>
      <t>Note that the preparation step performs two functions: Verification and
conversion.  Conversion translates input shares into output shares that are
compatible with the aggregation function.  Verification ensures that aggregating
the recovered output shares will not lead to a garbled aggregate result.</t>
      <!--
For some VDAFs, like Prio3 ({{prio3}}) or Poplar1 ({{poplar1}}), the output shares
are recovered first, then validated. For other protocols, like Prio+ [AGJOP21],
there is no explicit verification step.
-->

<t>The remainder of this section defines the VDAF interface in terms of an abstract
base class <tt>Vdaf</tt>. This class defines the set of methods and attributes a
concrete VDAF must provide. The attributes are listed in <xref target="vdaf-param"/>; the
methods are defined in the subsections that follow.</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>ROUNDS</tt></td>
            <td align="left">Number of rounds of communication during the preparation phase (<xref target="sec-vdaf-prepare"/>)</td>
          </tr>
          <tr>
            <td align="left">
              <tt>SHARES</tt></td>
            <td align="left">Number of input shares into which each measurement is sharded (<xref target="sec-vdaf-shard"/>)</td>
          </tr>
          <tr>
            <td align="left">
              <tt>Measurement</tt></td>
            <td align="left">Type of each measurement</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PublicParam</tt></td>
            <td align="left">Type of public parameter used by the Client during the sharding phase (<xref target="sec-vdaf-shard"/>)</td>
          </tr>
          <tr>
            <td align="left">
              <tt>VerifyParam</tt></td>
            <td align="left">Type of verification parameter used by each Aggregator during the preparation phase (<xref target="sec-vdaf-prepare"/>)</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggParam</tt></td>
            <td align="left">Type of aggregation parameter</td>
          </tr>
          <tr>
            <td align="left">
              <tt>Prep</tt></td>
            <td align="left">State of each Aggregator during the preparation phase (<xref target="sec-vdaf-prepare"/>)</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>
      <section anchor="sec-vdaf-setup">
        <name>Setup</name>
        <t>Before execution of the VDAF can begin, it is necessary to distribute long-lived
parameters to the Client and Aggregators. The long-lived parameters are
generated by the following algorithm:</t>
        <ul spacing="normal">
          <li>
            <tt>Vdaf.setup() -&gt; (PublicParam, Vec[VerifyParam])</tt> is the randomized setup
algorithm used to generate the public parameter used by the Clients and the
verification parameters used by the Aggregators. The length of the latter <bcp14>MUST</bcp14>
be equal to <tt>SHARES</tt>. In general, an Aggregator's verification parameter is
considered secret and <bcp14>MUST NOT</bcp14> be revealed to the Clients, Collector or other
Aggregators. The parameters <bcp14>MAY</bcp14> be reused across multiple VDAF evaluations.
See <xref target="security"/> for a discussion of the security implications this has
depending on the threat model.</li>
        </ul>
      </section>
      <section anchor="sec-vdaf-shard">
        <name>Sharding</name>
        <t>In order to protect the privacy of its measurements, a VDAF Client splits its
measurements into "input shares".  The <tt>measurement_to_input_shares</tt> method is
used for this purpose.</t>
        <ul spacing="normal">
          <li>
            <tt>Vdaf.measurement_to_input_shares(public_param: PublicParam, input:
Measurement) -&gt; Vec[Bytes]</tt> is the randomized input-distribution algorithm run
by each Client. It consumes the public parameter and input measurement and
produces a sequence of input shares, one for each Aggregator. The length of
the output <bcp14>MUST</bcp14> be <tt>SHARES</tt>.</li>
        </ul>
        <figure anchor="shard-flow">
          <name>The Client divides its measurement input into input shares and distributes them to the Aggregators.</name>
          <artwork><![CDATA[
    Client
    ======

    measurement
      |
      V
    +----------------------------------------------+
    | measurement_to_input_shares                  |
    +----------------------------------------------+
      |              |              ...  |
      V              V                   V
     input_share_0  input_share_1       input_share_[SHARES-1]
      |              |              ...  |
      V              V                   V
    Aggregator 0   Aggregator 1        Aggregator SHARES-1
]]></artwork>
        </figure>
        <ul empty="true">
          <li>
            <t>CP The <tt>public_param</tt> is intended to allow for protocols that require the
Client to use a public key for sharding its measurement. When rotating the
<tt>verify_param</tt> for such a scheme, it would be necessary to also update the
<tt>public_param</tt> with which the clients are configured. For PPM it would be nice
if we could rotate the <tt>verify_param</tt> without also having to update the
clients. We should consider dropping this at some point. See
https://github.com/cjpatton/vdaf/issues/19.</t>
          </li>
        </ul>
      </section>
      <section anchor="sec-vdaf-prepare">
        <name>Preparation</name>
        <t>To recover and verify output shares, the Aggregators interact with one another
over <tt>ROUNDS</tt> rounds. Prior to each round, each Aggregator constructs an
outbound message. Next, the sequence of outbound messages is combined into a
single message, called a "preparation message". (Each of the outbound messages
are called "preparation-message shares".) Finally, the preparation message is
distributed to the Aggregators to begin the next round.</t>
        <t>An Aggregator begins the first round with its input share and it begins each
subsequent round with the previous preparation message. Its output in the last
round is its output share and its output in each of the preceding rounds is a
preparation-message share.</t>
        <t>This process involves a value called the "aggregation parameter" used to map the
input shares to output shares. The Aggregators need to agree on this parameter
before they can begin preparing inputs for aggregation.</t>
        <figure anchor="prep-flow">
          <name>VDAF preparation process on the input shares for a single measurement. At the end of the computation, each Aggregator holds an output share or an error.</name>
          <artwork><![CDATA[
    Aggregator 0   Aggregator 1        Aggregator SHARES-1
    ============   ============        ===================

    input_share_0  input_share_1       input_share_[SHARES-1]
      |              |              ...  |
      V              V                   V
    +-----------+  +-----------+       +-----------+
    | prep_init |  | prep_init |       | prep_init |
    +-----------+  +------------+      +-----------+
      |              |              ...  |             \
      V              V                   V             |
    +-----------+  +-----------+       +-----------+   |
    | prep_next |  | prep_next |       | prep_next |   |
    +-----------+  +-----------+       +-----------+   |
      |              |              ...  |             |
      V              V                   V             | x ROUNDS
    +----------------------------------------------+   |
    | prep_shares_to_prep                          |   |
    +----------------------------------------------+   |
                     |                                 |
      +--------------+-------------------+             |
      |              |              ...  |             |
      V              V                   V             /
     ...            ...                 ...
      |              |                   |
      V              V                   V
    +-----------+  +-----------+       +-----------+
    | prep_next |  | prep_next |       | prep_next |
    +-----------+  +-----------+       +-----------+
      |              |              ...  |
      V              V                   V
    out_share_0    out_share_1         out_share_[SHARES-1]
]]></artwork>
        </figure>
        <t>To facilitate the preparation process, a concrete VDAF implements the following
class methods:</t>
        <ul spacing="normal">
          <li>
            <tt>Vdaf.prep_init(verify_param: VerifyParam, agg_param: AggParam, nonce: Bytes,
input_share: Bytes) -&gt; Prep</tt> is the deterministic preparation-state
initialization algorithm run by each Aggregator to begin processing its input
share into an output share. Its inputs are its verification parameter
(<tt>verify_param</tt>), the aggregation parameter (<tt>agg_param</tt>), the nonce provided
by the environment (<tt>nonce</tt>, see <xref target="run-vdaf"/>), and one of the input shares
generated by the client (<tt>input_share</tt>). Its output is the Aggregator's
initial preparation state.</li>
          <li>
            <tt>Vdaf.prep_next(prep: Prep, inbound: Optional[Bytes]) -&gt; Union[Tuple[Prep,
Bytes], OutShare]</tt> is the deterministic preparation-state update algorithm run
by each Aggregator. It updates the Aggregator's preparation state (<tt>prep</tt>) and
returns either its next preparation state and its message share for the
current round or, if this is the last round, its output share. An exception is
raised if a valid output share could not be recovered. The input of this
algorithm is the inbound preparation message or, if this is the first round,
<tt>None</tt>.</li>
          <li>
            <tt>Vdaf.prep_shares_to_prep(agg_param: AggParam, prep_shares: Vec[Bytes]) -&gt;
Bytes</tt> is the deterministic preparation-message pre-processing algorithm. It
combines the preparation-message shares generated by the Aggregators in the
previous round into the preparation message consumed by each in the next
round.</li>
        </ul>
        <t>In effect, each Aggregator moves through a linear state machine with <tt>ROUNDS+1</tt>
states.  The Aggregator enters the first state on using the initialization
algorithm, and the update algorithm advances the Aggregator to the next state.
Thus, in addition to defining the number of rounds (<tt>ROUNDS</tt>), a VDAF instance
defines the state of the Aggregator after each round.</t>
        <ul empty="true">
          <li>
            <t>TODO Consider how to bake this "linear state machine" condition into the
syntax. Given that Python 3 is used as our pseudocode, it's easier to specify
the preparation state using a class.</t>
          </li>
        </ul>
        <t>The preparation-state update accomplishes two tasks: recovery of output shares
from the input shares and ensuring that the recovered output shares are valid.
The abstraction boundary is drawn so that an Aggregator only recovers an output
share if it is deemed valid (at least, based on the Aggregator's view of the
protocol). Another way to draw this boundary would be to have the Aggregators
recover output shares first, then verify that they are valid. However, this
would allow the possibility of misusing the API by, say, aggregating an invalid
output share. Moreover, in protocols like Prio+ <xref target="AGJOP21"/> based on oblivious
transfer, it is necessary for the Aggregators to interact in order to recover
aggregatable output shares at all.</t>
        <t>Note that it is possible for a VDAF to specify <tt>ROUNDS == 0</tt>, in which case each
Aggregator runs the preparation-state update algorithm once and immediately
recovers its output share without interacting with the other Aggregators.
However, most, if not all, constructions will require some amount of interaction
in order to ensure validity of the output shares (while also maintaining
privacy).</t>
        <ul empty="true">
          <li>
            <t>OPEN ISSUE Depending on what we do for issue#20, we may end up needing to
revise the above paragraph.</t>
          </li>
        </ul>
      </section>
      <section anchor="sec-vdaf-aggregate">
        <name>Aggregation</name>
        <t>Once an Aggregator holds output shares for a batch of measurements (where
batches are defined by the application), it combines them into a share of the
desired aggregate result.  This algorithm is performed locally at each
Aggregator, without communication with the other Aggregators.</t>
        <ul spacing="normal">
          <li>
            <tt>Vdaf.out_shares_to_agg_share(agg_param: AggParam, output_shares:
Vec[OutShare]) -&gt; agg_share: AggShare</tt> is the deterministic aggregation
algorithm. It is run by each Aggregator over the output shares it has computed
over a batch of measurement inputs.</li>
        </ul>
        <figure anchor="agg-flow">
          <name>Aggregation of output shares. `B` indicates the number of measurements in the batch.</name>
          <artwork><![CDATA[
    Aggregator 0    Aggregator 1        Aggregator SHARES-1
    ============    ============        ===================

    out_share_0_0   out_share_1_0       out_share_[SHARES-1]_0
    out_share_0_1   out_share_1_1       out_share_[SHARES-1]_1
    out_share_0_2   out_share_1_2       out_share_[SHARES-1]_2
         ...             ...                     ...
    out_share_0_B   out_share_1_B       out_share_[SHARES-1]_B
      |               |                   |
      V               V                   V
    +-----------+   +-----------+       +-----------+
    | out2agg   |   | out2agg   |   ... | out2agg   |
    +-----------+   +-----------+       +-----------+
      |               |                   |
      V               V                   V
    agg_share_0     agg_share_1         agg_share_[SHARES-1]
]]></artwork>
        </figure>
        <t>For simplicity, we have written this algorithm and the unsharding algorithm
below in "one-shot" form, where all shares for a batch are provided at the same
time.  Some VDAFs may also support a "streaming" form, where shares are
processed one at a time.</t>
      </section>
      <section anchor="sec-vdaf-unshard">
        <name>Unsharding</name>
        <t>After the Aggregators have aggregated a sufficient number of output shares, each
sends its aggregate share to the Collector, who runs the following algorithm to
recover the following output:</t>
        <ul spacing="normal">
          <li>
            <tt>Vdaf.agg_shares_to_result(agg_param: AggParam, agg_shares: Vec[AggShare]) -&gt;
AggResult</tt> is run by the Collector in order to compute the aggregate result
from the Aggregators' shares. The length of <tt>agg_shares</tt> <bcp14>MUST</bcp14> be <tt>SHARES</tt>.
This algorithm is deterministic.</li>
        </ul>
        <figure anchor="unshard-flow">
          <name>Computation of the final aggregate result from aggregate shares.</name>
          <artwork><![CDATA[
    Aggregator 0    Aggregator 1        Aggregator SHARES-1
    ============    ============        ===================

    agg_share_0     agg_share_1         agg_share_[SHARES-1]
      |               |                   |
      V               V                   V
    +-----------------------------------------------+
    | agg_shares_to_result                          |
    +-----------------------------------------------+
      |
      V
    agg_result

    Collector
    =========
]]></artwork>
        </figure>
        <ul empty="true">
          <li>
            <t>QUESTION Maybe the aggregation algorithms should be randomized in order to
allow the Aggregators (or the Collector) to add noise for differential
privacy. (See the security considerations of <xref target="I-D.draft-gpew-priv-ppm"/>.) Or
is this out-of-scope of this document?</t>
          </li>
        </ul>
      </section>
      <section anchor="execution">
        <name>Execution of a VDAF</name>
        <t>Executing a VDAF involves the concurrent evaluation of the VDAF on individual
inputs and aggregation of the recovered output shares. This is captured by the
following example algorithm:</t>
        <figure anchor="run-vdaf">
          <name>Execution of a VDAF.</name>
          <artwork><![CDATA[
def run_vdaf(Vdaf,
             agg_param: Vdaf.AggParam,
             nonces: Vec[Bytes],
             measurements: Vec[Vdaf.Measurement]):
    # Distribute long-lived parameters.
    (public_param, verify_params) = Vdaf.setup()

    out_shares = []
    for (nonce, measurement) in zip(nonces, measurements):

        # Each Client shards its input into shares.
        input_shares = Vdaf.measurement_to_input_shares(public_param,
                                                        measurement)

        # Each Aggregator initializes its preparation state.
        prep_states = []
        for j in range(Vdaf.SHARES):
            state = Vdaf.prep_init(verify_params[j],
                                   agg_param,
                                   nonce,
                                   input_shares[j])
            prep_states.append(state)

        # Aggregators recover their output shares.
        inbound = None
        for i in range(Vdaf.ROUNDS+1):
            outbound = []
            for j in range(Vdaf.SHARES):
                out = Vdaf.prep_next(prep_states[j], inbound)
                if i < Vdaf.ROUNDS:
                    (prep_states[j], out) = out
                outbound.append(out)
            # This is where we would send messages over the
            # network in a distributed VDAF computation.
            if i < Vdaf.ROUNDS:
                inbound = Vdaf.prep_shares_to_prep(agg_param,
                                                   outbound)

        # The final outputs of prepare phasre are the output shares.
        out_shares.append(outbound)

    # Each Aggregator aggregates its output shares into an
    # aggregate share.
    agg_shares = []
    for j in range(Vdaf.SHARES):
        out_shares_j = [out[j] for out in out_shares]
        agg_share_j = Vdaf.out_shares_to_agg_share(agg_param,
                                                   out_shares_j)
        agg_shares.append(agg_share_j)

    # Collector unshards the aggregate.
    agg_result = Vdaf.agg_shares_to_result(agg_param, agg_shares)
    return agg_result
]]></artwork>
        </figure>
        <t>The inputs to this algorithm are the aggregation parameter <tt>agg_param</tt>, a list
of nonces <tt>nonces</tt>, and a batch of Client inputs <tt>input_batch</tt>. The aggregation
parameter is chosen by the Aggregators prior to executing the VDAF. This
document does not specify how the nonces are chosen, but security requires that
the nonces be unique for each measurement. See <xref target="security"/> for details.</t>
        <t>Another important question this document leaves out of scope is how a VDAF is to
be executed by Aggregators distributed over a real network. Algorithm <tt>run_vdaf</tt>
prescribes the protocol's execution in a "benign" environment in which there is
no adversary and 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="I-D.draft-gpew-priv-ppm"/> that implements
suitable cryptographic functionalities. 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 VDAF in various
adversarial environments and what properties the wrapper protocol needs to
provide in each.</t>
        <!--
## VDAFs in the Literature

* Prio [CGB17] defines the composition of a linear secret sharing scheme and an
  affine-aggregatable encoding of a statistic.

* A special case of zero-knowledge proofs over distributed data [BBCGGI19] in
  which the client speaks once.

* The composition of an incremental distributed point function and the
  secure-sketching protocol for subset histograms defined in [BBCGGI21].

* Prio+ [AGJOP21] has the client upload XOR shares and then has the servers
  convert them to additive shares over a number of rounds.
-->

</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>
            <tt>MODULUS: Unsigned</tt> is the prime modulus that defines the field.</li>
          <li>
            <tt>ENCODED_SIZE: Unsigned</tt> is the number of bytes used to encode a field element
as a byte string.</li>
        </ul>
        <t>A concrete <tt>Field</tt> also implements the following class methods:</t>
        <ul spacing="normal">
          <li>
            <tt>Field.zeros(length: Unsigned) -&gt; output: Vec[Field]</tt> returns a vector of
zeros. The length of <tt>output</tt> <bcp14>MUST</bcp14> be <tt>length</tt>.</li>
          <li>
            <tt>Field.rand_vec(length: Unsigned) -&gt; output: Vec[Field]</tt> returns a vector of
random field elements. The length of <tt>output</tt> <bcp14>MUST</bcp14> be <tt>length</tt>.</li>
        </ul>
        <t>A field element is an instance of a concrete <tt>Field</tt>. The concrete class defines
the usual arithmetic operations on field elements. In addition, it defines the
following instance method for converting a field element to an unsigned integer:</t>
        <ul spacing="normal">
          <li>
            <tt>elem.as_unsigned() -&gt; Unsigned</tt> returns the integer representation of
field element <tt>elem</tt>.</li>
        </ul>
        <t>Likewise, each concrete <tt>Field</tt> implements a constructor for converting an
unsigned integer into a field element:</t>
        <ul spacing="normal">
          <li>
            <tt>Field(integer: Unsigned)</tt> returns <tt>integer</tt> represented as a field element.
If <tt>integer &gt;= Field.MODULUS</tt>, then <tt>integer</tt> is first reduced modulo
<tt>Field.MODULUS</tt>.</li>
        </ul>
        <t>Finally, each concrete <tt>Field</tt> has two derived class methods, one for encoding
a vector of field elements as a byte string and another for decoding a vector of
field elements.</t>
        <figure anchor="field-derived-methods">
          <name>Derived class methods for finite fields.</name>
          <artwork><![CDATA[
def encode_vec(Field, data: Vec[Field]) -> Bytes:
    encoded = Bytes()
    for x in data:
        encoded += I2OSP(x.as_unsigned(), Field.ENCODED_SIZE)
    return encoded

def decode_vec(Field, encoded: Bytes) -> Vec[Field]:
    L = Field.ENCODED_SIZE
    if len(encoded) % L != 0:
        raise ERR_DECODE

    vec = []
    for i in range(0, len(encoded), L):
        encoded_x = encoded[i:i+L]
        x = Field(OS2IP(encoded_x))
        vec.append(x)
    return vec
]]></artwork>
        </figure>
        <section anchor="auxiliary-functions">
          <name>Auxiliary Functions</name>
          <t>The following auxiliary functions on vectors of field elements are used in the
remainder of this document. Note that an exception is raised by each function if
the operands are not the same length.</t>
          <figure anchor="field-helper-functions">
            <name>Common functions for finite fields.</name>
            <artwork><![CDATA[
# Compute the inner product of the operands.
def inner_product(left: Vec[Field], right: Vec[Field]) -> Field:
    return sum(map(lambda x: x[0] * x[1], zip(left, right)))

# Subtract the right operand from the left and return the result.
def vec_sub(left: Vec[Field], right: Vec[Field]):
    return list(map(lambda x: x[0] - x[1], zip(left, right)))

# Add the right operand to the left and return the result.
def vec_add(left: Vec[Field], right: Vec[Field]):
    return list(map(lambda x: x[0] + x[1], zip(left, right)))
]]></artwork>
          </figure>
        </section>
        <section anchor="field-fft-friendly">
          <name>FFT-Friendly Fields</name>
          <t>Some VDAFs require fields that are suitable for efficient computation of the
discrete Fourier transform. (One example is Prio3 (<xref target="prio3"/>) when instantiated
with the generic FLP of <xref target="flp-generic-construction"/>.) Specifically, a field is
said to be "FFT-friendly" if, in addition to satisfying the interface described
in <xref target="field"/>, it implements the following method:</t>
          <ul spacing="normal">
            <li>
              <tt>Field.gen() -&gt; Field</tt> returns the generator of a large subgroup of the
multiplicative group.</li>
          </ul>
          <t>FFT-friendly fields also define the following parameter:</t>
          <ul spacing="normal">
            <li>
              <tt>GEN_ORDER: Unsigned</tt> is the order of a multiplicative subgroup generated by
<tt>Field.gen()</tt>. This value <bcp14>MUST</bcp14> be a power of 2.</li>
          </ul>
        </section>
        <section anchor="parameters">
          <name>Parameters</name>
          <t>The tables below define finite fields used in the remainder of this document.</t>
          <table anchor="field64">
            <name>Field64, an FFT-friendly field.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">MODULUS</td>
                <td align="left">2^32 * 4294967295 + 1</td>
              </tr>
              <tr>
                <td align="left">ENCODED_SIZE</td>
                <td align="left">8</td>
              </tr>
              <tr>
                <td align="left">Generator</td>
                <td align="left">7^4294967295</td>
              </tr>
              <tr>
                <td align="left">GEN_ORDER</td>
                <td align="left">2^32</td>
              </tr>
            </tbody>
          </table>
          <table anchor="field128">
            <name>Field128, an FFT-friendly field.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">MODULUS</td>
                <td align="left">2^66 * 4611686018427387897 + 1</td>
              </tr>
              <tr>
                <td align="left">ENCODED_SIZE</td>
                <td align="left">16</td>
              </tr>
              <tr>
                <td align="left">Generator</td>
                <td align="left">7^4611686018427387897</td>
              </tr>
              <tr>
                <td align="left">GEN_ORDER</td>
                <td align="left">2^66</td>
              </tr>
            </tbody>
          </table>
        </section>
      </section>
      <section anchor="prg">
        <name>Pseudorandom Generators</name>
        <t>A pseudorandom generator (PRG) is used to expand a short, (pseudo)random seed
into a long string of pseudorandom bits. A PRG suitable for this document
implements the interface specified in this section. Concrete constructions are
described in the subsections that folllow.</t>
        <t>PRGs are defined by a class <tt>Prg</tt> with the following associated parameter:</t>
        <ul spacing="normal">
          <li>
            <tt>SEED_SIZE: Unsigned</tt> is the size (in bytes) of a seed.</li>
        </ul>
        <t>A concrete <tt>Prg</tt> implements the following class method:</t>
        <ul spacing="normal">
          <li>
            <tt>Prg(seed: Bytes, info: Bytes)</tt> constructs an instance of <tt>Prg</tt> from the given
seed and info string. The seed <bcp14>MUST</bcp14> be of length <tt>SEED_SIZE</tt> and <bcp14>MUST</bcp14> be
generated securely (i.e., it is either the output of <tt>gen_rand</tt> or a previous
invocation of the PRG). The info string is used for domain separation.</li>
          <li>
            <tt>prg.next(length: Unsigned)</tt> returns the next <tt>length</tt> bytes of output of PRG.
If the seed was securely generated, the output can be treated as pseudorandom.</li>
        </ul>
        <t>Each <tt>Prg</tt> has two derived class methods. The first is used to derive a fresh
seed from an existing one. The second is used to compute a sequence of
pseudorandom field elements. For each method, the seed <bcp14>MUST</bcp14> be of length
<tt>SEED_SIZE</tt> and <bcp14>MUST</bcp14> be generated securely (i.e., it is either the output of
<tt>gen_rand</tt> or a previous invocation of the PRG).</t>
        <figure anchor="prg-derived-methods">
          <name>Derived class methods for PRGs.</name>
          <artwork><![CDATA[
# Derive a new seed.
def derive_seed(Prg, seed: Bytes, info: Bytes) -> bytes:
    prg = Prg(seed, info)
    return prg.next(Prg.SEED_SIZE)

# Expand a seed into a vector of Field elements.
def expand_into_vec(Prg,
                    Field,
                    seed: Bytes,
                    info: Bytes,
                    length: Unsigned):
    m = next_power_of_2(Field.MODULUS) - 1
    prg = Prg(seed, info)
    vec = []
    while len(vec) < length:
        x = OS2IP(prg.next(Field.ENCODED_SIZE))
        x &= m
        if x < Field.MODULUS:
            vec.append(Field(x))
    return vec
]]></artwork>
        </figure>
        <section anchor="prg-aes128">
          <name>PrgAes128</name>
          <ul empty="true">
            <li>
              <t>OPEN ISSUE Phillipp points out that a fixed-key mode of AES may be more
performant (https://eprint.iacr.org/2019/074.pdf). See
https://github.com/cjpatton/vdaf/issues/32 for details.</t>
            </li>
          </ul>
          <t>Our first construction, <tt>PrgAes128</tt>, converts a blockcipher, namely AES-128,
into a PRG. Seed expansion involves two steps. In the first step, CMAC
<xref target="RFC4493"/> is applied to the seed and info string to get a fresh key. In the
second step, the fresh key is used in CTR-mode to produce a key stream for
generating the output. A fixed initialization vector (IV) is used.</t>
          <figure>
            <name>Definition of PRG PrgAes128.</name>
            <artwork><![CDATA[
class PrgAes128:

    SEED_SIZE: Unsigned = 16

    def __init__(self, seed, info):
        self.length_consumed = 0

        # Use CMAC as a pseudorandom function to derive a key.
        self.key = AES128-CMAC(seed, info)

    def next(self, length):
        self.length_consumed += length

        # CTR-mode encryption of the all-zero string of the desired
        # length and using a fixed, all-zero IV.
        stream = AES128-CTR(key, zeros(16), zeros(self.length_consumed))
        return stream[-length:]
]]></artwork>
          </figure>
        </section>
      </section>
    </section>
    <section anchor="prio3">
      <name>Prio3</name>
      <ul empty="true">
        <li>
          <t>NOTE This construction has not undergone significant security analysis.</t>
        </li>
      </ul>
      <t>This section describes "Prio3", a VDAF for Prio <xref target="CGB17"/>. Prio is suitable for
a wide variety of aggregation functions, including (but not limited to) sum,
mean, standard deviation, estimation of quantiles (e.g., median), and linear
regression. In fact, the scheme described in this section is compatible with any
aggregation function that has the following structure:</t>
      <ul spacing="normal">
        <li>Each measurement is encoded as a vector over some finite field.</li>
        <li>Input validity is determined by an arithmetic circuit evaluated over the
encoded input. (An "arithmetic circuit" is a function comprised of arithmetic
operations in the field.) The circuit's output is a single field element: if
zero, then the input is said to be "valid"; otherwise, if the output is
non-zero, then the input is said to "invalid".</li>
        <li>The aggregate result is obtained by summing up the encoded input vectors and
computing some function of the sum.</li>
      </ul>
      <t>At a high level, Prio3 distributes this computation as follows. Each Client
first shards its measurement by first encoding it, then splitting the vector into
secret shares and sending a share to each Aggregator. Next, in the preparation
phase, the Aggregators carry out a multi-party computation to determine if their
shares correspond to a valid input (as determined by the arithmetic circuit).
This computation involves a "proof" of validity generated by the Client. Next,
each Aggregator sums up its input shares locally. Finally, the Collector sums up
the aggregate shares and computes the aggregate result.</t>
      <t>This VDAF does not have an aggregation parameter. Instead, the output share is
derived from the 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>As the name implies, "Prio3" is a descendant of the original Prio construction.
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 core component of Prio3 is a "Fully Linear Proof (FLP)" system. Introduced
by <xref target="BBCGGI19"/>, the FLP encapsulates the functionality required for encoding
and validating inputs. Prio3 can be thought of as a transformation of a
particular class of FLPs into a VDAF.</t>
      <t>The remainder of this section is structured as follows. The syntax for FLPs is
described in <xref target="flp"/>. The generic transformation of an FLP into Prio3 is
specified in <xref target="prio3-construction"/>. Next, a concrete FLP suitable for any
validity circuit is specified in <xref target="flp-generic"/>. Finally, instantiations of
Prio3 for various types of measurements are specified in
<xref target="prio3-instantiations"/>. Test vectors can be found in <xref target="test-vectors"/>.</t>
      <section anchor="flp">
        <name>Fully Linear Proof (FLP) Systems</name>
        <t>Conceptually, an FLP is a two-party protocol executed by a prover and a
verifier. In actual use, however, the prover's computation is carried out by the
Client, and the verifier's computation is distributed among the Aggregators. The
Client generates a "proof" of its input's validity and distributes shares of the
proof to the Aggregators. Each Aggregator then performs some a computation on
its input share and proof share locally and sends the result to the other
Aggregators. Combining the exchanged messages allows each Aggregator to decide
if it holds a share of a valid input. (See <xref target="prio3-construction"/> for details.)</t>
        <t>As usual, we will describe the interface implemented by a concrete FLP in terms
of an abstract base class <tt>Flp</tt> that specifies the set of methods and parameters
a concrete FLP must provide.</t>
        <t>The parameters provided by a concrete FLP are listed in <xref target="flp-param"/>.</t>
        <table anchor="flp-param">
          <name>Constants and types defined by a concrete FLP.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>PROVE_RAND_LEN</tt></td>
              <td align="left">Length of the prover randomness, the number of random field elements consumed by the prover when generating a proof</td>
            </tr>
            <tr>
              <td align="left">
                <tt>QUERY_RAND_LEN</tt></td>
              <td align="left">Length of the query randomness, the number of random field elements consumed by the verifier</td>
            </tr>
            <tr>
              <td align="left">
                <tt>JOINT_RAND_LEN</tt></td>
              <td align="left">Length of the joint randomness, the number of random field elements consumed by both the prover and verifier</td>
            </tr>
            <tr>
              <td align="left">
                <tt>INPUT_LEN</tt></td>
              <td align="left">Length of the encoded measurement (<xref target="flp-encode"/>)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>OUTPUT_LEN</tt></td>
              <td align="left">Length of the aggregatable output (<xref target="flp-encode"/>)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>PROOF_LEN</tt></td>
              <td align="left">Length of the proof</td>
            </tr>
            <tr>
              <td align="left">
                <tt>VERIFIER_LEN</tt></td>
              <td align="left">Length of the verifier message generated by querying the input 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>Field</tt></td>
              <td align="left">As defined in (<xref target="field"/>)</td>
            </tr>
          </tbody>
        </table>
        <t>An FLP specifies the following algorithms for generating and verifying proofs of
validity (encoding is described below in <xref target="flp-encode"/>):</t>
        <ul spacing="normal">
          <li>
            <tt>Flp.prove(input: Vec[Field], prove_rand: Vec[Field], joint_rand: Vec[Field])
-&gt; Vec[Field]</tt> is the deterministic proof-generation algorithm run by the
prover. Its inputs are the encoded input, the "prover randomness"
<tt>prove_rand</tt>, and the "joint randomness" <tt>joint_rand</tt>. The proof randomness is
used only by the prover, but the joint randomness is shared by both the prover
and verifier.</li>
          <li>
            <tt>Flp.query(input: Vec[Field], proof: Vec[Field], query_rand: Vec[Field],
joint_rand: Vec[Field]) -&gt; Vec[Field]</tt> is the query-generation algorithm run
by the verifier. This is used to "query" the input and proof. The result of
the query (i.e., the output of this function) is called the "verifier
message". In addition to the input 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.</li>
          <li>
            <tt>Flp.decide(verifier: Vec[Field]) -&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 input from which it was generated is
valid.</li>
        </ul>
        <t>Our application requires that the FLP is "fully linear" in the sense defined in
<xref target="BBCGGI19"/> As a practical matter, what this property implies is that, when run
on a share of the input and proof, the query-generation algorithm outputs a
share of the verifier message. Furthermore, the "zero-knowledge" property of the
FLP system ensures that the verifier message reveals nothing about the input's
validity. Therefore, to decide if an input is valid, the Aggregators will run
the query-generation algorithm locally, exchange verifier shares, combine
them to recover the verifier message, and run the decision algorithm.</t>
        <t>An FLP is executed by the prover and verifier as follows:</t>
        <figure anchor="run-flp">
          <name>Execution of an FLP.</name>
          <artwork><![CDATA[
def run_flp(Flp, inp: Vec[Flp.Field], num_shares: Unsigned):
    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(inp, prove_rand, joint_rand)

    # Verifier queries the input and proof.
    verifier = Flp.query(inp, proof, query_rand, joint_rand, num_shares)

    # Verifier decides if the input is valid.
    return Flp.decide(verifier)
]]></artwork>
        </figure>
        <t>The proof system is constructed so that, if <tt>input</tt> is a valid input, then
<tt>run_flp(Flp, input)</tt> always returns <tt>True</tt>. On the other hand, if <tt>input</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 overwhelming probability.</t>
        <t>We remark that <xref target="BBCGGI19"/> defines a much larger class of fully linear proof
systems than we consider here. In particular, what is called an "FLP" here is
called a 1.5-round, public-coin, interactive oracle proof system in their paper.</t>
        <section anchor="flp-encode">
          <name>Encoding the Input</name>
          <t>The type of measurement being aggregated is defined by the FLP. Hence, the FLP
also specifies a method of encoding raw measurements as a vector of field
elements:</t>
          <ul spacing="normal">
            <li>
              <tt>Flp.encode(measurement: Measurement) -&gt; Vec[Field]</tt> encodes a raw measurement
as a vector of field elements. The return value <bcp14>MUST</bcp14> be of length <tt>INPUT_LEN</tt>.</li>
          </ul>
          <t>For some FLPs, the encoded input also includes redundant field elements that are
useful for checking the proof, but which are not needed after the proof has been
checked. An example is the "integer sum" data type from <xref target="CGB17"/> in which an
integer in range <tt>[0, 2^k)</tt> is encoded as a vector of <tt>k</tt> field elements (this
type is also defined in <xref target="prio3-instantiations"/>). After consuming this vector,
all that is needed is the integer it represents. Thus the FLP defines an
algorithm for truncating the input to the length of the aggregated output:</t>
          <ul spacing="normal">
            <li>
              <tt>Flp.truncate(input: Vec[Field]) -&gt; Vec[Field]</tt> maps an encoded input to an
aggregatable output. The length of the input <bcp14>MUST</bcp14> be <tt>INPUT_LEN</tt> and the length
of the output <bcp14>MUST</bcp14> be <tt>OUTPUT_LEN</tt>.</li>
          </ul>
          <t>We remark that, taken together, these two functionalities correspond roughly to
the notion of "Affine-aggregatable encodings (AFEs)" from <xref target="CGB17"/>.</t>
        </section>
      </section>
      <section anchor="prio3-construction">
        <name>Construction</name>
        <t>This section specifies <tt>Prio3</tt>, an implementation of the <tt>Vdaf</tt> interface
(<xref target="vdaf"/>). It has two generic parameters: an <tt>Flp</tt> (<xref target="flp"/>) and a <tt>Prg</tt>
(<xref target="prg"/>). The associated constants and types required by the <tt>Vdaf</tt> interface
are defined in <xref target="prio3-param"/>. The methods required for sharding, preparation,
aggregation, and unsharding are described in the remaining subsections.</t>
        <table anchor="prio3-param">
          <name>Associated parameters for the Prio3 VDAF.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>ROUNDS</tt></td>
              <td align="left">
                <tt>1</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>SHARES</tt></td>
              <td align="left">in <tt>[2, 255)</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">
                <tt>Flp.Measurement</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PublicParam</tt></td>
              <td align="left">
                <tt>None</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>VerifyParam</tt></td>
              <td align="left">
                <tt>Tuple[Unsigned, Bytes]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggParam</tt></td>
              <td align="left">
                <tt>None</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>Prep</tt></td>
              <td align="left">
                <tt>Tuple[Vec[Flp.Field], Optional[Bytes], Bytes]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>OutShare</tt></td>
              <td align="left">
                <tt>Vec[Flp.Field]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggShare</tt></td>
              <td align="left">
                <tt>Vec[Flp.Field]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">
                <tt>Vec[Unsigned]</tt></td>
            </tr>
          </tbody>
        </table>
        <section anchor="setup">
          <name>Setup</name>
          <t>The setup algorithm generates a symmetric key shared by all of the Aggregators.
The key is used to derive query randomness for the FLP query-generation
algorithm run by the Aggregators during preparation. An Aggregator's
verification parameter also includes its "ID", a unique integer in <tt>[0,
SHARES)</tt>.</t>
          <figure anchor="prio3-eval-setup">
            <name>The setup algorithm for Prio3.</name>
            <artwork><![CDATA[
def setup(Prio3):
    k_query_init = gen_rand(Prio3.Prg.SEED_SIZE)
    verify_param = [(j, k_query_init) for j in range(Prio3.SHARES)]
    return (None, verify_param)
]]></artwork>
          </figure>
        </section>
        <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
input in a way that allows the Aggregators to reconstruct it from their input
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 input-distribution algorithm involves the following steps:</t>
          <ol spacing="normal" type="1"><li>Encode the Client's raw measurement as an input for the FLP</li>
            <li>Shard the input into a sequence of input shares</li>
            <li>Derive the joint randomness from the input shares</li>
            <li>Run the FLP proof-generation algorithm using the derived joint randomness</li>
            <li>Shard the proof into a sequence of proof shares</li>
          </ol>
          <t>The algorithm is specified below. Notice that only one set input and proof shares
(called the "leader" shares below) are vectors of field elements. The other
shares (called the "helper" shares) are represented instead by PRG seeds, which
are expanded into vectors of field elements.</t>
          <t>The code refers to a pair of auxiliary functions for encoding the shares. These
are called <tt>encode_leader_share</tt> and <tt>encode_helper_share</tt> respectively and they
are described in <xref target="prio3-helper-functions"/>.</t>
          <figure anchor="prio3-eval-input">
            <name>Input-distribution algorithm for Prio3.</name>
            <artwork><![CDATA[
def measurement_to_input_shares(Prio3, _public_param, measurement):
    dst = b"vdaf-00 prio3"
    inp = Prio3.Flp.encode(measurement)
    k_joint_rand = zeros(Prio3.Prg.SEED_SIZE)

    # Generate input shares.
    leader_input_share = inp
    k_helper_input_shares = []
    k_helper_blinds = []
    k_helper_hints = []
    for j in range(Prio3.SHARES-1):
        k_blind = gen_rand(Prio3.Prg.SEED_SIZE)
        k_share = gen_rand(Prio3.Prg.SEED_SIZE)
        helper_input_share = Prio3.Prg.expand_into_vec(
            Prio3.Flp.Field,
            k_share,
            dst + byte(j+1),
            Prio3.Flp.INPUT_LEN
        )
        leader_input_share = vec_sub(leader_input_share,
                                     helper_input_share)
        encoded = Prio3.Flp.Field.encode_vec(helper_input_share)
        k_hint = Prio3.Prg.derive_seed(k_blind,
                                       byte(j+1) + encoded)
        k_joint_rand = xor(k_joint_rand, k_hint)
        k_helper_input_shares.append(k_share)
        k_helper_blinds.append(k_blind)
        k_helper_hints.append(k_hint)
    k_leader_blind = gen_rand(Prio3.Prg.SEED_SIZE)
    encoded = Prio3.Flp.Field.encode_vec(leader_input_share)
    k_leader_hint = Prio3.Prg.derive_seed(k_leader_blind,
                                          byte(0) + encoded)
    k_joint_rand = xor(k_joint_rand, k_leader_hint)

    # Finish joint randomness hints.
    for j in range(Prio3.SHARES-1):
        k_helper_hints[j] = xor(k_helper_hints[j], k_joint_rand)
    k_leader_hint = xor(k_leader_hint, k_joint_rand)

    # Generate the proof shares.
    prove_rand = Prio3.Prg.expand_into_vec(
        Prio3.Flp.Field,
        gen_rand(Prio3.Prg.SEED_SIZE),
        dst,
        Prio3.Flp.PROVE_RAND_LEN
    )
    joint_rand = Prio3.Prg.expand_into_vec(
        Prio3.Flp.Field,
        k_joint_rand,
        dst,
        Prio3.Flp.JOINT_RAND_LEN
    )
    proof = Prio3.Flp.prove(inp, prove_rand, joint_rand)
    leader_proof_share = proof
    k_helper_proof_shares = []
    for j in range(Prio3.SHARES-1):
        k_share = gen_rand(Prio3.Prg.SEED_SIZE)
        k_helper_proof_shares.append(k_share)
        helper_proof_share = Prio3.Prg.expand_into_vec(
            Prio3.Flp.Field,
            k_share,
            dst + byte(j+1),
            Prio3.Flp.PROOF_LEN
        )
        leader_proof_share = vec_sub(leader_proof_share,
                                     helper_proof_share)

    input_shares = []
    input_shares.append(Prio3.encode_leader_share(
        leader_input_share,
        leader_proof_share,
        k_leader_blind,
        k_leader_hint,
    ))
    for j in range(Prio3.SHARES-1):
        input_shares.append(Prio3.encode_helper_share(
            k_helper_input_shares[j],
            k_helper_proof_shares[j],
            k_helper_blinds[j],
            k_helper_hints[j],
        ))
    return input_shares
]]></artwork>
          </figure>
        </section>
        <section anchor="preparation">
          <name>Preparation</name>
          <t>This section describes the process of recovering output shares from the input
shares. The high-level idea is that each Aggregator first queries its input and
proof share locally, then exchanges its verifier share with the other
Aggregators. The verifier shares are then combined into the verifier message,
which is used to decide whether to accept.</t>
          <t>In addition, the Aggregators must ensure that they have all used the same joint
randomness for the query-generation algorithm. The joint randomness is generated
by a PRG seed. Each Aggregator derives an XOR secret share of this seed from its
input share and the "blind" generated by the client. Thus, before running the
query-generation algorithm, it must first gather the XOR secret shares derived
by the other Aggregators.</t>
          <t>In order to avoid extra round of communication, the Client sends each Aggregator
a "hint" equal to the XOR of the other Aggregators' shares of the joint
randomness seed. 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 XOR shares of the PRG seed
along with their verifier shares.</t>
          <ul empty="true">
            <li>
              <t>NOTE This optimization somewhat diverges from Section 6.2.3 of <xref target="BBCGGI19"/>.
Security analysis is needed.</t>
            </li>
          </ul>
          <t>The algorithms required for preparation are defined as follows. These algorithms
make use of encoding and decoding methods defined in <xref target="prio3-helper-functions"/>.</t>
          <figure anchor="prio3-prep-state">
            <name>Preparation state for Prio3.</name>
            <artwork><![CDATA[
def prep_init(Prio3, verify_param, _agg_param, nonce, input_share):
    dst = b"vdaf-00 prio3"
    (j, k_query_init) = verify_param

    (input_share, proof_share, k_blind, k_hint) = \
        Prio3.decode_leader_share(input_share) if j == 0 else \
        Prio3.decode_helper_share(dst, j, input_share)

    out_share = Prio3.Flp.truncate(input_share)

    k_query_rand = Prio3.Prg.derive_seed(k_query_init,
                                         byte(255) + nonce)
    query_rand = Prio3.Prg.expand_into_vec(
        Prio3.Flp.Field,
        k_query_rand,
        dst,
        Prio3.Flp.QUERY_RAND_LEN
    )
    joint_rand, k_joint_rand, k_joint_rand_share = [], None, None
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        encoded = Prio3.Flp.Field.encode_vec(input_share)
        k_joint_rand_share = Prio3.Prg.derive_seed(k_blind,
                                                   byte(j) + encoded)
        k_joint_rand = xor(k_hint, k_joint_rand_share)
        joint_rand = Prio3.Prg.expand_into_vec(
            Prio3.Flp.Field,
            k_joint_rand,
            dst,
            Prio3.Flp.JOINT_RAND_LEN
        )
    verifier_share = Prio3.Flp.query(input_share,
                                     proof_share,
                                     query_rand,
                                     joint_rand,
                                     Prio3.SHARES)

    prep_msg = Prio3.encode_prepare_message(verifier_share,
                                            k_joint_rand_share)
    return (out_share, k_joint_rand, prep_msg)

def prep_next(Prio3, prep, inbound):
    (out_share, k_joint_rand, prep_msg) = prep

    if inbound is None:
        return (prep, prep_msg)

    (verifier, k_joint_rand_check) = \
        Prio3.decode_prepare_message(inbound)

    if k_joint_rand_check != k_joint_rand or \
            not Prio3.Flp.decide(verifier):
        raise ERR_VERIFY

    return out_share

def prep_shares_to_prep(Prio3, _agg_param, prep_shares):
    verifier = Prio3.Flp.Field.zeros(Prio3.Flp.VERIFIER_LEN)
    k_joint_rand_check = zeros(Prio3.Prg.SEED_SIZE)
    for encoded in prep_shares:
        (verifier_share, k_joint_rand_share) = \
            Prio3.decode_prepare_message(encoded)

        verifier = vec_add(verifier, verifier_share)

        if Prio3.Flp.JOINT_RAND_LEN > 0:
            k_joint_rand_check = xor(k_joint_rand_check,
                                     k_joint_rand_share)

    return Prio3.encode_prepare_message(verifier,
                                        k_joint_rand_check)
]]></artwork>
          </figure>
        </section>
        <section anchor="aggregation">
          <name>Aggregation</name>
          <t>Aggregating a set of output shares is simply a matter of adding up the vectors
element-wise.</t>
          <figure anchor="prio3-out2agg">
            <name>Aggregation algorithm for Prio3.</name>
            <artwork><![CDATA[
def out_shares_to_agg_share(Prio3, _agg_param, out_shares):
    agg_share = Prio3.Flp.Field.zeros(Prio3.Flp.OUTPUT_LEN)
    for out_share in out_shares:
        agg_share = vec_add(agg_share, out_share)
    return agg_share
]]></artwork>
          </figure>
        </section>
        <section anchor="unsharding">
          <name>Unsharding</name>
          <t>To unshard a set of aggregate shares, the Collector first adds up the vectors
element-wise. It then converts each element of the vector into an integer.</t>
          <figure anchor="prio3-agg-output">
            <name>Computation of the aggregate result for Prio3.</name>
            <artwork><![CDATA[
def agg_shares_to_result(Prio3, _agg_param, agg_shares):
    agg = Prio3.Flp.Field.zeros(Prio3.Flp.OUTPUT_LEN)
    for agg_share in agg_shares:
        agg = vec_add(agg, agg_share)
    return list(map(lambda x: x.as_unsigned(), agg))
]]></artwork>
          </figure>
        </section>
        <section anchor="prio3-helper-functions">
          <name>Auxiliary Functions</name>
          <figure anchor="prio3-helpers">
            <name>Helper functions required for Prio3.</name>
            <artwork><![CDATA[
def encode_leader_share(Prio3,
                        input_share,
                        proof_share,
                        k_blind,
                        k_hint):
    encoded = Bytes()
    encoded += Prio3.Flp.Field.encode_vec(input_share)
    encoded += Prio3.Flp.Field.encode_vec(proof_share)
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        encoded += k_blind
        encoded += k_hint
    return encoded

def decode_leader_share(Prio3, encoded):
    l = Prio3.Flp.Field.ENCODED_SIZE * Prio3.Flp.INPUT_LEN
    encoded_input_share, encoded = encoded[:l], encoded[l:]
    input_share = Prio3.Flp.Field.decode_vec(encoded_input_share)
    l = Prio3.Flp.Field.ENCODED_SIZE * Prio3.Flp.PROOF_LEN
    encoded_proof_share, encoded = encoded[:l], encoded[l:]
    proof_share = Prio3.Flp.Field.decode_vec(encoded_proof_share)
    l = Prio3.Prg.SEED_SIZE
    k_blind, k_hint = None, None
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        k_blind, encoded = encoded[:l], encoded[l:]
        k_hint, encoded = encoded[:l], encoded[l:]
    if len(encoded) != 0:
        raise ERR_DECODE
    return (input_share, proof_share, k_blind, k_hint)

def encode_helper_share(Prio3,
                        k_input_share,
                        k_proof_share,
                        k_blind,
                        k_hint):
    encoded = Bytes()
    encoded += k_input_share
    encoded += k_proof_share
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        encoded += k_blind
        encoded += k_hint
    return encoded

def decode_helper_share(Prio3, dst, j, encoded):
    l = Prio3.Prg.SEED_SIZE
    k_input_share, encoded = encoded[:l], encoded[l:]
    input_share = Prio3.Prg.expand_into_vec(Prio3.Flp.Field,
                                            k_input_share,
                                            dst + byte(j),
                                            Prio3.Flp.INPUT_LEN)
    k_proof_share, encoded = encoded[:l], encoded[l:]
    proof_share = Prio3.Prg.expand_into_vec(Prio3.Flp.Field,
                                            k_proof_share,
                                            dst + byte(j),
                                            Prio3.Flp.PROOF_LEN)
    k_blind, k_hint = None, None
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        k_blind, encoded = encoded[:l], encoded[l:]
        k_hint, encoded = encoded[:l], encoded[l:]
    if len(encoded) != 0:
        raise ERR_DECODE
    return (input_share, proof_share, k_blind, k_hint)

def encode_prepare_message(Prio3, verifier, k_joint_rand):
    encoded = Bytes()
    encoded += Prio3.Flp.Field.encode_vec(verifier)
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        encoded += k_joint_rand
    return encoded

def decode_prepare_message(Prio3, encoded):
    l = Prio3.Flp.Field.ENCODED_SIZE * Prio3.Flp.VERIFIER_LEN
    encoded_verifier, encoded = encoded[:l], encoded[l:]
    verifier = Prio3.Flp.Field.decode_vec(encoded_verifier)
    k_joint_rand = None
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        l = Prio3.Prg.SEED_SIZE
        k_joint_rand, encoded = encoded[:l], encoded[l:]
    if len(encoded) != 0:
        raise ERR_DECODE
    return (verifier, k_joint_rand)
]]></artwork>
          </figure>
        </section>
      </section>
      <section anchor="flp-generic">
        <name>A General-Purpose FLP</name>
        <t>This section describes an FLP based on the construction from in <xref target="BBCGGI19"/>,
Section 4.2. We begin in <xref target="flp-generic-overview"/> with an overview of their proof
system and the extensions to their proof system made here. The construction is
specified in <xref target="flp-generic-construction"/>.</t>
        <ul empty="true">
          <li>
            <t>OPEN ISSUE We're not yet sure if specifying this general-purpose FLP is
desirable. It might be preferable to specify specialized FLPs for each data
type that we want to standardize, for two reasons. First, clear and concise
specifications are likely easier to write for specialized FLPs rather than the
general one. Second, we may end up tailoring each FLP to the measurement type
in a way that improves performance, but breaks compatibility with the
general-purpose FLP.</t>
            <t>In any case, we can't make this decision until we know which data types to
standardize, so for now, we'll stick with the general-purpose construction.
The reference implementation can be found at
https://github.com/cjpatton/vdaf/tree/main/poc.</t>
          </li>
        </ul>
        <ul empty="true">
          <li>
            <t>OPEN ISSUE Chris Wood points out that the this section reads more like a paper
than a standard. Eventually we'll want to work this into something that is
readily consumable by the CFRG.</t>
          </li>
        </ul>
        <section anchor="flp-generic-overview">
          <name>Overview</name>
          <t>In the proof system of <xref target="BBCGGI19"/>, validity is defined via an arithmetic
circuit evaluated over the input: If the circuit output is zero, then the input
is deemed valid; otherwise, if the circuit output is non-zero, then the input is
deemed invalid. Thus the goal of the proof system is merely to allow the
verifier to evaluate the validity circuit over the input. For our application
(<xref target="prio3"/>), this computation is distributed among multiple Aggregators, each of
which has only a share of the input.</t>
          <t>Suppose for a moment that the validity circuit <tt>C</tt> is affine, meaning its only
operations are addition and multiplication-by-constant. In particular, suppose
the circuit does not contain a multiplication gate whose operands are both
non-constant. Then to decide if an input <tt>x</tt> is valid, each Aggregator could
evaluate <tt>C</tt> on its share of <tt>x</tt> locally, broadcast the output share to its
peers, then combine the output shares locally to recover <tt>C(x)</tt>. This is true
because for any <tt>SHARES</tt>-way secret sharing of <tt>x</tt> it holds that</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 may be necessary to scale any
constants in the circuit by <tt>SHARES</tt>.) However this is not the case if <tt>C</tt> is
not-affine (i.e., it contains at least one multiplication gate whose operands
are non-constant). In the proof system of <xref target="BBCGGI19"/>, the proof is designed to
allow the (distributed) verifier to compute the non-affine operations using only
linear operations on (its share of) the input and proof.</t>
          <t>To make this work, the proof system is restricted to validity circuits that
exhibit a special structure. Specifically, an arithmetic circuit with "G-gates"
(see <xref target="BBCGGI19"/>, Definition 5.2) is composed of affine gates and any number of
instances of a distinguished gate <tt>G</tt>, which may be non-affine. We will refer to
this class of circuits as "gadget circuits" and to <tt>G</tt> as the "gadget".</t>
          <t>As an illustrative example, consider a validity circuit <tt>C</tt> that recognizes the
set <tt>L = set([0], [1])</tt>. That is, <tt>C</tt> takes as input a length-1 vector <tt>x</tt> and
returns 0 if <tt>x[0]</tt> is in <tt>[0,2)</tt> and outputs something else otherwise. This
circuit can be expressed as the following degree-2 polynomial:</t>
          <artwork><![CDATA[
C(x) = (x[0] - 1) * x[0] = x[0]^2 - x[0]
]]></artwork>
          <t>This polynomial recognizes <tt>L</tt> because <tt>x[0]^2 = x[0]</tt> is only true if <tt>x[0] ==
0</tt> or <tt>x[0] == 1</tt>. Notice that the polynomial involves a non-affine operation,
<tt>x[0]^2</tt>. In order to apply <xref target="BBCGGI19"/>, Theorem 4.3, the circuit needs to be
rewritten in terms of a gadget that subsumes this non-affine operation. For
example, the gadget might be multiplication:</t>
          <artwork><![CDATA[
Mul(left, right) = left * right
]]></artwork>
          <t>The validity circuit can then be rewritten in terms of <tt>Mul</tt> like so:</t>
          <artwork><![CDATA[
C(x[0]) = Mul(x[0], x[0]) - x[0]
]]></artwork>
          <t>The proof system of <xref target="BBCGGI19"/> allows the verifier to evaluate each instance
of the gadget (i.e., <tt>Mul(x[0], x[0])</tt> in our example) using a linear function
of the input and proof. The proof is constructed roughly as follows. Let <tt>C</tt> be
the validity circuit and suppose the gadget is arity-<tt>L</tt> (i.e., it has <tt>L</tt> input
wires.). Let <tt>wire[j-1,k-1]</tt> denote the value of the <tt>j</tt>th wire of the <tt>k</tt>th
call to the gadget during the evaluation of <tt>C(x)</tt>. Suppose there are <tt>M</tt> such
calls and fix distinct field elements <tt>alpha[0], ..., alpha[M-1]</tt>. (We will
require these points to have a special property, as we'll discuss in
<xref target="flp-generic-overview-extensions"/>; but for the moment it is only important
that they are distinct.)</t>
          <t>The prover constructs from <tt>wire</tt> and <tt>alpha</tt> a polynomial that, when evaluated
at <tt>alpha[k-1]</tt>, produces the output of the <tt>k</tt>th call to the gadget. Let us
call this the "gadget polynomial". Polynomial evaluation is linear, which means
that, in the distributed setting, the Client can disseminate additive shares of
the gadget polynomial that the Aggregators then use to compute additive shares
of each gadget output, allowing each Aggregator to compute its share of <tt>C(x)</tt>
locally.</t>
          <t>There is one more wrinkle, however: It is still possible for a malicious prover
to produce a gadget polynomial that would result in <tt>C(x)</tt> being computed
incorrectly, potentially resulting in an invalid input being accepted. To
prevent this, the verifier performs a probabilistic test to check that the
gadget polynomial is well-formed. This test, and the procedure for constructing
the gadget polynomial, are described in detail in <xref target="flp-generic-construction"/>.</t>
          <section anchor="flp-generic-overview-extensions">
            <name>Extensions</name>
            <t>The FLP described in the next section extends the proof system <xref target="BBCGGI19"/>,
Section 4.2 in three ways.</t>
            <t>First, the validity circuit in our construction includes an additional, random
input (this is the "joint randomness" derived from the input 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(inp, r) = r * Range2(inp[0]) + ... + r^N * Range2(inp[N-1])
]]></artwork>
            <t>(Note that this is a special case of <xref target="BBCGGI19"/>, Theorem 5.2.) Here <tt>inp</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>inp</tt> is valid (i.e., each <tt>inp[j]</tt> is in <tt>[0,2)</tt>),
then the circuit will evaluate to 0 regardless of the value of <tt>r</tt>; but if
<tt>inp[j]</tt> is not in <tt>[0,2)</tt> for some <tt>j</tt>, the output will be non-zero with high
probability.</t>
            <t>The second extension implemented by our FLP allows the validity circuit to
contain multiple gadget types. (This generalization was suggested in
<xref target="BBCGGI19"/>, Remark 4.5.) For example, the following circuit is allowed, where
<tt>Mul</tt> and <tt>Range2</tt> are the gadgets defined above (the input has length <tt>N+1</tt>):</t>
            <artwork><![CDATA[
C(inp, r) = r * Range2(inp[0]) + ... + r^N * Range2(inp[N-1]) + \
            2^0 * inp[0]       + ... + 2^(N-1) * inp[N-1]     - \
            Mul(inp[N], inp[N])
]]></artwork>
            <t>Finally, <xref target="BBCGGI19"/>, Theorem 4.3 makes no restrictions on the choice of the
fixed points <tt>alpha[0], ..., alpha[M-1]</tt>, other than to require that the points
are distinct. In this document, the fixed points are chosen so that the gadget
polynomial can be constructed efficiently using the Cooley-Tukey FFT ("Fast
Fourier Transform") algorithm. Note that this requires the field to be
"FFT-friendly" as defined in <xref target="field-fft-friendly"/>.</t>
          </section>
        </section>
        <section anchor="flp-generic-valid">
          <name>Validity Circuits</name>
          <t>The FLP described in <xref target="flp-generic-construction"/> is defined in terms of a
validity circuit <tt>Valid</tt> that implements the interface described here.</t>
          <t>A concrete <tt>Valid</tt> defines the following parameters:</t>
          <table>
            <name>Validity circuit parameters.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Description</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">A list of gadgets</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">Number of times each gadget is called</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>INPUT_LEN</tt></td>
                <td align="left">Length of the input</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">Length of the aggregatable output</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">Length of the random input</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">The type of measurement</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">An FFT-friendly finite field as defined in <xref target="field-fft-friendly"/></td>
              </tr>
            </tbody>
          </table>
          <t>Each gadget <tt>G</tt> in <tt>GADGETS</tt> defines a constant <tt>DEGREE</tt> that specifies the
circuit's "arithmetic degree". This is defined to be the degree of the
polynomial that computes it. For example, the <tt>Mul</tt> circuit in
<xref target="flp-generic-overview"/> is defined by the polynomial <tt>Mul(x) = x * x</tt>, which
has degree <tt>2</tt>. Hence, the arithmetic degree of this gadget is <tt>2</tt>.</t>
          <t>Each gadget also defines a parameter <tt>ARITY</tt> that specifies the circuit's arity
(i.e., the number of input wires).</t>
          <t>A concrete <tt>Valid</tt> provides the following methods for encoding a measurement as
an input vector and truncating an input vector to the length of an aggregatable
output:</t>
          <ul spacing="normal">
            <li>
              <tt>Valid.encode(measurement: Measurement) -&gt; Vec[Field]</tt> returns a vector of
length <tt>INPUT_LEN</tt> representing a measurement.</li>
            <li>
              <tt>Valid.truncate(input: Vec[Field]) -&gt; Vec[Field]</tt> returns a vector of length
<tt>OUTPUT_LEN</tt> representing an aggregatable output.</li>
          </ul>
          <t>Finally, the following class methods are derived for each concrete <tt>Valid</tt>:</t>
          <figure>
            <name>Derived methods for validity circuits.</name>
            <artwork><![CDATA[
# Length of the prover randomness.
def prove_rand_len(Valid):
    return sum(map(lambda g: g.ARITY, Valid.GADGETS))

# Length of the query randomness.
def query_rand_len(Valid):
    return len(Valid.GADGETS)

# Length of the proof.
def proof_len(Valid):
    length = 0
    for (g, g_calls) in zip(Valid.GADGETS, Valid.GADGET_CALLS):
        P = next_power_of_2(1 + g_calls)
        length += g.ARITY + g.DEGREE * (P - 1) + 1
    return length

# Length of the verifier message.
def verifier_len(Valid):
    length = 1
    for g in Valid.GADGETS:
        length += g.ARITY + 1
    return length
]]></artwork>
          </figure>
        </section>
        <section anchor="flp-generic-construction">
          <name>Construction</name>
          <t>This section specifies <tt>FlpGeneric</tt>, an implementation of the <tt>Flp</tt> interface
(<xref target="flp"/>). It has as a generic parameter a validity circuit <tt>Valid</tt> implementing
the interface defined in <xref target="flp-generic-valid"/>.</t>
          <ul empty="true">
            <li>
              <t>NOTE A reference implementation can be found in
https://github.com/cjpatton/vdaf/blob/main/poc/flp_generic.sage.</t>
            </li>
          </ul>
          <t>The FLP parameters for <tt>FlpGeneric</tt> are defined in <xref target="flp-generic-param"/>. The
required methods for generating the proof, generating the verifier, and deciding
validity are specified in the remaining subsections.</t>
          <t>In the remainder, we let <tt>[n]</tt> denote the set <tt>{1, ..., n}</tt> for positive integer
<tt>n</tt>. We also define the following constants:</t>
          <ul spacing="normal">
            <li>Let <tt>H = len(Valid.GADGETS)</tt></li>
            <li>
              <t>For each <tt>i</tt> in <tt>[H]</tt>:
              </t>
              <ul spacing="normal">
                <li>Let <tt>G_i = Valid.GADGETS[i]</tt></li>
                <li>Let <tt>L_i = Valid.GADGETS[i].ARITY</tt></li>
                <li>Let <tt>M_i = Valid.GADGET_CALLS[i]</tt></li>
                <li>Let <tt>P_i = next_power_of_2(M_i+1)</tt></li>
                <li>Let <tt>alpha_i = Field.gen()^(Field.GEN_ORDER / P_i)</tt></li>
              </ul>
            </li>
          </ul>
          <t><br/></t>
          <table anchor="flp-generic-param">
            <name>FLP Parameters of FlpGeneric.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>PROVE_RAND_LEN</tt></td>
                <td align="left">
                  <tt>Valid.prove_rand_len()</tt> (see <xref target="flp-generic-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>QUERY_RAND_LEN</tt></td>
                <td align="left">
                  <tt>Valid.query_rand_len()</tt> (see <xref target="flp-generic-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>Valid.JOINT_RAND_LEN</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>INPUT_LEN</tt></td>
                <td align="left">
                  <tt>Valid.INPUT_LEN</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>Valid.OUTPUT_LEN</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOF_LEN</tt></td>
                <td align="left">
                  <tt>Valid.proof_len()</tt> (see <xref target="flp-generic-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>VERIFIER_LEN</tt></td>
                <td align="left">
                  <tt>Valid.verifier_len()</tt> (see <xref target="flp-generic-valid"/>)</td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>Valid.Measurement</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Valid.Field</tt></td>
              </tr>
            </tbody>
          </table>
          <section anchor="flp-generic-construction-prove">
            <name>Proof Generation</name>
            <t>On input <tt>inp</tt>, <tt>prove_rand</tt>, and <tt>joint_rand</tt>, the proof is computed as
follows:</t>
            <ol spacing="normal" type="1"><li>For each <tt>i</tt> in <tt>[H]</tt> create an empty table <tt>wire_i</tt>.</li>
              <li>Partition the prover randomness <tt>prove_rand</tt> into subvectors <tt>seed_1, ...,
seed_H</tt> where <tt>len(seed_i) == L_i</tt> for all <tt>i</tt> in <tt>[H]</tt>. Let us call these
the "wire seeds" of each gadget.</li>
              <li>Evaluate <tt>Valid</tt> on input of <tt>inp</tt> and <tt>joint_rand</tt>, recording the inputs of
each gadget in the corresponding table. Specifically, for every <tt>i</tt> in <tt>[H]</tt>,
set <tt>wire_i[j-1,k-1]</tt> to the value on the <tt>j</tt>th wire into the <tt>k</tt>th call to
gadget <tt>G_i</tt>.</li>
              <li>
                <t>Compute the "wire polynomials". That is, for every <tt>i</tt> in <tt>[H]</tt> and <tt>j</tt> in
<tt>[L_i]</tt>, construct <tt>poly_wire_i[j-1]</tt>, the <tt>j</tt>th wire polynomial for the
<tt>i</tt>th gadget, as follows:  </t>
                <ul spacing="normal">
                  <li>Let <tt>w = [seed_i[j-1], wire_i[j-1,0], ..., wire_i[j-1,M_i-1]]</tt>.</li>
                  <li>Let <tt>padded_w = w + Field.zeros(P_i - len(w))</tt>.</li>
                </ul>
                <ul empty="true">
                  <li>
                    <t>NOTE We pad <tt>w</tt> to the nearest power of 2 so that we can use FFT for
interpolating the wire polynomials. Perhaps there is some clever math for
picking <tt>wire_inp</tt> in a way that avoids having to pad.</t>
                  </li>
                </ul>
                <ul spacing="normal">
                  <li>Let <tt>poly_wire_i[j-1]</tt> be the lowest degree polynomial for which
<tt>poly_wire_i[j-1](alpha_i^k) == padded_w[k]</tt> for all <tt>k</tt> in <tt>[P_i]</tt>.</li>
                </ul>
              </li>
              <li>
                <t>Compute the "gadget polynomials". That is, for every <tt>i</tt> in <tt>[H]</tt>:  </t>
                <ul spacing="normal">
                  <li>Let <tt>poly_gadget_i = G_i(poly_wire_i[0], ..., poly_wire_i[L_i-1])</tt>. That
is, evaluate the circuit <tt>G_i</tt> on the wire polynomials for the <tt>i</tt>th
gadget. (Arithmetic is in the ring of polynomials over <tt>Field</tt>.)</li>
                </ul>
              </li>
            </ol>
            <t>The proof is the vector <tt>proof = seed_1 + coeff_1 + ... + seed_H + coeff_H</tt>,
where <tt>coeff_i</tt> is the vector of coefficients of <tt>poly_gadget_i</tt> for each <tt>i</tt> in
<tt>[H]</tt>.</t>
          </section>
          <section anchor="flp-generic-construction-query">
            <name>Query Generation</name>
            <t>On input of <tt>inp</tt>, <tt>proof</tt>, <tt>query_rand</tt>, and <tt>joint_rand</tt>, the verifier message
is generated as follows:</t>
            <ol spacing="normal" type="1"><li>For every <tt>i</tt> in <tt>[H]</tt> create an empty table <tt>wire_i</tt>.</li>
              <li>Partition <tt>proof</tt> into the subvectors <tt>seed_1</tt>, <tt>coeff_1</tt>, ..., <tt>seed_H</tt>,
<tt>coeff_H</tt> defined in <xref target="flp-generic-construction-prove"/>.</li>
              <li>Evaluate <tt>Valid</tt> on input of <tt>inp</tt> and <tt>joint_rand</tt>, recording the inputs of
each gadget in the corresponding table. This step is similar to the prover's
step (3.) except the verifier does not evaluate the gadgets. Instead, it
computes the output of the <tt>k</tt>th call to <tt>G_i</tt> by evaluating
<tt>poly_gadget_i(alpha_i^k)</tt>. Let <tt>v</tt> denote the output of the circuit
evaluation.</li>
              <li>Compute the wire polynomials just as in the prover's step (4.).</li>
              <li>
                <t>Compute the tests for well-formedness of the gadget polynomials. That is, for
every <tt>i</tt> in <tt>[H]</tt>:  </t>
                <ul spacing="normal">
                  <li>Let <tt>t = query_rand[i]</tt>. Check if <tt>t^(P_i) == 1</tt>: If so, then raise
ERR_ABORT and halt. (This prevents the verifier from inadvertently leaking
a gadget output in the verifier message.)</li>
                  <li>Let <tt>y_i = poly_gadget_i(t)</tt>.</li>
                  <li>For each <tt>j</tt> in <tt>[0,L_i)</tt> let <tt>x_i[j-1] = poly_wire_i[j-1](t)</tt>.</li>
                </ul>
              </li>
            </ol>
            <t>The verifier message is the vector <tt>verifier = [v] + x_1 + [y_1] + ... + x_H +
[y_H]</tt>.</t>
          </section>
          <section anchor="decision">
            <name>Decision</name>
            <t>On input of vector <tt>verifier</tt>, the verifier decides if the input is valid as
follows:</t>
            <ol spacing="normal" type="1"><li>Parse <tt>verifier</tt> into <tt>v</tt>, <tt>x_1</tt>, <tt>y_1</tt>, ..., <tt>x_H</tt>, <tt>y_H</tt> as defined in
<xref target="flp-generic-construction-query"/>.</li>
              <li>
                <t>Check for well-formedness of the gadget polynomials. For every <tt>i</tt> in <tt>[H]</tt>:  </t>
                <ul spacing="normal">
                  <li>Let <tt>z = G_i(x_i)</tt>. That is, evaluate the circuit <tt>G_i</tt> on <tt>x_i</tt> and set
<tt>z</tt> to the output.</li>
                  <li>If <tt>z != y_i</tt>, then return <tt>False</tt> and halt.</li>
                </ul>
              </li>
              <li>Return <tt>True</tt> if <tt>v == 0</tt> and <tt>False</tt> otherwise.</li>
            </ol>
          </section>
          <section anchor="encoding">
            <name>Encoding</name>
            <t>The FLP encoding and truncation methods invoke <tt>Valid.encode</tt> and
<tt>Valid.truncate</tt> in the natural way.</t>
          </section>
        </section>
      </section>
      <section anchor="prio3-instantiations">
        <name>Instantiations</name>
        <t>This section specifies instantiations of Prio3 for various measurement types.
Each uses <tt>FlpGeneric</tt> as the FLP (<xref target="flp-generic"/>) and is determined by a
validity circuit (<xref target="flp-generic-valid"/>) and a PRG (<xref target="prg"/>). Test vectors for
each can be found in <xref target="test-vectors"/>.</t>
        <ul empty="true">
          <li>
            <t>NOTE Reference implementations of each of these VDAFs can be found in
https://github.com/cjpatton/vdaf/blob/main/poc/vdaf_prio3.sage.</t>
          </li>
        </ul>
        <section anchor="prio3aes128count">
          <name>Prio3Aes128Count</name>
          <t>Our first instance of Prio3 is for a simple counter: Each measurement is either
one or zero and the aggregate result is the sum of the measurements.</t>
          <t>This instance uses <tt>PrgAes128</tt> (<xref target="prg-aes128"/>) as its PRG. Its validity
circuit, denoted <tt>Count</tt>, uses <tt>Field64</tt> (<xref target="field64"/>) as its finite field. Its
gadget, denoted <tt>Mul</tt>, is the degree-2, arity-2 gadget defined as</t>
          <artwork><![CDATA[
def Mul(x, y):
    return x * y
]]></artwork>
          <t>The validity circuit is defined as</t>
          <artwork><![CDATA[
def Count(inp: Vec[Field64]):
    return Mul(inp[0], inp[0]) - inp[0]
]]></artwork>
          <t>The measurement is encoded as a singleton vector in the natural way. The
parameters for this circuit are summarized below.</t>
          <t><br/></t>
          <table>
            <name>Parameters of validity circuit Count.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">
                  <tt>[Mul]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[1]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>INPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>0</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>Unsigned</tt>, in range <tt>[0,2)</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field64</tt> (<xref target="field64"/>)</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section anchor="prio3-sum">
          <name>Prio3Aes128Sum</name>
          <t>The next instance of Prio3 supports summing of integers in a pre-determined
range. Each measurement is an integer in range <tt>[0, 2^bits)</tt>, where <tt>bits</tt> is an
associated parameter.</t>
          <t>This instance of Prio3 uses <tt>PrgAes128</tt> (<xref target="prg-aes128"/>) as its PRG.
Its validity circuit, denoted <tt>Sum</tt>, uses <tt>Field128</tt> (<xref target="field128"/>) as its
finite field. The measurement is encoded as a length-<tt>bits</tt> vector of field
elements, where the <tt>l</tt>th element of the vector represents the <tt>l</tt>th bit of the
summand:</t>
          <artwork><![CDATA[
def encode(Sum, measurement: Integer):
    if 0 > measurement or measurement >= 2^Sum.INPUT_LEN:
        raise ERR_INPUT

    encoded = []
    for l in range(Sum.INPUT_LEN):
        encoded.append(Sum.Field((measurement >> l) & 1))
    return encoded

def truncate(Sum, inp):
    decoded = Sum.Field(0)
    for (l, b) in enumerate(inp):
        w = Sum.Field(1 << l)
        decoded += w * b
    return [decoded]
]]></artwork>
          <t>The validity circuit checks that the input comprised of ones and zeros. Its
gadget, denoted <tt>Range2</tt>, is the degree-2, arity-1 gadget defined as</t>
          <artwork><![CDATA[
def Range2(x):
    return x^2 - x
]]></artwork>
          <t>The validity circuit is defined as</t>
          <artwork><![CDATA[
def Sum(inp: Vec[Field128], joint_rand: Vec[Field128]):
    out = Field128(0)
    r = joint_rand[0]
    for x in inp:
        out += r * Range2(x)
        r *= joint_rand[0]
    return out
]]></artwork>
          <t><br/></t>
          <table>
            <name>Parameters of validity circuit Sum.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">
                  <tt>[Range2]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[bits]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>INPUT_LEN</tt></td>
                <td align="left">
                  <tt>bits</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>Unsigned</tt>, in range <tt>[0, 2^bits)</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="field128"/>)</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section anchor="prio3aes128histogram">
          <name>Prio3Aes128Histogram</name>
          <t>This instance of Prio3 allows for estimating the distribution of the
measurements by computing a simple histogram. Each measurement is an arbitrary
integer and the aggregate result counts the number of measurements that fall in
a set of fixed buckets.</t>
          <t>This instance of Prio3 uses <tt>PrgAes128</tt> (<xref target="prg-aes128"/>) as its PRG. Its
validity circuit, denoted <tt>Histogram</tt>, uses <tt>Field128</tt> (<xref target="field128"/>) as its
finite field. The measurement is encoded as a one-hot vector representing the
bucket into which the measurement falls (let <tt>bucket</tt> denote a sequence of
monotonically increasing integers):</t>
          <artwork><![CDATA[
def encode(Histogram, measurement: Integer):
    boundaries = buckets + [Infinity]
    encoded = [Field128(0) for _ in range(len(boundaries))]
    for i in range(len(boundaries)):
        if measurement <= boundaries[i]:
            encoded[i] = Field128(1)
            return encoded

def truncate(Histogram, inp: Vec[Field128]):
    return inp
]]></artwork>
          <t>The validity circuit uses <tt>Range2</tt> (see <xref target="prio3-sum"/>) as its single gadget. It
checks for one-hotness in two steps, as follows:</t>
          <artwork><![CDATA[
def Histogram(inp: Vec[Field128],
              joint_rand: Vec[Field128],
              num_shares: Unsigned):
    # Check that each bucket is one or zero.
    range_check = Field128(0)
    r = joint_rand[0]
    for x in inp:
        range_check += r * Range2(x)
        r *= joint_rand[0]

    # Check that the buckets sum to 1.
    sum_check = -Field128(1) * Field128(num_shares).inv()
    for b in inp:
        sum_check += b

    out = joint_rand[1]   * range_check + \
          joint_rand[1]^2 * sum_check
    return out
]]></artwork>
          <t>Note that this circuit depends on the number of shares into which the input is
sharded. This is provided to the FLP by Prio3.</t>
          <t><br/></t>
          <table>
            <name>Parameters of validity circuit Histogram.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">
                  <tt>GADGETS</tt></td>
                <td align="left">
                  <tt>[Range2]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[buckets + 1]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>INPUT_LEN</tt></td>
                <td align="left">
                  <tt>buckets + 1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>buckets + 1</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>JOINT_RAND_LEN</tt></td>
                <td align="left">
                  <tt>2</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Measurement</tt></td>
                <td align="left">
                  <tt>Integer</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="field128"/>)</td>
              </tr>
            </tbody>
          </table>
        </section>
      </section>
    </section>
    <section anchor="poplar1">
      <name>Poplar1</name>
      <ul empty="true">
        <li>
          <t>NOTE The spec for Poplar1 is still a work-in-progress. A partial
implementation can be found at
https://github.com/abetterinternet/libprio-rs/blob/main/src/vdaf/poplar1.rs.
The verification logic is nearly complete, however as of this draft the code
is missing the IDPF. An implementation of the IDPF can be found at
https://github.com/google/distributed_point_functions/.</t>
        </li>
      </ul>
      <t>This section specifies Poplar1, a VDAF for the following task. Each Client holds
a <tt>BITS</tt>-bit string and the Aggregators hold a set of <tt>l</tt>-bit strings, where <tt>l
&lt;= BITS</tt>. We will refer to the latter as the set of "candidate prefixes". The
Aggregators' goal is to count how many inputs are prefixed by each candidate
prefix.</t>
      <t>This functionality is the core component of Poplar <xref target="BBCGGI21"/>. At a high level,
the protocol works as follows.</t>
      <ol spacing="normal" type="1"><li>Each Clients runs the input-distribution algorithm on its <tt>n</tt>-bit string and
sends an input share to each Aggregator.</li>
        <li>The Aggregators agree on an initial set of candidate prefixes, say <tt>0</tt> and
<tt>1</tt>.</li>
        <li>The Aggregators evaluate the VDAF on each set of input shares and aggregate
the recovered output shares. The aggregation parameter is the set of
candidate prefixes.</li>
        <li>The Aggregators send their aggregate shares to the Collector, who combines
them to recover the counts of each candidate prefix.</li>
        <li>Let <tt>H</tt> denote the set of prefixes that occurred at least <tt>t</tt> times. If the
prefixes all have length <tt>BITS</tt>, then <tt>H</tt> is the set of <tt>t</tt>-heavy-hitters.
Otherwise compute the next set of candidate prefixes as follows. For each <tt>p</tt>
in <tt>H</tt>, add add <tt>p || 0</tt> and <tt>p || 1</tt> to the set. Repeat step 3 with the new
set of candidate prefixes.</li>
      </ol>
      <t>Poplar1 is constructed from an "Incremental Distributed Point Function (IDPF)", a
primitive described by <xref target="BBCGGI21"/> that generalizes the notion of a Distributed
Point Function (DPF) <xref target="GI14"/>. Briefly, a DPF is used to distribute the
computation of a "point function", a function that evaluates to zero on every
input except at a programmable "point". The computation is distributed in such a
way that no one party knows either the point or what it evaluates to.</t>
      <t>An IDPF generalizes this "point" to a path on a full binary tree from the root
to one of the leaves. It is evaluated on an "index" representing a unique node
of the tree. If the node is on the path, then function evaluates to to a
non-zero value; otherwise it evaluates to zero. This structure allows an IDPF to
provide the functionality required for the above protocol, while at the same
time ensuring the same degree of privacy as a DPF.</t>
      <t>Our VDAF composes an IDPF with the "secure sketching" protocol of <xref target="BBCGGI21"/>.
This protocol ensures that evaluating a set of input shares on a unique set of
candidate prefixes results in shares of a "one-hot" vector, i.e., a vector that
is zero everywhere except for one element, which is equal to one.</t>
      <section anchor="incremental-distributed-point-functions-idpfs">
        <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 constant
defined by the IDPF. The Client specifies an index <tt>alpha</tt> and a pair of values
<tt>beta</tt>, one for each "level" <tt>1 &lt;= l &lt;= BITS</tt>. The key generation generates two
IDPF keys, one for each Aggregator. When evaluated at index <tt>0 &lt;= x &lt; 2^l</tt>, each
IDPF share returns an additive share of <tt>beta[l]</tt> if <tt>x</tt> is the <tt>l</tt>-bit prefix
of <tt>alpha</tt> and shares of zero otherwise.</t>
        <ul empty="true">
          <li>
            <t>CP What does it mean for <tt>x</tt> to be the <tt>l</tt>-bit prefix of <tt>alpha</tt>? We need to
be a bit more precise here.</t>
          </li>
        </ul>
        <ul empty="true">
          <li>
            <t>CP Why isn't the domain size actually <tt>2^(BITS+1)</tt>, i.e., the number of nodes
in a binary tree of height <tt>BITS</tt> (excluding the root)?</t>
          </li>
        </ul>
        <t>Each <tt>beta[l]</tt> is a pair of elements of a finite field. Each level <bcp14>MAY</bcp14> have
different field parameters. Thus a concrete IDPF specifies associated types
<tt>Field[1]</tt>, <tt>Field[2]</tt>, ..., and <tt>Field[BITS]</tt> defining, respectively, the field
parameters at level 1, level 2, ..., and level <tt>BITS</tt>.</t>
        <t>An IDPF is comprised of the following algorithms (let type <tt>Value[l]</tt> denote
<tt>(Field[l], Field[l])</tt> for each level <tt>l</tt>):</t>
        <ul spacing="normal">
          <li>
            <tt>idpf_gen(alpha: Unsigned, beta: (Value[1], ..., Value[BITS])) -&gt; key:
(IDPFKey, IDPFKey)</tt> is the randomized key-generation algorithm run by the
client. Its inputs are the index <tt>alpha</tt> and the values <tt>beta</tt>. The value of
<tt>alpha</tt> <bcp14>MUST</bcp14> be in range <tt>[0, 2^BITS)</tt>.</li>
          <li>
            <tt>IDPFKey.eval(l: Unsigned, x: Unsigned) -&gt; value: Value[l])</tt> is deterministic,
stateless key-evaluation algorithm run by each Aggregator. It returns the
value corresponding to index <tt>x</tt>. The value of <tt>l</tt> <bcp14>MUST</bcp14> be in <tt>[1, BITS]</tt> and
the value of <tt>x</tt> <bcp14>MUST</bcp14> be in range <tt>[2^(l-1), 2^l)</tt>.</li>
        </ul>
        <t>A concrete IDPF specifies a single associated constant:</t>
        <ul spacing="normal">
          <li>
            <tt>BITS: Unsigned</tt> is the length of each Client input.</li>
        </ul>
        <t>A concrete IDPF also specifies the following associated types:</t>
        <ul spacing="normal">
          <li>
            <tt>Field[l]</tt> for each level <tt>1 &lt;= l &lt;= BITS</tt>. Each defines the same methods and
associated constants as <tt>Field</tt> in <xref target="prio3"/>.</li>
        </ul>
        <t>Note that IDPF construction of <xref target="BBCGGI21"/> uses one field for the inner nodes of
the tree and a different, larger field for the leaf nodes. See <xref target="BBCGGI21"/>,
Section 4.3.</t>
        <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 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.</t>
      </section>
      <section anchor="poplar1-construction">
        <name>Construction</name>
        <t>The VDAF involves two rounds of communication (<tt>ROUNDS == 2</tt>) and is defined for
two Aggregators (<tt>SHARES == 2</tt>).</t>
        <section anchor="setup-1">
          <name>Setup</name>
          <t>The verification parameter is a symmetric key shared by both Aggregators. This
VDAF has no public parameter.</t>
          <figure anchor="poplar1-eval-setup">
            <name>The setup algorithm for poplar1.</name>
            <artwork><![CDATA[
def vdaf_setup():
  k_verify_init = gen_rand(SEED_SIZE)
  return (None, [(0, k_verify_init), (1, k_verify_init)])
]]></artwork>
          </figure>
          <section anchor="client">
            <name>Client</name>
            <t>The client's input is an IDPF index, denoted <tt>alpha</tt>. The 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 secure sketching protocol of <xref target="BBCGGI21"/>. After evaluating
their IDPF key shares on the set of candidate prefixes, the sketching protocol
is used by the Aggregators to verify that they hold shares of a one-hot vector.
In addition, for each level of the tree, the prover generates random elements
<tt>a</tt>, <tt>b</tt>, and <tt>c</tt> and computes</t>
            <artwork><![CDATA[
    A = -2*a + k
    B = a*a + b - k*a + c
]]></artwork>
            <t>and sends additive shares of <tt>a</tt>, <tt>b</tt>, <tt>c</tt>, <tt>A</tt> and <tt>B</tt> to the Aggregators.
Putting everything together, the input-distribution algorithm is defined as
follows. Function <tt>encode_input_share</tt> is defined in <xref target="poplar1-helper-functions"/>.</t>
            <figure anchor="poplar1-mes2inp">
              <name>The input-distribution algorithm for poplar1.</name>
              <artwork><![CDATA[
def measurement_to_input_shares(_, alpha):
  if alpha < 2**BITS: raise ERR_INVALID_INPUT

  # Prepare IDPF values.
  beta = []
  correlation_shares_0, correlation_shares_1 = [], []
  for l in range(1,BITS+1):
    (k, a, b, c) = Field[l].rand_vec(4)

    # Construct values of the form (1, k), where k
    # is a random field element.
    beta += [(1, k)]

    # Create secret shares of correlations to aid
    # the Aggregators' computation.
    A = -2*a+k
    B = a*a + b - a * k + c
    correlation_share = Field[l].rand_vec(5)
    correlation_shares_1.append(correlation_share)
    correlation_shares_0.append(
      [a, b, c, A, B] - correlation_share)

  # Generate IDPF shares.
  (key_0, key_1) = idpf_gen(alpha, beta)

  input_shares = [
    encode_input_share(key_0, correlation_shares_0),
    encode_input_share(key_1, correlation_shares_1),
  ]

  return input_shares
]]></artwork>
            </figure>
            <ul empty="true">
              <li>
                <t>TODO It would be more efficient to represent the shares of <tt>a</tt>, <tt>b</tt>, and <tt>c</tt>
using PRG seeds as suggested in <xref target="BBCGGI21"/>.</t>
              </li>
            </ul>
          </section>
        </section>
        <section anchor="preparation-1">
          <name>Preparation</name>
          <t>The aggregation parameter encodes a sequence of candidate prefixes. When an
Aggregator receives an input share from the Client, it begins by evaluating its
IDPF share on each candidate prefix, recovering a pair of vectors of field
elements <tt>data_share</tt> and <tt>auth_share</tt>, The Aggregators use <tt>auth_share</tt> and the
correlation shares provided by the Client to verify that their <tt>data_share</tt>
vectors are additive shares of a one-hot vector.</t>
          <ul empty="true">
            <li>
              <t>CP Consider adding aggregation parameter as input to <tt>k_verify_rand</tt>
derivation.</t>
            </li>
          </ul>
          <figure anchor="poplar1-prep-state">
            <name>Preparation state for poplar1.</name>
            <artwork><![CDATA[
class PrepState:
  def __init__(verify_param, agg_param, nonce, input_share):
    (self.l, self.candidate_prefixes) = decode_indexes(agg_param)
    (self.idpf_key,
     self.correlation_shares) = decode_input_share(input_share)
    (self.party_id, k_verify_init) = verify_param
    self.k_verify_rand = get_key(k_verify_init, nonce)
    self.step = "ready"

  def next(self, inbound: Optional[Bytes]):
    l = self.l
    (a_share, b_share, c_share,
     A_share, B_share) = correlation_shares[l-1]

    if self.step == "ready" and inbound == None:
      # Evaluate IDPF on candidate prefixes.
      data_share, auth_share = [], []
      for x in self.candidate_prefixes:
        value = self.idpf_key.eval(l, x)
        data_share.append(value[0])
        auth_share.append(value[1])

      # Prepare first sketch verification message.
      r = Prg.expand_into_vec(Field[l], self.k_verify_rand, len(data_share))
      verifier_share_1 = [
         a_share + inner_product(data_share, r),
         b_share + inner_product(data_share, r * r),
         c_share + inner_product(auth_share, r),
      ]

      self.output_share = data_share
      self.step = "sketch round 1"
      return verifier_share_1

    elif self.step == "sketch round 1" and inbound != None:
      verifier_1 = Field[l].decode_vec(inbound)
      verifier_share_2 = [
        (verifier_1[0] * verifier_1[0] \
         - verifier_1[1] \
         - verifier_1[2]) * self.party_id \
        + A_share * verifier_1[0] \
        + B_share
      ]

      self.step = "sketch round 2"
      return Field[l].encode_vec(verifier_share_2)

    elif self.step == "sketch round 2" and inbound != None:
      verifier_2 = Field[l].decode_vec(inbound)
      if verifier_2 != 0: raise ERR_INVALID
      return Field[l].encode_vec(self.output_share)

    else: raise ERR_INVALID_STATE

def prep_shares_to_prep(agg_param, inbound: Vec[Bytes]):
  if len(inbound) != 2:
    raise ERR_INVALID_INPUT

  (l, _) = decode_indexes(agg_param)
  verifier = Field[l].decode_vec(inbound[0]) + \
             Field[l].decode_vec(inbound[1])

  return Field[l].encode_vec(verifier)
]]></artwork>
          </figure>
        </section>
        <section anchor="aggregation-1">
          <name>Aggregation</name>
          <figure anchor="poplar1-out2agg">
            <name>Aggregation algorithm for poplar1.</name>
            <artwork><![CDATA[
def out_shares_to_agg_share(agg_param, output_shares: Vec[Bytes]):
  (l, candidate_prefixes) = decode_indexes(agg_param)
  if len(output_shares) != len(candidate_prefixes):
    raise ERR_INVALID_INPUT

  agg_share = Field[l].zeros(len(candidate_prefixes))
  for output_share in output_shares:
    agg_share += Field[l].decode_vec(output_share)

  return Field[l].encode_vec(agg_share)
]]></artwork>
          </figure>
        </section>
        <section anchor="unsharding-1">
          <name>Unsharding</name>
          <figure anchor="poplar1-agg-output">
            <name>Computation of the aggregate result for poplar1.</name>
            <artwork><![CDATA[
def agg_shares_to_result(agg_param, agg_shares: Vec[Bytes]):
  (l, _) = decode_indexes(agg_param)
  if len(agg_shares) != 2:
    raise ERR_INVALID_INPUT

  agg = Field[l].decode_vec(agg_shares[0]) + \
        Field[l].decode_vec(agg_shares[1]J)

  return Field[l].encode_vec(agg)
]]></artwork>
          </figure>
        </section>
        <section anchor="poplar1-helper-functions">
          <name>Helper Functions</name>
          <ul empty="true">
            <li>
              <t>TODO Specify the following functionalities:</t>
            </li>
          </ul>
          <ul spacing="normal">
            <li>
              <tt>encode_input_share</tt> is used to encode an input share, consisting of an IDPF
key share and correlation shares.</li>
            <li>
              <tt>decode_input_share</tt> is used to decode an input share.</li>
            <li>
              <tt>decode_indexes(encoded: Bytes) -&gt; (l: Unsigned, indexes: Vec[Unsigned])</tt>
decodes a sequence of indexes, i.e., candidate indexes for IDPF evaluation.
The value of <tt>l</tt> <bcp14>MUST</bcp14> be in range <tt>[1, BITS]</tt> and <tt>indexes[i]</tt> <bcp14>MUST</bcp14> be in range
<tt>[2^(l-1), 2^l)</tt> for all <tt>i</tt>. An error is raised if <tt>encoded</tt> cannot be
decoded.</li>
          </ul>
        </section>
      </section>
    </section>
    <section anchor="security">
      <name>Security Considerations</name>
      <ul empty="true">
        <li>
          <t>NOTE: This is a brief outline of the security considerations.  This section
will be filled out more as the draft matures and security analyses are
completed.</t>
        </li>
      </ul>
      <t>VDAFs have two essential security goals:</t>
      <ol spacing="normal" type="1"><li>Privacy: An attacker that controls the network, the Collector, and a subset
of Clients and Aggregators learns nothing about the measurements of honest
Clients beyond what it can deduce from the aggregate result.</li>
        <li>Robustness: An attacker that controls the network and a subset of Clients
cannot cause the Collector to compute anything other than the aggregate of
the measurements of honest Clients.</li>
      </ol>
      <t>Note that, to achieve robustness, it is important to ensure that the
verification parameters distributed to the Aggregators (<tt>verify_params</tt>, see
<xref target="setup"/>) is never revealed to the Clients.</t>
      <t>It is also possible to consider a stronger form of robustness, where the
attacker also controls a subset of Aggregators (see <xref target="BBCGGI19"/>, Section 6.3).
To satisfy this stronger notion of robustness, it is necessary to prevent the
attacker from sharing the verification parameters with the Clients. It is
therefore <bcp14>RECOMMENDED</bcp14> that the Aggregators generate <tt>verify_params</tt> only after a
set of Client inputs has been collected for verification, and re-generate them
for each such set of inputs.</t>
      <t>In order to achieve robustness, the Aggregators <bcp14>MUST</bcp14> ensure that the nonces used
to process the measurements in a batch are all unique.</t>
      <t>A VDAF is the core cryptographic primitive of a protocol that achieves
the above privacy and robustness goals. It is not sufficient on its own,
however. The application will need to assure a few security properties,
for example:</t>
      <ul spacing="normal">
        <li>Securely distributing the long-lived parameters.</li>
        <li>
          <t>Establishing secure channels:
          </t>
          <ul spacing="normal">
            <li>Confidential and authentic channels among Aggregators, and between the
Aggregators and the Collector; and</li>
            <li>Confidential and Aggregator-authenticated channels between Clients and
Aggregators.</li>
          </ul>
        </li>
        <li>Enforcing the non-collusion properties required of the specific VDAF in use.</li>
      </ul>
      <t>In such an environment, a VDAF provides the high-level privacy property
described above: The Collector learns only the aggregate measurement, and
nothing about individual measurements aside from what can be inferred from the
aggregate result.  The Aggregators learn neither individual measurements nor the
aggregate result.  The Collector is assured that the aggregate statistic
accurately reflects the inputs as long as the Aggregators correctly executed
their role in the VDAF.</t>
      <t>On their own, VDAFs do not mitigate 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 inputs for the remaining Clients.  Applications can guard against
these risks by adding additional controls on measurement submission, such as
client authentication and rate limits.</t>
      <t>VDAFs do not inherently provide differential privacy <xref target="Dwo06"/>.  The VDAF approach
to private measurement can be viewed as complementary to differential privacy,
relying on non-collusion instead of statistical noise to protect the privacy of
the inputs.  It is possible that a future VDAF could incorporate differential
privacy features, e.g., by injecting noise before the sharding stage and
removing it after unsharding.</t>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document makes no request of IANA.</t>
    </section>
  </middle>
  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner">
              <organization/>
            </author>
            <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">
              <organization/>
            </author>
            <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="RFC8017">
          <front>
            <title>PKCS #1: RSA Cryptography Specifications Version 2.2</title>
            <author fullname="K. Moriarty" initials="K." role="editor" surname="Moriarty">
              <organization/>
            </author>
            <author fullname="B. Kaliski" initials="B." surname="Kaliski">
              <organization/>
            </author>
            <author fullname="J. Jonsson" initials="J." surname="Jonsson">
              <organization/>
            </author>
            <author fullname="A. Rusch" initials="A." surname="Rusch">
              <organization/>
            </author>
            <date month="November" year="2016"/>
            <abstract>
              <t>This document provides recommendations for the implementation of public-key cryptography based on the RSA algorithm, covering cryptographic primitives, encryption schemes, signature schemes with appendix, and ASN.1 syntax for representing keys and for identifying the schemes.</t>
              <t>This document represents a republication of PKCS #1 v2.2 from RSA Laboratories' Public-Key Cryptography Standards (PKCS) series.  By publishing this RFC, change control is transferred to the IETF.</t>
              <t>This document also obsoletes RFC 3447.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8017"/>
          <seriesInfo name="DOI" value="10.17487/RFC8017"/>
        </reference>
        <reference anchor="RFC4493">
          <front>
            <title>The AES-CMAC Algorithm</title>
            <author fullname="JH. Song" initials="JH." surname="Song">
              <organization/>
            </author>
            <author fullname="R. Poovendran" initials="R." surname="Poovendran">
              <organization/>
            </author>
            <author fullname="J. Lee" initials="J." surname="Lee">
              <organization/>
            </author>
            <author fullname="T. Iwata" initials="T." surname="Iwata">
              <organization/>
            </author>
            <date month="June" year="2006"/>
            <abstract>
              <t>The National Institute of Standards and Technology (NIST) has recently specified the Cipher-based Message Authentication Code (CMAC), which is equivalent to the One-Key CBC MAC1 (OMAC1) submitted by Iwata and Kurosawa.  This memo specifies an authentication algorithm based on CMAC with the 128-bit Advanced Encryption Standard (AES). This new authentication algorithm is named AES-CMAC. The purpose of this document is to make the AES-CMAC algorithm conveniently available to the Internet Community.  This memo provides information for the Internet community.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="4493"/>
          <seriesInfo name="DOI" value="10.17487/RFC4493"/>
        </reference>
      </references>
      <references>
        <name>Informative References</name>
        <reference anchor="AGJOP21" target="https://ia.cr/2021/576">
          <front>
            <title>Prio+: Privacy Preserving Aggregate Statistics via Boolean Shares</title>
            <author initials="S." surname="Addanki">
              <organization/>
            </author>
            <author initials="K." surname="Garbe">
              <organization/>
            </author>
            <author initials="E." surname="Jaffe">
              <organization/>
            </author>
            <author initials="R." surname="Ostrovsky">
              <organization/>
            </author>
            <author initials="A." surname="Polychroniadou">
              <organization/>
            </author>
            <date year="2021"/>
          </front>
        </reference>
        <reference anchor="BBCGGI19" target="https://ia.cr/2019/188">
          <front>
            <title>Zero-Knowledge Proofs on Secret-Shared Data via Fully Linear PCPs</title>
            <author initials="D." surname="Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2019"/>
          </front>
          <seriesInfo name="CRYPTO 2019" value=""/>
        </reference>
        <reference anchor="BBCGGI21" target="https://ia.cr/2021/017">
          <front>
            <title>Lightweight Techniques for Private Heavy Hitters</title>
            <author initials="D." surname="Boneh">
              <organization/>
            </author>
            <author initials="E." surname="Boyle">
              <organization/>
            </author>
            <author initials="H." surname="Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2021"/>
          </front>
          <seriesInfo name="IEEE S&amp;P 2021" value=""/>
        </reference>
        <reference anchor="CGB17" target="https://dl.acm.org/doi/10.5555/3154630.3154652">
          <front>
            <title>Prio: Private, Robust, and Scalable Computation of Aggregate Statistics</title>
            <author initials="H." surname="Corrigan-Gibbs">
              <organization/>
            </author>
            <author initials="D." surname="Boneh">
              <organization/>
            </author>
            <date year="2017"/>
          </front>
          <seriesInfo name="NSDI 2017" value=""/>
        </reference>
        <reference anchor="Dou02" target="https://doi.org/10.1007/3-540-45748-8_24">
          <front>
            <title>The Sybil Attack</title>
            <author initials="J." surname="Douceur">
              <organization/>
            </author>
            <date year="2002"/>
          </front>
          <seriesInfo name="IPTPS 2002" value=""/>
        </reference>
        <reference anchor="Dwo06" target="https://link.springer.com/chapter/10.1007/11787006_1">
          <front>
            <title>Differential Privacy</title>
            <author initials="C." surname="Dwork">
              <organization/>
            </author>
            <date year="2006"/>
          </front>
          <seriesInfo name="ICALP 2006" value=""/>
        </reference>
        <reference anchor="EPK14" target="https://dl.acm.org/doi/10.1145/2660267.2660348">
          <front>
            <title>RAPPOR: Randomized Aggregatable Privacy-Preserving Ordinal Response</title>
            <author initials="Ú." surname="Erlingsson">
              <organization/>
            </author>
            <author initials="V." surname="Pihur">
              <organization/>
            </author>
            <author initials="A." surname="Korolova">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <seriesInfo name="CCS 2014" value=""/>
        </reference>
        <reference anchor="ENPA" target="https://covid19-static.cdn-apple.com/applications/covid19/current/static/contact-tracing/pdf/ENPA_White_Paper.pdf">
          <front>
            <title>Exposure Notification Privacy-preserving Analytics (ENPA) White Paper</title>
            <author>
              <organization/>
            </author>
            <date year="2021"/>
          </front>
        </reference>
        <reference anchor="GI14" target="https://link.springer.com/chapter/10.1007/978-3-642-55220-5_35">
          <front>
            <title>Distributed Point Functions and Their Applications</title>
            <author initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2014"/>
          </front>
          <seriesInfo name="EUROCRYPT 2014" value=""/>
        </reference>
        <reference anchor="OriginTelemetry" target="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="Vad16" target="https://link.springer.com/chapter/10.1007/978-3-319-57048-8_7">
          <front>
            <title>The Complexity of Differential Privacy</title>
            <author initials="S." surname="Vadhan">
              <organization/>
            </author>
            <date year="2016"/>
          </front>
        </reference>
        <reference anchor="I-D.draft-gpew-priv-ppm">
          <front>
            <title>Privacy Preserving Measurement</title>
            <author fullname="Tim Geoghegan">
              <organization>ISRG</organization>
            </author>
            <author fullname="Christopher Patton">
              <organization>Cloudflare</organization>
            </author>
            <author fullname="Eric Rescorla">
              <organization>Mozilla</organization>
            </author>
            <author fullname="Christopher A. Wood">
              <organization>Cloudflare</organization>
            </author>
            <date day="7" month="March" year="2022"/>
            <abstract>
              <t>   There are many situations in which it is desirable to take
   measurements of data which people consider sensitive.  In these
   cases, the entity taking the measurement is usually not interested in
   people's individual responses but rather in aggregated data.
   Conventional methods require collecting individual responses and then
   aggregating them, thus representing a threat to user privacy and
   rendering many such measurements difficult and impractical.  This
   document describes a multi-party privacy preserving measurement (PPM)
   protocol which can be used to collect aggregate data without
   revealing any individual user's data.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-gpew-priv-ppm-01"/>
        </reference>
      </references>
    </references>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>Thanks to David Cook, Henry Corrigan-Gibbs, Armando Faz-Hernandez, Mariana
Raykova, and Christopher Wood for useful feedback on and contributions to the
spec.</t>
    </section>
    <section numbered="false" anchor="test-vectors">
      <name>Test Vectors</name>
      <t>Test vectors cover the generation of input shares and the conversion of input
shares into output shares. Vectors specify the public and verification
parameters, the measurement, the aggregation parameter, the expected input
shares, the prepare messages, and the expected output shares.</t>
      <t>Test vectors are encoded in JSON. Input shares and prepare messages are
represented as hexadecimal streams. To make the tests deterministic,
<tt>gen_rand()</tt> was replaced with a function that returns the requested number of
<tt>0x01</tt> octets.</t>
      <section numbered="false" anchor="prio3aes128count-1">
        <name>Prio3Aes128Count</name>
        <t>For this test, the value of <tt>SHARES</tt> is <tt>2</tt>.</t>
        <artwork><![CDATA[
{
    "public_param": null,
    "verify_params": [
        [
            0,
            "01010101010101010101010101010101"
        ],
        [
            1,
            "01010101010101010101010101010101"
        ]
    ],
    "agg_param": null,
    "prep": [
        {
            "measurement": 1,
            "nonce": "01010101010101010101010101010101",
            "input_shares": [
                "05ac22db75e9b262e9642de9ec1ec37990625f92bf426c52e12c88d7c6e53ed673a3a8a3c7944170e09a52b96573259d",
                "0101010101010101010101010101010101010101010101010101010101010101"
            ],
            "prep_shares": [
                [
                    "48771012eeda70a056cf2fd53022cf7b2edf45090eaa765c2b6cefb7a4abc524",
                    "b788efec11258f61fa53dd238a164da076bfd3f2e4bd966634b24bb64c2fa160"
                ]
            ],
            "out_shares": [
                [
                    408739992155304546
                ],
                [
                    18038004077259279776
                ]
            ]
        }
    ]
}
]]></artwork>
      </section>
      <section numbered="false" anchor="prio3aes128sum">
        <name>Prio3Aes128Sum</name>
        <t>For this test:</t>
        <ul spacing="normal">
          <li>The value of <tt>SHARES</tt> is <tt>2</tt>.</li>
          <li>The value of <tt>bits</tt> is <tt>8</tt>.</li>
        </ul>
        <artwork><![CDATA[
{
    "public_param": null,
    "verify_params": [
        [
            0,
            "01010101010101010101010101010101"
        ],
        [
            1,
            "01010101010101010101010101010101"
        ]
    ],
    "agg_param": null,
    "prep": [
        {
            "measurement": 100,
            "nonce": "01010101010101010101010101010101",
            "input_shares": [
                "05ac22dc75e9b243140aab68977b81a3958c5e79d27edaa00c6b33842dc57724c50207f8c00abf4aaa8ac6a09b5c684d0e59db99532526f582b7524f30d800486ec480e493439573ec2eff20748556c94d7e446de9717ff49ddcfa6fd0ad0a1a9d6de6270bd7ea53092a7e8205b312344bae6f4b6b9456d87695dba9c28514a4e9642deaec1ec35b90625f93bf426c52069601a28cc673c1f0dc7109dee4ca90e0ff309abc86571f3509a1bb33b9e896edd08f984ca3e301e945a8fa1665e19311ae9976f0e8ec34714740fc23cd88500902c8557088fa5acbde164aa52a6e118dff362e6b0b5f784a9c7260312d3b2a1f1a54d8233e4c56bcf5c2f5484fa1460af85fc46fdcdba9bbad76589159c4d6c49c786a160d9dbbd18100c52fe81ba838a57b45d13c764ff9efa7b451235a51384935e831635714ee447bbc02473cb26d536e274c701416619abb2c743ced75c9928483c926ae3ab0f0e3328c79338dd2a496c9468fe9e470aee30b94150f7356e7b19c668175df4f978736e7d3a7c710aa38a446ed62022bcb5ff783d05b428d5a16cdeae0b98268e9ded44a1f7fc734a9baafae0f029dfe79a7c176d58baf68cef928b502b5e59e4fb1925c690745ea06264fa20fa47217120d4343b9a360cad2b5424760e6df18c1214937928e1ef17005cb32815a105f471dff2bbced99f2708ddd70e28bcab86e71dde3d891ea9156b271ab9d025fabcceba3b24c673774e4f474e869c32e818f80c387c1e2197f6612c627287cd9e0a193e70a64ad4546dc0573de3c8b99a0002e67707f58974b8c40bb09f974938b96e14f901084b455f1f4ee3ec4f3b7ce02d42fe0cac452e35b4ff8e5d38e5e99c132b88d122e8ae2b6b97a62206e6f39ba74de00cbb69501010101010101010101010101010101dfed32c071cc6899645ab72c36bd3670",
                "0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010b9e7430cc7a71a356d6bd09d36d1fdb"
            ],
            "prep_shares": [
                [
                    "2bcc0144c56fcf120a7aab22d57cde99fd2ee2301be4c59983d5e68e79f04cd8978b2c4598eafab7b1e8b0af8ba4bda20b9e7430cc7a71a356d6bd09d36d1fdb",
                    "d433febb3a9030d1f58554dd2a8321682eff019a7a26e88471ed622fbd956e5e0af1c04b5573400ed13ae90b325aed4edfed32c071cc6899645ab72c36bd3670"
                ]
            ],
            "out_shares": [
                [
                    178602842237398423407215704739732627917
                ],
                [
                    161679524683540039539650068628168138392
                ]
            ]
        }
    ]
}
]]></artwork>
      </section>
      <section numbered="false" anchor="prio3aes128histogram-1">
        <name>Prio3Aes128Histogram</name>
        <t>For this test:</t>
        <ul spacing="normal">
          <li>The value of <tt>SHARES</tt> is <tt>2</tt>.</li>
          <li>The value of <tt>buckets</tt> is <tt>[1, 10, 100]</tt>.</li>
        </ul>
        <artwork><![CDATA[
{
    "public_param": null,
    "verify_params": [
        [
            0,
            "01010101010101010101010101010101"
        ],
        [
            1,
            "01010101010101010101010101010101"
        ]
    ],
    "agg_param": null,
    "prep": [
        {
            "measurement": 50,
            "nonce": "01010101010101010101010101010101",
            "input_shares": [
                "05ac22dc75e9b243140aab68977b81a3958c5e79d27edaa00c6b33842dc57724c50207f8c00abf4aaa8ac6a09b5c684d0e59db99532526f582b7524f30d80048e9642deaec1ec35b90625f93bf426c52f7ee6bcda3008ff165f5a4dda4bf3382726b89e1455450fb07187cc5b1f4e5b8076d88ca6a52fc73893f179286ed2293f2ba224171991de5cad6ec008bfb16d0990681811a5d149cad81d5177733e8dbabf41f2912442107c7600326e510c0d4a17daddb4577dda42dc84334e51821bb48542744f26726abec63e901571c2841a53f4e93c9bac99d39f87c3773f8173d93465cd2d31f7513516566b9d3aa7a4088d9fb35185b7d6233a9306f40f834c5c3dea78561a999332ab95825a559a131bad2b5cd6a32ed918564d534513aac896d2da35f81b74c226d75f832957209f6df24dc1c9ddf93d4e28a0b30df4a873401010101010101010101010101010101688dfdc50bd6d3a9ecf1613c58b7ced1",
                "0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101014a3951bdbf7a4564e422499e59351ba7"
            ],
            "prep_shares": [
                [
                    "03faf09f79624d05e3a1e17bf1e5117ea6eec816dbd047641506a0c1b1e817fa1ebb27507cea09b00b47e0615ba82ff64a3951bdbf7a4564e422499e59351ba7",
                    "fc050f60869db2de1c5e1e840e1aee830a99091f9a820099b6b9591984046f48b6b6d58ddb1675ef43101aa8773f3025688dfdc50bd6d3a9ecf1613c58b7ced1"
                ]
            ],
            "out_shares": [
                [
                    7539922107207114695252505926366364067,
                    198783809130402957557687312006462666532,
                    261868461448231140209796284667530078285,
                    19075760356742656327154126012204712008
                ],
                [
                    332742444813731348251613267441534402142,
                    141498557790535505389178461361438099677,
                    78413905472707322737069488700370687925,
                    321206606564195806619711647355696054201
                ]
            ]
        }
    ]
}
]]></artwork>
      </section>
    </section>
  </back>
  <!-- ##markdown-source:
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
/Ypw7x+7XedMcAyUCljhwqmX26GsTeXHgvq0GXFDXqWJpB2p+fexcvrud6uT
M+8Y1PIQzsN+xUUi9m2bMzv5uSQIWl6yWZ4ucLRLc+rVfvGiZKTrUYtLirjI
lj89pmenKyBfkd/+Vfn+VSeeyx5NiVh9tWqsSe0Pldznm9adPhIP3TsdiQJ4
/+s3X31J4Hwkm+OntEB6zl3olv4cXItODn5JwfPrqwJ6TRXtm7727LF29vRR
yvjTOUeREvUCsYtXFyGhycb6j/f2LTLEJ/3HpfPujc1T9j3jYPUY+OuRPnrj
KNNbdebT6fBJ6uVc9n28iOmJn08PBQ/bi7pGoU76fPd44uQhunJx0VfGTlaR
Br46rBz9c/Umnq3PLjlh/P0/J/Pli1NP1k3yn9/kZtHwyfxGdT0yUofVgN6t
H7fQbVx23JkWs+Dz+3t1dOMyXWf1+MM4dUhC5Gh18VEYUbxRIhdfEi9JWu+Z
Ebp6EasSJmlRuEjOZZtM0bJkY2WQwQWZrFeKW1aYD1pEb7SVQvt8cnzMzAfI
9sNlfzSls6jfN+Sbn7TblLMWbQsgbbAsMG1SFTVryYRI1UZRclWaeVZCsEYn
EU0qNdqgQoRc1C0Dbe1G61ypECcX2lXDa9AyZyFd4EblwKyJNcsqiorZG2Ok
ikLFaFQSFZewkxvNfvve4e/eP+G3j14xZ6X3XnCNASutzM2n3hzf7W1xx6Rj
TDFroQDCemtvaW1z+28/dmPa/NjzV28cVfoBUNQi17+9F42Ov58PGH3qfsOq
n4pV7HiEHx+tUkcrJbliIUTjoGPR8SC9dkkX67OwMOPAWDJRSgdESxrqqJJm
gtnqEmMBiBYCoCuZwHzUyTiVWQFkRe81sEuYqp0AMApVJcuk0s6UpBwrykuF
Z1lZkii1oknlNADDq2yLUgb4abmtVfmcUw2mZhbwhwef8Z0RlkVcCCBgXgRb
nGA6Si6kUjEUU1U00SttsrPGaxA/n4TTXAU10Dl0dNZxoLOc0JkZbxgPwqUE
ZE68MsiKM59LUSkAu1jFWDwQywGgeZUAtMAjZBR9cd6UnJmr3uFiWSTjBd0I
jnDI6MK95DwU762prDh0QFmurGI1CZmyc5oBHuEetLbM4S5MVswFMBfgEoIp
nLuM58PJmMiirtYpDM0KwzD4LKMIvPKgVXZCSnRYm5gqkLZq5RQ6oQwL1ema
FCSaSC4xhgwwdp5rn1Q2SaE9Zwg3MyYyZu6gnxBMLY7H4IC62kalM4fDMqpW
X2qgDyB8HTSHqnipi5PcSMhHQWzKxpiYUBAn/CP8gSnCqmQZV5AKhyyjSFZJ
EDCrEyDUKSeTFyYUGSKDpKTEfFgPPQTuB+VJT4yr8LEKjqZAzphtrlm1Upti
I/fJGMethsOp3gKZ8WmWwdJUhoAxQMXgegU8U0yQIwQpM1RICZc1xp5IQ9Co
E8YVzH1WCpK1NVkJgccQKr6uTPhcYStol1sMzMVQjYNPwxAi7CRqGENRFf0R
sA4PJdclQOEgtyBYDcoKbrlgWcEaog/SsBQy7lOQlmHF5Mpd4oJDphaNFl4q
GALTKUIiHD1lukKFoBMCMi7Z+wrTgJQyeAQ6kUKExeGCXGTGHJeAeTZRWB6i
zwyaD0VOJQaojiKFt1ahw1DJ4oxPUmDSXXUsSYcxFsG9rZgykWCBAh9lX2CU
XhZMA5Q0k9/LicGu8cDkgANAEAZttRagAS2zKrqkWIzMY2IwLFwDtcYsAc6c
gh7pyiu0BsAA0Ig2FSaygvZBMkmBPcFmoXWu6CzxF2wpcSkiCBUX6G0ogkzf
BiNgykACidmyKhfoMCiB1/chKiY0S5GY5QAA54EWOkQrkjQxS2PZx2Bj9/4A
WmAfLCUbMHPQ8YzeAJOkybzm+FHYHAwjwUIJQ2qqUNJg4SjgOjSmHWKvGURP
AOEi4Yz3MCBdYC3WV6aAZTA7mLXS3hVYS4RRFhcJfWIAT4P63zeoO9ggbEXW
AsAFGMOpcGiVBuABF5wU3DhyJwygYoMwxTlYBxm6qOCGwAYNfa08MRUBsVIx
VgBkQGQGg9IBdl7uVYBfg01yQDADDgohwSrxL7oKrIBXAIp6xAWwP8/tL6CY
hhvr4ZiNkxpigC+WiDgYM84AWQCe0kkv/jes83Bq78fhnv2owH4BpSpwRv+x
b39joj+Rier/IyJ6HxGstoBkpRwkA6Gr3OiqA3AG6FXRD/g/E52H6wL6gHlE
AAYcYtKR3JeODmEpCF0KBsyNeIPzEr4bThzEQwj8ImIQAgE/957nouH4wY3x
rAi+YACE6BCcL/giuBZIWciOZ82ttWB2DtQNHeVVeC6UEpyB2hiYMTBPc5bA
KAK3OeQMj2ot9Rpyc4BO9I07AcIKvq1Aw1QVBkMJsSQjgYPAGA6urPBYiYF4
ELEYQMqy9BXjA0GQFcxKZhB4xPAZrBPECLxPQ0IGrhc0C9iLcNhlXyM+djpa
ILAEYEsGas6qk5i9BIoQrNMGnN6D2gkwEkwSOKQGoZbgmkSEUjYBLCR7NINg
X0sQTTwggWnj0fAa6EwEmRQglha/SIGgQoBcgDoJlRNPCCAwqwB24QJQnoES
BkfQf49GGwwAHFkj0DAYky9wggakFywPpCQfa/wHGe8v/VFkFjzmWCFhyKPA
QSjvoemQM3jORyECTNZQIVHrDSTKNEg5L9zGyqFKHEGYKSXBZWR4b7BW4uEw
w8TJ4SOEw8Xg91ZDQwtZJ2NR2cIM14gmRK3m3kHdQQQqeCarhoGo5ghL5oAL
PFKxghALAQiDXjHPq8djEFZ54oXac3hThuhHOfxOnB0mAleoSwUEIfCDbkDD
JajxvQrwaxABC7fsBdk3wI4jfoPPxg/TCI+kwR/FjL1dQBgpohoHEUimGNkF
KI+B6oPLMaMQhSAkleL2m4XhDihqQAARSuLBAFtPGoDPIC1gonWIqO96MrN4
FAOnswBTbSQCDq04wlSQdCgJ9cD9fPICsEC7Cl3joEdcoouapgZIpqB+UqG3
XN0xMgSdylOAbT3TUkOUgGbwLYxVYrgkMI9w5fabcRmXuA+BGwIaKQQiJma8
cg5RGf2vA8LfIRWwU4QkhkEeigPqGMW+mFMDSqc1vXYAIDP+MynXfwHdY4Rz
eK0BAA==

-->

</rfc>
