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

<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
measurement that would result in an invalid 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>
    <?line 199?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>[TO BE REMOVED BY RFC EDITOR: The source for this draft and and the reference
implementation can be found at https://github.com/cfrg/draft-irtf-cfrg-vdaf.]</t>
      <t>The ubiquity of the Internet makes it an ideal platform for measurement of
large-scale phenomena, whether public health trends or the behavior of computer
systems at scale. There is substantial overlap, however, between information
that is valuable to measure and information that users consider private.</t>
      <t>For example, consider an application that provides health information to users.
The operator of an application might want to know which parts of their
application are used most often, as a way to guide future development of the
application.  Specific users' patterns of usage, though, could reveal sensitive
things about them, such as which users are researching a given health condition.</t>
      <t>In many situations, the measurement collector is only interested in aggregate
statistics, e.g., which portions of an application are most used or what
fraction of people have experienced a given disease.  Thus systems that provide
aggregate statistics while protecting individual measurements can deliver the
value of the measurements while protecting users' privacy.</t>
      <t>This problem is often formulated in terms of differential privacy (DP)
<xref target="Dwo06"/>. Roughly speaking, a data aggregation system that is differentially
private ensures that the degree to which any individual measurement influences
the value of the aggregate result can be precisely controlled. For example, in
systems like RAPPOR <xref target="EPK14"/>, each user samples noise from a well-known
distribution and adds it to their measurement before submitting to the
aggregation server. The aggregation server then adds up the noisy measurements,
and because it knows the distribution from which the noise was sampled, it can
estimate the true sum with reasonable accuracy.</t>
      <t>However, even when noise is added to the measurements, collecting them in the
clear still reveals a significant amount of information to the collector. On
the one hand, depending on the "amount" of noise a client adds to its
measurement, it may be possible for a curious collector to make a reasonable
guess of the measurement's true value. On the other hand, the more noise the
clients add, the less reliable will be the server's estimate of the output.
Thus systems relying solely on a DP mechanism 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 (MPC): No participant in the protocol should learn
anything about an individual measurement beyond what it can deduce from the
differentially private aggregate <xref target="MPRV09"/>. In this document, we describe
Verifiable Distributed Aggregation Functions (VDAFs) as a general class of
delegated MPC protocols that can be used to 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
measurement is ever accessible to any party besides the client that submitted
it. VDAFs can also be composed with various DP mechanisms, thereby ensuring the
aggregate result does not leak too much information about any one measurmment.
At the same time, VDAFs are "verifiable" in the sense that malformed
measurements that would otherwise garble the result of the computation can be
detected and removed from the set of measurements. We refer to this property as
"robustness".</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 requirements, sometimes in
subtle but consequential ways. This document therefore has two important goals:</t>
      <ol spacing="normal" type="1"><li>
          <t>Providing higher-level protocols like <xref target="DAP"/> with
a simple, uniform interface for accessing privacy-preserving measurement
schemes, documenting relevant operational and security requirements, and
specifying constraints for safe usage:  </t>
          <ol spacing="normal" type="1"><li>
              <t>General patterns of communications among the various actors involved in
the system (clients, aggregation servers, and the collector of the
aggregate result);</t>
            </li>
            <li>
              <t>Capabilities of a malicious coalition of servers attempting to divulge
information about client measurements; and</t>
            </li>
            <li>
              <t>Conditions that are necessary to ensure that malicious clients cannot
corrupt the computation.</t>
            </li>
          </ol>
        </li>
        <li>
          <t>Providing cryptographers with design criteria that provide a clear
deployment roadmap for new constructions.</t>
        </li>
      </ol>
      <t>This document also specifies two concrete VDAF schemes, each based on a protocol
from the literature.</t>
      <ul spacing="normal">
        <li>
          <t>The 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>
              <t>Each client shards its measurement into a sequence of additive shares and
distributes the shares among the aggregation servers.</t>
            </li>
            <li>
              <t>Next, each server adds up its shares locally, resulting in an additive
share of the aggregate.</t>
            </li>
            <li>
              <t>Finally, the aggregation servers send their aggregate shares to the data
collector, who combines them to obtain the aggregate result.</t>
            </li>
          </ol>
          <t>
The difficult part of this system is ensuring that the servers hold shares of
a valid, aggregatable value, e.g., the measurement 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 strings that occur at least <tt>t</tt> times. The
core primitive used in their protocol is a specialized 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 string. 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 string.  </t>
          <t>
In <xref target="poplar1"/> we describe a VDAF called Poplar1 that implements this
functionality.</t>
        </li>
      </ul>
      <t>Finally, perhaps the most complex aspect of schemes like Prio3 and Poplar1 is
the process by which the client-generated measurements are prepared for
aggregation. Because these constructions are based on secret sharing, the
servers will be required to exchange some amount of information in order to
verify the measurement is valid and can be aggregated. Depending on the
construction, this process may require multiple round trips over the network.</t>
      <t>There are applications in which this verification step may not be necessary,
e.g., when the client's software is run a trusted execution environment. To
support these applications, this document also defines Distributed Aggregation
Functions (DAFs) as a simpler class of protocols that aim to provide the same
privacy guarantee as VDAFs but fall short of being verifiable.</t>
      <ul empty="true">
        <li>
          <t>OPEN ISSUE Decide if we should give one or two example DAFs. There are natural
variants of Prio3 and Poplar1 that might be worth describing.</t>
        </li>
      </ul>
      <t>The remainder of this document is organized as follows: <xref target="overview"/> gives a
brief overview of DAFs and VDAFs; <xref target="daf"/> defines the syntax for DAFs; <xref target="vdaf"/>
defines the syntax for VDAFs; <xref target="prelim"/> defines various functionalities that
are common to 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 anchor="change-log">
        <name>Change Log</name>
        <t>(*) Indicates a change that breaks wire compatibility with the previous draft.</t>
        <t>09:</t>
        <ul spacing="normal">
          <li>
            <t>Poplar1: Make prefix tree traversal stricter by requiring each node to be a
child of a node that was already visited. This change is intended to make it
harder for a malicious Aggregator to steer traversal towards
non-heavy-hitting measurements.</t>
          </li>
          <li>
            <t>Prio3: Add more explicit guidance for choosing the field size.</t>
          </li>
          <li>
            <t>IDPF: Define extractability and clarify (un)safe usage of intermediate prefix
counts. Accordingly, add text ensuring public share consistency to security
considerations.</t>
          </li>
        </ul>
        <t>08:</t>
        <ul spacing="normal">
          <li>
            <t>Poplar1: Bind the report nonce to the authenticator vector programmed into
the IDPF. (*)</t>
          </li>
          <li>
            <t>IdpfPoplar: Modify <tt>extend()</tt> by stealing each control bit from its
corresponding seed. This improves performance by reducing the number of AES
calls per level from 3 to 2. The cost is a slight reduction in the concrete
privacy bound. (*)</t>
          </li>
          <li>
            <t>Prio3: Add support for generating and verifying mutliple proofs per
measurement. This enables a trade-off between communication cost and runtime:
if more proofs are used, then a smaller field can be used without impacting
robustness. (*)</t>
          </li>
          <li>
            <t>Replace SHAKE128 with TurboSHAKE128. (*)</t>
          </li>
        </ul>
        <t>07:</t>
        <ul spacing="normal">
          <li>
            <t>Rename PRG to XOF ("eXtendable Output Function"). Accordingly, rename PrgSha3
to XofShake128 and PrgFixedKeyAes128 to XofFixedKeyAes128. "PRG" is a misnomer
since we don't actually treat this object as a pseudorandom generator in
existing security analysis.</t>
          </li>
          <li>
            <t>Replace cSHAKE128 with SHAKE128, re-implementing domain separation for the
customization string using a simpler scheme. This change addresses the
reality that implementations of cSHAKE128 are less common. (*)</t>
          </li>
          <li>
            <t>Define a new VDAF, called Prio3SumVec, that generalizes Prio3Sum to a vector
of summands.</t>
          </li>
          <li>
            <t>Prio3Histogram: Update the codepoint and use the parallel sum optimization
introduced by Prio3SumVec to reduce the proof size. (*)</t>
          </li>
          <li>
            <t>Daf, Vdaf: Rename interface methods to match verbiage in the draft.</t>
          </li>
          <li>
            <t>Daf: Align with Vdaf by adding a nonce to <tt>shard()</tt> and <tt>prep()</tt>.</t>
          </li>
          <li>
            <t>Vdaf: Have <tt>prep_init()</tt> compute the first prep share. This change is
intended to simplify the interface by making the input to <tt>prep_next()</tt> not
optional.</t>
          </li>
          <li>
            <t>Prio3: Split sharding into two auxiliary functions, one for sharding with
joint randomness and another without. This change is intended to improve
readability.</t>
          </li>
          <li>
            <t>Fix bugs in the ping-pong interface discovered after implementing it.</t>
          </li>
        </ul>
        <t>06:</t>
        <ul spacing="normal">
          <li>
            <t>Vdaf: Define a wrapper interface for preparation that is suitable for the
"ping-pong" topology in which two Aggregators exchange messages over a
request/response protocol, like HTTP, and take turns executing the
computation until input from the peer is required.</t>
          </li>
          <li>
            <t>Prio3Histogram: Generalize the measurement type so that the histogram can be
used more easily with discrete domains. (*)</t>
          </li>
          <li>
            <t>Daf, Vdaf: Change the aggregation parameter validation algorithm to take the
set of previous parameters rather than a list. (The order of the parameters
is irrelevant.)</t>
          </li>
          <li>
            <t>Daf, Vdaf, Idpf: Add parameter <tt>RAND_SIZE</tt> that specifies the number of
random bytes consumed by the randomized algorithm (<tt>shard()</tt> for Daf and Vdaf
and <tt>gen()</tt> for Idpf).</t>
          </li>
        </ul>
        <t>05:</t>
        <ul spacing="normal">
          <li>
            <t>IdpfPoplar: Replace PrgSha3 with PrgFixedKeyAes128, a fixed-key mode for
AES-128 based on a construction from <xref target="GKWWY20"/>. This change is intended to
improve performance of IDPF evaluation. Note that the new PRG is not suitable
for all applications. (*)</t>
          </li>
          <li>
            <t>Idpf: Add a binder string to the key-generation and evaluation algorithms.
This is used to plumb the nonce generated by the Client to the PRG.</t>
          </li>
          <li>
            <t>Plumb random coins through the interface of randomized algorithms.
Specifically, add a random input to (V)DAF sharding algorithm and IDPF
key-generation algorithm and require implementations to specify the length of
the random input. Accordingly, update Prio3, Poplar1, and IdpfPoplar to match
the new interface. This change is intended to improve coverage of test
vectors.</t>
          </li>
          <li>
            <t>Use little-endian byte-order for field element encoding. (*)</t>
          </li>
          <li>
            <t>Poplar1: Move the last step of sketch evaluation from <tt>prep_next()</tt> to
<tt>prep_shares_to_prep()</tt>.</t>
          </li>
        </ul>
        <t>04:</t>
        <ul spacing="normal">
          <li>
            <t>Align security considerations with the security analysis of <xref target="DPRS23"/>.</t>
          </li>
          <li>
            <t>Vdaf: Pass the nonce to the sharding algorithm.</t>
          </li>
          <li>
            <t>Vdaf: Rather than allow the application to choose the nonce length, have each
implementation of the Vdaf interface specify the expected nonce length. (*)</t>
          </li>
          <li>
            <t>Prg: Split "info string" into two components: the "customization string",
intended for domain separation; and the "binder string", used to bind the
output to ephemeral values, like the nonce, associated with execution of a
(V)DAF.</t>
          </li>
          <li>
            <t>Replace PrgAes128 with PrgSha3, an implementation of the Prg interface based
on SHA-3, and use the new scheme as the default. Accordingly, replace
Prio3Aes128Count with Prio3Count, Poplar1Aes128 with Poplar1, and so on. SHA-3
is a safer choice for instantiating a random oracle, which is used in the
analysis of Prio3 of <xref target="DPRS23"/>. (*)</t>
          </li>
          <li>
            <t>Prio3, Poplar1: Ensure each invocation of the Prg uses a distinct
customization string, as suggested by <xref target="DPRS23"/>. This is intended to make
domain separation clearer, thereby simplifying security analysis. (*)</t>
          </li>
          <li>
            <t>Prio3: Replace "joint randomness hints" sent in each input share with "joint
randomness parts" sent in the public share. This reduces communication
overhead when the number of shares exceeds two. (*)</t>
          </li>
          <li>
            <t>Prio3: Bind nonce to joint randomness parts. This is intended to address
birthday attacks on robustness pointed out by <xref target="DPRS23"/>. (*)</t>
          </li>
          <li>
            <t>Poplar1: Use different Prg invocations for producing the correlated randomness
for inner and leaf nodes of the IDPF tree. This is intended to simplify
implementations. (*)</t>
          </li>
          <li>
            <t>Poplar1: Don't bind the candidate prefixes to the verifier randomness. This is
intended to improve performance, while not impacting security. According to
the analysis of <xref target="DPRS23"/>, it is necessary to restrict Poplar1 usage such
that no report is aggregated more than once at a given level of the IDPF tree;
otherwise, attacks on privacy may be possible. In light of this restriction,
there is no added benefit of binding to the prefixes themselves. (*)</t>
          </li>
          <li>
            <t>Poplar1: During preparation, assert that all candidate prefixes are unique
and appear in order. Uniqueness is required to avoid erroneously rejecting a
valid report; the ordering constraint ensures the uniqueness check can be
performed efficiently. (*)</t>
          </li>
          <li>
            <t>Poplar1: Increase the maximum candidate prefix count in the encoding of the
aggregation parameter. (*)</t>
          </li>
          <li>
            <t>Poplar1: Bind the nonce to the correlated randomness derivation. This is
intended to provide defense-in-depth by ensuring the Aggregators reject the
report if the nonce does not match what the Client used for sharding. (*)</t>
          </li>
          <li>
            <t>Poplar1: Clarify that the aggregation parameter encoding is <bcp14>OPTIONAL</bcp14>.
Accordingly, update implementation considerations around cross-aggregation
state.</t>
          </li>
          <li>
            <t>IdpfPoplar: Add implementation considerations around branching on the values
of control bits.</t>
          </li>
          <li>
            <t>IdpfPoplar: When decoding the the control bits in the public share, assert
that the trailing bits of the final byte are all zero. (*)</t>
          </li>
        </ul>
        <t>03:</t>
        <ul spacing="normal">
          <li>
            <t>Define codepoints for (V)DAFs and use them for domain separation in Prio3 and
Poplar1. (*)</t>
          </li>
          <li>
            <t>Prio3: Align joint randomness computation with revised paper <xref target="BBCGGI19"/>.
This change mitigates an attack on robustness. (*)</t>
          </li>
          <li>
            <t>Prio3: Remove an intermediate PRG evaluation from query randomness generation.
(*)</t>
          </li>
          <li>
            <t>Add additional guidance for choosing FFT-friendly fields.</t>
          </li>
        </ul>
        <t>02:</t>
        <ul spacing="normal">
          <li>
            <t>Complete the initial specification of Poplar1.</t>
          </li>
          <li>
            <t>Extend (V)DAF syntax to include a "public share" output by the Client and
distributed to all of the Aggregators. This is to accommodate "extractable"
IDPFs as required for Poplar1. (See <xref target="BBCGGI21"/>, Section 4.3 for details.)</t>
          </li>
          <li>
            <t>Extend (V)DAF syntax to allow the unsharding step to take into account the
number of measurements aggregated.</t>
          </li>
          <li>
            <t>Extend FLP syntax by adding a method for decoding the aggregate result from a
vector of field elements. The new method takes into account the number of
measurements.</t>
          </li>
          <li>
            <t>Prio3: Align aggregate result computation with updated FLP syntax.</t>
          </li>
          <li>
            <t>Prg: Add a method for statefully generating a vector of field elements.</t>
          </li>
          <li>
            <t>Field: Require that field elements are fully reduced before decoding. (*)</t>
          </li>
          <li>
            <t>Define new field Field255.</t>
          </li>
        </ul>
        <t>01:</t>
        <ul spacing="normal">
          <li>
            <t>Require that VDAFs specify serialization of aggregate shares.</t>
          </li>
          <li>
            <t>Define Distributed Aggregation Functions (DAFs).</t>
          </li>
          <li>
            <t>Prio3: Move proof verifier check from <tt>prep_next()</tt> to
<tt>prep_shares_to_prep()</tt>. (*)</t>
          </li>
          <li>
            <t>Remove public parameter and replace verification parameter with a
"verification key" and "Aggregator ID".</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="conventions-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>
      <?line -18?>

<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>A variable with type <tt>Bytes</tt> is a byte string. This document defines several
byte-string constants. When comprised of printable ASCII characters, they are
written as Python 3 byte-string literals (e.g., <tt>b'some constant string'</tt>).</t>
      <t>A global constant <tt>VERSION</tt> of type <tt>Unsigned</tt> is defined, which algorithms are
free to use as desired. Its value <bcp14>SHALL</bcp14> be <tt>8</tt>.</t>
      <t>This document describes algorithms for multi-party computations in which the
parties typically communicate over a network. Wherever a quantity is defined
that must be be transmitted from one party to another, this document prescribes
a particular encoding of that quantity as a byte string.</t>
      <ul empty="true">
        <li>
          <t>OPEN ISSUE It might be better to not be prescriptive about how quantities are
encoded on the wire. See issue #58.</t>
        </li>
      </ul>
      <t>Some common functionalities:</t>
      <ul spacing="normal">
        <li>
          <t><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>.</t>
        </li>
        <li>
          <t><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>.</t>
        </li>
        <li>
          <t><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>.</t>
        </li>
        <li>
          <t><tt>concat(parts: Vec[Bytes]) -&gt; Bytes</tt> returns the concatenation of the input
byte strings, i.e., <tt>parts[0] || ... || parts[len(parts)-1]</tt>.</t>
        </li>
        <li>
          <t><tt>front(length: Unsigned, vec: Vec[Any]) -&gt; (Vec[Any], Vec[Any])</tt> splits <tt>vec</tt>
into two vectors, where the first vector is made up of the first <tt>length</tt>
elements of the input. I.e., <tt>(vec[:length], vec[length:])</tt>.</t>
        </li>
        <li>
          <t><tt>xor(left: Bytes, right: Bytes) -&gt; Bytes</tt> returns the bitwise XOR of <tt>left</tt>
and <tt>right</tt>. An exception is raised if the inputs are not the same length.</t>
        </li>
        <li>
          <t><tt>to_be_bytes(val: Unsigned, length: Unsigned) -&gt; Bytes</tt> converts <tt>val</tt> to
big-endian bytes; its value <bcp14>MUST</bcp14> be in range <tt>[0, 2^(8*length))</tt>. Function
<tt>from_be_bytes(encoded: Bytes) -&gt; Unsigned</tt> computes the inverse.</t>
        </li>
        <li>
          <t><tt>to_le_bytes(val: Unsigned, length: Unsigned) -&gt; Bytes</tt> converts <tt>val</tt> to
little-endian bytes; its value <bcp14>MUST</bcp14> be in range <tt>[0, 2^(8*length))</tt>. Function
<tt>from_le_bytes(encoded: Bytes) -&gt; Unsigned</tt> computes the inverse.</t>
        </li>
        <li>
          <t><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.</t>
        </li>
        <li>
          <t><tt>additive_secret_share(vec: Vec[Field], num_shares: Unsigned, field: type)
-&gt; Vec[Vec[Field]]</tt> takes a vector of field elements and returns multiple
vectors of the same length, such that they all add up to the input vector,
and each proper subset of the vectors are indistinguishable from random.</t>
        </li>
      </ul>
    </section>
    <section anchor="overview">
      <name>Overview</name>
      <figure anchor="overall-flow">
        <name>Overall data flow of a (V)DAF</name>
        <artwork><![CDATA[
                 +--------------+
           +---->| Aggregator 0 |----+
           |     +--------------+    |
           |             ^           |
           |             |           |
           |             V           |
           |     +--------------+    |
           | +-->| Aggregator 1 |--+ |
           | |   +--------------+  | |
+--------+-+ |           ^         | +->+-----------+
| Client |---+           |         +--->| Collector |--> Aggregate
+--------+-+                         +->+-----------+
           |            ...          |
           |                         |
           |             |           |
           |             V           |
           |    +----------------+   |
           +--->| Aggregator N-1 |---+
                +----------------+

      Input shares           Aggregate shares
]]></artwork>
      </figure>
      <t>In a DAF- or 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>
          <t>To submit an individual measurement, the Client shards the measurement into
"input shares" and sends one input share to each Aggregator. We sometimes
refer to this sequence of input shares collectively as the Client's "report".</t>
        </li>
        <li>
          <t>The Aggregators refine their input shares into "output shares".
          </t>
          <ul spacing="normal">
            <li>
              <t>Output shares are in one-to-one correspondence with the input shares.</t>
            </li>
            <li>
              <t>Just as each Aggregator receives one input share of each measurement, if
this process succeeds, then each aggregator holds one output share.</t>
            </li>
            <li>
              <t>In VDAFs, Aggregators will need to exchange information among themselves
as part of the validation process.</t>
            </li>
          </ul>
        </li>
        <li>
          <t>Each Aggregator combines the output shares in the batch to compute the
"aggregate share" for that batch, i.e., its share of the desired aggregate
result.</t>
        </li>
        <li>
          <t>The Aggregators submit their aggregate shares to the Collector, who combines
them to obtain the aggregate result over the batch.</t>
        </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, in the case of VDAFs, 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 measurements.  Thus Clients trust Aggregators
not to collude (typically it is required that at least one Aggregator is
honest), and Collectors trust Aggregators to correctly run the protocol.</t>
      <t>Within the bounds of the non-collusion requirements of a given (V)DAF instance,
it is possible for the same entity to play more than one role.  For example, the
Collector could also act as an Aggregator, effectively using the other
Aggregator(s) to augment a basic client-server protocol.</t>
      <t>In this document, we describe the computations performed by the actors in this
system. It is up to the higher-level protocol making use of the (V)DAF to
arrange for the required information to be delivered to the proper actors in the
proper sequence. In general, we assume that all communications are confidential
and mutually authenticated, with the exception that Clients submitting
measurements may be anonymous.</t>
    </section>
    <section anchor="daf">
      <name>Definition of DAFs</name>
      <t>By way of a gentle introduction to VDAFs, this section describes a simpler class
of schemes called Distributed Aggregation Functions (DAFs). Unlike VDAFs, DAFs
do not provide verifiability of the computation. Clients must therefore be
trusted to compute their input shares correctly. Because of this fact, the use
of a DAF is <bcp14>NOT RECOMMENDED</bcp14> for most applications. See <xref target="security"/> for
additional discussion.</t>
      <t>A DAF scheme is used to compute a particular "aggregation function" over a set
of measurements generated by Clients. Depending on the aggregation function, the
Collector might select an "aggregation parameter" and disseminates it to the
Aggregators. The semantics of this parameter is specific to the aggregation
function, but in general it is used to represent the set of "queries" that can
be made on the measurement set. For example, the aggregation parameter is used
to represent the candidate prefixes in Poplar1 <xref target="poplar1"/>.</t>
      <t>Execution of a DAF has four distinct stages:</t>
      <ul spacing="normal">
        <li>
          <t>Sharding - Each Client generates input shares from its measurement and
distributes them among the Aggregators.</t>
        </li>
        <li>
          <t>Preparation - Each Aggregator converts each input share into an output share
compatible with the aggregation function. This computation involves the
aggregation parameter. In general, each aggregation parameter may result in a
different an output share.</t>
        </li>
        <li>
          <t>Aggregation - Each Aggregator combines a sequence of output shares into its
aggregate share and sends the aggregate share to the Collector.</t>
        </li>
        <li>
          <t>Unsharding - The Collector combines the aggregate shares into the aggregate
result.</t>
        </li>
      </ul>
      <t>Sharding and Preparation are done once per measurement. Aggregation and
Unsharding are done over a batch of measurements (more precisely, over the
recovered output shares).</t>
      <t>A concrete DAF specifies an algorithm for the computation needed in each of
these stages. The interface of each algorithm is defined in the remainder of
this section. In addition, a concrete DAF defines the associated constants and
types enumerated in the following table.</t>
      <table anchor="daf-param">
        <name>Constants and types defined by each concrete DAF.</name>
        <thead>
          <tr>
            <th align="left">Parameter</th>
            <th align="left">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>ID</tt></td>
            <td align="left">Algorithm identifier for this DAF. A 32-bit, unsigned integer.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>SHARES</tt></td>
            <td align="left">Number of input shares into which each measurement is sharded.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>NONCE_SIZE</tt></td>
            <td align="left">Size of the nonce passed by the application.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>RAND_SIZE</tt></td>
            <td align="left">Size of the random byte string passed to sharding algorithm.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>Measurement</tt></td>
            <td align="left">Type of each measurement.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PublicShare</tt></td>
            <td align="left">Type of each public share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>InputShare</tt></td>
            <td align="left">Type of each input share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggParam</tt></td>
            <td align="left">Type of aggregation parameter.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>OutShare</tt></td>
            <td align="left">Type of each output share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggShare</tt></td>
            <td align="left">Type of the aggregate share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggResult</tt></td>
            <td align="left">Type of the aggregate result.</td>
          </tr>
        </tbody>
      </table>
      <t>These types define the inputs and outputs of DAF methods at various stages of
the computation. Some of these values need to be written to the network in
order to carry out the computation. In particular, it is <bcp14>RECOMMENDED</bcp14> that
concrete instantiations of the <tt>Daf</tt> interface specify a method of encoding the
<tt>PublicShare</tt>, <tt>InputShare</tt>, and <tt>AggShare</tt>.</t>
      <t>Each DAF is identified by a unique, 32-bit integer <tt>ID</tt>. Identifiers for each
(V)DAF specified in this document are defined in <xref target="codepoints"/>.</t>
      <section anchor="sec-daf-shard">
        <name>Sharding</name>
        <t>In order to protect the privacy of its measurements, a DAF Client shards its
measurements into a sequence of input shares. The <tt>shard</tt> method is used for
this purpose.</t>
        <ul spacing="normal">
          <li>
            <t><tt>Daf.shard(measurement: Measurement, nonce: bytes[Daf.NONCE_SIZE], rand:
bytes[Daf.RAND_SIZE]) -&gt; tuple[PublicShare, list[InputShare]]</tt> is the
randomized sharding algorithm run by each Client. The input <tt>rand</tt> consists
of the random bytes consumed by the algorithm. This value <bcp14>MUST</bcp14> be generated
using a cryptographically secure pseudorandom number generator (CSPRNG). It
consumes the measurement and produces a "public share", distributed to each
of the Aggregators, and a corresponding sequence of input shares, one for
each Aggregator. The length of the output vector <bcp14>MUST</bcp14> be <tt>SHARES</tt>.</t>
          </li>
        </ul>
        <figure anchor="shard-flow">
          <name>The Client divides its measurement into input shares and distributes them to the Aggregators. The public share is broadcast to all Aggregators.</name>
          <artwork><![CDATA[
    Client
    ======

    measurement
      |
      V
    +----------------------------------------------+
    | shard                                        |
    +----------------------------------------------+
      |              |              |     |
      |              |         ...  |    public_share
      |              |              |     |
      |    +---------|-----+--------|-----+
      |    |         |     |        |     |
      V    |         V     |        V     |
     input_share_0  input_share_1  input_share_[SHARES-1]
      |    |         |     |   ...  |     |
      V    V         V     V        V     V
    Aggregator 0   Aggregator 1    Aggregator SHARES-1
]]></artwork>
        </figure>
      </section>
      <section anchor="sec-daf-prepare">
        <name>Preparation</name>
        <t>Once an Aggregator has received the public share and one of the input shares,
the next step is to prepare the input share for aggregation. This is
accomplished using the following algorithm:</t>
        <ul spacing="normal">
          <li>
            <t><tt>Daf.prep(agg_id: Unsigned, agg_param: AggParam, nonce: bytes[NONCE_SIZE],
public_share: PublicShare, input_share: InputShare) -&gt; OutShare</tt> is the
deterministic preparation algorithm. It takes as input the public share and
one of the input shares generated by a Client, the Aggregator's unique
identifier, the aggregation parameter selected by the Collector, and a nonce
and returns an output share.</t>
          </li>
        </ul>
        <t>The protocol in which the DAF is used <bcp14>MUST</bcp14> ensure that the Aggregator's
identifier is equal to the integer in range <tt>[0, SHARES)</tt> that matches the index
of <tt>input_share</tt> in the sequence of input shares output by the Client.</t>
      </section>
      <section anchor="sec-daf-validity-scopes">
        <name>Validity of Aggregation Parameters</name>
        <t>Concrete DAFs implementations <bcp14>MAY</bcp14> impose certain restrictions for input shares
and aggregation parameters. Protocols using a DAF <bcp14>MUST</bcp14> ensure that for each
input share and aggregation parameter <tt>agg_param</tt>, <tt>Daf.prep</tt> is only called if
<tt>Daf.is_valid(agg_param, previous_agg_params)</tt> returns True, where
<tt>previous_agg_params</tt> contains all aggregation parameters that have previously
been used with the same input share.</t>
        <t>DAFs <bcp14>MUST</bcp14> implement the following function:</t>
        <ul spacing="normal">
          <li>
            <t><tt>Daf.is_valid(agg_param: AggParam, previous_agg_params: set[AggParam]) -&gt;
Bool</tt>: Checks if the <tt>agg_param</tt> is compatible with all elements of
<tt>previous_agg_params</tt>.</t>
          </li>
        </ul>
      </section>
      <section anchor="sec-daf-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:</t>
        <ul spacing="normal">
          <li>
            <t><tt>Daf.aggregate(agg_param: AggParam, out_shares: list[OutShare]) -&gt; AggShare</tt>
is the deterministic aggregation algorithm. It is run by each Aggregator a
set of recovered output shares.</t>
          </li>
        </ul>
        <figure anchor="aggregate-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
    +-----------+   +-----------+       +-----------+
    | aggregate |   | aggregate |   ... | aggregate |
    +-----------+   +-----------+       +-----------+
      |               |                   |
      V               V                   V
    agg_share_0     agg_share_1         agg_share_[SHARES-1]
]]></artwork>
        </figure>
        <t>For simplicity, we have written this algorithm in a "one-shot" form, where all
output shares for a batch are provided at the same time. Many DAFs may also
support a "streaming" form, where shares are processed one at a time.</t>
        <t>Implementation note: For most natural DAFs (and VDAFs) it is not necessary for
an Aggregator to store all output shares individually before aggregating.
Typically it is possible to merge output shares into aggregate shares as they
arrive, merge these into other aggregate shares, and so on. In particular, this
is the case when the output shares are vectors over some finite field and
aggregating them involves merely adding up the vectors element-wise. Such is the
case for Prio3 <xref target="prio3"/> and Poplar1 <xref target="poplar1"/>.</t>
      </section>
      <section anchor="sec-daf-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>
            <t><tt>Daf.unshard(agg_param: AggParam, agg_shares: list[AggShare],
num_measurements: Unsigned) -&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>. <tt>num_measurements</tt> is the number of
measurements that contributed to each of the aggregate shares. This algorithm
is deterministic.</t>
          </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
    +-----------------------------------------------+
    | unshard                                       |
    +-----------------------------------------------+
      |
      V
    agg_result

    Collector
    =========
]]></artwork>
        </figure>
      </section>
      <section anchor="daf-execution">
        <name>Execution of a DAF</name>
        <t>Securely executing a DAF involves emulating the following procedure.</t>
        <!--
Simon Friedberger: I think this would be easier to understand (also a bit
longer) if there was an Aggregator class which behaved like an actual aggregator
but with messages being sent by calling functions.
-->
<figure anchor="run-daf">
          <name>Execution of a DAF.</name>
          <artwork><![CDATA[
def run_daf(Daf,
            agg_param: Daf.AggParam,
            measurements: list[Daf.Measurement],
            nonces: list[bytes[Daf.NONCE_SIZE]]):
    out_shares = [[] for j in range(Daf.SHARES)]
    for (measurement, nonce) in zip(measurements, nonces):
        # Each Client shards its measurement into input shares and
        # distributes them among the Aggregators.
        rand = gen_rand(Daf.RAND_SIZE)
        (public_share, input_shares) = \
            Daf.shard(measurement, nonce, rand)

        # Each Aggregator prepares its input share for aggregation.
        for j in range(Daf.SHARES):
            out_shares[j].append(
                Daf.prep(j, agg_param, nonce,
                         public_share, input_shares[j]))

    # Each Aggregator aggregates its output shares into an aggregate
    # share and sends it to the Collector.
    agg_shares = []
    for j in range(Daf.SHARES):
        agg_share_j = Daf.aggregate(agg_param,
                                    out_shares[j])
        agg_shares.append(agg_share_j)

    # Collector unshards the aggregate result.
    num_measurements = len(measurements)
    agg_result = Daf.unshard(agg_param, agg_shares,
                             num_measurements)
    return agg_result
]]></artwork>
        </figure>
        <t>The inputs to this procedure are the same as the aggregation function computed by
the DAF: An aggregation parameter and a sequence of measurements. The procedure
prescribes how a DAF is executed in a "benign" environment in which there is no
adversary and the messages are passed among the protocol participants over
secure point-to-point channels. In reality, these channels need to be
instantiated by some "wrapper protocol", such as <xref target="DAP"/>,
that realizes these channels using suitable cryptographic mechanisms. Moreover,
some fraction of the Aggregators (or Clients) may be malicious and diverge from
their prescribed behaviors. <xref target="security"/> describes the execution of the DAF in
various adversarial environments and what properties the wrapper protocol needs
to provide in each.</t>
      </section>
    </section>
    <section anchor="vdaf">
      <name>Definition of VDAFs</name>
      <t>Like DAFs described in the previous section, a VDAF scheme is used to compute a
particular aggregation function over a set of Client-generated measurements.
Evaluation of a VDAF involves the same four stages as for DAFs: Sharding,
Preparation, Aggregation, and Unsharding. However, the Preparation stage will
require interaction among the Aggregators in order to facilitate verifiability
of the computation's correctness. Accommodating this interaction will require
syntactic changes.</t>
      <t>Overall execution of a VDAF comprises the following stages:</t>
      <ul spacing="normal">
        <li>
          <t>Sharding - Computing input shares from an individual measurement</t>
        </li>
        <li>
          <t>Preparation - Conversion and verification of input shares to output shares
compatible with the aggregation function being computed</t>
        </li>
        <li>
          <t>Aggregation - Combining a sequence of output shares into an aggregate share</t>
        </li>
        <li>
          <t>Unsharding - Combining a sequence of aggregate shares into an aggregate
result</t>
        </li>
      </ul>
      <t>In contrast to DAFs, the Preparation stage for VDAFs now performs an additional
task: Verification of the validity of the recovered output shares. This process
ensures that aggregating the 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. The attributes are
listed in <xref target="vdaf-param"/> are defined by each concrete VDAF.</t>
      <table anchor="vdaf-param">
        <name>Constants and types defined by each concrete VDAF.</name>
        <thead>
          <tr>
            <th align="left">Parameter</th>
            <th align="left">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>ID</tt></td>
            <td align="left">Algorithm identifier for this VDAF.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>VERIFY_KEY_SIZE</tt></td>
            <td align="left">Size (in bytes) of the verification key (<xref target="sec-vdaf-prepare"/>).</td>
          </tr>
          <tr>
            <td align="left">
              <tt>RAND_SIZE</tt></td>
            <td align="left">Size of the random byte string passed to sharding algorithm.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>NONCE_SIZE</tt></td>
            <td align="left">Size (in bytes) of the nonce.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>ROUNDS</tt></td>
            <td align="left">Number of rounds of communication during the Preparation stage (<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>PublicShare</tt></td>
            <td align="left">Type of each public share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>InputShare</tt></td>
            <td align="left">Type of each input share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggParam</tt></td>
            <td align="left">Type of aggregation parameter.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>OutShare</tt></td>
            <td align="left">Type of each output share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggShare</tt></td>
            <td align="left">Type of the aggregate share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>AggResult</tt></td>
            <td align="left">Type of the aggregate result.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PrepState</tt></td>
            <td align="left">Aggregator's state during preparation.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PrepShare</tt></td>
            <td align="left">Type of each prep share.</td>
          </tr>
          <tr>
            <td align="left">
              <tt>PrepMessage</tt></td>
            <td align="left">Type of each prep message.</td>
          </tr>
        </tbody>
      </table>
      <t>Some of these values need to be written to the network in order to carry out
the computation. In particular, it is <bcp14>RECOMMENDED</bcp14> that concrete instantiations
of the <tt>Vdaf</tt> interface specify a method of encoding the <tt>PublicShare</tt>,
<tt>InputShare</tt>, <tt>AggShare</tt>, <tt>PrepShare</tt>, and <tt>PrepMessage</tt>.</t>
      <t>Each VDAF is identified by a unique, 32-bit integer <tt>ID</tt>. Identifiers for each
(V)DAF specified in this document are defined in <xref target="codepoints"/>. The following
method is defined for every VDAF:</t>
      <artwork><![CDATA[
def domain_separation_tag(Vdaf, usage: Unsigned) -> Bytes:
    """
    Format domain separation tag for this VDAF with the given usage.
    """
    return format_dst(0, Vdaf.ID, usage)
]]></artwork>
      <t>It is used to construct a domain separation tag for an instance of <tt>Xof</tt> used by
the VDAF. (See <xref target="xof"/>.)</t>
      <section anchor="sec-vdaf-shard">
        <name>Sharding</name>
        <t>Sharding transforms a measurement into input shares as it does in DAFs
(cf. <xref target="sec-daf-shard"/>); in addition, it takes a nonce as input and
produces a public share:</t>
        <ul spacing="normal">
          <li>
            <t><tt>Vdaf.shard(measurement: Measurement, nonce: bytes[Vdaf.NONCE_SIZE], rand:
bytes[Vdaf.RAND_SIZE]) -&gt; tuple[PublicShare, list[InputShare]]</tt> is the
randomized sharding algorithm run by each Client. Input <tt>rand</tt> consists of
the random bytes consumed by the algorithm. It consumes the measurement and
the nonce and produces a public share, distributed to each of Aggregators,
and the corresponding sequence of input shares, one for each Aggregator.
Depending on the VDAF, the input shares may encode additional information
used to verify the recovered output shares (e.g., the "proof shares" in Prio3
<xref target="prio3"/>). The length of the output vector <bcp14>MUST</bcp14> be <tt>SHARES</tt>.</t>
          </li>
        </ul>
        <t>In order to ensure privacy of the measurement, the Client <bcp14>MUST</bcp14> generate the
random bytes and nonce using a CSPRNG. (See <xref target="security"/> for details.)</t>
      </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", or "prep message" for short.
(Each of the outbound messages are called "preparation-message shares", or
"prep shares" for short.) 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 prep message. Its output in the last round
is its output share and its output in each of the preceding rounds is a prep
share.</t>
        <t>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 the measurement shares 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_shares_to_prep                          |   |
    +----------------------------------------------+   |
      |              |              ...  |             |
      V              V                   V             | x ROUNDS
    +-----------+  +-----------+       +-----------+   |
    | prep_next |  | prep_next |       | prep_next |   |
    +-----------+  +-----------+       +-----------+   |
      |              |              ...  |             |
      V              V                   V             /
     ...            ...                 ...
      |              |              ...  |
      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
methods:</t>
        <ul spacing="normal">
          <li>
            <t><tt>Vdaf.prep_init(verify_key: bytes[Vdaf.VERIFY_KEY_SIZE], agg_id: Unsigned,
agg_param: AggParam, nonce: bytes[Vdaf.NONCE_SIZE], public_share:
PublicShare, input_share: InputShare) -&gt; tuple[PrepState, PrepShare]</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 the shared verification key (<tt>verify_key</tt>), the Aggregator's
unique identifier (<tt>agg_id</tt>), the aggregation parameter (<tt>agg_param</tt>), the
nonce provided by the environment (<tt>nonce</tt>, see <xref target="run-vdaf"/>), the public
share (<tt>public_share</tt>), and one of the input shares generated by the Client
(<tt>input_share</tt>). Its output is the Aggregator's initial preparation state and
initial prep share.  </t>
            <t>
It is up to the high level protocol in which the VDAF is used to arrange for
the distribution of the verification key prior to generating and processing
reports. (See <xref target="security"/> for details.)  </t>
            <t>
Protocols using the VDAF <bcp14>MUST</bcp14> ensure that the Aggregator's identifier is equal
to the integer in range <tt>[0, SHARES)</tt> that matches the index of <tt>input_share</tt>
in the sequence of input shares output by the Client.  </t>
            <t>
Protocols <bcp14>MUST</bcp14> ensure that public share consumed by each of the Aggregators is
identical. This is security critical for VDAFs such as Poplar1.</t>
          </li>
          <li>
            <t><tt>Vdaf.prep_next(prep_state: PrepState, prep_msg: PrepMessage) -&gt;
Union[tuple[PrepState, PrepShare], OutShare]</tt> is the deterministic
preparation-state update algorithm run by each Aggregator. It updates the
Aggregator's preparation state (<tt>prep_state</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.</t>
          </li>
          <li>
            <t><tt>Vdaf.prep_shares_to_prep(agg_param: AggParam, prep_shares: list[PrepShare])
-&gt; PrepMessage</tt> is the deterministic preparation-message pre-processing
algorithm. It combines the prep shares generated by the Aggregators in the
previous round into the prep message consumed by each in the next round.</t>
          </li>
        </ul>
        <t>In effect, each Aggregator moves through a linear state machine with <tt>ROUNDS</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>
        <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>
      </section>
      <section anchor="sec-vdaf-validity-scopes">
        <name>Validity of Aggregation Parameters</name>
        <t>Similar to DAFs (see <xref target="sec-daf-validity-scopes"/>), VDAFs <bcp14>MAY</bcp14> impose
restrictions for input shares and aggregation parameters. Protocols using a VDAF
<bcp14>MUST</bcp14> ensure that for each input share and aggregation parameter <tt>agg_param</tt>, the
preparation phase (including <tt>Vdaf.prep_init</tt>, <tt>Vdaf.prep_next</tt>, and
<tt>Vdaf.prep_shares_to_prep</tt>; see <xref target="sec-vdaf-prepare"/>) is only called if
<tt>Vdaf.is_valid(agg_param, previous_agg_params)</tt> returns True, where
<tt>previous_agg_params</tt> contains all aggregation parameters that have previously
been used with the same input share.</t>
        <t>VDAFs <bcp14>MUST</bcp14> implement the following function:</t>
        <ul spacing="normal">
          <li>
            <t><tt>Vdaf.is_valid(agg_param: AggParam, previous_agg_params: list[AggParam]) -&gt;
Bool</tt>: Checks if the <tt>agg_param</tt> is compatible with all elements of
<tt>previous_agg_params</tt>.</t>
          </li>
        </ul>
      </section>
      <section anchor="sec-vdaf-aggregate">
        <name>Aggregation</name>
        <t>VDAF Aggregation is identical to DAF Aggregation (cf. <xref target="sec-daf-aggregate"/>):</t>
        <ul spacing="normal">
          <li>
            <t><tt>Vdaf.aggregate(agg_param: AggParam, out_shares: list[OutShare]) -&gt; AggShare</tt>
is the deterministic aggregation algorithm. It is run by each Aggregator over
the output shares it has computed for a batch of measurements.</t>
          </li>
        </ul>
        <t>The data flow for this stage is illustrated in <xref target="aggregate-flow"/>. Here again,
we have the aggregation algorithm in a "one-shot" form, where all shares for a
batch are provided at the same time. VDAFs typically also support a "streaming"
form, where shares are processed one at a time.</t>
      </section>
      <section anchor="sec-vdaf-unshard">
        <name>Unsharding</name>
        <t>VDAF Unsharding is identical to DAF Unsharding (cf. <xref target="sec-daf-unshard"/>):</t>
        <ul spacing="normal">
          <li>
            <t><tt>Vdaf.unshard(agg_param: AggParam, agg_shares: list[AggShare],
num_measurements: Unsigned) -&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>. <tt>num_measurements</tt> is the number of
measurements that contributed to each of the aggregate shares. This algorithm
is deterministic.</t>
          </li>
        </ul>
        <t>The data flow for this stage is illustrated in <xref target="unshard-flow"/>.</t>
      </section>
      <section anchor="vdaf-execution">
        <name>Execution of a VDAF</name>
        <t>Secure execution of a VDAF involves simulating the following procedure.</t>
        <figure anchor="run-vdaf">
          <name>Execution of a VDAF.</name>
          <artwork><![CDATA[
def run_vdaf(Vdaf,
             verify_key: bytes[Vdaf.VERIFY_KEY_SIZE],
             agg_param: Vdaf.AggParam,
             nonces: list[bytes[Vdaf.NONCE_SIZE]],
             measurements: list[Vdaf.Measurement]):
    out_shares = []
    for (nonce, measurement) in zip(nonces, measurements):
        # Each Client shards its measurement into input shares.
        rand = gen_rand(Vdaf.RAND_SIZE)
        (public_share, input_shares) = \
            Vdaf.shard(measurement, nonce, rand)

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

        # Aggregators recover their output shares.
        for i in range(Vdaf.ROUNDS-1):
            prep_msg = Vdaf.prep_shares_to_prep(agg_param,
                                                outbound)
            outbound = []
            for j in range(Vdaf.SHARES):
                out = Vdaf.prep_next(prep_states[j], prep_msg)
                (prep_states[j], out) = out
                outbound.append(out)

        # The final outputs of the prepare phase are the output shares.
        prep_msg = Vdaf.prep_shares_to_prep(agg_param,
                                            outbound)
        outbound = []
        for j in range(Vdaf.SHARES):
            out_share = Vdaf.prep_next(prep_states[j], prep_msg)
            outbound.append(out_share)
        out_shares.append(outbound)

    # Each Aggregator aggregates its output shares into an
    # aggregate share. In a distributed VDAF computation, the
    # aggregate shares are sent over the network.
    agg_shares = []
    for j in range(Vdaf.SHARES):
        out_shares_j = [out[j] for out in out_shares]
        agg_share_j = Vdaf.aggregate(agg_param, out_shares_j)
        agg_shares.append(agg_share_j)

    # Collector unshards the aggregate.
    num_measurements = len(measurements)
    agg_result = Vdaf.unshard(agg_param, agg_shares,
                              num_measurements)
    return agg_result
]]></artwork>
        </figure>
        <t>The inputs to this algorithm are the aggregation parameter, a list of
measurements, and a nonce for each measurement. This document does not specify
how the nonces are chosen, but security requires that the nonces be unique. See
<xref target="security"/> for details. As explained in <xref target="daf-execution"/>, the secure
execution of a VDAF requires the application to instantiate secure channels
between each of the protocol participants.</t>
      </section>
      <section anchor="vdaf-prep-comm">
        <name>Communication Patterns for Preparation</name>
        <t>In each round of preparation, each Aggregator writes a prep share to some
broadcast channel, which is then processed into the prep message using the
public <tt>prep_shares_to_prep()</tt> algorithm and broadcast to the Aggregators to
start the next round. In this section we describe some approaches to realizing
this broadcast channel functionality in protocols that use VDAFs.</t>
        <t>The state machine of each Aggregator is shown in <xref target="vdaf-prep-state-machine"/>.</t>
        <figure anchor="vdaf-prep-state-machine">
          <name>State machine for VDAF preparation.</name>
          <sourcecode type="state"><![CDATA[
               +----------------+
               |                |
               v                |
Start ------> Continued(prep_state) --> Finished(out_share)
 |                |
 |                |
 +--> Rejected <--+
]]></sourcecode>
        </figure>
        <t>State transitions are made when the state is acted upon by the host's local
inputs and/or messages sent by the peers. The initial state is <tt>Start</tt>. The
terminal states are <tt>Rejected</tt>, which indicates that the report cannot be
processed any further, and <tt>Finished(out_share)</tt>, which indicates that the
Aggregator has recovered an output share <tt>out_share</tt>.</t>
        <artwork><![CDATA[
class State:
    pass

class Start(State):
    pass

class Continued(State):
    def __init__(self, prep_state):
        self.prep_state = prep_state

class Finished(State):
    def __init__(self, output_share):
        self.output_share = output_share

class Rejected(State):
    def __init__(self):
        pass
]]></artwork>
        <t>Note that there is no representation of the <tt>Start</tt> state as it is never
instantiated in the ping-pong topology.</t>
        <t>For convenience, the methods described in this section are defined in terms of
opaque byte strings. A compatible <tt>Vdaf</tt> <bcp14>MUST</bcp14> specify methods for encoding
public shares, input shares, prep shares, prep messages, and aggregation
parameters. Minimally:</t>
        <ul spacing="normal">
          <li>
            <t><tt>Vdaf.decode_public_share(encoded: bytes) -&gt; Vdaf.PublicShare</tt> decodes a
public share.</t>
          </li>
          <li>
            <t><tt>Vdaf.decode_input_share(agg_id: Unsigned, encoded: bytes) -&gt;
Vdaf.InputShare</tt> decodes an input share, using the aggregator ID as optional
context.</t>
          </li>
          <li>
            <t><tt>Vdaf.encode_prep_share(prep_share: Vdaf.PrepShare) -&gt; bytes</tt> encodes a prep
share.</t>
          </li>
          <li>
            <t><tt>Vdaf.decode_prep_share(prep_state: Vdaf.PrepState, encoded: bytes) -&gt;
Vdaf.PrepShare</tt> decodes a prep share, using the prep state as optional
context.</t>
          </li>
          <li>
            <t><tt>Vdaf.encode_prep_msg(prep_msg: Vdaf.PrepMessage) -&gt; bytes</tt> encodes a prep
message.</t>
          </li>
          <li>
            <t><tt>Vdaf.decode_prep_msg(prep_state: Vdaf.PrepState, encoded: bytes) -&gt;
Vdaf.PrepMessage</tt> decodes a prep message, using the prep state as optional
decoding context.</t>
          </li>
          <li>
            <t><tt>Vdaf.decode_agg_param(encoded: bytes) -&gt; Vdaf.AggParam</tt> decodes an
aggregation parameter.</t>
          </li>
          <li>
            <t><tt>Vdaf.encode_agg_param(agg_param: Vdaf.AggParam) -&gt; bytes</tt> encodes an
aggregation parameter.</t>
          </li>
        </ul>
        <t>Implementations of Prio3 and Poplar1 <bcp14>MUST</bcp14> use the encoding scheme specified in
<xref target="prio3-encode"/> and <xref target="poplar1-encode"/> respectively.</t>
      </section>
      <section anchor="ping-pong-topology-only-two-aggregators">
        <name>Ping-Pong Topology (Only Two Aggregators)</name>
        <t>For VDAFs with precisely two Aggregators (i.e., <tt>Vdaf.SHARES == 2</tt>), the
following "ping pong" communication pattern can be used. It is compatible with
any request/response transport protocol, such as HTTP.</t>
        <t>Let us call the initiating party the "Leader" and the responding party the
"Helper". The high-level idea is that the Leader and Helper will take turns
running the computation locally until input from their peer is required:</t>
        <ul spacing="normal">
          <li>
            <t>For a 1-round VDAF (e.g., Prio3 (<xref target="prio3"/>)), the Leader sends its prep share
to the Helper, who computes the prep message locally, computes its output
share, then sends the prep message to the Leader. Preparation requires just
one round trip between the Leader and the Helper.</t>
          </li>
          <li>
            <t>For a 2-round VDAF (e.g., Poplar1 (<xref target="poplar1"/>)), the Leader sends its
first-round prep share to the Helper, who replies with the first-round prep
message and its second-round prep share. In the next request, the Leader
computes its second-round prep share locally, computes its output share, and
sends the second-round prep message to the Helper. Finally, the Helper
computes its own output share.</t>
          </li>
          <li>
            <t>In general, each request includes the Leader's prep share for the previous
round and/or the prep message for the current round; correspondingly, each
response consists of the prep message for the current round and the Helper's
prep share for the next round.</t>
          </li>
        </ul>
        <t>The Aggregators proceed in this ping-ponging fashion until a step of the
computation fails (indicating the report is invalid and should be rejected) or
preparation is completed. All told there there are <tt>ceil((Vdaf.ROUNDS+1)/2)</tt>
requests sent.</t>
        <t>Each message in the ping-pong protocol is structured as follows (expressed in
TLS syntax as defined in <xref section="3" sectionFormat="of" target="RFC8446"/>):</t>
        <artwork><![CDATA[
enum {
  initialize(0),
  continue(1),
  finish(2),
  (255)
} MessageType;

struct {
  MessageType type;
  select (Message.type) {
    case initialize:
      opaque prep_share<0..2^32-1>;
    case continue:
      opaque prep_msg<0..2^32-1>;
      opaque prep_share<0..2^32-1>;
    case finish:
      opaque prep_msg<0..2^32-1>;
  };
} Message;
]]></artwork>
        <t>These messages are used to transition between the states described in
<xref target="vdaf-prep-comm"/>. They are encoded and decoded to or from byte buffers as
described <xref section="3" sectionFormat="of" target="RFC8446"/>) using the following routines:</t>
        <ul spacing="normal">
          <li>
            <t><tt>encode_ping_pong_message(message: Message) -&gt; bytes</tt> encodes a <tt>Message</tt> into
an opaque byte buffer.</t>
          </li>
          <li>
            <t><tt>decode_pong_pong_message(encoded: bytes) -&gt; Message</tt> decodes an opaque byte
buffer into a <tt>Message</tt>, raising an error if the bytes are not a valid
encoding.</t>
          </li>
        </ul>
        <t>The Leader's initial transition is computed with the following procedure:</t>
        <sourcecode type="transition"><![CDATA[
def ping_pong_leader_init(
            Vdaf,
            vdaf_verify_key: bytes[Vdaf.VERIFY_KEY_SIZE],
            agg_param: bytes,
            nonce: bytes[Vdaf.NONCE_SIZE],
            public_share: bytes,
            input_share: bytes,
        ) -> tuple[State, bytes]:
    try:
        (prep_state, prep_share) = Vdaf.prep_init(
            vdaf_verify_key,
            0,
            Vdaf.decode_agg_param(agg_param),
            nonce,
            Vdaf.decode_public_share(public_share),
            Vdaf.decode_input_share(0, input_share),
        )
        outbound = Message.initialize(
            Vdaf.encode_prep_share(prep_share))
        return (Continued(prep_state), encode_ping_pong_message(outbound))
    except:
        return (Rejected(), None)
]]></sourcecode>
        <t>The output is the <tt>State</tt> to which the Leader has transitioned and an encoded
<tt>Message</tt>. If the Leader's state is <tt>Rejected</tt>, then processing halts.
Otherwise, if the state is <tt>Continued</tt>, then processing continues.</t>
        <t>The Leader sends the outbound message to the Helper. The Helper's initial
transition is computed using the following procedure:</t>
        <sourcecode type="transition"><![CDATA[
def ping_pong_helper_init(
            Vdaf,
            vdaf_verify_key: bytes[Vdaf.VERIFY_KEY_SIZE],
            agg_param: bytes,
            nonce: bytes[Vdaf.NONCE_SIZE],
            public_share: bytes,
            input_share: bytes,
            inbound_encoded: bytes,
        ) -> tuple[State, bytes]:
    try:
        (prep_state, prep_share) = Vdaf.prep_init(
            vdaf_verify_key,
            1,
            Vdaf.decode_agg_param(agg_param),
            nonce,
            Vdaf.decode_public_share(public_share),
            Vdaf.decode_input_share(1, input_share),
        )

        inbound = decode_ping_pong_message(inbound_encoded)

        if inbound.type != 0: # initialize
            return (Rejected(), None)

        prep_shares = [
            Vdaf.decode_prep_share(prep_state, inbound.prep_share),
            prep_share,
        ]
        return Vdaf.ping_pong_transition(
            agg_param,
            prep_shares,
            prep_state,
        )
    except:
        return (Rejected(), None)
]]></sourcecode>
        <t>Procedure <tt>ping_pong_transition()</tt> takes in the prep shares, combines them into
the prep message, and computes the next prep state of the caller:</t>
        <artwork><![CDATA[
def ping_pong_transition(
            Vdaf,
            agg_param: Vdaf.AggParam,
            prep_shares: list[Vdaf.PrepShare],
            prep_state: Vdaf.PrepState,
         ) -> (State, bytes):
    prep_msg = Vdaf.prep_shares_to_prep(agg_param,
                                        prep_shares)
    out = Vdaf.prep_next(prep_state, prep_msg)
    if type(out) == Vdaf.OutShare:
        outbound = Message.finish(Vdaf.encode_prep_msg(prep_msg))
        return (Finished(out), encode_ping_pong_message(outbound))
    (prep_state, prep_share) = out
    outbound = Message.continue(
        Vdaf.encode_prep_msg(prep_msg),
        Vdaf.encode_prep_share(prep_share),
    )
    return (Continued(prep_state), encode_ping_pong_message(outbound))
]]></artwork>
        <t>The output is the <tt>State</tt> to which the Helper has transitioned and an encoded
<tt>Message</tt>. If the Helper's state is <tt>Finished</tt> or <tt>Rejected</tt>, then processing
halts. Otherwise, if the state is <tt>Continued</tt>, then processing continues.</t>
        <t>Next, the Helper sends the outbound message to the Leader. The Leader computes
its next state transition using the function <tt>ping_pong_leader_continued</tt>:</t>
        <sourcecode type="transition"><![CDATA[
def ping_pong_leader_continued(
            Vdaf,
            agg_param: bytes,
            state: State,
            inbound_encoded: bytes,
        ) -> (State, Optional[bytes]):
    return Vdaf.ping_pong_continued(
        True,
        agg_param,
        state,
        inbound_encoded,
    )

def ping_pong_continued(
            Vdaf,
            is_leader: bool,
            agg_param: bytes,
            state: State,
            inbound_encoded: bytes,
        ) -> (State, Optional[bytes]):
    try:
        inbound = decode_ping_pong_message(inbound_encoded)

        if inbound.type == 0: # initialize
            return (Rejected(), None)

        if !isinstance(state, Continued):
            return (Rejected(), None)

        prep_msg = Vdaf.decode_prep_msg(state.prep_state, inbound.prep_msg)
        out = Vdaf.prep_next(state.prep_state, prep_msg)
        if type(out) == tuple[Vdaf.PrepState, Vdaf.PrepShare] \
                and inbound.type == 1:
            # continue
            (prep_state, prep_share) = out
            prep_shares = [
                Vdaf.decode_prep_share(prep_state, inbound.prep_share),
                prep_share,
            ]
            if is_leader:
                prep_shares.reverse()
            return Vdaf.ping_pong_transition(
                Vdaf.decode_agg_param(agg_param),
                prep_shares,
                prep_state,
            )
        elif type(out) == Vdaf.OutShare and inbound.type == 2:
            # finish
            return (Finished(out), None)
        else:
            return (Rejected(), None)

    except:
        return (Rejected(), None)
]]></sourcecode>
        <t>If the Leader's state is <tt>Finished</tt> or <tt>Rejected</tt>, then processing halts.
Otherwise, the Leader sends the outbound message to the Helper. The Helper
computes its next state transition using the function
<tt>ping_pong_helper_continued</tt>:</t>
        <sourcecode type="transition"><![CDATA[
def ping_pong_helper_continued(
            Vdaf,
            agg_param: bytes,
            state: State,
            inbound_encoded: bytes,
        ) -> (State, Optional[bytes]):
    return Vdaf.ping_pong_continued(
        False,
        agg_param,
        state,
        inbound_encoded,
    )
]]></sourcecode>
        <t>They continue in this way until processing halts. Note that, depending on the
number of rounds of preparation that are required, there may be one more
message to send before the peer can also finish processing (i.e., <tt>outbound !=
None</tt>).</t>
      </section>
      <section anchor="star-topology-any-number-of-aggregators">
        <name>Star Topology (Any Number of Aggregators)</name>
        <t>The ping-pong topology of the previous section is only suitable for VDAFs
involving exactly two Aggregators. If more Aggregators are required, the star
topology described in this section can be used instead.</t>
        <ul empty="true">
          <li>
            <t>TODO Describe the Leader-emulated broadcast channel architecture that was
originally envisioned for DAP. (As of DAP-05 we are going with the ping pong
architecture described in the previous section.)</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="prelim">
      <name>Preliminaries</name>
      <t>This section describes the primitives that are common to the VDAFs specified in
this document.</t>
      <section anchor="field">
        <name>Finite Fields</name>
        <t>Both Prio3 and Poplar1 use finite fields of prime order. Finite field
elements are represented by a class <tt>Field</tt> with the following associated
parameters:</t>
        <ul spacing="normal">
          <li>
            <t><tt>MODULUS: Unsigned</tt> is the prime modulus that defines the field.</t>
          </li>
          <li>
            <t><tt>ENCODED_SIZE: Unsigned</tt> is the number of bytes used to encode a field element
as a byte string.</t>
          </li>
        </ul>
        <t>A concrete <tt>Field</tt> also implements the following class methods:</t>
        <ul spacing="normal">
          <li>
            <t><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>.</t>
          </li>
          <li>
            <t><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>.</t>
          </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>
            <t><tt>elem.as_unsigned() -&gt; Unsigned</tt> returns the integer representation of
field element <tt>elem</tt>.</t>
          </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>
            <t><tt>Field(integer: Unsigned)</tt> returns <tt>integer</tt> represented as a field element.
The value of <tt>integer</tt> <bcp14>MUST</bcp14> be less than <tt>Field.MODULUS</tt>.</t>
          </li>
        </ul>
        <t>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 += to_le_bytes(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 = from_le_bytes(encoded_x)
        if x >= Field.MODULUS:
            raise ERR_DECODE # Integer is larger than modulus
        vec.append(Field(x))
    return vec
]]></artwork>
        </figure>
        <t>Finally, <tt>Field</tt> implements the following methods for representing a value as
a sequence of field elements, each of which represents a bit of the input.</t>
        <figure anchor="field-bit-rep">
          <name>Derived class methods to encode integers into bit vector representation.</name>
          <artwork><![CDATA[
def encode_into_bit_vector(Field,
                           val: Unsigned,
                           bits: Unsigned) -> Vec[Field]:
    """
    Encode the bit representation of `val` with at most `bits` number
    of bits, as a vector of field elements.
    """
    if val >= 2 ** bits:
        # Sanity check we are able to represent `val` with `bits`
        # number of bits.
        raise ValueError("Number of bits is not enough to represent "
                         "the input integer.")
    encoded = []
    for l in range(bits):
        encoded.append(Field((val >> l) & 1))
    return encoded

def decode_from_bit_vector(Field, vec: Vec[Field]) -> Field:
    """
    Decode the field element from the bit representation, expressed
    as a vector of field elements `vec`.
    """
    bits = len(vec)
    if Field.MODULUS >> bits == 0:
        raise ValueError("Number of bits is too large to be "
                         "represented by field modulus.")
    decoded = Field(0)
    for (l, bit) in enumerate(vec):
        decoded += Field(1 << l) * bit
    return decoded
]]></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[
def vec_sub(left: Vec[Field], right: Vec[Field]):
    """
    Subtract the right operand from the left and return the result.
    """
    return list(map(lambda x: x[0] - x[1], zip(left, right)))

def vec_add(left: Vec[Field], right: Vec[Field]):
    """Add the right operand to the left and return the result."""
    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, as this allows for fast polynomial interpolation.
(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>
              <t><tt>Field.gen() -&gt; Field</tt> returns the generator of a large subgroup of the
multiplicative group. To be FFT-friendly, the order of this subgroup <bcp14>MUST</bcp14> be a
power of 2. In addition, the size of the subgroup dictates how large
interpolated polynomials can be. It is <bcp14>RECOMMENDED</bcp14> that a generator is chosen
with order at least <tt>2^20</tt>.</t>
            </li>
          </ul>
          <t>FFT-friendly fields also define the following parameter:</t>
          <ul spacing="normal">
            <li>
              <t><tt>GEN_ORDER: Unsigned</tt> is the order of a multiplicative subgroup generated by
<tt>Field.gen()</tt>.</t>
            </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="fields">
            <name>Parameters for the finite fields used in this document.</name>
            <thead>
              <tr>
                <th align="left">Parameter</th>
                <th align="left">Field64</th>
                <th align="left">Field128</th>
                <th align="left">Field255</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">MODULUS</td>
                <td align="left">2^32 * 4294967295 + 1</td>
                <td align="left">2^66 * 4611686018427387897 + 1</td>
                <td align="left">2^255 - 19</td>
              </tr>
              <tr>
                <td align="left">ENCODED_SIZE</td>
                <td align="left">8</td>
                <td align="left">16</td>
                <td align="left">32</td>
              </tr>
              <tr>
                <td align="left">Generator</td>
                <td align="left">7^4294967295</td>
                <td align="left">7^4611686018427387897</td>
                <td align="left">n/a</td>
              </tr>
              <tr>
                <td align="left">GEN_ORDER</td>
                <td align="left">2^32</td>
                <td align="left">2^66</td>
                <td align="left">n/a</td>
              </tr>
            </tbody>
          </table>
        </section>
      </section>
      <section anchor="xof">
        <name>Extendable Output Functions</name>
        <t>VDAFs in this specification use extendable output functions (XOFs) to extract
short, fixed-length strings we call "seeds" from long input strings and expand
seeds into long output strings. We specify a single interface that is suitable
for both purposes.</t>
        <t>XOFs are defined by a class <tt>Xof</tt> with the following associated parameter and
methods:</t>
        <ul spacing="normal">
          <li>
            <t><tt>SEED_SIZE: Unsigned</tt> is the size (in bytes) of a seed.</t>
          </li>
          <li>
            <t><tt>Xof(seed: Bytes[Xof.SEED_SIZE], dst: Bytes, binder: Bytes)</tt> constructs an
instance of <tt>Xof</tt> from the given seed, domain separation tag, and binder
string. (See below for definitions of these.) 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 XOF).</t>
          </li>
          <li>
            <t><tt>xof.next(length: Unsigned)</tt> returns the next <tt>length</tt> bytes of output of
<tt>xof</tt>.</t>
          </li>
        </ul>
        <t>Each <tt>Xof</tt> has two derived methods. The first is used to derive a fresh seed
from an existing one. The second is used to compute a sequence of field
elements.</t>
        <figure anchor="xof-derived-methods">
          <name>Derived methods for XOFs.</name>
          <artwork><![CDATA[
def derive_seed(Xof,
                seed: Bytes[Xof.SEED_SIZE],
                dst: Bytes,
                binder: Bytes):
    """Derive a new seed."""
    xof = Xof(seed, dst, binder)
    return xof.next(Xof.SEED_SIZE)

def next_vec(self, Field, length: Unsigned):
    """Output the next `length` elements of `Field`."""
    m = next_power_of_2(Field.MODULUS) - 1
    vec = []
    while len(vec) < length:
        x = from_le_bytes(self.next(Field.ENCODED_SIZE))
        x &= m
        if x < Field.MODULUS:
            vec.append(Field(x))
    return vec

def expand_into_vec(Xof,
                    Field,
                    seed: Bytes[Xof.SEED_SIZE],
                    dst: Bytes,
                    binder: Bytes,
                    length: Unsigned):
    """
    Expand the input `seed` into vector of `length` field elements.
    """
    xof = Xof(seed, dst, binder)
    return xof.next_vec(Field, length)
]]></artwork>
        </figure>
        <section anchor="xof-turboshake128">
          <name>XofTurboShake128</name>
          <t>This section describes XofTurboShake128, an XOF based on the
TurboSHAKE128 <xref target="TurboSHAKE"/>. This
XOF is <bcp14>RECOMMENDED</bcp14> for all use cases within VDAFs. The length of the
domain separation string <tt>dst</tt> passed to XofTurboShake128 <bcp14>MUST NOT</bcp14>
exceed 255 bytes.</t>
          <figure>
            <name>Definition of XOF XofTurboShake128.</name>
            <artwork><![CDATA[
class XofTurboShake128(Xof):
    """XOF wrapper for TurboSHAKE128."""

    # Associated parameters
    SEED_SIZE = 16

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

    def next(self, length: Unsigned) -> Bytes:
        self.l += length

        # Function `TurboSHAKE128(M, D, L)` is as defined in
        # Section 2.2 of [TurboSHAKE].
        #
        # Implementation note: Rather than re-generate the output
        # stream each time `next()` is invoked, most implementations
        # of TurboSHAKE128 will expose an "absorb-then-squeeze" API that
        # allows stateful handling of the stream.
        stream = TurboSHAKE128(self.m, 1, self.l)
        return stream[-length:]
]]></artwork>
          </figure>
        </section>
        <section anchor="xof-fixed-key-aes128">
          <name>XofFixedKeyAes128</name>
          <t>While XofTurboShake128 as described above can be securely used in all cases
where a XOF is needed in the VDAFs described in this document, there are some
cases where a more efficient instantiation based on fixed-key AES is possible.
For now, this is limited to the XOF used inside the Idpf <xref target="idpf"/>
implementation in Poplar1 <xref target="idpf-poplar"/>. It is <bcp14>NOT RECOMMENDED</bcp14> to use this
XOF anywhere else. The length of the domain separation string <tt>dst</tt> passed to
XofFixedKeyAes128 <bcp14>MUST NOT</bcp14> exceed 255 bytes. See Security Considerations
<xref target="security"/> for a more detailed discussion.</t>
          <artwork><![CDATA[
class XofFixedKeyAes128(Xof):
    """
    XOF based on a circular collision-resistant hash function from
    fixed-key AES.
    """

    # Associated parameters
    SEED_SIZE = 16

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

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

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

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

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

        Function `AES128(key, block)` is the AES-128 blockcipher.
        """
        lo, hi = block[:8], block[8:]
        sigma_block = concat([hi, xor(hi, lo)])
        return xor(AES128(self.fixed_key, sigma_block), sigma_block)
]]></artwork>
        </section>
        <section anchor="the-domain-separation-tag-and-binder-string">
          <name>The Domain Separation Tag and Binder String</name>
          <t>XOFs are used to map a seed to a finite domain, e.g., a fresh seed or a vector
of field elements. To ensure domain separation, the derivation is needs to be
bound to some distinguished domain separation tag. The domain separation tag
encodes the following values:</t>
          <ol spacing="normal" type="1"><li>
              <t>The document version (i.e.,<tt>VERSION</tt>);</t>
            </li>
            <li>
              <t>The "class" of the algorithm using the output (e.g., VDAF);</t>
            </li>
            <li>
              <t>A unique identifier for the algorithm; and</t>
            </li>
            <li>
              <t>Some indication of how the output is used (e.g., for deriving the measurement
shares in Prio3 <xref target="prio3"/>).</t>
            </li>
          </ol>
          <t>The following algorithm is used in the remainder of this document in order to
format the domain separation tag:</t>
          <artwork><![CDATA[
def format_dst(algo_class: Unsigned,
               algo: Unsigned,
               usage: Unsigned) -> Bytes:
    """Format XOF domain separation tag for use within a (V)DAF."""
    return concat([
        to_be_bytes(VERSION, 1),
        to_be_bytes(algo_class, 1),
        to_be_bytes(algo, 4),
        to_be_bytes(usage, 2),
    ])
]]></artwork>
          <t>It is also sometimes necessary to bind the output to some ephemeral value that
multiple parties need to agree on. We call this input the "binder string".</t>
        </section>
      </section>
    </section>
    <section anchor="prio3">
      <name>Prio3</name>
      <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>
          <t>Each measurement is encoded as a vector over some finite field.</t>
        </li>
        <li>
          <t>Measurement validity is determined by an arithmetic circuit evaluated over
the encoded measurement. (An "arithmetic circuit" is a function comprised of
arithmetic operations in the field.) The circuit's output is a single field
element: if zero, then the measurement is said to be "valid"; otherwise, if
the output is non-zero, then the measurement is said to be "invalid".</t>
        </li>
        <li>
          <t>The aggregate result is obtained by summing up the encoded measurement
vectors and computing some function of the sum.</t>
        </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 measurement (as determined by the arithmetic
circuit). This computation involves a "proof" of validity generated by the
Client. Next, each Aggregator sums up its 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 measurement 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 measurements. 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 measurement's validity and
distributes shares of the proof to the Aggregators. Each Aggregator then
performs some computation on its measurement 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 measurement.
(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>MEAS_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 measurement and proof</td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">Type of the measurement</td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">Type of the aggregate result</td>
            </tr>
            <tr>
              <td align="left">
                <tt>Field</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>
            <t><tt>Flp.prove(meas: 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 measurement, the "prover randomness"
<tt>prove_rand</tt>, and the "joint randomness" <tt>joint_rand</tt>. The prover randomness
is used only by the prover, but the joint randomness is shared by both the
prover and verifier.</t>
          </li>
          <li>
            <t><tt>Flp.query(meas: Vec[Field], proof: Vec[Field], query_rand: Vec[Field],
joint_rand: Vec[Field], num_shares: Unsigned) -&gt; Vec[Field]</tt> is the
query-generation algorithm run by the verifier. This is used to "query" the
measurement and proof. The result of the query (i.e., the output of this
function) is called the "verifier message". In addition to the measurement
and proof, this algorithm takes as input the query randomness <tt>query_rand</tt>
and the joint randomness <tt>joint_rand</tt>. The former is used only by the
verifier. <tt>num_shares</tt> specifies how many shares were generated.</t>
          </li>
          <li>
            <t><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 measurement from which it was generated
is valid.</t>
          </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 measurement and proof, the query-generation algorithm
outputs a share of the verifier message. Furthermore, the privacy property of
the FLP system ensures that the verifier message reveals nothing about the measurement
other than whether it is valid. Therefore, to decide if a measurement 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>The query-generation algorithm includes a parameter <tt>num_shares</tt> that specifies
the number of shares that were generated. If these data are not secret shared,
then <tt>num_shares == 1</tt>. This parameter is useful for certain FLP constructions.
For example, the FLP in <xref target="flp-generic"/> is defined in terms of an arithmetic
circuit; when the circuit contains constants, it is sometimes necessary to
normalize those constants to ensure that the circuit's output, when run on a
valid measurement, is the same regardless of the number of shares.</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, meas: 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(meas, prove_rand, joint_rand)

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

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

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

    # Verifier decides if the measurement is valid.
    return flp.decide(verifier)

]]></artwork>
        </figure>
        <t>The proof system is constructed so that, if <tt>meas</tt> is valid, then <tt>run_flp(Flp,
meas, 1)</tt> always returns <tt>True</tt>. On the other hand, if <tt>meas</tt> is invalid, then
as long as <tt>joint_rand</tt> and <tt>query_rand</tt> are generated uniform randomly, the
output is <tt>False</tt> with high probability. False positives are possible: there is
a small probability that a verifier accepts an invalid input as valid. An FLP
is said to be "sound" if this probability is sufficiently small. The soundness
of the FLP depends on a variety of parameters, like the length of the
input and the size of the field. See <xref target="flp-generic"/> for details.</t>
        <t>Note that soundness of an FLP system is not the same as robustness for a VDAF
In particular, soundness of the FLP is necessary, but insufficient for
robusntess of Prio3 (<xref target="prio3"/>). See <xref target="security-multiproof"/> for details.</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>
              <t><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>MEAS_LEN</tt>.</t>
            </li>
          </ul>
          <t>For some FLPs, the encoded measurement also includes redundant field elements
that are useful for checking the proof, but which are not needed after the
proof has been checked. An example is the "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, each representing a bit of the integer (this type is also
defined in <xref target="prio3sum"/>). After consuming this vector, all that is needed is
the integer it represents. Thus the FLP defines an algorithm for truncating the
encoded measurement to the length of the aggregated output:</t>
          <ul spacing="normal">
            <li>
              <t><tt>Flp.truncate(meas: Vec[Field]) -&gt; Vec[Field]</tt> maps an encoded measurement
(e.g., the bit-encoding of the measurement) to an aggregatable output (e.g.,
the singleton vector containing the measurement). The length of the input
<bcp14>MUST</bcp14> be <tt>MEAS_LEN</tt> and the length of the output <bcp14>MUST</bcp14> be <tt>OUTPUT_LEN</tt>.</t>
            </li>
          </ul>
          <t>Once the aggregate shares have been computed and combined together, their sum
can be converted into the aggregate result. This could be a projection from
the FLP's field to the integers, or it could include additional
post-processing.</t>
          <ul spacing="normal">
            <li>
              <t><tt>Flp.decode(output: Vec[Field], num_measurements: Unsigned) -&gt; AggResult</tt>
maps a sum of aggregate shares to an aggregate result. The length of the
input <bcp14>MUST</bcp14> be <tt>OUTPUT_LEN</tt>. <tt>num_measurements</tt> is the number of measurements
that contributed to the aggregated output.</t>
            </li>
          </ul>
          <t>We remark that, taken together, these three functionalities correspond roughly
to the notion of "Affine-aggregatable encodings (AFEs)" from <xref target="CGB17"/>.</t>
        </section>
        <section anchor="multiproofs">
          <name>Multiple Proofs</name>
          <t>It is sometimes desirable to generate and verify multiple independent proofs
for the same input. First, this improves the soundness of the proof system
without having to change any of its parameters. Second, it allows a smaller
field to be used (e.g., replace Field128 with Field64, see <xref target="flp-generic"/>)
without sacrificing soundness. Generally, choosing a smaller field can
significantly reduce communication cost. (This is a trade-off, of course, since
generating and verifying more proofs requires more time.) Given these benefits,
this feature is implemented by Prio3 (<xref target="prio3"/>).</t>
          <t>To generate these proofs for a specific measurement, the prover calls
<tt>Flp.prove</tt> multiple times, each time using an independently generated prover
and joint randomness string. The verifier checks each proof independently, each
time with an independently generated query randomness string. It accepts the
measurement only if all the decision algorithm accepts on each proof.</t>
          <t>See <xref target="security-multiproof"/> below for discussions on choosing the right number
of proofs.</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>Xof</tt>
(<xref target="xof"/>). It also has an associated constant, <tt>PROOFS</tt>,  with a value within
 the range of <tt>[1, 256)</tt>, denoting the number of FLPs generated by the Client
 (<xref target="multiproofs"/>). The value of <tt>PROOFS</tt> is <tt>1</tt> unless explicitly specified.</t>
        <t>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. These methods refer to constants enumerated in
 <xref target="prio3-const"/>.</t>
        <table anchor="prio3-param">
          <name>VDAF parameters for Prio3.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>VERIFY_KEY_SIZE</tt></td>
              <td align="left">
                <tt>Xof.SEED_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>RAND_SIZE</tt></td>
              <td align="left">
                <tt>Xof.SEED_SIZE * (1 + 2 * (SHARES - 1)) if Flp.JOINT_RAND_LEN == 0 else Xof.SEED_SIZE * (1 + 2 * (SHARES - 1) + SHARES)</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>NONCE_SIZE</tt></td>
              <td align="left">
                <tt>16</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>ROUNDS</tt></td>
              <td align="left">
                <tt>1</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>SHARES</tt></td>
              <td align="left">in <tt>[2, 256)</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>AggParam</tt></td>
              <td align="left">
                <tt>None</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PublicShare</tt></td>
              <td align="left">
                <tt>Optional[list[bytes]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>InputShare</tt></td>
              <td align="left">
                <tt>Union[tuple[list[Flp.Field], list[Flp.Field], Optional[bytes]], tuple[bytes, bytes, Optional[bytes]]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>OutShare</tt></td>
              <td align="left">
                <tt>list[Flp.Field]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggShare</tt></td>
              <td align="left">
                <tt>list[Flp.Field]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">
                <tt>Flp.AggResult</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepState</tt></td>
              <td align="left">
                <tt>tuple[list[Flp.Field], Optional[Bytes]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepShare</tt></td>
              <td align="left">
                <tt>tuple[list[Flp.Field], Optional[Bytes]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepMessage</tt></td>
              <td align="left">
                <tt>Optional[bytes]</tt></td>
            </tr>
          </tbody>
        </table>
        <table anchor="prio3-const">
          <name>Constants used by Prio3.</name>
          <thead>
            <tr>
              <th align="left">Variable</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>USAGE_MEAS_SHARE: Unsigned</tt></td>
              <td align="left">1</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_PROOF_SHARE: Unsigned</tt></td>
              <td align="left">2</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_JOINT_RANDOMNESS: Unsigned</tt></td>
              <td align="left">3</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_PROVE_RANDOMNESS: Unsigned</tt></td>
              <td align="left">4</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_QUERY_RANDOMNESS: Unsigned</tt></td>
              <td align="left">5</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_JOINT_RAND_SEED: Unsigned</tt></td>
              <td align="left">6</td>
            </tr>
            <tr>
              <td align="left">
                <tt>USAGE_JOINT_RAND_PART: Unsigned</tt></td>
              <td align="left">7</td>
            </tr>
          </tbody>
        </table>
        <section anchor="sharding">
          <name>Sharding</name>
          <t>Recall from <xref target="flp"/> that the FLP syntax calls for "joint randomness" shared by
the prover (i.e., the Client) and the verifier (i.e., the Aggregators). VDAFs
have no such notion. Instead, the Client derives the joint randomness from its
measurement in a way that allows the Aggregators to reconstruct it from their
shares. (This idea is based on the Fiat-Shamir heuristic and is described in
Section 6.2.3 of <xref target="BBCGGI19"/>.)</t>
          <t>The sharding algorithm involves the following steps:</t>
          <ol spacing="normal" type="1"><li>
              <t>Encode the Client's measurement for the FLP</t>
            </li>
            <li>
              <t>Shard the measurement into a sequence of measurement shares</t>
            </li>
            <li>
              <t>Derive the joint randomness from the measurement shares and nonce</t>
            </li>
            <li>
              <t>Run the FLP proof-generation algorithm using the derived joint randomness</t>
            </li>
            <li>
              <t>Shard the proof into a sequence of proof shares</t>
            </li>
            <li>
              <t>Return the public share, consisting of the joint randomness parts, and the
input shares, each consisting of the measurement share, proof share, and
blind of one of the Aggregators</t>
            </li>
          </ol>
          <t>As described in <xref target="multiproofs"/>, the soundness of the FLP can be amplified
by generating and verifying multiple FLPs. (This in turn improves the
robustness of Prio3.) To support this, in Prio3:</t>
          <ul spacing="normal">
            <li>
              <t>In step 3, derive as much joint randomness as required by <tt>PROOFS</tt> proofs</t>
            </li>
            <li>
              <t>Repeat step 4 <tt>PROOFS</tt> times, each time with a unique joint randomness</t>
            </li>
          </ul>
          <t>Depending on the FLP, joint randomness may not be required. In particular, when
<tt>Flp.JOINT_RAND_LEN == 0</tt>, the Client does not derive the joint randomness
(Step 3). The sharding algorithm is specified below.</t>
          <figure anchor="prio3-eval-input">
            <name>Input-distribution algorithm for Prio3.</name>
            <artwork><![CDATA[
def shard(Prio3, measurement, nonce, rand):
    l = Prio3.Xof.SEED_SIZE
    seeds = [rand[i:i+l] for i in range(0, Prio3.RAND_SIZE, l)]

    meas = Prio3.Flp.encode(measurement)
    if Prio3.Flp.JOINT_RAND_LEN > 0:
        return Prio3.shard_with_joint_rand(meas, nonce, seeds)
    else:
        return Prio3.shard_without_joint_rand(meas, seeds)
]]></artwork>
          </figure>
          <t>It starts by splitting the randomness into seeds. It then encodes the
measurement as prescribed by the FLP and calls one of two methods, depending on
whether joint randomness is required by the FLP. The methods are defined in the
subsections below.</t>
          <section anchor="flps-without-joint-randomness">
            <name>FLPs without joint randomness</name>
            <t>The following method is used for FLPs that do not require joint randomness,
i.e., when <tt>Flp.JOINT_RAND_LEN == 0</tt>:</t>
            <figure anchor="prio3-shard-without-joint-rand">
              <name>Sharding an encoded measurement without joint randomness.</name>
              <artwork><![CDATA[
def shard_without_joint_rand(Prio3, meas, seeds):
  k_helper_seeds, seeds = front((Prio3.SHARES-1) * 2, seeds)
  k_helper_meas_shares = [
      k_helper_seeds[i]
      for i in range(0, (Prio3.SHARES-1) * 2, 2)
  ]
  k_helper_proofs_shares = [
      k_helper_seeds[i]
      for i in range(1, (Prio3.SHARES-1) * 2, 2)
  ]
  (k_prove,), seeds = front(1, seeds)

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

  # Generate and shard each proof into shares.
  prove_rands = Prio3.prove_rands(k_prove)
  leader_proofs_share = []
  for _ in range(Prio3.PROOFS):
      prove_rand, prove_rands = front(
          Prio3.Flp.PROVE_RAND_LEN, prove_rands)
      leader_proofs_share += Prio3.Flp.prove(meas, prove_rand, [])
  for j in range(Prio3.SHARES-1):
      leader_proofs_share = vec_sub(
          leader_proofs_share,
          Prio3.helper_proofs_share(j+1, k_helper_proofs_shares[j]),
      )

  # Each Aggregator's input share contains its measurement share
  # and share of proof(s).
  input_shares = []
  input_shares.append((
      leader_meas_share,
      leader_proofs_share,
      None,
  ))
  for j in range(Prio3.SHARES-1):
      input_shares.append((
          k_helper_meas_shares[j],
          k_helper_proofs_shares[j],
          None,
      ))
  return (None, input_shares)
]]></artwork>
            </figure>
            <t>The steps in this method are as follows:</t>
            <ol spacing="normal" type="1"><li>
                <t>Shard the encoded measurement into shares</t>
              </li>
              <li>
                <t>Generate and shard each proof into shares</t>
              </li>
              <li>
                <t>Encode each measurement and shares of each proof into an input share</t>
              </li>
            </ol>
            <t>Notice that only one pair of measurement and proof(s) share (called the
"leader" shares above) are vectors of field elements. The other shares
(called the "helper" shares) are represented instead by XOF seeds, which
are expanded into vectors of field elements.</t>
            <t>The methods on <tt>Prio3</tt> for deriving the prover randomness, measurement shares,
and proof shares and the methods for encoding the input shares are defined in
<xref target="prio3-auxiliary"/>.</t>
          </section>
          <section anchor="flps-with-joint-randomness">
            <name>FLPs with joint randomness</name>
            <t>The following method is used for FLPs that require joint randomness,
i.e., for which <tt>Flp.JOINT_RAND_LEN &gt; 0</tt>:</t>
            <figure anchor="prio3-shard-with-joint-rand">
              <name>Sharding an encoded measurement with joint randomness.</name>
              <artwork><![CDATA[
def shard_with_joint_rand(Prio3, meas, nonce, seeds):
  k_helper_seeds, seeds = front((Prio3.SHARES-1) * 3, seeds)
  k_helper_meas_shares = [
      k_helper_seeds[i]
      for i in range(0, (Prio3.SHARES-1) * 3, 3)
  ]
  k_helper_proofs_shares = [
      k_helper_seeds[i]
      for i in range(1, (Prio3.SHARES-1) * 3, 3)
  ]
  k_helper_blinds = [
      k_helper_seeds[i]
      for i in range(2, (Prio3.SHARES-1) * 3, 3)
  ]
  (k_leader_blind,), seeds = front(1, seeds)
  (k_prove,), seeds = front(1, seeds)

  # Shard the encoded measurement into shares and compute the
  # joint randomness parts.
  leader_meas_share = meas
  k_joint_rand_parts = []
  for j in range(Prio3.SHARES-1):
      helper_meas_share = Prio3.helper_meas_share(
          j+1, k_helper_meas_shares[j])
      leader_meas_share = vec_sub(leader_meas_share,
                                  helper_meas_share)
      k_joint_rand_parts.append(Prio3.joint_rand_part(
          j+1, k_helper_blinds[j], helper_meas_share, nonce))
  k_joint_rand_parts.insert(0, Prio3.joint_rand_part(
      0, k_leader_blind, leader_meas_share, nonce))

  # Generate and shard each proof into shares.
  prove_rands = Prio3.prove_rands(k_prove)
  joint_rands = Prio3.joint_rands(
      Prio3.joint_rand_seed(k_joint_rand_parts))
  leader_proofs_share = []
  for _ in range(Prio3.PROOFS):
      prove_rand, prove_rands = front(
          Prio3.Flp.PROVE_RAND_LEN, prove_rands)
      joint_rand, joint_rands = front(
          Prio3.Flp.JOINT_RAND_LEN, joint_rands)
      leader_proofs_share += Prio3.Flp.prove(meas,
                                             prove_rand, joint_rand)
  for j in range(Prio3.SHARES-1):
      leader_proofs_share = vec_sub(
          leader_proofs_share,
          Prio3.helper_proofs_share(j+1, k_helper_proofs_shares[j]),
      )

  # Each Aggregator's input share contains its measurement share,
  # share of proof(s), and blind. The public share contains the
  # Aggregators' joint randomness parts.
  input_shares = []
  input_shares.append((
      leader_meas_share,
      leader_proofs_share,
      k_leader_blind,
  ))
  for j in range(Prio3.SHARES-1):
      input_shares.append((
          k_helper_meas_shares[j],
          k_helper_proofs_shares[j],
          k_helper_blinds[j],
      ))
  return (k_joint_rand_parts, input_shares)
]]></artwork>
            </figure>
            <t>The difference between this procedure and previous one is that here we compute
joint randomnesses <tt>joint_rands</tt>, split it into multiple <tt>joint_rand</tt>,
and pass each <tt>joint_rand</tt> to the proof generationg algorithm.
(In <xref target="prio3-shard-without-joint-rand"/> the joint randomness is the empty
vector, <tt>[]</tt>.) This requires generating an additional value, called the
"blind", that is incorporated into each input share.</t>
            <t>The joint randomness computation involves the following steps:</t>
            <ol spacing="normal" type="1"><li>
                <t>Compute a "joint randomness part" from each measurement share and blind</t>
              </li>
              <li>
                <t>Compute a "joint randomness seed" from the joint randomness parts</t>
              </li>
              <li>
                <t>Compute the joint randomness for each proof evaluation from the joint randomness seed</t>
              </li>
            </ol>
            <t>This three-step process is designed to ensure that the joint randomness does
not leak the measurement to the Aggregators while preventing a malicious Client
from tampering with the joint randomness in a way that allows it to break
robustness. To bootstrap the required check, the Client encodes the joint
randomness parts in the public share. (See <xref target="prio3-preparation"/> for details.)</t>
            <t>The methods used in this computation are defined in <xref target="prio3-auxiliary"/>.</t>
          </section>
        </section>
        <section anchor="prio3-preparation">
          <name>Preparation</name>
          <t>This section describes the process of recovering output shares from the input
shares. The high-level idea is that each Aggregator first queries its
measurement and share of proof(s) locally, then exchanges its share of
verifier(s) with the other Aggregators. The shares of verifier(s) are then
combined into the verifier message(s) used to decide whether to accept.</t>
          <t>In addition, for FLPs that require joint randomness, the Aggregators must
ensure that they have all used the same joint randomness for the
query-generation algorithm. To do so, they collectively re-derive the joint
randomness from their measurement shares just as the Client did during
sharding.</t>
          <t>In order to avoid extra round of communication, the Client sends each
Aggregator a "hint" consisting of the joint randomness parts. This leaves open
the possibility that the Client cheated by, say, forcing the Aggregators to use
joint randomness that biases the proof check procedure some way in its favor.
To mitigate this, the Aggregators also check that they have all computed the
same joint randomness seed before accepting their output shares. To do so, they
exchange their parts of the joint randomness along with their shares of
verifier(s).</t>
          <t>The definitions of constants and a few auxiliary functions are defined in
<xref target="prio3-auxiliary"/>.</t>
          <figure anchor="prio3-prep-state">
            <name>Preparation state for Prio3.</name>
            <artwork><![CDATA[
def prep_init(Prio3, verify_key, agg_id, _agg_param,
            nonce, public_share, input_share):
  k_joint_rand_parts = public_share
  (meas_share, proofs_share, k_blind) = \
      Prio3.expand_input_share(agg_id, input_share)
  out_share = Prio3.Flp.truncate(meas_share)

  # Compute the joint randomness.
  joint_rand = []
  k_corrected_joint_rand, k_joint_rand_part = None, None
  if Prio3.Flp.JOINT_RAND_LEN > 0:
      k_joint_rand_part = Prio3.joint_rand_part(
          agg_id, k_blind, meas_share, nonce)
      k_joint_rand_parts[agg_id] = k_joint_rand_part
      k_corrected_joint_rand = Prio3.joint_rand_seed(
          k_joint_rand_parts)
      joint_rands = Prio3.joint_rands(k_corrected_joint_rand)

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

  prep_state = (out_share, k_corrected_joint_rand)
  prep_share = (verifiers_share, k_joint_rand_part)
  return (prep_state, prep_share)

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

  # If joint randomness was used, check that the value computed by the
  # Aggregators matches the value indicated by the Client.
  if k_joint_rand != k_corrected_joint_rand:
      raise ERR_VERIFY  # joint randomness check failed

  return out_share

def prep_shares_to_prep(Prio3, _agg_param, prep_shares):
  # Unshard the verifier shares into the verifier message.
  verifiers = Prio3.Flp.Field.zeros(
      Prio3.Flp.VERIFIER_LEN * Prio3.PROOFS)
  k_joint_rand_parts = []
  for (verifiers_share, k_joint_rand_part) in prep_shares:
      verifiers = vec_add(verifiers, verifiers_share)
      if Prio3.Flp.JOINT_RAND_LEN > 0:
          k_joint_rand_parts.append(k_joint_rand_part)

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

  # Combine the joint randomness parts computed by the
  # Aggregators into the true joint randomness seed. This is
  # used in the last step.
  k_joint_rand = None
  if Prio3.Flp.JOINT_RAND_LEN > 0:
      k_joint_rand = Prio3.joint_rand_seed(k_joint_rand_parts)
  return k_joint_rand
]]></artwork>
          </figure>
        </section>
        <section anchor="validity-of-aggregation-parameters">
          <name>Validity of Aggregation Parameters</name>
          <t>Every input share <bcp14>MUST</bcp14> only be used once, regardless of the aggregation
parameters used.</t>
          <figure anchor="prio3-validity-scope">
            <name>Validity of aggregation parameters for Prio3.</name>
            <artwork><![CDATA[
def is_valid(Prio3, agg_param, previous_agg_params):
    return len(previous_agg_params) == 0
]]></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 aggregate(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 unshard(Prio3, _agg_param,
            agg_shares, num_measurements):
    agg = Prio3.Flp.Field.zeros(Prio3.Flp.OUTPUT_LEN)
    for agg_share in agg_shares:
        agg = vec_add(agg, agg_share)
    return Prio3.Flp.decode(agg, num_measurements)
]]></artwork>
          </figure>
        </section>
        <section anchor="prio3-auxiliary">
          <name>Auxiliary Functions</name>
          <t>This section defines a number of auxiliary functions referenced by the main
algorithms for Prio3 in the preceding sections.</t>
          <t>The following methods are called by the sharding and preparation algorithms.</t>
          <artwork><![CDATA[
def helper_meas_share(Prio3, agg_id, k_share):
    return Prio3.Xof.expand_into_vec(
        Prio3.Flp.Field,
        k_share,
        Prio3.domain_separation_tag(USAGE_MEAS_SHARE),
        byte(agg_id),
        Prio3.Flp.MEAS_LEN,
    )

def helper_proofs_share(Prio3, agg_id, k_share):
  return Prio3.Xof.expand_into_vec(
      Prio3.Flp.Field,
      k_share,
      Prio3.domain_separation_tag(USAGE_PROOF_SHARE),
      byte(Prio3.PROOFS) + byte(agg_id),
      Prio3.Flp.PROOF_LEN * Prio3.PROOFS,
  )

def expand_input_share(Prio3, agg_id, input_share):
  (meas_share, proofs_share, k_blind) = input_share
  if agg_id > 0:
      meas_share = Prio3.helper_meas_share(agg_id, meas_share)
      proofs_share = Prio3.helper_proofs_share(agg_id, proofs_share)
  return (meas_share, proofs_share, k_blind)

def prove_rands(Prio3, k_prove):
  return Prio3.Xof.expand_into_vec(
      Prio3.Flp.Field,
      k_prove,
      Prio3.domain_separation_tag(USAGE_PROVE_RANDOMNESS),
      byte(Prio3.PROOFS),
      Prio3.Flp.PROVE_RAND_LEN * Prio3.PROOFS,
  )

def query_rands(Prio3, verify_key, nonce):
  return Prio3.Xof.expand_into_vec(
      Prio3.Flp.Field,
      verify_key,
      Prio3.domain_separation_tag(USAGE_QUERY_RANDOMNESS),
      byte(Prio3.PROOFS) + nonce,
      Prio3.Flp.QUERY_RAND_LEN * Prio3.PROOFS,
  )

def joint_rand_part(Prio3, agg_id, k_blind, meas_share, nonce):
    return Prio3.Xof.derive_seed(
        k_blind,
        Prio3.domain_separation_tag(USAGE_JOINT_RAND_PART),
        byte(agg_id) + nonce + Prio3.Flp.Field.encode_vec(meas_share),
    )

def joint_rand_seed(Prio3, k_joint_rand_parts):
    """Derive the joint randomness seed from its parts."""
    return Prio3.Xof.derive_seed(
        zeros(Prio3.Xof.SEED_SIZE),
        Prio3.domain_separation_tag(USAGE_JOINT_RAND_SEED),
        concat(k_joint_rand_parts),
    )

def joint_rands(Prio3, k_joint_rand_seed):
  """Derive the joint randomness from its seed."""
  return Prio3.Xof.expand_into_vec(
      Prio3.Flp.Field,
      k_joint_rand_seed,
      Prio3.domain_separation_tag(USAGE_JOINT_RANDOMNESS),
      byte(Prio3.PROOFS),
      Prio3.Flp.JOINT_RAND_LEN * Prio3.PROOFS,
  )
]]></artwork>
        </section>
        <section anchor="prio3-encode">
          <name>Message Serialization</name>
          <t>This section defines serialization formats for messages exchanged over the
network while executing Prio3. It is <bcp14>RECOMMENDED</bcp14> that implementations provide
serialization methods for them.</t>
          <t>Message structures are defined following <xref section="3" sectionFormat="of" target="RFC8446"/>). In the
remainder we use <tt>S</tt> as an alias for <tt>Prio3.Xof.SEED_SIZE</tt> and <tt>F</tt> as an alias
for <tt>Prio3.Field.ENCODED_SIZE</tt>. XOF seeds are represented as follows:</t>
          <artwork><![CDATA[
opaque Prio3Seed[S];
]]></artwork>
          <t>Field elements are encoded in little-endian byte order (as defined in
<xref target="field"/>) and represented as follows:</t>
          <artwork><![CDATA[
opaque Prio3Field[F];
]]></artwork>
          <section anchor="public-share">
            <name>Public Share</name>
            <t>The encoding of the public share depends on whether joint randomness is
required for the underlying FLP (i.e., <tt>Prio3.Flp.JOINT_RAND_LEN &gt; 0</tt>). If
joint randomness is not used, then the public share is the empty string. If
joint randomness is used, then the public share encodes the joint randomness
parts as follows:</t>
            <artwork><![CDATA[
struct {
    Prio3Seed k_joint_rand_parts[S * Prio3.SHARES];
} Prio3PublicShareWithJointRand;
]]></artwork>
          </section>
          <section anchor="input-share">
            <name>Input share</name>
            <t>Just as for the public share, the encoding of the input shares depends on
whether joint randomness is used. If so, then each input share includes the
Aggregator's blind for generating its joint randomness part.</t>
            <t>In addition, the encoding of the input shares depends on which aggregator is
receiving the message. If the aggregator ID is <tt>0</tt>, then the input share
includes the full measurement and share of proof(s). Otherwise, if the aggregator ID
is greater than <tt>0</tt>, then the measurement and shares of proof(s) are represented
by XOF seeds. We shall call the former the "Leader" and the latter the
"Helpers".</t>
            <t>In total there are four variants of the input share. When joint randomness is
not used, the Leader's share is structured as follows:</t>
            <artwork><![CDATA[
struct {
    Prio3Field meas_share[F * Prio3.Flp.MEAS_LEN];
    Prio3Field proofs_share[F * Prio3.Flp.PROOF_LEN * Prio3.PROOFS];
} Prio3LeaderShare;
]]></artwork>
            <t>When joint randomness is not used, the Helpers' shares are structured
as follows:</t>
            <artwork><![CDATA[
struct {
    Prio3Seed k_meas_share;
    Prio3Seed k_proofs_share;
} Prio3HelperShare;
]]></artwork>
            <t>When joint randomness is used, the Leader's input share is structured as
follows:</t>
            <artwork><![CDATA[
struct {
    Prio3LeaderShare inner;
    Prio3Seed k_blind;
} Prio3LeaderShareWithJointRand;
]]></artwork>
            <t>Finally, when joint randomness is used, the Helpers' shares are structured as
follows:</t>
            <artwork><![CDATA[
struct {
    Prio3HelperShare inner;
    Prio3Seed k_blind;
} Prio3HelperShareWithJointRand;
]]></artwork>
          </section>
          <section anchor="prep-share">
            <name>Prep Share</name>
            <t>When joint randomness is not used, the prep share is structured as follows:</t>
            <artwork><![CDATA[
struct {
    Prio3Field verifiers_share[F * Prio3.Flp.VERIFIER_LEN * Prio3.PROOFS];
} Prio3PrepShare;
]]></artwork>
            <t>When joint randomness is used, the prep share includes the Aggregator's joint
randomness part and is structured as follows:</t>
            <artwork><![CDATA[
struct {
    Prio3Field verifiers_share[F * Prio3.Flp.VERIFIER_LEN * Prio3.PROOFS];
    Prio3Seed k_joint_rand_part;
} Prio3PrepShareWithJointRand;
]]></artwork>
          </section>
          <section anchor="prep-message">
            <name>Prep Message</name>
            <t>When joint randomness is not used, the prep message is the empty string.
Otherwise the prep message consists of the joint randomness seed computed by
the Aggregators:</t>
            <artwork><![CDATA[
struct {
    Prio3Seed k_joint_rand;
} Prio3PrepMessageWithJointRand;
]]></artwork>
          </section>
          <section anchor="aggregation-1">
            <name>Aggregation</name>
            <t>Aggregate shares are structured as follows:</t>
            <artwork><![CDATA[
struct {
    Prio3Field agg_share[F * Prio3.Flp.OUTPUT_LEN];
} Prio3AggShare;
]]></artwork>
          </section>
        </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/cfrg/draft-irtf-cfrg-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 encoded measurement: If the circuit output is zero,
then the measurement is deemed valid; otherwise, if the circuit output is
non-zero, then the measurement is deemed invalid. Thus the goal of the proof
system is merely to allow the verifier to evaluate the validity circuit over
the measurement. For our application (<xref target="prio3"/>), this computation is
distributed among multiple Aggregators, each of which has only a share of the
measurement.</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 a measurement <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 measurement 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 measurement 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 measurement 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 of <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 measurement shares in
Prio3; see <xref target="prio3-construction"/>). This allows for circuit optimizations that
trade a small soundness error for a shorter proof. For example, consider a
circuit that recognizes the set of length-<tt>N</tt> vectors for which each element is
either one or zero. A deterministic circuit could be constructed for this
language, but it would involve a large number of multiplications that would
result in a large proof. (See the discussion in <xref target="BBCGGI19"/>, Section 5.2 for
details). A much shorter proof can be constructed for the following randomized
circuit:</t>
            <artwork><![CDATA[
C(meas, r) = r * Range2(meas[0]) + ... + r^N * Range2(meas[N-1])
]]></artwork>
            <t>(Note that this is a special case of <xref target="BBCGGI19"/>, Theorem 5.2.) Here <tt>meas</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>meas</tt> is valid (i.e., each <tt>meas[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>meas[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.) This provides additional flexibility for designing
circuits by allowing multiple, non-affine sub-components. For example, the
following circuit is allowed:</t>
            <artwork><![CDATA[
C(meas, r) = r * Range2(meas[0]) + ... + r^L * Range2(meas[L-1]) + \
            r^(L+1) * Range3(meas[L]) + ... + r^N * Range3(meas[N-1])
]]></artwork>
            <t>where <tt>Range3(x) = x^3 - 3x^2 + 2x</tt>. This circuit checks that the first <tt>L</tt>
inputs are in range <tt>[0,2)</tt> and the last <tt>N-L</tt> inputs are in range <tt>[0,3)</tt>. Of
course, the same circuit can be expressed using a sub-component that the
gadgets have in common, namely <tt>Mul</tt>, but the resulting proof would be longer.</t>
            <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>MEAS_LEN</tt></td>
                <td align="left">Length of the measurement</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>AggResult</tt></td>
                <td align="left">Type of the aggregate result</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>Gadgets provide a method to evaluate their circuit on a list of inputs,
<tt>eval()</tt>. The inputs can either belong to the validity circuit's field, or the
polynomial ring over that field.</t>
          <t>A concrete <tt>Valid</tt> provides the following methods for encoding a measurement as
an input vector, truncating an input vector to the length of an aggregatable
output, and converting an aggregated output to an aggregate result:</t>
          <ul spacing="normal">
            <li>
              <t><tt>Valid.encode(measurement: Measurement) -&gt; Vec[Field]</tt> returns a vector of
length <tt>MEAS_LEN</tt> representing a measurement.</t>
            </li>
            <li>
              <t><tt>Valid.truncate(meas: Vec[Field]) -&gt; Vec[Field]</tt> returns a vector of length
<tt>OUTPUT_LEN</tt> representing an aggregatable output.</t>
            </li>
            <li>
              <t><tt>Valid.decode(output: Vec[Field], num_measurements: Unsigned) -&gt; AggResult</tt>
returns an aggregate result.</t>
            </li>
          </ul>
          <t>Finally, the following methods are derived for each concrete <tt>Valid</tt>:</t>
          <figure>
            <name>Derived methods for validity circuits.</name>
            <artwork><![CDATA[
def prove_rand_len(self):
    """Length of the prover randomness."""
    return sum(g.ARITY for g in Valid.GADGETS)

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

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

def verifier_len(self):
    """Length of the verifier message."""
    length = 1
    for g in self.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/cfrg/draft-irtf-cfrg-vdaf/blob/main/poc/flp_generic.py.</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>
              <t>Let <tt>H = len(Valid.GADGETS)</tt></t>
            </li>
            <li>
              <t>For each <tt>i</tt> in <tt>[H]</tt>:
              </t>
              <ul spacing="normal">
                <li>
                  <t>Let <tt>G_i = Valid.GADGETS[i]</tt></t>
                </li>
                <li>
                  <t>Let <tt>L_i = Valid.GADGETS[i].ARITY</tt></t>
                </li>
                <li>
                  <t>Let <tt>M_i = Valid.GADGET_CALLS[i]</tt></t>
                </li>
                <li>
                  <t>Let <tt>P_i = next_power_of_2(M_i+1)</tt></t>
                </li>
                <li>
                  <t>Let <tt>alpha_i = Field.gen()^(Field.GEN_ORDER / P_i)</tt></t>
                </li>
              </ul>
            </li>
          </ul>
          <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>MEAS_LEN</tt></td>
                <td align="left">
                  <tt>Valid.MEAS_LEN</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>Valid.OUTPUT_LEN</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>PROOF_LEN</tt></td>
                <td align="left">
                  <tt>Valid.proof_len()</tt> (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 of <tt>meas</tt>, <tt>prove_rand</tt>, and <tt>joint_rand</tt>, the proof is computed as
follows:</t>
            <ol spacing="normal" type="1"><li>
                <t>For each <tt>i</tt> in <tt>[H]</tt> create an empty table <tt>wire_i</tt>.</t>
              </li>
              <li>
                <t>Partition the prover randomness <tt>prove_rand</tt> into sub-vectors <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.</t>
              </li>
              <li>
                <t>Evaluate <tt>Valid</tt> on input of <tt>meas</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>.</t>
              </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>
                    <t>Let <tt>w = [seed_i[j-1], wire_i[j-1,0], ..., wire_i[j-1,M_i-1]]</tt>.</t>
                  </li>
                  <li>
                    <t>Let <tt>padded_w = w + Field.zeros(P_i - len(w))</tt>.</t>
                  </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>
                    <t>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>.</t>
                  </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>
                    <t>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>.)</t>
                  </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>meas</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>
                <t>For every <tt>i</tt> in <tt>[H]</tt> create an empty table <tt>wire_i</tt>.</t>
              </li>
              <li>
                <t>Partition <tt>proof</tt> into the sub-vectors <tt>seed_1</tt>, <tt>coeff_1</tt>, ..., <tt>seed_H</tt>,
<tt>coeff_H</tt> defined in <xref target="flp-generic-construction-prove"/>.</t>
              </li>
              <li>
                <t>Evaluate <tt>Valid</tt> on input of <tt>meas</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.</t>
              </li>
              <li>
                <t>Compute the wire polynomials just as in the prover's step (4.).</t>
              </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>
                    <t>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.)</t>
                  </li>
                  <li>
                    <t>Let <tt>y_i = poly_gadget_i(t)</tt>.</t>
                  </li>
                  <li>
                    <t>For each <tt>j</tt> in <tt>[0,L_i)</tt> let <tt>x_i[j-1] = poly_wire_i[j-1](t)</tt>.</t>
                  </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 measurement is valid
as follows:</t>
            <ol spacing="normal" type="1"><li>
                <t>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"/>.</t>
              </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>
                    <t>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.</t>
                  </li>
                  <li>
                    <t>If <tt>z != y_i</tt>, then return <tt>False</tt> and halt.</t>
                  </li>
                </ul>
              </li>
              <li>
                <t>Return <tt>True</tt> if <tt>v == 0</tt> and <tt>False</tt> otherwise.</t>
              </li>
            </ol>
          </section>
          <section anchor="encoding">
            <name>Encoding</name>
            <t>The FLP encoding and truncation methods invoke <tt>Valid.encode</tt>,
<tt>Valid.truncate</tt>, and <tt>Valid.decode</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 XOF (<xref target="xof"/>). 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/cfrg/draft-irtf-cfrg-vdaf/blob/main/poc/vdaf_prio3.sage.</t>
          </li>
        </ul>
        <section anchor="prio3count">
          <name>Prio3Count</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 XofTurboShake128 (<xref target="xof-turboshake128"/>) as its XOF. Its
validity circuit, denoted <tt>Count</tt>, uses <tt>Field64</tt> (<xref target="fields"/>) as its finite
field. Its gadget, denoted <tt>Mul</tt>, is the degree-2, arity-2 gadget defined as</t>
          <artwork><![CDATA[
def eval(self, Field, inp):
    self.check_gadget_eval(inp)
    return inp[0] * inp[1]
]]></artwork>
          <t>The call to <tt>check_gadget_eval()</tt> raises an error if the length of the input is
not equal to the gadget's <tt>ARITY</tt> parameter.</t>
          <t>The <tt>Count</tt> validity circuit is defined as</t>
          <artwork><![CDATA[
def eval(self, meas, joint_rand, _num_shares):
    return self.GADGETS[0].eval(self.Field, [meas[0], meas[0]]) \
        - meas[0]
]]></artwork>
          <t>The measurement is encoded and decoded as a singleton vector in the natural
way. The parameters for this circuit are summarized below.</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>MEAS_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>AggResult</tt></td>
                <td align="left">
                  <tt>Unsigned</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field64</tt> (<xref target="fields"/>)</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section anchor="prio3sum">
          <name>Prio3Sum</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 XofTurboShake128 (<xref target="xof-turboshake128"/>) as its
XOF. Its validity circuit, denoted <tt>Sum</tt>, uses <tt>Field128</tt> (<xref target="fields"/>) 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(self, measurement):
    if 0 > measurement or measurement >= 2 ** self.MEAS_LEN:
        raise ERR_INPUT

    return self.Field.encode_into_bit_vector(measurement,
                                             self.MEAS_LEN)

def truncate(self, meas):
    return [self.Field.decode_from_bit_vector(meas)]

def decode(self, output, _num_measurements):
    return output[0].as_unsigned()
]]></artwork>
          <t>The validity circuit checks that the input consists of ones and zeros. Its
gadget, denoted <tt>Range2</tt>, is the degree-2, arity-1 gadget defined as</t>
          <artwork><![CDATA[
def eval(self, Field, inp):
    self.check_gadget_eval(inp)
    return inp[0] * inp[0] - inp[0]
]]></artwork>
          <t>The <tt>Sum</tt> validity circuit is defined as</t>
          <artwork><![CDATA[
def eval(self, meas, joint_rand, _num_shares):
    self.check_valid_eval(meas, joint_rand)
    out = self.Field(0)
    r = joint_rand[0]
    for b in meas:
        out += r * self.GADGETS[0].eval(self.Field, [b])
        r *= joint_rand[0]
    return out
]]></artwork>
          <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>MEAS_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>AggResult</tt></td>
                <td align="left">
                  <tt>Unsigned</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section anchor="prio3sumvec">
          <name>Prio3SumVec</name>
          <t>This instance of Prio3 supports summing a vector of integers. It has three
parameters, <tt>length</tt>, <tt>bits</tt>, and <tt>chunk_length</tt>. Each measurement is a vector
of positive integers with length equal to the <tt>length</tt> parameter. Each element
of the measurement is an integer in the range <tt>[0, 2^bits)</tt>. It is <bcp14>RECOMMENDED</bcp14>
to set <tt>chunk_length</tt> to an integer near the square root of <tt>length * bits</tt>
(see <xref target="parallel-sum-chunk-length"/>).</t>
          <t>This instance uses XofTurboShake128 (<xref target="xof-turboshake128"/>) as its XOF. Its
validity circuit, denoted <tt>SumVec</tt>, uses <tt>Field128</tt> (<xref target="fields"/>) as its finite
field.</t>
          <t>Measurements are encoded as a vector of field elements with length <tt>length *
bits</tt>. The field elements in the encoded vector represent all the bits of the
measurement vector's elements, consecutively, in LSB to MSB order:</t>
          <artwork><![CDATA[
def encode(self, measurement: Vec[Unsigned]):
    if len(measurement) != self.length:
        raise ERR_INPUT

    encoded = []
    for val in measurement:
        if 0 > val or val >= 2 ** self.bits:
            raise ERR_INPUT

        encoded += self.Field.encode_into_bit_vector(val, self.bits)
    return encoded

def truncate(self, meas):
    truncated = []
    for i in range(self.length):
        truncated.append(self.Field.decode_from_bit_vector(
            meas[i * self.bits: (i + 1) * self.bits]
        ))
    return truncated

def decode(self, output, _num_measurements):
    return [x.as_unsigned() for x in output]
]]></artwork>
          <t>This validity circuit uses a <tt>ParallelSum</tt> gadget to achieve a smaller proof
size. This optimization for "parallel-sum circuits" is described in
<xref target="BBCGGI19"/>, section 4.4. Briefly, for circuits that add up the output of
multiple identical subcircuits, it is possible to achieve smaller proof sizes
(on the order of O(sqrt(MEAS_LEN)) instead of O(MEAS_LEN)) by packaging more
than one such subcircuit into a gadget.</t>
          <t>The <tt>ParallelSum</tt> gadget is parameterized with an arithmetic subcircuit, and a
<tt>count</tt> of how many times it evaluates that subcircuit. It takes in a list of
inputs and passes them through to instances of the subcircuit in the same order.
It returns the sum of the subcircuit outputs. Note that only the <tt>ParallelSum</tt>
gadget itself, and not its subcircuit, participates in <tt>FlpGeneric</tt>'s wire
recording during evaluation, gadget consistency proofs, and proof validation,
even though the subcircuit is provided to <tt>ParallelSum</tt> as an implementation
of the <tt>Gadget</tt> interface.</t>
          <artwork><![CDATA[
def eval(self, Field, inp):
    self.check_gadget_eval(inp)
    out = Field(0)
    for i in range(self.count):
        start_index = i * self.subcircuit.ARITY
        end_index = (i + 1) * self.subcircuit.ARITY
        out += self.subcircuit.eval(Field, inp[start_index:end_index])
    return out
]]></artwork>
          <t>The <tt>SumVec</tt> validity circuit checks that the encoded measurement consists of
ones and zeros. Rather than use the <tt>Range2</tt> gadget on each element, as in the
<tt>Sum</tt> validity circuit, it instead uses <tt>Mul</tt> subcircuits and "free" constant
multiplication and addition gates to simultaneously evaluate the same range
check polynomial on each element, and multiply by a constant. One of the two
<tt>Mul</tt> subcircuit inputs is equal to a measurement element multiplied by a power
of the joint randomness value, and the other is equal to the same measurement
element minus one. These <tt>Mul</tt> subcircuits are evaluated by a <tt>ParallelSum</tt>
gadget, and the results are added up both within the <tt>ParallelSum</tt> gadget and
after it.</t>
          <artwork><![CDATA[
def eval(self, meas, joint_rand, num_shares):
    self.check_valid_eval(meas, joint_rand)

    out = Field128(0)
    r = joint_rand[0]
    r_power = r
    shares_inv = self.Field(num_shares).inv()

    for i in range(self.GADGET_CALLS[0]):
        inputs = [None] * (2 * self.chunk_length)
        for j in range(self.chunk_length):
            index = i * self.chunk_length + j
            if index < len(meas):
                meas_elem = meas[index]
            else:
                meas_elem = self.Field(0)

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

            r_power *= r

        out += self.GADGETS[0].eval(self.Field, inputs)

    return out
]]></artwork>
          <table>
            <name>Parameters of validity circuit SumVec.</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>[ParallelSum(Mul(), chunk_length)]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[(length * bits + chunk_length - 1) // chunk_length]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>MEAS_LEN</tt></td>
                <td align="left">
                  <tt>length * bits</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>length</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>Vec[Unsigned]</tt>, each element in range <tt>[0, 2^bits)</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">
                  <tt>Vec[Unsigned]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
            </tbody>
          </table>
          <section anchor="parallel-sum-chunk-length">
            <name>Selection of <tt>ParallelSum</tt> chunk length</name>
            <t>The <tt>chunk_length</tt> parameter provides a trade-off between the arity of the
<tt>ParallelSum</tt> gadget and the number of times the gadget is called. The proof
length is asymptotically minimized when the chunk length is near the square root
of the length of the measurement. However, the relationship between VDAF
parameters and proof length is complicated, involving two forms of rounding (the
circuit pads the inputs to its last <tt>ParallelSum</tt> gadget call, up to the chunk
length, and FlpGeneric rounds the degree of wire polynomials -- determined by
the number of times a gadget is called -- up to the next power of two).
Therefore, the optimal choice of <tt>chunk_length</tt> for a concrete measurement size
will vary, and must be found through trial and error. Setting <tt>chunk_length</tt>
equal to the square root of the appropriate measurement length will result in
proofs up to 50% larger than the optimal proof size.</t>
          </section>
        </section>
        <section anchor="prio3histogram">
          <name>Prio3Histogram</name>
          <t>This instance of Prio3 allows for estimating the distribution of some quantity
by computing a simple histogram. Each measurement increments one histogram
bucket, out of a set of fixed buckets. (Bucket indexing begins at <tt>0</tt>.) For
example, the buckets might quantize the real numbers, and each measurement would
report the bucket that the corresponding client's real-numbered value falls
into. The aggregate result counts the number of measurements in each bucket.</t>
          <t>This instance of Prio3 uses XofTurboShake128 (<xref target="xof-turboshake128"/>) as its
XOF. Its validity circuit, denoted <tt>Histogram</tt>, uses <tt>Field128</tt> (<xref target="fields"/>) as
its finite field. It has two parameters, <tt>length</tt>, the number of histogram
buckets, and <tt>chunk_length</tt>, which is used by by a circuit optimization
described below. It is <bcp14>RECOMMENDED</bcp14> to set <tt>chunk_length</tt> to an integer near the
square root of <tt>length</tt> (see <xref target="parallel-sum-chunk-length"/>).</t>
          <t>The measurement is encoded as a one-hot vector representing the bucket into
which the measurement falls:</t>
          <artwork><![CDATA[
def encode(self, measurement):
    encoded = [self.Field(0)] * self.length
    encoded[measurement] = self.Field(1)
    return encoded

def truncate(self, meas):
    return meas

def decode(self, output, _num_measurements):
    return [bucket_count.as_unsigned() for bucket_count in output]
]]></artwork>
          <t>The <tt>Histogram</tt> validity circuit checks for one-hotness in two steps, by
checking that the encoded measurement consists of ones and zeros, and by
checking that the sum of all elements in the encoded measurement is equal to
one. All the individual checks are combined together in a random linear
combination.</t>
          <t>As in the <tt>SumVec</tt> validity circuit (<xref target="prio3sumvec"/>), the first part of the
validity circuit uses the <tt>ParallelSum</tt> gadget to perform range checks while
achieving a smaller proof size. The <tt>ParallelSum</tt> gadget uses <tt>Mul</tt> subcircuits
to evaluate a range check polynomial on each element, and includes an additional
constant multiplication. One of the two <tt>Mul</tt> subcircuit inputs is equal to a
measurement element multiplied by a power of the first joint randomness value,
and the other is equal to the same measurement element minus one. The results
are added up both within the <tt>ParallelSum</tt> gadget and after it.</t>
          <artwork><![CDATA[
def eval(self, meas, joint_rand, num_shares):
    self.check_valid_eval(meas, joint_rand)

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

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

            r_power *= r

        range_check += r * self.GADGETS[0].eval(self.Field, inputs)

    # Check that the buckets sum to 1.
    sum_check = -shares_inv
    for b in meas:
        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
measurement is sharded. This is provided to the FLP by Prio3.</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>[ParallelSum(Mul(), chunk_length)]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>GADGET_CALLS</tt></td>
                <td align="left">
                  <tt>[(length + chunk_length - 1) // chunk_length]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>MEAS_LEN</tt></td>
                <td align="left">
                  <tt>length</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>OUTPUT_LEN</tt></td>
                <td align="left">
                  <tt>length</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>Unsigned</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>AggResult</tt></td>
                <td align="left">
                  <tt>Vec[Unsigned]</tt></td>
              </tr>
              <tr>
                <td align="left">
                  <tt>Field</tt></td>
                <td align="left">
                  <tt>Field128</tt> (<xref target="fields"/>)</td>
              </tr>
            </tbody>
          </table>
        </section>
      </section>
    </section>
    <section anchor="poplar1">
      <name>Poplar1</name>
      <t>This section specifies Poplar1, a VDAF for the following task. Each Client holds
a string of length <tt>BITS</tt> 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 measurements are prefixed
by each candidate prefix.</t>
      <t>This functionality is the core component of the Poplar protocol <xref target="BBCGGI21"/>,
which was designed to compute the heavy hitters over a set of input strings. At
a high level, the protocol works as follows.</t>
      <ol spacing="normal" type="1"><li>
          <t>Each Client splits its string into input shares and sends one share to each
Aggregator.</t>
        </li>
        <li>
          <t>The Aggregators agree on an initial set of candidate prefixes, say <tt>0</tt> and
<tt>1</tt>.</t>
        </li>
        <li>
          <t>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.</t>
        </li>
        <li>
          <t>The Aggregators send their aggregate shares to the Collector, who combines
them to recover the counts of each candidate prefix.</t>
        </li>
        <li>
          <t>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, e.g., for each <tt>p</tt> in
<tt>H</tt>, add <tt>p || 0</tt> and <tt>p || 1</tt> to the set. Repeat step 3 with the new set of
candidate prefixes.</t>
        </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 programmed path, then the function evaluates
to a non-zero value; otherwise it evaluates to zero. This structure allows an
IDPF to provide the functionality required for the above protocol: To compute
the hit count for an index, just evaluate each set of IDPF shares at that index
and add up the results.</t>
      <t>Consider the sub-tree constructed from a set of input strings and a target
threshold <tt>t</tt> by including all indices that prefix at least <tt>t</tt> of the input
strings. We shall refer to this structure as the "prefix tree" for the batch of
inputs and target threshold. To compute the <tt>t</tt>-heavy hitters for a set of
inputs, the Aggregators and Collector first compute the prefix tree, then
extract the heavy hitters from the leaves of this tree. (Note that the prefix
tree may leak more information about the set than the heavy hitters themselves;
see <xref target="agg-param-privacy"/> for details.)</t>
      <t>Poplar1 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>
      <t>The remainder of this section is structured as follows. IDPFs are defined in
<xref target="idpf"/>; a concrete instantiation is given <xref target="idpf-poplar"/>. The Poplar1 VDAF is
defined in <xref target="poplar1-construction"/> in terms of a generic IDPF. Finally, a
concrete instantiation of Poplar1 is specified in <xref target="poplar1-inst"/>;
test vectors can be found in <xref target="test-vectors"/>.</t>
      <section anchor="idpf">
        <name>Incremental Distributed Point Functions (IDPFs)</name>
        <t>An IDPF is defined over a domain of size <tt>2^BITS</tt>, where <tt>BITS</tt> is constant
defined by the IDPF. Indexes into the IDPF tree are encoded as integers in range
<tt>[0, 2^BITS)</tt>. The Client specifies an index <tt>alpha</tt> and a vector of
values <tt>beta</tt>, one for each "level" <tt>L</tt> in range <tt>[0, BITS)</tt>. The key generation
algorithm generates one IDPF "key" for each Aggregator. When evaluated at level
<tt>L</tt> and index <tt>0 &lt;= prefix &lt; 2^L</tt>, each IDPF key returns an additive share of
<tt>beta[L]</tt> if <tt>prefix</tt> is the <tt>L</tt>-bit prefix of <tt>alpha</tt> and shares of zero
otherwise.</t>
        <t>An index <tt>x</tt> is defined to be a prefix of another index <tt>y</tt> as follows. Let
<tt>LSB(x, N)</tt> denote the least significant <tt>N</tt> bits of positive integer <tt>x</tt>. By
definition, a positive integer <tt>0 &lt;= x &lt; 2^L</tt> is said to be the length-<tt>L</tt>
prefix of positive integer <tt>0 &lt;= y &lt; 2^BITS</tt> if <tt>LSB(x, L)</tt> is equal to the most
significant <tt>L</tt> bits of <tt>LSB(y, BITS)</tt>, For example, 6 (110 in binary) is the
length-3 prefix of 25 (11001), but 7 (111) is not.</t>
        <t>Each of the programmed points <tt>beta</tt> is a vector of elements of some finite
field. We distinguish two types of fields: One for inner nodes (denoted
<tt>FieldInner</tt>), and one for leaf nodes (<tt>FieldLeaf</tt>). (Our
instantiation of Poplar1 (<xref target="poplar1-inst"/>) will use a much larger field for
leaf nodes than for inner nodes. This is to ensure the IDPF is "extractable" as
defined in <xref target="BBCGGI21"/>, Definition 1.)</t>
        <t>A concrete IDPF defines the types and constants enumerated in <xref target="idpf-param"/>.
In the remainder we write <tt>Output</tt> as shorthand for the type
<tt>Union[list[list[FieldInner]], list[list[FieldLeaf]]]</tt>. (This type
denotes either a vector of inner node field elements or leaf node field
elements.) The scheme is comprised of the following algorithms:</t>
        <ul spacing="normal">
          <li>
            <t><tt>Idpf.gen(alpha: Unsigned, beta_inner: list[list[FieldInner]], beta_leaf:
list[FieldLeaf], binder: bytes, rand: bytes[Idpf.RAND_SIZE]) -&gt; tuple[bytes,
list[bytes]]</tt> is the randomized IDPF-key generation algorithm. (Input <tt>rand</tt>
consists of the random bytes it consumes.) Its inputs are the index <tt>alpha</tt>
the values <tt>beta</tt>, and a binder string. The value of <tt>alpha</tt> <bcp14>MUST</bcp14> be in range
<tt>[0, 2^BITS)</tt>. The output is a public part that is sent to all Aggregators
and a vector of private IDPF keys, one for each aggregator. The binder string
is used to derive the key in the underlying XofFixedKeyAes128 XOF that is used
for expanding seeds at each level. It <bcp14>MUST</bcp14> be chosen uniformly at random by
the Client (see <xref target="nonce-requirements"/>).  </t>
            <ul empty="true">
              <li>
                <t>TODO(issue #255) Decide whether to treat the public share as an opaque byte
string or to replace it with an explicit type.</t>
              </li>
            </ul>
          </li>
          <li>
            <t><tt>Idpf.eval(agg_id: Unsigned, public_share: bytes, key: bytes, level:
Unsigned, prefixes: tuple[Unsigned, ...], binder: Bytes) -&gt; Output</tt> is the
deterministic, stateless IDPF-key evaluation algorithm run by each
Aggregator. Its inputs are the Aggregator's unique identifier, the public
share distributed to all of the Aggregators, the Aggregator's IDPF key, the
"level" at which to evaluate the IDPF, the sequence of candidate prefixes,
and a binder string. It returns the share of the value corresponding to each
candidate prefix.  </t>
            <t>
The output type (i.e., <tt>Output</tt>) depends on the value of <tt>level</tt>: If <tt>level &lt;
Idpf.BITS-1</tt>, the output is the value for an inner node, which has type
<tt>list[list[Idpf.FieldInner]]</tt>; otherwise, if <tt>level == Idpf.BITS-1</tt>, then the
output is the value for a leaf node, which has type
<tt>list[list[Idpf.FieldLeaf]]</tt>.  </t>
            <t>
The value of <tt>level</tt> <bcp14>MUST</bcp14> be in range <tt>[0, BITS)</tt>. The indexes in <tt>prefixes</tt>
              <bcp14>MUST</bcp14> all be distinct and in range <tt>[0, 2^level)</tt>.  </t>
            <t>
Applications <bcp14>MUST</bcp14> ensure that the Aggregator's identifier is equal to the
integer in range <tt>[0, SHARES)</tt> that matches the index of <tt>key</tt> in the sequence
of IDPF keys output by the Client.</t>
          </li>
        </ul>
        <t>In addition, the following method is derived for each concrete <tt>Idpf</tt>:</t>
        <artwork><![CDATA[
def current_field(Idpf, level):
    return Idpf.FieldInner if level < Idpf.BITS-1 \
                else Idpf.FieldLeaf
]]></artwork>
        <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. See <xref target="idpf-poplar"/> for details.</t>
        <table anchor="idpf-param">
          <name>Constants and types defined by a concrete IDPF.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">SHARES</td>
              <td align="left">Number of IDPF keys output by IDPF-key generator</td>
            </tr>
            <tr>
              <td align="left">BITS</td>
              <td align="left">Length in bits of each input string</td>
            </tr>
            <tr>
              <td align="left">VALUE_LEN</td>
              <td align="left">Number of field elements of each output value</td>
            </tr>
            <tr>
              <td align="left">RAND_SIZE</td>
              <td align="left">Size of the random string consumed by the IDPF-key generator. Equal to twice the XOF's seed size.</td>
            </tr>
            <tr>
              <td align="left">KEY_SIZE</td>
              <td align="left">Size in bytes of each IDPF key</td>
            </tr>
            <tr>
              <td align="left">FieldInner</td>
              <td align="left">Implementation of <tt>Field</tt> (<xref target="field"/>) used for values of inner nodes</td>
            </tr>
            <tr>
              <td align="left">FieldLeaf</td>
              <td align="left">Implementation of <tt>Field</tt> used for values of leaf nodes</td>
            </tr>
            <tr>
              <td align="left">Output</td>
              <td align="left">Alias of <tt>Union[list[list[FieldInner]], list[list[FieldLeaf]]]</tt></td>
            </tr>
            <tr>
              <td align="left">FieldVec</td>
              <td align="left">Alias of <tt>Union[list[FieldInner], list[FieldLeaf]]</tt></td>
            </tr>
          </tbody>
        </table>
      </section>
      <section anchor="poplar1-construction">
        <name>Construction</name>
        <t>This section specifies <tt>Poplar1</tt>, an implementation of the <tt>Vdaf</tt> interface
(<xref target="vdaf"/>). It is defined in terms of any <tt>Idpf</tt> (<xref target="idpf"/>) for which
<tt>Idpf.SHARES == 2</tt> and <tt>Idpf.VALUE_LEN == 2</tt> and an implementation of <tt>Xof</tt>
(<xref target="xof"/>). The associated constants and types required by the <tt>Vdaf</tt> interface
are defined in <xref target="poplar1-param"/>. The methods required for sharding,
preparation, aggregation, and unsharding are described in the remaining
subsections. These methods make use of constants defined in <xref target="poplar1-const"/>.</t>
        <table anchor="poplar1-param">
          <name>VDAF parameters for Poplar1.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">
                <tt>VERIFY_KEY_SIZE</tt></td>
              <td align="left">
                <tt>Xof.SEED_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>RAND_SIZE</tt></td>
              <td align="left">
                <tt>Xof.SEED_SIZE * 3 + Idpf.RAND_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>NONCE_SIZE</tt></td>
              <td align="left">
                <tt>16</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>ROUNDS</tt></td>
              <td align="left">
                <tt>2</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>SHARES</tt></td>
              <td align="left">
                <tt>2</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>Measurement</tt></td>
              <td align="left">
                <tt>Unsigned</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggParam</tt></td>
              <td align="left">
                <tt>Tuple[Unsigned, Tuple[Unsigned, ...]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PublicShare</tt></td>
              <td align="left">
                <tt>bytes</tt> (IDPF public share)</td>
            </tr>
            <tr>
              <td align="left">
                <tt>InputShare</tt></td>
              <td align="left">
                <tt>tuple[bytes, bytes, list[Idpf.FieldInner], list[Idpf.FieldLeaf]]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>OutShare</tt></td>
              <td align="left">
                <tt>Idpf.FieldVec</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggShare</tt></td>
              <td align="left">
                <tt>Idpf.FieldVec</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>AggResult</tt></td>
              <td align="left">
                <tt>Vec[Unsigned]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepState</tt></td>
              <td align="left">
                <tt>tuple[bytes, Unsigned, Idpf.FieldVec]</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepShare</tt></td>
              <td align="left">
                <tt>Idpf.FieldVec</tt></td>
            </tr>
            <tr>
              <td align="left">
                <tt>PrepMessage</tt></td>
              <td align="left">
                <tt>Optional[Idpf.FieldVec]</tt></td>
            </tr>
          </tbody>
        </table>
        <table anchor="poplar1-const">
          <name>Constants used by Poplar1.</name>
          <thead>
            <tr>
              <th align="left">Variable</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">USAGE_SHARD_RAND: Unsigned</td>
              <td align="left">1</td>
            </tr>
            <tr>
              <td align="left">USAGE_CORR_INNER: Unsigned</td>
              <td align="left">2</td>
            </tr>
            <tr>
              <td align="left">USAGE_CORR_LEAF: Unsigned</td>
              <td align="left">3</td>
            </tr>
            <tr>
              <td align="left">USAGE_VERIFY_RAND: Unsigned</td>
              <td align="left">4</td>
            </tr>
          </tbody>
        </table>
        <section anchor="client">
          <name>Client</name>
          <t>The Client's measurement is interpreted as an IDPF index, denoted <tt>alpha</tt>. The
programmed IDPF values are pairs of field elements <tt>(1, k)</tt> where each <tt>k</tt> is
chosen at random. This random value is used as part of the secure sketching
protocol of <xref target="BBCGGI21"/>, Appendix C.4. After evaluating their IDPF key shares
on a given sequence 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^2 + b - k*a + c
]]></artwork>
          <t>and sends additive shares of <tt>a</tt>, <tt>b</tt>, <tt>c</tt>, <tt>A</tt> and <tt>B</tt> to the Aggregators.
Putting everything together, the sharding algorithm is defined as
follows.</t>
          <figure anchor="poplar1-mes2inp">
            <name>The sharding algorithm for Poplar1.</name>
            <artwork><![CDATA[
def shard(Poplar1, measurement, nonce, rand):
    l = Poplar1.Xof.SEED_SIZE

    # Split the random input into random input for IDPF key
    # generation, correlated randomness, and sharding.
    if len(rand) != Poplar1.RAND_SIZE:
        raise ERR_INPUT # unexpected length for random input
    idpf_rand, rand = front(Poplar1.Idpf.RAND_SIZE, rand)
    seeds = [rand[i:i+l] for i in range(0,3*l,l)]
    corr_seed, seeds = front(2, seeds)
    (k_shard,), seeds = front(1, seeds)

    xof = Poplar1.Xof(
        k_shard,
        Poplar1.domain_separation_tag(USAGE_SHARD_RAND),
        nonce,
    )

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

    # Generate the IDPF keys.
    (public_share, keys) = Poplar1.Idpf.gen(measurement,
                                            beta_inner,
                                            beta_leaf,
                                            nonce,
                                            idpf_rand)

    # Generate correlated randomness used by the Aggregators to
    # compute a sketch over their output shares. XOF seeds are
    # used to encode shares of the `(a, b, c)` triples.
    # (See [BBCGGI21, Appendix C.4].)
    corr_offsets = vec_add(
        Poplar1.Xof.expand_into_vec(
            Poplar1.Idpf.FieldInner,
            corr_seed[0],
            Poplar1.domain_separation_tag(USAGE_CORR_INNER),
            byte(0) + nonce,
            3 * (Poplar1.Idpf.BITS-1),
        ),
        Poplar1.Xof.expand_into_vec(
            Poplar1.Idpf.FieldInner,
            corr_seed[1],
            Poplar1.domain_separation_tag(USAGE_CORR_INNER),
            byte(1) + nonce,
            3 * (Poplar1.Idpf.BITS-1),
        ),
    )
    corr_offsets += vec_add(
        Poplar1.Xof.expand_into_vec(
            Poplar1.Idpf.FieldLeaf,
            corr_seed[0],
            Poplar1.domain_separation_tag(USAGE_CORR_LEAF),
            byte(0) + nonce,
            3,
        ),
        Poplar1.Xof.expand_into_vec(
            Poplar1.Idpf.FieldLeaf,
            corr_seed[1],
            Poplar1.domain_separation_tag(USAGE_CORR_LEAF),
            byte(1) + nonce,
            3,
        ),
    )

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

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

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

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

    # Get shares of the correlated randomness for computing the
    # Aggregator's share of the sketch for the given level of the IDPF
    # tree.
    if level < Poplar1.Idpf.BITS - 1:
        corr_xof = Poplar1.Xof(
            corr_seed,
            Poplar1.domain_separation_tag(USAGE_CORR_INNER),
            byte(agg_id) + nonce,
        )
        # Fast-forward the XOF state to the current level.
        corr_xof.next_vec(Field, 3 * level)
    else:
        corr_xof = Poplar1.Xof(
            corr_seed,
            Poplar1.domain_separation_tag(USAGE_CORR_LEAF),
            byte(agg_id) + nonce,
        )
    (a_share, b_share, c_share) = corr_xof.next_vec(Field, 3)
    (A_share, B_share) = corr_inner[2*level:2*(level+1)] \
        if level < Poplar1.Idpf.BITS - 1 else corr_leaf

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

    prep_mem = [A_share, B_share, Field(agg_id)] + out_share
    return ((b'sketch round 1', level, prep_mem),
            sketch_share)

def prep_next(Poplar1, prep_state, prep_msg):
    prev_sketch = prep_msg
    (step, level, prep_mem) = prep_state
    Field = Poplar1.Idpf.current_field(level)

    if step == b'sketch round 1':
        if prev_sketch == None:
            prev_sketch = Field.zeros(3)
        elif len(prev_sketch) != 3:
            raise ERR_INPUT  # prep message malformed
        (A_share, B_share, agg_id), prep_mem = \
            prep_mem[:3], prep_mem[3:]
        sketch_share = [
            agg_id * (prev_sketch[0] ** 2
                      - prev_sketch[1]
                      - prev_sketch[2])
            + A_share * prev_sketch[0]
            + B_share
        ]
        return ((b'sketch round 2', level, prep_mem),
                sketch_share)

    elif step == b'sketch round 2':
        if prev_sketch == None:
            return prep_mem  # Output shares
        else:
            raise ERR_INPUT  # prep message malformed

    raise ERR_INPUT  # unexpected input

def prep_shares_to_prep(Poplar1, agg_param, prep_shares):
    if len(prep_shares) != 2:
        raise ERR_INPUT  # unexpected number of prep shares
    (level, _) = agg_param
    Field = Poplar1.Idpf.current_field(level)
    sketch = vec_add(prep_shares[0], prep_shares[1])
    if len(sketch) == 3:
        return sketch
    elif len(sketch) == 1:
        if sketch == Field.zeros(1):
            # In order to reduce communication overhead, let `None`
            # denote a successful sketch verification.
            return None
        else:
            raise ERR_VERIFY  # sketch verification failed
    else:
        raise ERR_INPUT  # unexpected input length
]]></artwork>
          </figure>
        </section>
        <section anchor="validity-of-aggregation-parameters-1">
          <name>Validity of Aggregation Parameters</name>
          <t>Aggregation parameters are valid for a given input share if no aggregation
parameter with the same level has been used with the same input share before.
The whole preparation phase <bcp14>MUST NOT</bcp14> be run more than once for a given
combination of input share and level. This function checks that levels are
increasing between calls, and also enforces that the prefixes at each level are
suffixes of the previous level's prefixes.</t>
          <figure anchor="poplar1-validity-scope">
            <name>Validity of aggregation parameters for Poplar1.</name>
            <artwork><![CDATA[
def get_ancestor(input, this_level, last_level):
    # Helper function to determine the prefix of `input` at `last_level`.
    return input >> (this_level - last_level)

def is_valid(Poplar1, agg_param, previous_agg_params):
    # Exit early if this is the first time.
    if len(previous_agg_params) < 1:
      return True

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

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

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

    return True
]]></artwork>
          </figure>
        </section>
        <section anchor="aggregation-2">
          <name>Aggregation</name>
          <t>Aggregation involves simply adding up the output shares.</t>
          <figure anchor="poplar1-out2agg">
            <name>Aggregation algorithm for Poplar1.</name>
            <artwork><![CDATA[
def aggregate(Poplar1, agg_param, out_shares):
    (level, prefixes) = agg_param
    Field = Poplar1.Idpf.current_field(level)
    agg_share = Field.zeros(len(prefixes))
    for out_share in out_shares:
        agg_share = vec_add(agg_share, out_share)
    return agg_share
]]></artwork>
          </figure>
        </section>
        <section anchor="unsharding-1">
          <name>Unsharding</name>
          <t>Finally, the Collector unshards the aggregate result by adding up the aggregate
shares.</t>
          <figure anchor="poplar1-agg-output">
            <name>Computation of the aggregate result for Poplar1.</name>
            <artwork><![CDATA[
def unshard(Poplar1, agg_param,
            agg_shares, _num_measurements):
    (level, prefixes) = agg_param
    Field = Poplar1.Idpf.current_field(level)
    agg = Field.zeros(len(prefixes))
    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="poplar1-encode">
          <name>Message Serialization</name>
          <t>This section defines serialization formats for messages exchanged over the
network while executing <tt>Poplar1</tt>. It is <bcp14>RECOMMENDED</bcp14> that implementations
provide serialization methods for them.</t>
          <t>Message structures are defined following <xref section="3" sectionFormat="of" target="RFC8446"/>). In the
remainder we use <tt>S</tt> as an alias for <tt>Poplar1.Xof.SEED_SIZE</tt>, <tt>Fi</tt> as an alias
for <tt>Poplar1.Idpf.FieldInner</tt> and <tt>Fl</tt> as an alias for
<tt>Poplar1.Idpf.FieldLeaf</tt>. XOF seeds are represented as follows:</t>
          <artwork><![CDATA[
opaque Poplar1Seed[S];
]]></artwork>
          <t>Elements of the inner field are encoded in little-endian byte order (as defined
in <xref target="field"/>) and are represented as follows:</t>
          <artwork><![CDATA[
opaque Poplar1FieldInner[Fi];
]]></artwork>
          <t>Likewise, elements of the leaf field are encoded in little-endian byte order
(as defined in <xref target="field"/>) and are represented as follows:</t>
          <artwork><![CDATA[
opaque Poplar1FieldLeaf[Fl];
]]></artwork>
          <section anchor="public-share-1">
            <name>Public Share</name>
            <t>The public share is equal to the IDPF public share, which is a byte string.
(See <xref target="idpf"/>.)</t>
          </section>
          <section anchor="input-share-1">
            <name>Input Share</name>
            <t>Each input share is structured as follows:</t>
            <artwork><![CDATA[
struct {
    opaque idpf_key[Poplar1.Idpf.KEY_SIZE];
    Poplar1Seed corr_seed;
    Poplar1FieldInner corr_inner[Fi * 2 * (Poplar1.Idpf.BITS - 1)];
    Poplar1FieldLeaf corr_leaf[Fl * 2];
} Poplar1InputShare;
]]></artwork>
          </section>
          <section anchor="prep-share-1">
            <name>Prep Share</name>
            <t>Encoding of the prep share depends on the round of sketching: if the first
round, then each sketch share has three field elements; if the second round,
then each sketch share has one field element. The field that is used depends on
the level of the IDPF tree specified by the aggregation parameter, either the
inner field or the leaf field.</t>
            <t>For the first round and inner field:</t>
            <artwork><![CDATA[
struct {
    Poplar1FieldInner sketch_share[Fi * 3];
} Poplar1PrepShareRoundOneInner;
]]></artwork>
            <t>For the first round and leaf field:</t>
            <artwork><![CDATA[
struct {
    Poplar1FieldLeaf sketch_share[Fl * 3];
} Poplar1PrepShareRoundOneLeaf;

For the second round and inner field:
]]></artwork>
            <artwork><![CDATA[
struct {
    Poplar1FieldInner sketch_share;
} Poplar1PrepShareRoundTwoInner;
]]></artwork>
            <t>For the second round and leaf field:</t>
            <artwork><![CDATA[
struct {
    Poplar1FieldLeaf sketch_share;
} Poplar1PrepShareRoundTwoLeaf;
]]></artwork>
          </section>
          <section anchor="prep-message-1">
            <name>Prep Message</name>
            <t>Likewise, the structure of the prep message for Poplar1 depends on the
sketching round and field. For the first round and inner field:</t>
            <artwork><![CDATA[
struct {
    Poplar1FieldInner[Fi * 3];
} Poplar1PrepMessageRoundOneInner;
]]></artwork>
            <t>For the first round and leaf field:</t>
            <artwork><![CDATA[
struct {
    Poplar1FieldLeaf sketch[Fl * 3];
} Poplar1PrepMessageRoundOneLeaf;
]]></artwork>
            <t>Note that these messages have the same structures as the prep shares for the
first round.</t>
            <t>The second-round prep message is the empty string. This is because the sketch
shares are expected to sum to a particular value if the output shares are
valid; we represent a successful preparation with the empty string and
otherwise return an error.</t>
          </section>
          <section anchor="aggregate-share">
            <name>Aggregate Share</name>
            <t>The encoding of the aggregate share depends on whether the inner or leaf field
is used, and the number of candidate prefixes. Both of these are determined by
 the aggregation parameter.</t>
            <t>Let <tt>prefix_count</tt> denote the number of candidate prefixes. For the inner field:</t>
            <artwork><![CDATA[
struct {
    Poplar1FieldInner agg_share[Fi * prefix_count];
} Poplar1AggShareInner;
]]></artwork>
            <t>For the leaf field:</t>
            <artwork><![CDATA[
struct {
    Poplar1FieldLeaf agg_share[Fl * prefix_count];
} Poplar1AggShareLeaf;
]]></artwork>
          </section>
          <section anchor="aggregation-parameter">
            <name>Aggregation Parameter</name>
            <t>The aggregation parameter is encoded as follows:</t>
            <ul empty="true">
              <li>
                <t>TODO(issue #255) Express the aggregation parameter encoding in TLS syntax.
Decide whether to RECOMMEND this encoding, and if so, add it to test vectors.</t>
              </li>
            </ul>
            <artwork><![CDATA[
def encode_agg_param(Poplar1, (level, prefixes)):
    if level > 2 ** 16 - 1:
        raise ERR_INPUT # level too deep
    if len(prefixes) > 2 ** 32 - 1:
        raise ERR_INPUT # too many prefixes
    encoded = Bytes()
    encoded += to_be_bytes(level, 2)
    encoded += to_be_bytes(len(prefixes), 4)
    packed = 0
    for (i, prefix) in enumerate(prefixes):
        packed |= prefix << ((level+1) * i)
    l = ((level+1) * len(prefixes) + 7) // 8
    encoded += to_be_bytes(packed, l)
    return encoded

def decode_agg_param(Poplar1, encoded):
    encoded_level, encoded = encoded[:2], encoded[2:]
    level = from_be_bytes(encoded_level)
    encoded_prefix_count, encoded = encoded[:4], encoded[4:]
    prefix_count = from_be_bytes(encoded_prefix_count)
    l = ((level+1) * prefix_count + 7) // 8
    encoded_packed, encoded = encoded[:l], encoded[l:]
    packed = from_be_bytes(encoded_packed)
    prefixes = []
    m = 2 ** (level+1) - 1
    for i in range(prefix_count):
        prefixes.append(packed >> ((level+1) * i) & m)
    if len(encoded) != 0:
        raise ERR_INPUT
    return (level, tuple(prefixes))
]]></artwork>
            <t>Implementation note: The aggregation parameter includes the level of the IDPF
tree and the sequence of indices to evaluate. For implementations that perform
per-report caching across executions of the VDAF, this may be more information
than is strictly needed. In particular, it may be sufficient to convey which
indices from the previous execution will have their children included in the
next. This would help reduce communication overhead.</t>
          </section>
        </section>
      </section>
      <section anchor="idpf-poplar">
        <name>The IDPF scheme of <xref target="BBCGGI21"/></name>
        <t>In this section we specify a concrete IDPF, called IdpfPoplar, suitable for
instantiating Poplar1. The scheme gets its name from the name of the protocol of
<xref target="BBCGGI21"/>.</t>
        <ul empty="true">
          <li>
            <t>TODO We should consider giving <tt>IdpfPoplar</tt> a more distinctive name.</t>
          </li>
        </ul>
        <t>The constant and type definitions required by the <tt>Idpf</tt> interface are given in
<xref target="idpf-poplar-param"/>.</t>
        <t>IdpfPoplar requires a XOF for deriving the output shares, as well as a variety
of other artifacts used internally. For performance reasons, we instantiate
this object using XofFixedKeyAes128 (<xref target="xof-fixed-key-aes128"/>). See
<xref target="xof-vs-ro"/> for justification of this choice.</t>
        <table anchor="idpf-poplar-param">
          <name>Constants and type definitions for IdpfPoplar.</name>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Value</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">SHARES</td>
              <td align="left">
                <tt>2</tt></td>
            </tr>
            <tr>
              <td align="left">BITS</td>
              <td align="left">any positive integer</td>
            </tr>
            <tr>
              <td align="left">VALUE_LEN</td>
              <td align="left">any positive integer</td>
            </tr>
            <tr>
              <td align="left">KEY_SIZE</td>
              <td align="left">
                <tt>Xof.SEED_SIZE</tt></td>
            </tr>
            <tr>
              <td align="left">FieldInner</td>
              <td align="left">
                <tt>Field64</tt> (<xref target="fields"/>)</td>
            </tr>
            <tr>
              <td align="left">FieldLeaf</td>
              <td align="left">
                <tt>Field255</tt> (<xref target="fields"/>)</td>
            </tr>
          </tbody>
        </table>
        <section anchor="key-generation">
          <name>Key Generation</name>
          <ul empty="true">
            <li>
              <t>TODO Describe the construction in prose, beginning with a gentle introduction
to the high level idea.</t>
            </li>
          </ul>
          <t>The description of the IDPF-key generation algorithm makes use of auxiliary
functions <tt>extend()</tt>, <tt>convert()</tt>, and <tt>encode_public_share()</tt> defined in
<xref target="idpf-poplar-helper-functions"/>. In the following, we let <tt>Field2</tt> denote the
field <tt>GF(2)</tt>.</t>
          <figure anchor="idpf-poplar-gen">
            <name>IDPF-key generation algorithm of IdpfPoplar.</name>
            <artwork><![CDATA[
def gen(IdpfPoplar, alpha, beta_inner, beta_leaf, binder, rand):
    if alpha >= 2 ** IdpfPoplar.BITS:
        raise ERR_INPUT # alpha too long
    if len(beta_inner) != IdpfPoplar.BITS - 1:
        raise ERR_INPUT # beta_inner vector is the wrong size
    if len(rand) != IdpfPoplar.RAND_SIZE:
        raise ERR_INPUT # unexpected length for random input

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

    seed = init_seed.copy()
    ctrl = [Field2(0), Field2(1)]
    correction_words = []
    for level in range(IdpfPoplar.BITS):
        Field = IdpfPoplar.current_field(level)
        keep = (alpha >> (IdpfPoplar.BITS - level - 1)) & 1
        lose = 1 - keep
        bit = Field2(keep)

        (s0, t0) = IdpfPoplar.extend(seed[0], binder)
        (s1, t1) = IdpfPoplar.extend(seed[1], binder)
        seed_cw = xor(s0[lose], s1[lose])
        ctrl_cw = (
            t0[0] + t1[0] + bit + Field2(1),
            t0[1] + t1[1] + bit,
        )

        x0 = xor(s0[keep], ctrl[0].conditional_select(seed_cw))
        x1 = xor(s1[keep], ctrl[1].conditional_select(seed_cw))
        (seed[0], w0) = IdpfPoplar.convert(level, x0, binder)
        (seed[1], w1) = IdpfPoplar.convert(level, x1, binder)
        ctrl[0] = t0[keep] + ctrl[0] * ctrl_cw[keep]
        ctrl[1] = t1[keep] + ctrl[1] * ctrl_cw[keep]

        b = beta_inner[level] if level < IdpfPoplar.BITS-1 \
                else beta_leaf
        if len(b) != IdpfPoplar.VALUE_LEN:
            raise ERR_INPUT # beta too long or too short

        w_cw = vec_add(vec_sub(b, w0), w1)
        # Implementation note: Here we negate the correction word if
        # the control bit `ctrl[1]` is set. We avoid branching on the
        # value in order to reduce leakage via timing side channels.
        mask = Field(1) - Field(2) * Field(ctrl[1].as_unsigned())
        for i in range(len(w_cw)):
            w_cw[i] *= mask

        correction_words.append((seed_cw, ctrl_cw, w_cw))

    public_share = IdpfPoplar.encode_public_share(correction_words)
    return (public_share, init_seed)
]]></artwork>
          </figure>
        </section>
        <section anchor="key-evaluation">
          <name>Key Evaluation</name>
          <ul empty="true">
            <li>
              <t>TODO Describe in prose how IDPF-key evaluation algorithm works.</t>
            </li>
          </ul>
          <t>The description of the IDPF-evaluation algorithm makes use of auxiliary
functions <tt>extend()</tt>, <tt>convert()</tt>, and <tt>decode_public_share()</tt> defined in
<xref target="idpf-poplar-helper-functions"/>.</t>
          <figure anchor="idpf-poplar-eval">
            <name>IDPF-evaluation generation algorithm of IdpfPoplar.</name>
            <artwork><![CDATA[
def eval(IdpfPoplar, agg_id, public_share, init_seed,
         level, prefixes, binder):
    if agg_id >= IdpfPoplar.SHARES:
        raise ERR_INPUT # invalid aggregator ID
    if level >= IdpfPoplar.BITS:
        raise ERR_INPUT # level too deep
    if len(set(prefixes)) != len(prefixes):
        raise ERR_INPUT # candidate prefixes are non-unique

    correction_words = IdpfPoplar.decode_public_share(public_share)
    out_share = []
    for prefix in prefixes:
        if prefix >= 2 ** (level+1):
            raise ERR_INPUT # prefix too long

        # The Aggregator's output share is the value of a node of
        # the IDPF tree at the given `level`. The node's value is
        # computed by traversing the path defined by the candidate
        # `prefix`. Each node in the tree is represented by a seed
        # (`seed`) and a set of control bits (`ctrl`).
        seed = init_seed
        ctrl = Field2(agg_id)
        for current_level in range(level+1):
            bit = (prefix >> (level - current_level)) & 1

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

def eval_next(IdpfPoplar, prev_seed, prev_ctrl,
              correction_word, level, bit, binder):
    """
    Compute the next node in the IDPF tree along the path determined by
    a candidate prefix. The next node is determined by `bit`, the bit of
    the prefix corresponding to the next level of the tree.

    TODO Consider implementing some version of the optimization
    discussed at the end of [BBCGGI21, Appendix C.2]. This could on
    average reduce the number of AES calls by a constant factor.
    """

    Field = IdpfPoplar.current_field(level)
    (seed_cw, ctrl_cw, w_cw) = correction_word
    (s, t) = IdpfPoplar.extend(prev_seed, binder)
    s[0] = xor(s[0], prev_ctrl.conditional_select(seed_cw))
    s[1] = xor(s[1], prev_ctrl.conditional_select(seed_cw))
    t[0] += ctrl_cw[0] * prev_ctrl
    t[1] += ctrl_cw[1] * prev_ctrl

    next_ctrl = t[bit]
    (next_seed, y) = IdpfPoplar.convert(level, s[bit], binder)
    # Implementation note: Here we add the correction word to the
    # output if `next_ctrl` is set. We avoid branching on the value of
    # the control bit in order to reduce side channel leakage.
    mask = Field(next_ctrl.as_unsigned())
    for i in range(len(y)):
        y[i] += w_cw[i] * mask

    return (next_seed, next_ctrl, y)
]]></artwork>
          </figure>
        </section>
        <section anchor="idpf-poplar-helper-functions">
          <name>Auxiliary Functions</name>
          <figure anchor="idpf-poplar-helpers">
            <name>Helper functions for IdpfPoplar.</name>
            <artwork><![CDATA[
def extend(IdpfPoplar, seed, binder):
    xof = XofFixedKeyAes128(seed, format_dst(1, 0, 0), binder)
    s = [
        bytearray(xof.next(XofFixedKeyAes128.SEED_SIZE)),
        bytearray(xof.next(XofFixedKeyAes128.SEED_SIZE)),
    ]
    # Use the least significant bits as the control bit correction,
    # and then zero it out. This gives effectively 127 bits of
    # security, but reduces the number of AES calls needed by 1/3.
    t = [Field2(s[0][0] & 1), Field2(s[1][0] & 1)]
    s[0][0] &= 0xFE
    s[1][0] &= 0xFE
    return (s, t)

def convert(IdpfPoplar, level, seed, binder):
    xof = XofFixedKeyAes128(seed, format_dst(1, 0, 1), binder)
    next_seed = xof.next(XofFixedKeyAes128.SEED_SIZE)
    Field = IdpfPoplar.current_field(level)
    w = xof.next_vec(Field, IdpfPoplar.VALUE_LEN)
    return (next_seed, w)

def encode_public_share(IdpfPoplar, correction_words):
    encoded = Bytes()
    control_bits = list(itertools.chain.from_iterable(
        cw[1] for cw in correction_words
    ))
    encoded += pack_bits(control_bits)
    for (level, (seed_cw, _, w_cw)) \
        in enumerate(correction_words):
        Field = IdpfPoplar.current_field(level)
        encoded += seed_cw
        encoded += Field.encode_vec(w_cw)
    return encoded

def decode_public_share(IdpfPoplar, encoded):
    l = (2*IdpfPoplar.BITS + 7) // 8
    encoded_ctrl, encoded = encoded[:l], encoded[l:]
    control_bits = unpack_bits(encoded_ctrl, 2 * IdpfPoplar.BITS)
    correction_words = []
    for level in range(IdpfPoplar.BITS):
        Field = IdpfPoplar.current_field(level)
        ctrl_cw = (
            control_bits[level * 2],
            control_bits[level * 2 + 1],
        )
        l = XofFixedKeyAes128.SEED_SIZE
        seed_cw, encoded = encoded[:l], encoded[l:]
        l = Field.ENCODED_SIZE * IdpfPoplar.VALUE_LEN
        encoded_w_cw, encoded = encoded[:l], encoded[l:]
        w_cw = Field.decode_vec(encoded_w_cw)
        correction_words.append((seed_cw, ctrl_cw, w_cw))
    if len(encoded) != 0:
        raise ERR_DECODE
    return correction_words
]]></artwork>
          </figure>
          <t>Here, <tt>pack_bits()</tt> takes a list of bits, packs each group of eight bits into a
byte, in LSB to MSB order, padding the most significant bits of the last byte
with zeros as necessary, and returns the byte array. <tt>unpack_bits()</tt> performs
the reverse operation: it takes in a byte array and a number of bits, and
returns a list of bits, extracting eight bits from each byte in turn, in LSB to
MSB order, and stopping after the requested number of bits. If the byte array
has an incorrect length, or if unused bits in the last bytes are not zero, it
throws an error.</t>
        </section>
      </section>
      <section anchor="poplar1-inst">
        <name>Instantiation</name>
        <t>By default, Poplar1 is instantiated with IdpfPoplar (<tt>VALUE_LEN == 2</tt>) and
XofTurboShake128 (<xref target="xof-turboshake128"/>). This VDAF is suitable for any
positive value of <tt>BITS</tt>. Test vectors can be found in <xref target="test-vectors"/>.</t>
      </section>
    </section>
    <section anchor="security">
      <name>Security Considerations</name>
      <t>VDAFs have two essential security goals:</t>
      <ol spacing="normal" type="1"><li>
          <t>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.</t>
        </li>
        <li>
          <t>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.</t>
        </li>
      </ol>
      <t>Formal definitions of privacy and robustness can be found in <xref target="DPRS23"/>. 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>
          <t>Securely distributing the long-lived parameters, in particular the
verification key.</t>
        </li>
        <li>
          <t>Establishing secure channels:  </t>
          <ul spacing="normal">
            <li>
              <t>Confidential and authentic channels among Aggregators, and between the
Aggregators and the Collector; and</t>
            </li>
            <li>
              <t>Confidential and Aggregator-authenticated channels between Clients and
Aggregators.</t>
            </li>
          </ul>
        </li>
        <li>
          <t>Enforcing the non-collusion properties required of the specific VDAF in use.</t>
        </li>
      </ul>
      <t>In such an environment, a VDAF provides the high-level privacy property
described above: The Collector learns only the aggregate 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 measurements for the remaining Clients.  Applications can guard
against these risks by adding additional controls on report submission,
such as Client authentication and rate limits.</t>
      <t>VDAFs do not, on their own, provide differential privacy <xref target="Dwo06"/>. Depending
on the distribution of the measurements, the aggregate result itself can still
leak a significant amount of information about an individual measurement or the
person that generated it.</t>
      <section anchor="requirements-for-the-verification-key">
        <name>Requirements for the Verification Key</name>
        <t>The Aggregators are responsible for exchanging the verification key in advance
of executing the VDAF. Any procedure is acceptable as long as the following
conditions are met:</t>
        <ol spacing="normal" type="1"><li>
            <t>To ensure robustness of the computation, the Aggregators <bcp14>MUST NOT</bcp14> reveal the
verification key to the Clients. Otherwise, a malicious Client might be able
to exploit knowledge of this key to craft an invalid report that would be
accepted by the Aggregators.</t>
          </li>
          <li>
            <t>To ensure privacy of the measurements, the Aggregators <bcp14>MUST</bcp14> commit to the
verification key prior to processing reports generated by Clients. Otherwise,
a malicious Aggregator may be able to craft a verification key that, for a
given report, causes an honest Aggregator to leak information about the
measurement during preparation.</t>
          </li>
        </ol>
        <t>Meeting these conditions is required in order to leverage security analysis in
the framework of <xref target="DPRS23"/>. Their definition of robustness allows the attacker,
playing the role of a cohort of malicious Clients, to submit arbitrary reports
to the Aggregators and eavesdrop on their communications as they process them.
Security in this model is achievable as long as the verification key is kept
secret from the attacker.</t>
        <t>The privacy definition of <xref target="DPRS23"/> considers an active attacker that controls
the network and a subset of Aggregators; in addition, the attacker is allowed to
choose the verification key used by each honest Aggregator over the course of
the experiment. Security is achievable in this model as long as the key is
picked at the start of the experiment, prior to any reports being generated.
(The model also requires nonces to be generated at random; see
<xref target="nonce-requirements"/> below.)</t>
        <t>Meeting these requirements is relatively straightforward. For example, the
Aggregators may designate one of their peers to generate the verification key
and distribute it to the others. To assure Clients of key commitment, the
Clients and (honest) Aggregators could bind reports to a shared context string
derived from the key. For instance, the "task ID" of DAP <xref target="DAP"/> could be set to
the hash of the verification key; then as long as honest Aggregators only
consume reports for the task indicated by the Client, forging a new key after
the fact would reduce to finding collisions in the underlying hash function.
(Keeping the key secret from the Clients would require the hash function to be
one-way.) However, since rotating the key implies rotating the task ID, this
scheme would not allow key rotation over the lifetime of a task.</t>
      </section>
      <section anchor="nonce-requirements">
        <name>Requirements for the Nonce</name>
        <t>The sharding and preparation steps of VDAF execution depend on a nonce
associated with the Client's report. To ensure privacy of the underlying
measurement, the Client <bcp14>MUST</bcp14> generate this nonce using a CSPRNG. This is
required in order to leverage security analysis for the privacy definition of
<xref target="DPRS23"/>, which assumes the nonce is chosen at random prior to generating the
report.</t>
        <t>Other security considerations may require the nonce to be non-repeating. For
example, to achieve differential privacy it is necessary to avoid "over
exposing" a report by including it too many times in a single batch or across
multiple batches. It is <bcp14>RECOMMENDED</bcp14> that the nonce generated by the Client be
used by the Aggregators for replay protection.</t>
      </section>
      <section anchor="requirements-for-the-public-share">
        <name>Requirements for the Public Share</name>
        <t>The Aggregators <bcp14>MUST</bcp14> ensure they have both received the same public share from
the Client. It is sufficient, for example, to exchange a hash of the public
share over a secure channel.</t>
      </section>
      <section anchor="requirements-for-aggregation-parameters">
        <name>Requirements for Aggregation Parameters</name>
        <t>As described in <xref target="sec-daf-validity-scopes"/> and <xref target="sec-vdaf-validity-scopes"/>
respectively, DAFs and VDAFs may impose restrictions on the re-use of input
shares. This is to ensure that correlated randomness provided by the Client
through the input share is not used more than once, which might compromise
confidentiality of the Client's measurements.</t>
        <t>Protocols that make use of VDAFs therefore <bcp14>MUST</bcp14> call <tt>Vdaf.is_valid</tt>
on the set of all aggregation parameters used for a Client's input share, and
only proceed with the preparation and aggregation phases if that function call
returns <tt>True</tt>.</t>
        <section anchor="agg-param-privacy">
          <name>Additional Privacy Considerations</name>
          <t>Aggregating a batch of reports multiple times, each time with a different
aggregation parameter, could result in information leakage beyond what is used
by the application.</t>
          <t>For example, when Poplar1 is used for heavy hitters, the Aggregators learn not
only the heavy hitters themselves, but also the prefix tree (as defined in
<xref target="poplar1"/>) computed along the way. Indeed, this leakage is inherent to any
construction that uses an IDPF (<xref target="idpf"/>) in the same way. Depending on the
distribution of the measurements, the prefix tree can leak a significant amount
of information about unpopular inputs. For instance, it is possible (though
perhaps unlikely) for a large set of non-heavy-hitter values to share a common
prefix, which would be leaked by a prefix tree with a sufficiently small
threshold.</t>
          <t>A malicious adversary controlling the Collector and one of the Aggregators can
further turn arbitrary non-heavy prefixes into heavy ones by tampering with the
IDPF output at any position. While our construction ensures that the nodes
evaluated at one level are children of the nodes evaluated at the previous
level, this still may allow an adversary to discover individual non-heavy
strings.</t>
          <t>The only practical, general-purpose approach to mitigating these leakages is via
differential privacy, which is <bcp14>RECOMMENDED</bcp14> for all protocols using Poplar1 for
heavy-hitter type applications.</t>
        </section>
        <section anchor="safe-usage-of-idpf-outputs">
          <name>Safe Usage of IDPF Outputs</name>
          <t>The secure sketch described in <xref target="poplar1"/> is used by the Aggregators to check
that the shares of the vector obtained by evaluating a Client's IDPF at a
sequence of candidate prefixes has at most one non-zero value, and that the
non-zero value is <tt>1</tt>. Depending on how the values are used, the secure sketch
on its own may not be sufficient for robustness of the application. In
particular, a malicious Client may attempt to influence the computation by
choosing an IDPF that evaluates to <tt>1</tt> at more than one node at a given
level of the tree.</t>
          <t>This issue can be mitigated by using an IDPF that is extractable as defined in
in Appendix D of <xref target="BBCGGI21"/>. Extractability ensures that, for a particular
level of the tree, it is infeasible for an attacker to control values of the
IDPF such that it takes on chosen non-zero values at more than one node. (It
can practically only achieve the zero function, a point function, or a
pseudorandom function.)</t>
          <t>The IDPF specified in <xref target="idpf"/> only guarantees extractability at the last level
of the tree. (This is by virtue of using a larger field for the leaves than for
the inner nodes.) For intermediate levels, it is feasible for a client to
produce IDPF shares with two controlled non-zero nodes.</t>
          <t>This is not an issue for running heavy hitters, since (1) each node in the
prefix tree is a child of a previously traversed node, (2) the secure sketch
would detect double voting at every level of the prefix tree, and (3) the IDPF
is extractable at the last level of the tree. However, the lack of
extractability at intermediate levels may result in attacks on the robustness
of certain applications.</t>
          <t>Thus applications <bcp14>SHOULD NOT</bcp14> use prefix counts for intermediate levels for any
purpose beyond the heavy-hitters tree traversal.</t>
        </section>
      </section>
      <section anchor="xof-vs-ro">
        <name>Requirements for XOFs</name>
        <t>As described in <xref target="xof"/>, our constructions rely on eXtendable
Output Functions (XOFs). In the security analyses of our protocols, these are
usually modeled as random oracles. XofTurboShake128 is designed to be
indifferentiable from a random oracle <xref target="MRH04"/>, making it a suitable choice
for most situations.</t>
        <t>The one exception is the Idpf implementation IdpfPoplar <xref target="idpf-poplar"/>.
Here, a random oracle is not needed to prove privacy, since the analysis of
<xref target="BBCGGI21"/>, Proposition 1, only requires a Pseudorandom Generator (PRG).
As observed in <xref target="GKWY20"/>, a PRG can be instantiated from a correlation-robust
hash function <tt>H</tt>. Informally, correlation robustness requires that for a random
<tt>r</tt>, <tt>H(xor(r, x))</tt> is computationally indistinguishable from a random function of <tt>x</tt>.
A PRG can therefore be constructed as</t>
        <artwork><![CDATA[
PRG(r) = H(xor(r, 1)) || H(xor(r, 2)) || ...
]]></artwork>
        <t>since each individual hash function evaluation is indistinguishable from a random
function.</t>
        <t>Our construction at <xref target="xof-fixed-key-aes128"/> implements a correlation-robust
hash function using fixed-key AES. For security, it assumes that AES with a
fixed key can be modeled as a random permutation <xref target="GKWY20"/>. Additionally, we
use a different AES key for every client, which in the ideal cipher model leads
to better concrete security <xref target="GKWWY20"/>.</t>
        <t>We note that for robustness, the analysis of <xref target="BBCGGI21"/> still assumes a random
oracle to make the Idpf extractable. While XofFixedKeyAes128 has been shown
to be differentiable from a random oracle <xref target="GKWWY20"/>, there are no known
attacks exploiting this difference.
We also stress that even if the Idpf is not extractable, Poplar1 guarantees
that every client can contribute to at most one prefix among the ones being
evaluated by the helpers.</t>
      </section>
      <section anchor="security-multiproof">
        <name>Choosing the Field Size</name>
        <t>Prio3 and other systems built from FLPs (<xref target="flp-generic"/> in particular) may
benefit from choosing a field size that is as small as possible. Generally
speaking, a smaller field results in lower communication and storage costs.
Care must be taken, however, since a smaller field also results in degraded (or
even vacuous) robustness.</t>
        <t>Different variants of Prio3 (<xref target="prio3"/>) use different field sizes: Prio3Count
uses Field64; but Prio3Sum, Prio3SumVec, and Prio3Histogram use Field128, a
field that is twice as large as Field64. This is due to the use of joint
randomness (<xref target="flp"/>) in the latter variants. Joint randomness allows for more
flexible circuit design (see <xref target="flp-generic-overview-extensions"/>), but opens up
Prio3 to precomputation attacks, which the larger field mitigates. (See
<xref target="DPRS23"/>, Theorem 1.) Note that privacy is not susceptible to such attacks.</t>
        <t>Another way to mitigate this issue (or improve robustness in general) is to
generate and verify multiple, independent proofs. (See <xref target="multiproofs"/>.) For
Prio3, the <tt>PROOFS</tt> parameter controls the number of proofs (at least one) that
are generated and verified.</t>
        <t>In general, Field128 is <bcp14>RECOMMENDED</bcp14> for use in Prio3 when the circuit uses
joint randomness (<tt>JOINT_RAND_LEN &gt; 0</tt>) and <tt>PROOFS == 1</tt>. Field64 <bcp14>MAY</bcp14> be used
instead, but <tt>PROOFS</tt> <bcp14>MUST</bcp14> be set to at least <tt>3</tt>. Breaking robustness for
<tt>PROOFS == 2</tt> is feasible, if impractical; but <tt>PROOFS == 1</tt> is completely
broken for such a small field.</t>
      </section>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>A codepoint for each (V)DAF in this document is defined in the table below. Note
that <tt>0xFFFF0000</tt> through <tt>0xFFFFFFFF</tt> are reserved for private use.</t>
      <table anchor="codepoints">
        <name>Unique identifiers for (V)DAFs.</name>
        <thead>
          <tr>
            <th align="left">Value</th>
            <th align="left">Scheme</th>
            <th align="left">Type</th>
            <th align="left">Reference</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">
              <tt>0x00000000</tt></td>
            <td align="left">Prio3Count</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3count"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000001</tt></td>
            <td align="left">Prio3Sum</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3sum"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000002</tt></td>
            <td align="left">Prio3SumVec</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3sumvec"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000003</tt></td>
            <td align="left">Prio3Histogram</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="prio3histogram"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00000004</tt> to <tt>0x00000FFF</tt></td>
            <td align="left">reserved for Prio3</td>
            <td align="left">VDAF</td>
            <td align="left">n/a</td>
          </tr>
          <tr>
            <td align="left">
              <tt>0x00001000</tt></td>
            <td align="left">Poplar1</td>
            <td align="left">VDAF</td>
            <td align="left">
              <xref target="poplar1-inst"/></td>
          </tr>
          <tr>
            <td align="left">
              <tt>0xFFFF0000</tt> to <tt>0xFFFFFFFF</tt></td>
            <td align="left">reserved</td>
            <td align="left">n/a</td>
            <td align="left">n/a</td>
          </tr>
        </tbody>
      </table>
      <ul empty="true">
        <li>
          <t>TODO Add IANA considerations for the codepoints summarized in <xref target="codepoints"/>.</t>
        </li>
      </ul>
    </section>
  </middle>
  <back>
    <references>
      <name>References</name>
      <references anchor="sec-normative-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"/>
            <date month="March" year="1997"/>
            <abstract>
              <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        <reference anchor="RFC8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
        <reference anchor="RFC8446">
          <front>
            <title>The Transport Layer Security (TLS) Protocol Version 1.3</title>
            <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
            <date month="August" year="2018"/>
            <abstract>
              <t>This document specifies version 1.3 of the Transport Layer Security (TLS) protocol. TLS allows client/server applications to communicate over the Internet in a way that is designed to prevent eavesdropping, tampering, and message forgery.</t>
              <t>This document updates RFCs 5705 and 6066, and obsoletes RFCs 5077, 5246, and 6961. This document also specifies new requirements for TLS 1.2 implementations.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8446"/>
          <seriesInfo name="DOI" value="10.17487/RFC8446"/>
        </reference>
        <reference anchor="TurboSHAKE">
          <front>
            <title>KangarooTwelve and TurboSHAKE</title>
            <author fullname="Benoît Viguier" initials="B." surname="Viguier">
              <organization>ABN AMRO Bank</organization>
            </author>
            <author fullname="David Wong" initials="D." surname="Wong">
              <organization>zkSecurity</organization>
            </author>
            <author fullname="Gilles Van Assche" initials="G." surname="Van Assche">
              <organization>STMicroelectronics</organization>
            </author>
            <author fullname="Quynh Dang" initials="Q." surname="Dang">
              <organization>National Institute of Standards and Technology</organization>
            </author>
            <author fullname="Joan Daemen" initials="J." surname="Daemen">
              <organization>Radboud University</organization>
            </author>
            <date day="9" month="May" year="2024"/>
            <abstract>
              <t>   This document defines four eXtendable Output Functions (XOF), hash
   functions with output of arbitrary length, named TurboSHAKE128,
   TurboSHAKE256, KT128 and KT256.

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

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

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-kangarootwelve-14"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="AGJOP21" target="https://ia.cr/2021/576">
          <front>
            <title>Prio+: Privacy Preserving Aggregate Statistics via Boolean Shares</title>
            <author initials="S." surname="Addanki">
              <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="DPRS23" target="https://ia.cr/2023/130">
          <front>
            <title>Verifiable Distributed Aggregation Functions</title>
            <author initials="H." surname="Davis">
              <organization/>
            </author>
            <author initials="C." surname="Patton">
              <organization/>
            </author>
            <author initials="M." surname="Rosulek">
              <organization/>
            </author>
            <author initials="P." surname="Schoppmann">
              <organization/>
            </author>
            <date>n.d.</date>
          </front>
        </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="GKWWY20" target="https://link.springer.com/chapter/10.1007/978-3-030-56880-1_28">
          <front>
            <title>Better concrete security for half-gates garbling (in the multi-instance setting)</title>
            <author initials="C." surname="Guo">
              <organization/>
            </author>
            <author initials="J." surname="Katz">
              <organization/>
            </author>
            <author initials="X." surname="Wang">
              <organization/>
            </author>
            <author initials="C." surname="Weng">
              <organization/>
            </author>
            <author initials="Y." surname="Yu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <seriesInfo name="CRYPTO 2020" value=""/>
        </reference>
        <reference anchor="GKWY20" target="https://eprint.iacr.org/2019/074">
          <front>
            <title>Efficient and Secure Multiparty Computation from Fixed-Key Block Ciphers</title>
            <author initials="C." surname="Guo">
              <organization/>
            </author>
            <author initials="J." surname="Katz">
              <organization/>
            </author>
            <author initials="X." surname="Wang">
              <organization/>
            </author>
            <author initials="Y." surname="Yu">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <seriesInfo name="S&amp;P 2020" value=""/>
        </reference>
        <reference anchor="MPRV09" target="https://link.springer.com/chapter/10.1007/978-3-642-03356-8_8">
          <front>
            <title>Computational Differential Privacy</title>
            <author initials="I." surname="Mironov">
              <organization/>
            </author>
            <author initials="O." surname="Pandey">
              <organization/>
            </author>
            <author initials="O." surname="Reingold">
              <organization/>
            </author>
            <author initials="S." surname="Vadhan">
              <organization/>
            </author>
            <date>n.d.</date>
          </front>
          <seriesInfo name="CRYPTO 2009" value=""/>
        </reference>
        <reference anchor="MRH04" target="https://doi.org/10.1007/978-3-540-24638-1_2">
          <front>
            <title>Indifferentiability, impossibility results on reductions, and applications to the random oracle methodology</title>
            <author initials="U." surname="Maurer" fullname="Ueli Maurer">
              <organization>ETH Zurich</organization>
            </author>
            <author initials="R." surname="Renner" fullname="Renato Renner">
              <organization>ETH Zurich</organization>
            </author>
            <author initials="C." surname="Holenstein" fullname="Clemens Holenstein">
              <organization>ETH Zurich</organization>
            </author>
            <date year="2004" month="February"/>
          </front>
          <seriesInfo name="In" value="TCC 2004: Theory of Cryptography"/>
          <seriesInfo name="pages" value="21-39"/>
          <seriesInfo name="DOI" value="10.1007/978-3-540-24638-1_2"/>
        </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="DAP">
          <front>
            <title>Distributed Aggregation Protocol for Privacy Preserving Measurement</title>
            <author fullname="Tim Geoghegan" initials="T." surname="Geoghegan">
              <organization>ISRG</organization>
            </author>
            <author fullname="Christopher Patton" initials="C." surname="Patton">
              <organization>Cloudflare</organization>
            </author>
            <author fullname="Brandon Pitman" initials="B." surname="Pitman">
              <organization>ISRG</organization>
            </author>
            <author fullname="Eric Rescorla" initials="E." surname="Rescorla">
              <organization>Mozilla</organization>
            </author>
            <author fullname="Christopher A. Wood" initials="C. A." surname="Wood">
              <organization>Cloudflare</organization>
            </author>
            <date day="29" month="February" year="2024"/>
            <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 distributed aggregation protocol
   (DAP) for privacy preserving measurement (PPM) which can be used to
   collect aggregate data without revealing any individual user's data.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-ppm-dap-10"/>
        </reference>
      </references>
    </references>
    <?line 4765?>

<section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The security considerations in <xref target="security"/> are based largely on the security
analysis of <xref target="DPRS23"/>. Thanks to Hannah Davis and Mike Rosulek, who lent their
time to developing definitions and security proofs.</t>
      <t>Thanks to Junye Chen, Henry Corrigan-Gibbs, Armando Faz-Hernández, Simon
Friedberger, Tim Geoghegan, Albert Liu, Brandon Pitman, Mariana Raykova, Jacob
Rothstein, Shan Wang, Xiao Wang, Bas Westerbaan, 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>[TO BE REMOVED BY RFC EDITOR: Machine-readable test vectors can be found at
https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec.]</t>
      <t>Test vectors cover the generation of input shares and the conversion of input
shares into output shares. Vectors specify the verification key, measurements,
aggregation parameter, and any parameters needed to construct the VDAF. (For
example, for <tt>Prio3Sum</tt>, the user specifies the number of bits for representing
each summand.)</t>
      <t>Byte strings are encoded in hexadecimal. To make the tests deterministic, the
random inputs of randomized algorithms were fixed to the byte sequence starting
with <tt>0</tt>, incrementing by <tt>1</tt>, and wrapping at <tt>256</tt>:</t>
      <artwork><![CDATA[
0, 1, 2, ..., 255, 0, 1, 2, ...
]]></artwork>
      <section numbered="false" anchor="testvec-prio3count">
        <name>Prio3Count</name>
        <ul empty="true">
          <li>
            <t>TODO Copy the machine readable vectors from the source repository
(https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec) and
format them for humans.</t>
          </li>
        </ul>
      </section>
      <section numbered="false" anchor="testvec-prio3sum">
        <name>Prio3Sum</name>
        <ul empty="true">
          <li>
            <t>TODO Copy the machine readable vectors from the source repository
(https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec) and
format them for humans.</t>
          </li>
        </ul>
      </section>
      <section numbered="false" anchor="testvec-prio3sumvec">
        <name>Prio3SumVec</name>
        <ul empty="true">
          <li>
            <t>TODO Copy the machine readable vectors from the source repository
(https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec) and
format them for humans.</t>
          </li>
        </ul>
      </section>
      <section numbered="false" anchor="testvec-prio3histogram">
        <name>Prio3Histogram</name>
        <ul empty="true">
          <li>
            <t>TODO Copy the machine readable vectors from the source repository
(https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec) and
format them for humans.</t>
          </li>
        </ul>
      </section>
      <section numbered="false" anchor="testvec-poplar1">
        <name>Poplar1</name>
        <ul empty="true">
          <li>
            <t>TODO Copy the machine readable vectors from the source repository
(https://github.com/cfrg/draft-irtf-cfrg-vdaf/tree/main/poc/test_vec) and
format them for humans.</t>
          </li>
        </ul>
      </section>
    </section>
  </back>
  <!-- ##markdown-source:
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

-->

</rfc>
