<?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.17 (Ruby 3.3.3) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-savage-ppm-3phm-mpc-00" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.22.0 -->
  <front>
    <title abbrev="3 Party MPC">Efficient Protocols for Binary Fields in the 3-Party Honest Majority MPC Setting</title>
    <seriesInfo name="Internet-Draft" value="draft-savage-ppm-3phm-mpc-00"/>
    <author initials="B." surname="Savage" fullname="Ben Savage">
      <organization>Meta</organization>
      <address>
        <email>btsavage@meta.com</email>
      </address>
    </author>
    <author initials="M." surname="Thomson" fullname="Martin Thomson">
      <organization>Mozilla</organization>
      <address>
        <email>mt@lowentropy.net</email>
      </address>
    </author>
    <date year="2024" month="July" day="08"/>
    <area>Security</area>
    <workgroup>Privacy Preserving Measurement</workgroup>
    <keyword>arithmetic</keyword>
    <keyword>polynomial</keyword>
    <keyword>vector</keyword>
    <abstract>
      <?line 50?>

<t>TODO</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://private-attribution.github.io/i-d/draft-savage-ppm-3phm-mpc.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-savage-ppm-3phm-mpc/"/>.
      </t>
      <t>
        Discussion of this document takes place on the
        Privacy Preserving Measurement Working Group mailing list (<eref target="mailto:ppm@ietf.org"/>),
        which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/ppm/"/>.
        Subscribe at <eref target="https://www.ietf.org/mailman/listinfo/ppm/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/private-attribution/i-d"/>.</t>
    </note>
  </front>
  <middle>
    <?line 54?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>Multiparty Computation (MPC) can perform generic computations over inputs that
are never revealed to any single entity. MPC executes an agreed function,
revealing only the output of that function.</t>
      <t>This makes MPC well-suited to handling data that is sensitive or private. MPC in
a three-party honest majority setting, is broadly recognized as being extremely
efficient:</t>
      <ul spacing="normal">
        <li>
          <t>Addition and subtraction have zero communication cost and negligible
computation cost.</t>
        </li>
        <li>
          <t>Multiplication is possible with low communication and computation complexity.</t>
        </li>
        <li>
          <t>Strong guarantees can be made about correctness and confidentiality, relying
on only information-theoretic assumptions.</t>
        </li>
      </ul>
      <t>This document describes the basic elements required to compute basic MPC
circuits in this setting. This includes the basic elements of the replicated
secret sharing scheme that is used: generating shares, share addition, and
revealing shared values.</t>
      <t>The bulk of the document describes a protocol for multiplication over a binary
field. The basic multiplication protocol scales linearly and involves 1 bit of
communication per party.</t>
      <t>This basic multiplication protocol does not prevent an additive attack. To deal
with the additive attack, a batched validation protocol is used, which adds a
sub-linear overhead. This protocol comes with significant memory costs and
slightly increased computational costs, but adds negligible communication
overhead and latency when there are many multiplications to validate.</t>
      <section anchor="mpc-protocols-in-binary-fields">
        <name>MPC Protocols in Binary Fields</name>
        <t>This document describes a multiplication protocol that is specialized for use
with binary fields; see <xref target="fields"/>.</t>
        <t>Composing binary operations into a complete MPC system has proven to be more
efficient than alternatives using prime fields in a number of applications. Some
of the components in this document can be applied to rings or larger prime
fields, but the validation process used here has been specialized for use with
binary values.</t>
      </section>
    </section>
    <section anchor="three-party-honest-majority-mpc">
      <name>Three-Party Honest Majority MPC</name>
      <t>A three-party honest majority MPC system performs computations on secret-shared
values using a replicated scheme where each party receives two out of three
additive shares of input values. Strong guarantees are provided regarding the
confidentiality of inputs provided that no pair of parties reveals their shares
to either of the other parties.</t>
      <t>The protocols described in this document depend on having three MPC parties
execute them. The protocols described here are secure with abort, even when one
party is not honest.</t>
      <t>Concretely, this means that a single dishonest party cannot cause the value of
inputs to be revealed. Also, a single dishonest party cannot alter the output of
any operation without detection. The protocol is aborted if honest parties
detect an error that might indicate the actions of a dishonest party. This means
that a dishonest party can disrupt the protocol</t>
      <section anchor="mpc-protocol-prerequisites">
        <name>MPC Protocol Prerequisites</name>
        <t>MPC parties require channels to each of the other parties that provide
confidentiality, integrity and peer authentication. Mutually-authenticated TLS
<xref target="RFC8446"/> provides the necessary capabilities, however, this document does
not define how to arrange communication between parties; protocols that use
these mechanisms need to define how communication between parties is
established.</t>
        <t>The multiplication protocol described depends on shared randomness for
efficiency. The protocol depends on having a way for parties to pairwise agree
on random values. MPC parties can execute a coin toss protocol using the
communication channel, however it is considerably more efficient to use
pseudorandom secret sharing <xref target="PRSS"/> when there are a large number of
multiplications.</t>
        <t>This section describes basic operations of secret sharing (<xref target="sharing"/>), reveal
protocol (<xref target="reveal"/>), and addition (<xref target="addition"/>). Multiplication is more
involved and is the subject of subsequent sections (<xref target="multiplication"/>,
<xref target="validation"/>).</t>
      </section>
      <section anchor="fields">
        <name>Fields and Rings</name>
        <t>The basic multiplication protocol described in <xref target="multiplication"/> operates in
any commutative ring, which will be referred to as simply a "ring". A ring is a
group that defines addition and multiplication operations that are both
associative and commutative. A ring has an additive inverse for every element,
which enables subtraction. A ring contains a "zero" element that is an additive
identity plus a "one" element that is a multiplicative identity.</t>
        <t>A simple realization of a ring is formed of integers modulo a chosen integer
that is greater than 1.</t>
        <t>The validation protocol described in this document (see <xref target="validation"/>) uses a
modulo 2 ring. This ring is referred to throughput as a binary field as it is
also a field and it contains two values: 0 and 1. Addition and multiplication in
a binary field correspond to Boolean operations. Addition in a binary field is
equivalent to the Boolean exclusive OR (XOR) operation. Multiplication in a
binary field is equivalent to the Boolean AND operation.</t>
        <t>The security properties of the validation protocol depend on the use of a prime
field of sufficient size. Fields support the same operations as rings, adding
multiplicative inversion of elements, which enables a division operation. A
prime field can be realized from integers modulo any prime. The validation
protocol integrates the projection of values in a binary field to a larger prime
field, rather than requiring a separate conversion step.</t>
      </section>
      <section anchor="sharing">
        <name>Secret Sharing</name>
        <t>Each input value (<tt>x</tt>) is split into three shares (<tt>x₁</tt>, <tt>x₂</tt>,
<tt>x₃</tt>), such that <tt>x = x₁ + x₂ + x₃</tt>. Any
method can be used, but the following process is typical:</t>
        <sourcecode type="pseudocode"><![CDATA[
x₁ = random()
x₂ = random()
x₃ = x - x₁ - x₂
]]></sourcecode>
        <t>Then, each party in the MPC receives a different set of two values. This
document adopts the convention that P<sub>1</sub> receives (<tt>x₁</tt>,
<tt>x₂</tt>), P<sub>2</sub> receives (<tt>x₂</tt>, <tt>x₃</tt>), and
P<sub>3</sub> receives (<tt>x₃</tt>, <tt>x₁</tt>). From this sharing, no
single party is able to construct the original value (<tt>x</tt>), but the values from
any two parties include all three shares and can be used to reconstruct the
original value.</t>
        <t>Some protocols might require that the parties construct a sharing of a value
which is known to all the parties. In that case, the value of <tt>x₁</tt> is
set to the known value, with <tt>x₂</tt> and <tt>x₃</tt> both set to zero.</t>
      </section>
      <section anchor="identifying-shares-and-parties">
        <name>Identifying Shares and Parties</name>
        <t>This document identifies shares and parties by number. Three parties are
identified as P<sub>1</sub>, P<sub>2</sub>, and P<sub>3</sub>. The first, or
left share, value held by each party is identified with the same subscript.  The
other share, or right share, held by each is the next highest-numbered share
(with <tt>x₁</tt> being the next highest after <tt>x₃</tt>). This is
illustrated in <xref target="fig-shares-parties"/>:</t>
        <figure anchor="fig-shares-parties">
          <name>Parties and Shares</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="112" width="360" viewBox="0 0 360 112" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 56,32 L 80,32" fill="none" stroke="black"/>
                <path d="M 168,32 L 192,32" fill="none" stroke="black"/>
                <path d="M 280,32 L 304,32" fill="none" stroke="black"/>
                <path d="M 8,48 L 40,48" fill="none" stroke="black"/>
                <path d="M 96,48 L 152,48" fill="none" stroke="black"/>
                <path d="M 208,48 L 264,48" fill="none" stroke="black"/>
                <path d="M 320,48 L 352,48" fill="none" stroke="black"/>
                <path d="M 56,64 L 80,64" fill="none" stroke="black"/>
                <path d="M 168,64 L 192,64" fill="none" stroke="black"/>
                <path d="M 280,64 L 304,64" fill="none" stroke="black"/>
                <path d="M 24,80 L 336,80" fill="none" stroke="black"/>
                <path d="M 8,48 L 24,80" fill="none" stroke="black"/>
                <path d="M 336,80 L 352,48" fill="none" stroke="black"/>
                <path d="M 56,32 C 47.16936,32 40,39.16936 40,48" fill="none" stroke="black"/>
                <path d="M 80,32 C 88.83064,32 96,39.16936 96,48" fill="none" stroke="black"/>
                <path d="M 168,32 C 159.16936,32 152,39.16936 152,48" fill="none" stroke="black"/>
                <path d="M 192,32 C 200.83064,32 208,39.16936 208,48" fill="none" stroke="black"/>
                <path d="M 280,32 C 271.16936,32 264,39.16936 264,48" fill="none" stroke="black"/>
                <path d="M 304,32 C 312.83064,32 320,39.16936 320,48" fill="none" stroke="black"/>
                <path d="M 56,64 C 47.16936,64 40,56.83064 40,48" fill="none" stroke="black"/>
                <path d="M 80,64 C 88.83064,64 96,56.83064 96,48" fill="none" stroke="black"/>
                <path d="M 168,64 C 159.16936,64 152,56.83064 152,48" fill="none" stroke="black"/>
                <path d="M 192,64 C 200.83064,64 208,56.83064 208,48" fill="none" stroke="black"/>
                <path d="M 280,64 C 271.16936,64 264,56.83064 264,48" fill="none" stroke="black"/>
                <path d="M 304,64 C 312.83064,64 320,56.83064 320,48" fill="none" stroke="black"/>
                <g class="text">
                  <text x="28" y="36">x₁</text>
                  <text x="108" y="36">x₂</text>
                  <text x="140" y="36">x₂</text>
                  <text x="220" y="36">x₃</text>
                  <text x="252" y="36">x₃</text>
                  <text x="332" y="36">x₁</text>
                  <text x="68" y="52">P₁</text>
                  <text x="180" y="52">P₂</text>
                  <text x="292" y="52">P₃</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
         x₁ .----. x₂  x₂ .----. x₃  x₃ .----. x₁
       .---+  P₁  +------+  P₂  +------+  P₃  +---.
        \   `----'        `----'        `----'   /
         '--------------------------------------'
]]></artwork>
          </artset>
        </figure>
        <t>Three parties are identified as P<sub>1</sub>, P<sub>2</sub>, and P<sub>3</sub>.</t>
        <t>The three parties are logically placed in a ring, with higher numbered parties
to the right of lower-numbered parties. P<sub>3</sub> is placed to the left of
P<sub>1</sub>. This means that if a protocol involves sending a value to the
left, P<sub>1</sub> sends the value to P<sub>3</sub>, P<sub>2</sub> sends to
P<sub>1</sub>, and P<sub>3</sub> sends to P<sub>2</sub>. The sending directions
are illustrated in <xref target="fig-send-direction"/>.</t>
        <figure anchor="fig-send-direction">
          <name>Parties and Sending Directions</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="208" width="376" viewBox="0 0 376 208" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 104,48 L 128,48" fill="none" stroke="black"/>
                <path d="M 200,48 L 224,48" fill="none" stroke="black"/>
                <path d="M 296,48 L 320,48" fill="none" stroke="black"/>
                <path d="M 64,64 L 88,64" fill="none" stroke="black"/>
                <path d="M 152,64 L 184,64" fill="none" stroke="black"/>
                <path d="M 248,64 L 280,64" fill="none" stroke="black"/>
                <path d="M 344,64 L 368,64" fill="none" stroke="black"/>
                <path d="M 104,80 L 128,80" fill="none" stroke="black"/>
                <path d="M 200,80 L 224,80" fill="none" stroke="black"/>
                <path d="M 296,80 L 320,80" fill="none" stroke="black"/>
                <path d="M 80,96 L 352,96" fill="none" stroke="black"/>
                <path d="M 112,144 L 136,144" fill="none" stroke="black"/>
                <path d="M 208,144 L 232,144" fill="none" stroke="black"/>
                <path d="M 304,144 L 328,144" fill="none" stroke="black"/>
                <path d="M 64,160 L 88,160" fill="none" stroke="black"/>
                <path d="M 152,160 L 184,160" fill="none" stroke="black"/>
                <path d="M 248,160 L 280,160" fill="none" stroke="black"/>
                <path d="M 344,160 L 368,160" fill="none" stroke="black"/>
                <path d="M 112,176 L 136,176" fill="none" stroke="black"/>
                <path d="M 208,176 L 232,176" fill="none" stroke="black"/>
                <path d="M 304,176 L 328,176" fill="none" stroke="black"/>
                <path d="M 80,192 L 352,192" fill="none" stroke="black"/>
                <path d="M 64,160 L 80,192" fill="none" stroke="black"/>
                <path d="M 64,64 L 80,96" fill="none" stroke="black"/>
                <path d="M 352,96 L 368,64" fill="none" stroke="black"/>
                <path d="M 352,192 L 368,160" fill="none" stroke="black"/>
                <path d="M 104,48 C 95.16936,48 88,55.16936 88,64" fill="none" stroke="black"/>
                <path d="M 128,48 C 136.83064,48 144,55.16936 144,64" fill="none" stroke="black"/>
                <path d="M 200,48 C 191.16936,48 184,55.16936 184,64" fill="none" stroke="black"/>
                <path d="M 224,48 C 232.83064,48 240,55.16936 240,64" fill="none" stroke="black"/>
                <path d="M 296,48 C 287.16936,48 280,55.16936 280,64" fill="none" stroke="black"/>
                <path d="M 320,48 C 328.83064,48 336,55.16936 336,64" fill="none" stroke="black"/>
                <path d="M 104,80 C 95.16936,80 88,72.83064 88,64" fill="none" stroke="black"/>
                <path d="M 128,80 C 136.83064,80 144,72.83064 144,64" fill="none" stroke="black"/>
                <path d="M 200,80 C 191.16936,80 184,72.83064 184,64" fill="none" stroke="black"/>
                <path d="M 224,80 C 232.83064,80 240,72.83064 240,64" fill="none" stroke="black"/>
                <path d="M 296,80 C 287.16936,80 280,72.83064 280,64" fill="none" stroke="black"/>
                <path d="M 320,80 C 328.83064,80 336,72.83064 336,64" fill="none" stroke="black"/>
                <path d="M 112,144 C 103.16936,144 96,151.16936 96,160" fill="none" stroke="black"/>
                <path d="M 136,144 C 144.83064,144 152,151.16936 152,160" fill="none" stroke="black"/>
                <path d="M 208,144 C 199.16936,144 192,151.16936 192,160" fill="none" stroke="black"/>
                <path d="M 232,144 C 240.83064,144 248,151.16936 248,160" fill="none" stroke="black"/>
                <path d="M 304,144 C 295.16936,144 288,151.16936 288,160" fill="none" stroke="black"/>
                <path d="M 328,144 C 336.83064,144 344,151.16936 344,160" fill="none" stroke="black"/>
                <path d="M 112,176 C 103.16936,176 96,168.83064 96,160" fill="none" stroke="black"/>
                <path d="M 136,176 C 144.83064,176 152,168.83064 152,160" fill="none" stroke="black"/>
                <path d="M 208,176 C 199.16936,176 192,168.83064 192,160" fill="none" stroke="black"/>
                <path d="M 232,176 C 240.83064,176 248,168.83064 248,160" fill="none" stroke="black"/>
                <path d="M 304,176 C 295.16936,176 288,168.83064 288,160" fill="none" stroke="black"/>
                <path d="M 328,176 C 336.83064,176 344,168.83064 344,160" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="352,64 340,58.4 340,69.6" fill="black" transform="rotate(180,344,64)"/>
                <polygon class="arrowhead" points="288,160 276,154.4 276,165.6" fill="black" transform="rotate(0,280,160)"/>
                <polygon class="arrowhead" points="256,64 244,58.4 244,69.6" fill="black" transform="rotate(180,248,64)"/>
                <polygon class="arrowhead" points="192,160 180,154.4 180,165.6" fill="black" transform="rotate(0,184,160)"/>
                <polygon class="arrowhead" points="160,64 148,58.4 148,69.6" fill="black" transform="rotate(180,152,64)"/>
                <polygon class="arrowhead" points="96,160 84,154.4 84,165.6" fill="black" transform="rotate(0,88,160)"/>
                <g class="text">
                  <text x="20" y="36">send</text>
                  <text x="24" y="52">left:</text>
                  <text x="116" y="68">P₁</text>
                  <text x="212" y="68">P₂</text>
                  <text x="308" y="68">P₃</text>
                  <text x="20" y="132">send</text>
                  <text x="28" y="148">right:</text>
                  <text x="124" y="164">P₁</text>
                  <text x="220" y="164">P₂</text>
                  <text x="316" y="164">P₃</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
send
left:      .----.      .----.      .----.
       .--+  P₁  |<---+  P₂  |<---+  P₃  |<--.
        \  `----'      `----'      `----'   /
         '---------------------------------'

send
right:      .----.      .----.      .----.
       .-->|  P₁  +--->+  P₂  +--->|  P₃  +--.
        \   `----'      `----'      `----'  /
         '---------------------------------'
]]></artwork>
          </artset>
        </figure>
        <t>Protocols are often described in terms of the actions of a single party. The
party to the left of that party is P<sub>-</sub> and the party to the right is
P<sub>+</sub>. Where necessary, the current party is identified as
P<sub>=</sub>.</t>
        <t>The two shares that each party holds are referred to as "left" and "right"
shares. The "left" share is identified with a subscript of "-" (e.g.,
x_-); the numeric identifier for the left share at each party matches
the identifier for that party, so the left share of x that P<sub>1</sub> holds
is named x<sub>1</sub>. The right share is designated with a subscript of "+"
(e.g., y_+); the numeric identifier for the right share is one higher
than the identifier for the party, so the right share at P<sub>3</sub> is (also)
x<sub>1</sub>.</t>
      </section>
      <section anchor="reveal">
        <name>Reveal Protocol</name>
        <t>The output of a protocol can be revealed by sending all share values to the
entity that will receive the final result. This entity can validate the
consistency of the values it receives by ensuring that the replicated values it
receives are identical. That is, the value of x<sub>1</sub> received from
P<sub>1</sub> is the same as the value of x<sub>1</sub> it receives from
P<sub>3</sub> and so forth. If the value of shares are inconsistent, the
protocol fails. After discarding these duplicated values, the revealed value is
the sum of the shares that it receives.</t>
        <t>A value can be revealed by sending adjacent parties the one share value they do
not have. That is, P<sub>1</sub> sends x<sub>1</sub> to P<sub>2</sub> and
x<sub>2</sub> to P<sub>3</sub>; P<sub>2</sub> sends x<sub>2</sub> to
P<sub>3</sub> and x<sub>3</sub> to P<sub>1;</sub> P<sub>3</sub> sends
x<sub>3</sub> to P<sub>1</sub> and x<sub>1</sub> to P<sub>2</sub>. Each party
verifies that they receive the same value twice, and aborts if they do not.</t>
        <t>If the protocol is executed correctly, each party learns the revealed value,
which is the sum of the two shares it holds, plus the share that was received.</t>
        <t>This basic reveal protocol requires that each party send and receive two
elements. More efficient protocols are possible, but these are not defined in
this document.</t>
      </section>
      <section anchor="addition">
        <name>Addition</name>
        <t>Addition of two values in this setting is trivial and requires no communication
between parties. To add x to y, each party adds their shares. That is, to
compute z = x + y, each party separately computes the sum of the shares they
hold:</t>
        <sourcecode type="pseudocode"><![CDATA[
z₋ = x₋ + y₋
z₊ = x₊ + y₊
]]></sourcecode>
        <t>This produces shares of the sum without requiring communication.</t>
        <t>A similar process can be used for multiplication with a value that is known to
all parties, negation, and subtraction.</t>
        <aside>
          <t>Note: Addition in a binary field is the same as subtraction and both are
equivalent to the XOR operation.</t>
        </aside>
      </section>
    </section>
    <section anchor="multiplication">
      <name>Multiplication Protocol</name>
      <t>The product of two shared values, x and y, is computed using the following process.</t>
      <t>Since <tt>x = x₁ + x₂ + x₃</tt> and <tt>y = y₁ +
y₂ + y₃</tt> the product <tt>z = x · y</tt> can be expanded as:</t>
      <sourcecode type="pseudocode"><![CDATA[
z = (x₁ + x₂ + x₃) · (y₁ + y₂ + y₃)
]]></sourcecode>
      <t>This can be illustrated with a 3 by 3 table (<xref target="tab-mul"/>):</t>
      <table anchor="tab-mul">
        <name>Multiplication by Parts</name>
        <thead>
          <tr>
            <th align="left"> </th>
            <th align="left">y₁</th>
            <th align="left">y₂</th>
            <th align="left">y₃</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">x<sub>1</sub></td>
            <td align="left">x<sub>1</sub>*y<sub>1</sub></td>
            <td align="left">x<sub>1</sub>*y<sub>2</sub></td>
            <td align="left">x<sub>1</sub>*y<sub>3</sub></td>
          </tr>
          <tr>
            <td align="left">x<sub>2</sub></td>
            <td align="left">x<sub>2</sub>*y<sub>1</sub></td>
            <td align="left">x<sub>2</sub>*y<sub>2</sub></td>
            <td align="left">x<sub>2</sub>*y<sub>3</sub></td>
          </tr>
          <tr>
            <td align="left">x<sub>3</sub></td>
            <td align="left">x<sub>3</sub>*y<sub>1</sub></td>
            <td align="left">x<sub>3</sub>*y<sub>2</sub></td>
            <td align="left">x<sub>3</sub>*y<sub>3</sub></td>
          </tr>
        </tbody>
      </table>
      <t>To compute the product, each party locally computes the sum of three products as follows:</t>
      <sourcecode type="pseudocode"><![CDATA[
z₋ = x₋·y₋ + x₋·y₊ + x₊·y₋
]]></sourcecode>
      <t>To visualize this, <xref target="fig-mul"/> shows cells labeled with the party responsible for computing that partial product:</t>
      <figure anchor="fig-mul">
        <name>Multiplication by Party</name>
        <artset>
          <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="320" width="432" viewBox="0 0 432 320" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
              <path d="M 32,48 L 32,144" fill="none" stroke="black"/>
              <path d="M 32,192 L 32,288" fill="none" stroke="black"/>
              <path d="M 88,80 L 88,112" fill="none" stroke="black"/>
              <path d="M 88,256 L 88,288" fill="none" stroke="black"/>
              <path d="M 144,48 L 144,80" fill="none" stroke="black"/>
              <path d="M 144,192 L 144,224" fill="none" stroke="black"/>
              <path d="M 144,256 L 144,288" fill="none" stroke="black"/>
              <path d="M 200,48 L 200,144" fill="none" stroke="black"/>
              <path d="M 200,192 L 200,288" fill="none" stroke="black"/>
              <path d="M 256,48 L 256,144" fill="none" stroke="black"/>
              <path d="M 312,80 L 312,144" fill="none" stroke="black"/>
              <path d="M 368,112 L 368,144" fill="none" stroke="black"/>
              <path d="M 424,48 L 424,144" fill="none" stroke="black"/>
              <path d="M 32,48 L 200,48" fill="none" stroke="black"/>
              <path d="M 256,48 L 424,48" fill="none" stroke="black"/>
              <path d="M 88,80 L 144,80" fill="none" stroke="black"/>
              <path d="M 312,80 L 424,80" fill="none" stroke="black"/>
              <path d="M 32,112 L 88,112" fill="none" stroke="black"/>
              <path d="M 368,112 L 424,112" fill="none" stroke="black"/>
              <path d="M 32,144 L 200,144" fill="none" stroke="black"/>
              <path d="M 256,144 L 424,144" fill="none" stroke="black"/>
              <path d="M 32,192 L 200,192" fill="none" stroke="black"/>
              <path d="M 144,224 L 200,224" fill="none" stroke="black"/>
              <path d="M 32,256 L 88,256" fill="none" stroke="black"/>
              <path d="M 144,256 L 200,256" fill="none" stroke="black"/>
              <path d="M 32,288 L 200,288" fill="none" stroke="black"/>
              <g class="text">
                <text x="60" y="36">y₁</text>
                <text x="116" y="36">y₂</text>
                <text x="172" y="36">y₃</text>
                <text x="284" y="36">y₁</text>
                <text x="340" y="36">y₂</text>
                <text x="396" y="36">y₃</text>
                <text x="12" y="68">x₁</text>
                <text x="60" y="68">P₁</text>
                <text x="236" y="68">x₁</text>
                <text x="12" y="100">x₂</text>
                <text x="236" y="100">x₂</text>
                <text x="340" y="100">P₂</text>
                <text x="12" y="132">x₃</text>
                <text x="236" y="132">x₃</text>
                <text x="44" y="180">y₁</text>
                <text x="100" y="180">y₂</text>
                <text x="156" y="180">y₃</text>
                <text x="12" y="212">x₁</text>
                <text x="172" y="212">P₃</text>
                <text x="12" y="244">x₂</text>
                <text x="12" y="276">x₃</text>
                <text x="60" y="276">P₃</text>
                <text x="172" y="276">P₃</text>
              </g>
            </svg>
          </artwork>
          <artwork type="ascii-art"><![CDATA[
        y₁     y₂     y₃            y₁     y₂     y₃
     +-------------+------+      +--------------------+
  x₁ |  P₁         |      |   x₁ |                    |
     |      +------+      |      |      +-------------+
  x₂ |      |             |   x₂ |      |  P₂         |
     +------+             |      |      |      +------+
  x₃ |                    |   x₃ |      |      |      |
     +--------------------+      +------+------+------+

      y₁     y₂     y₃
     +-------------+------+
  x₁ |             |  P₃  |
     |             +------+
  x₂ |                    |
     +------+      +------+
  x₃ |  P₃  |      |  P₃  |
     +------+------+------+
]]></artwork>
        </artset>
      </figure>
      <t>The result is a non-replicated sharing of the result <tt>z = z₁ + z₂ + z₃</tt>.</t>
      <t>To reach the desired state where parties each have replicated shares of <tt>z</tt>, each
party needs to send its share, <tt>z₋</tt>, to the party to its left.</t>
      <t>Unfortunately, each party cannot simply send this value to another party, as
this would allow the recipient to reconstruct the full input values, <tt>x</tt> and
<tt>y</tt>, using <tt>z₋</tt>. To prevent this, the value of <tt>z₋</tt> is masked with a uniformly
distributed random mask that is unknown to party P<sub>-</sub>.</t>
      <t>Using a source of shared randomness (such as <xref target="PRSS"/>), each pair of helpers
generates a uniformly distributed random value known only to the two of
them. Let <tt>r₋</tt> denote the left value (known to P<sub>-</sub>) and <tt>r₊</tt> be the
right value (known to P<sub>+</sub>).</t>
      <t>Each party uses <tt>r₋</tt> and <tt>r₊</tt> to create a masked value of <tt>z₋</tt> as follows:</t>
      <sourcecode type="pseudocode"><![CDATA[
z₋ = x₋·y₋ + x₋·y₊ + x₊·y₋ + r₋ - r₊
]]></sourcecode>
      <t>Each of these three mask values are added once and subtracted once, so this
masking does not alter the result. Importantly, the value of <tt>r₊</tt> is not
known to P<sub>-</sub>, which ensures that <tt>z₋</tt> cannot be used by P<sub>-</sub>
to recover <tt>x</tt> or <tt>y</tt>. Thus, <tt>z₋</tt> is safe to send to P<sub>-</sub>.</t>
      <t>Upon receiving a value from its right -- which the recipient names <tt>z₊</tt> — each
helper is now in possession of two-of-three shares, (<tt>z₋</tt>, <tt>z₊</tt>), which is a
replicated secret sharing of the product of <tt>x</tt> and <tt>y</tt>.</t>
    </section>
    <section anchor="validation">
      <name>Validation Protocol</name>
      <t>The basic multiplication protocol in <xref target="multiplication"/> only offers semi-honest
security. It is secure up to an additive attack; see <xref target="additive-attack"/>. Validating multiplications
allows an additive attack to be detected, ensuring that a protocol is aborted
before any result is produced that might compromise the confidentiality of
inputs.</t>
      <section anchor="additive-attack">
        <name>Additive Attack</name>
        <t>By "additive attack", we mean that instead of sending the value <tt>z₋</tt>, a corrupted
party could instead send <tt>z₋ + a</tt>. In the context of boolean circuits, the only
possible additive attack is to add 1.</t>
        <t>The multiplication protocol described does not prevent this. Since the value
<tt>z₋</tt> is randomly distributed, the party (P<sub>-</sub>) that receives this
value cannot tell if an additive attack has been applied.</t>
        <t>While an additive attack does not result in information about the inputs being
revealed, it corrupts the results. If a protocol depends on revealing certain
values, this sort of corruption could be used to reveal information that might
not otherwise be revealed.</t>
        <t>For example, if the parties were computing a function that erases a value unless
it has reached some minimum such as:</t>
        <sourcecode type="python"><![CDATA[
if total_count > 1000:
    reveal(total_count)
else:
    reveal(0)
]]></sourcecode>
        <t>If a corrupted helper wanted to reveal a total_count that was less than 1000, it
could add 1 to the final multiplication used to compute the condition
<tt>total_count &gt; 1000</tt>. The result is that values below the minimum are revealed
(and values above the minimum are erased), violating the conditions on the
protocol.</t>
      </section>
      <section anchor="malicious-security">
        <name>Malicious Security</name>
        <t>Before any values are revealed, the parties perform a validation protocol. This
protocol confirms that all of the multiplications performed were performed
correctly. That is, that no additive attack was applied by any party.</t>
        <t>If this validation protocol fails, the parties abort the protocol and no values
are revealed. All parties destroy the shares they hold.</t>
      </section>
      <section anchor="overview-of-the-validation-protocol">
        <name>Overview of the Validation Protocol</name>
        <t>Each of the parties produces a "Zero Knowledge Proof" (ZKP) that proves to the
two other parties (P<sub>-</sub> and P<sub>+</sub>) that all of the
multiplications it performed were done correctly. The two other parties act as
"verifiers" and validate this zero knowledge proof.</t>
        <t>The validation protocol is therefore executed three times, with each party
acting as a prover.  Each validation can occur concurrently.</t>
        <t>When operating in a boolean field, if P<sub>=</sub> followed the protocol
correctly, this is how they would compute <tt>z₋</tt>:</t>
        <sourcecode type="pseudocode"><![CDATA[
z₋ = x₋·y₋ ⊕ x₋·y₊ ⊕ x₊·y₋ ⊕ r₋ ⊕ r₊
]]></sourcecode>
        <t>This can be restated as:</t>
        <sourcecode type="pseudocode"><![CDATA[
x₋·y₋ ⊕ x₋·y₊ ⊕ x₊·y₋ ⊕ r₋ ⊕ r₊ ⊕ z₋ = 0
]]></sourcecode>
        <t>The left hand side of this expression will equal zero if the protocol was followed
correctly, but it will equal one if there was an additive attack.</t>
        <t>Validation is made more efficient by validating multiple multiplications at the
same time.</t>
        <t>The above statement can be transformed to yield the result (either zero or one)
as a value in a large prime field <xref target="prime_field_transformation"/>. These values
can be summed across all the multiplications in a large batch. The total sum will
be the count of additive attacks applied, which will be zero if the prover correctly
followed the protocol. There will not be any wrapping around so long as the number
of multiplications in the batch is smaller than the prime used to define the field.</t>
        <t>For this protocol, the parties will use the field of integers mod <tt>p</tt>, where <tt>p</tt> is a large prime.</t>
      </section>
      <section anchor="distributed-zero-knowledge-proofs">
        <name>Distributed Zero-Knowledge Proofs</name>
        <t>The prover (P<sub>=</sub>) needs to prove that for each multiplication in a batch:</t>
        <sourcecode type="pseudocode"><![CDATA[
x₋·y₋ ⊕ x₋·y₊ ⊕ x₊·y₋ ⊕ r₋ ⊕ r₊ ⊕ z₋ = 0
]]></sourcecode>
        <t>The left verifier (P<sub>-</sub>) knows the values of <tt>y₋</tt>, <tt>x₋</tt>,
<tt>r₋</tt>, and <tt>z₋</tt>.</t>
        <t>The right verifier (P<sub>+</sub>) knows the values of <tt>x₊</tt>, <tt>y₊</tt>,
<tt>r₊</tt>.</t>
        <t>This means that the prover (P<sub>=</sub>) does not need to send any of these
values to the verifiers. Verifiers use information they already have to validate
the proof.</t>
        <t>Since the two verifiers possess all of this information distributed amongst
themselves, this approach is referred to as "Distributed Zero Knowledge Proofs".</t>
      </section>
      <section anchor="distributed-zero-knowledge-proofs-1">
        <name>Distributed Zero Knowledge Proofs</name>
        <t><xref target="FLPCP"/> describes a system of zero-knowledge
proofs that rely on linear operations. This is expanded in
<xref target="BOYLE"/> to apply to three-party
honest-majority MPC, requiring only O(logN) communication in total.  These
proofs are able to validate the computation of an inner product, or expressions
of the form:</t>
        <sourcecode type="pseudocode"><![CDATA[
sum(i=0..n, uᵢ · vᵢ) = t
]]></sourcecode>
        <t>This depends on the prover (P<sub>=</sub>) and left verifier (P<sub>-</sub>)
both possessing the n-vector <tt>u</tt>, the prover (P<sub>=</sub>) and the right
verifier (P<sub>+</sub>) possessing the n-vector <tt>v</tt>, and the verifiers
P<sub>-</sub> and P<sub>+</sub> jointly holding shares of the target value, <tt>t</tt>
(that is, P<sub>-</sub> holds <tt>t₋</tt> and P<sub>-</sub> holds <tt>t₊</tt> such that <tt>t₋
+ t₊ = t</tt>).</t>
        <t>However, the security of this protocol requires the vector elements <tt>u</tt> and <tt>v</tt>
to be members of a large field. So the first step of the validation protocol is
to take a batch of multiplications, and convert them into a dot product of
vectors with elements in a large field.</t>
      </section>
      <section anchor="prime_field_transformation">
        <name>Transforming into a Large Prime Field</name>
        <t><xref target="BINARY"/> describes how to apply <xref target="FLPCP"/>
efficiently for binary fields.  When binary values are directly lifted into a
large field, the XOR operation can be computed with the expression:</t>
        <sourcecode type="pseudocode"><![CDATA[
f(x, y) = x ⊕ y
        = x + y - 2·x·y
        = x·(1 - 2·y) + y
]]></sourcecode>
        <t>Using this relation, the expression that must be proven can be converted into a
dot-product of two vectors, one of which is known to both P<sub>=</sub> and
P<sub>-</sub>, the other being known to both P<sub>=</sub> and P<sub>+</sub>.</t>
        <t>Rearranging terms:</t>
        <sourcecode type="pseudocode"><![CDATA[
x₋·y₊ ⊕ (x₋·y₋ ⊕ z₋ ⊕ r₋ ) ⊕ x₊·y₋ ⊕ r₊ = 0
]]></sourcecode>
        <t>Define:</t>
        <sourcecode type="pseudocode"><![CDATA[
e₋ = x₋·y₋ ⊕ z₋ ⊕ r₋
]]></sourcecode>
        <t>Then:</t>
        <sourcecode type="pseudocode"><![CDATA[
(x₋·y₊ ⊕ e₋ ) ⊕ (x₊·y₋ ⊕ r₊) = 0
]]></sourcecode>
        <t>Using: <tt>x ⊕ y = x·(1 - 2·y) + y</tt></t>
        <sourcecode type="pseudocode"><![CDATA[
(x₋·y₊·(1 - 2e₋) + e₋) ⊕ (x₊·y₋·(1 - 2r₊) + r₊) = 0
]]></sourcecode>
        <t>Using: <tt>x ⊕ y = x + y - 2·x·y</tt></t>
        <sourcecode type="pseudocode"><![CDATA[
(x₋·y₊·(1 - 2e₋) + e₋)
+ (x₊·y₋·(1 - 2r₊) + r₊)
- 2(x₋·y₊·(1 - 2e₋) + e₋)(x₊·y₋·(1 - 2r₊) + r₊) = 0
]]></sourcecode>
        <t>Distributing and rearranging terms, plus subtracting 1/2 from both sides,
produces:</t>
        <sourcecode type="pseudocode"><![CDATA[
- 2x₋·y₋·(1 - 2e₋)·y₊·x₊·(1 - 2r₊)
+ y₋·x₊·(1 - 2r₊) - 2e₋·y₋·x₊·(1 - 2r₊)
+ x₋·(1 - 2e₋)·y₊ - 2x₋·(1 - 2e₋)·y₊·r₊
+ e₋ - 2e₋·r₊ + r₊ - ½ = - ½
]]></sourcecode>
        <t>Factoring allows this to be written as an expression with four terms, each with
a component taken from the left and a component from
the right.</t>
        <sourcecode type="pseudocode"><![CDATA[
[-2x₋·y₋·(1 - 2e₋)] · [y₊·x₊·(1 - 2r₊)]
+ [y₋(1 - 2e₋)] · [x₊·(1 - 2r₊)]
+ [x₋·(1 - 2e₋)] · [y₊(1 - 2r₊)]
+ [-½(1 - 2e₋)] · [(1 - 2r₊)] = -½
]]></sourcecode>
        <t>Components on the left form a vector that can be named <tt>g</tt>, and components on
the right form a vector, <tt>h</tt>. The result is the dot product of two four
dimensional vectors:</t>
        <sourcecode type="pseudocode"><![CDATA[
g₁·h₁ + g₂·h₂ + g₃·h₃ + g₄·h₄ = -½
]]></sourcecode>
        <t>Alternatively:</t>
        <sourcecode type="pseudocode"><![CDATA[
sum(i=1..4, gᵢ·hᵢ) = -½
]]></sourcecode>
        <t>From this point, each party can compute the vectors that they are able to.</t>
        <t>P<sub>=</sub> and P<sub>-</sub> both compute <tt>gᵢ</tt> as follows:</t>
        <sourcecode type="pseudocode"><![CDATA[
g₁ = -2·x₋·y₋·(1 - 2·e₋ )
g₂ = y₋·(1 - 2·e₋ )
g₃ = x₋·(1 - 2·e₋ )
g₄ = -½(1 - 2·e₋)
]]></sourcecode>
        <t>And where:</t>
        <sourcecode type="pseudocode"><![CDATA[
e₋ = x₋·y₋ ⊕ z₋ ⊕ r₋
]]></sourcecode>
        <t>P<sub>=</sub> and P<sub>+</sub> both compute <tt>hᵢ</tt> as follows:</t>
        <sourcecode type="pseudocode"><![CDATA[
h₁ = y₊·x₊·(1 - 2·r₊)
h₂ = x₊·(1 - 2·r₊)
h₃ = y₊·(1 - 2·r₊)
h₄ = 1 − 2·r₊
]]></sourcecode>
        <t>These vectors form the basis of later stages of the proof.</t>
        <aside>
          <t>In the prime field modulo 2<sup>61</sup>-1, the negative inverse of two (-½) is
1,152,921,504,606,846,975.</t>
        </aside>
      </section>
      <section anchor="initial-uv">
        <name>Validating a batch of multiplications</name>
        <t>Each multiplication therefore produces two vectors, with each vector being
length 4. To validate a batch of <tt>m</tt> multiplications, the prover
(P<sub>=</sub>), forms two vectors of length <tt>4m</tt>.</t>
        <t>The prover (P<sub>=</sub>), and left verifier (P<sub>-</sub>) both produce the vector <tt>u</tt> by concatenating the vectors from all multiplications:</t>
        <sourcecode type="pseudocode"><![CDATA[
u = (g₁⁽¹⁾, g₂⁽¹⁾, g₃⁽¹⁾, g₄⁽¹⁾,
     g₁⁽²⁾, g₂⁽²⁾, g₃⁽²⁾, g₄⁽²⁾,
     …
     g₁⁽ᵐ⁾, g₂⁽ᵐ⁾, g₃⁽ᵐ⁾, g₄⁽ᵐ⁾)
]]></sourcecode>
        <t>The prover (P<sub>=</sub>) and right verifier (P<sub>+</sub>) both compute the vector <tt>v</tt> in the same way:</t>
        <sourcecode type="pseudocode"><![CDATA[
v = (h₁⁽¹⁾, h₂⁽¹⁾, h₃⁽¹⁾, h₄⁽¹⁾,
     h₁⁽²⁾, h₂⁽²⁾, h₃⁽²⁾, h₄⁽²⁾,
     … ,
     h₁⁽ᵐ⁾, h₂⁽ᵐ⁾, h₃⁽ᵐ⁾, h₄⁽ᵐ⁾)
]]></sourcecode>
        <t>If no additive attacks were applied by the prover, the dot product of these two vectors should be:</t>
        <sourcecode type="pseudocode"><![CDATA[
u·v = -m/2
]]></sourcecode>
      </section>
      <section anchor="overview-of-recursive-proof-compression">
        <name>Overview of Recursive Proof Compression</name>
        <t>Now that we have expressed the work of the prover as a simple dot product of two
vectors of large field elements, we can use a recursive approach to prove this
expression with O(logN) communication.</t>
        <t>The process is iterative, where at each stage there is a pair of vectors, <tt>u</tt>
and <tt>v</tt>, and a target, <tt>t</tt>, where the goal is to prove that <tt>u·v = t</tt>. The
values of <tt>u</tt> and <tt>v</tt> start as described in <xref target="initial-uv"/>; with <tt>t</tt> initially
set to a value of <tt>-m/2</tt>.</t>
        <t>At each iteration:</t>
        <ol spacing="normal" type="1"><li>
            <t>Select a compression factor <tt>L</tt>.</t>
          </li>
          <li>
            <t>Chunk the vectors <tt>u</tt> and <tt>v</tt> into <tt>s</tt> segments of length <tt>L</tt>.  </t>
            <ol spacing="normal" type="1"><li>
                <t>Each chunk of <tt>u</tt> uniquely defines a polynomial of degree <tt>L - 1</tt> which
are named <tt>pᵢ(x)</tt>, indexed by <tt>i ∊ [0..s)</tt>.</t>
              </li>
              <li>
                <t>Each chunk of <tt>v</tt> uniquely defines a polynomial of degree <tt>L - 1</tt> which
are named <tt>qᵢ(x)</tt>, indexed by <tt>i ∊ [0..s)</tt>.</t>
              </li>
            </ol>
          </li>
          <li>
            <t>The polynomial <tt>G(x)</tt> is defined as: <tt>sum(i=0..s, pᵢ(x) · qᵢ(x))</tt>  </t>
            <t>
For <tt>x ∊ [0..L-1)</tt>, this polynomial <tt>G(x)</tt> computes the inner product of a
portion of <tt>u</tt> and <tt>v</tt>. So the goal becomes proving that <tt>sum(i=0..L-1, G(i)) = t</tt>.  </t>
            <t>
In the first iteration, the target value <tt>t</tt> is known by all parties to be
<tt>-m/2</tt>, so left verifier (<tt>P₋</tt>) sets their share <tt>t₋</tt> to <tt>-m/2</tt> and the right
verifier <tt>P₊</tt> sets their share <tt>t₊</tt> to zero. In subsequent iterations the
target value will not be known to both verifiers.  </t>
            <ol spacing="normal" type="1"><li>
                <t>The prover will compute the value of <tt>G(0)</tt>, <tt>G(1)</tt>, ... , <tt>G(2L - 2)</tt>,
the minimal number of points required to uniquely define it.</t>
              </li>
              <li>
                <t>These <tt>2L - 1</tt> points are split into two additive secret-shares
<tt>G(x)_-</tt> and <tt>G(x)_+</tt> and sent to the verifiers
<tt>P₋</tt> and <tt>P₊</tt>, respectively. These shares form the
distributed zero-knowledge proof.</t>
              </li>
              <li>
                <t>The verifiers each sum together the first <tt>L - 1</tt> points they were given:
<tt>P₋</tt> computes <tt>sum₋ = sum(i=0..L-1, G(i)_-)</tt>.
<tt>P₊</tt> computes <tt>sum₊ = sum(i=0..L-1, G(i)_+)</tt>.
where <tt>sum₋ + sum₊ = sum(0..L-1, G(i))</tt>.</t>
              </li>
              <li>
                <t>Now the verifiers verify the proposition <tt>sum(i=0..L-1, G(i)) = t</tt> by having
<tt>P₋</tt> compute <tt>b₋ = t₋ - sum₋</tt> and
<tt>P₊</tt> compute <tt>b₊ = t₊ - sum₊</tt>.
They send each other these values and confirm that
<tt>b₋ + b₊ = 0</tt>. If this test fails, the entire protocol is aborted.</t>
              </li>
            </ol>
          </li>
          <li>
            <t>At this point, the prover could have produced values for <tt>G(0..L-1)</tt> that
pass this test even if they had performed an additive attack. The proof needs
to be validated by confirming that <tt>G(r) = sum(i=0..s, pᵢ(r) ·
qᵢ(r))</tt> for a randomly selected challenge point <tt>r</tt>. As long as
the prover cannot control the choice of <tt>r</tt>, the likelihood that a dishonest
prover can cheat without detection is inversely proportional to the field size.  </t>
            <ol spacing="normal" type="1"><li>
                <t>If we define two new vectors <tt>u′ = { p₀(r), …,
pₛ₋₁(r) }</tt>, and <tt>v′ = { &lt;q₀(r), …,
qₛ₋₁(r) }</tt>, then we can rewrite the statement that needs to be
proven as: <tt>u′ · v′ = G(r)</tt>. This is of the same form as the original
statement, but with the new vectors <tt>u′</tt> and <tt>v′</tt> having length <tt>L</tt> times
shorter than the original vectors.</t>
              </li>
              <li>
                <t><tt>u′</tt> and <tt>v′</tt> need not be communicated, since the prover and left verifier (<tt>P₋</tt>)
can both compute each value <tt>pᵢ(r)</tt> using Lagrange interpolation,
just as the prover and right verifier (<tt>P₊</tt>) can compute each value <tt>qᵢ(r)</tt>.</t>
              </li>
              <li>
                <t>Each of the verifiers can use the <tt>2L - 1</tt> points they received (their share
of <tt>G(x)</tt>) to compute a share of <tt>G(r)</tt> using Lagrange interpolation. These
shares become their share of a new value for <tt>t</tt>.</t>
              </li>
              <li>
                <t>The Fiat-Shamir heuristic can be used to generate <tt>r</tt> by hashing the
distributed zero knowledge proof. This transforms this protocol from a
multi-round interactive protocol into a constant round protocol.</t>
              </li>
            </ol>
          </li>
          <li>
            <t>The vectors <tt>u</tt> and <tt>v</tt> are replaced by <tt>u′</tt> and <tt>v′</tt>, the value of <tt>t</tt> is
set to <tt>G(r)</tt>, and the next iteration is started.</t>
          </li>
        </ol>
        <t>The recursion ends when the vectors <tt>u</tt> and <tt>v</tt> have length less than <tt>L</tt>.  The
verifiers validate the soundness of the final iteration of the proof in a
simpler, more direct way; see <xref target="final-iteration"/>.</t>
      </section>
      <section anchor="detailed-validation-algorithm">
        <name>Detailed Validation Algorithm</name>
        <section anchor="selecting-the-compression-factor">
          <name>Selecting the Compression Factor</name>
          <t>For the first iteration, the parties will use a compression factor (<tt>L</tt>) of 32. In
all subsequent rounds they will use a compression factor of 8.</t>
          <t>Note: A larger value for <tt>L</tt> increases the compression factor, which reduces the
overall communication cost. However, because the computation of the proof
requires Lagrange interpolation (which is O(L<sup>2</sup>) computation), a
larger compression factor quickly becomes expensive. A slightly larger
compression factor on the first round is possible because there are only a small
number of possible input values, so the work can be reduced with the use of
lookup tables if necessary.</t>
        </section>
        <section anchor="producing-polynomials-px-and-qx">
          <name>Producing Polynomials <tt>p(x)</tt> and <tt>q(x)</tt></name>
          <t>The prover (P<sub>=</sub>) and the left verifier (P<sub>-</sub>), chunk the vector
<tt>u</tt> into <tt>s</tt> chunks of length <tt>L</tt>.</t>
          <ul spacing="normal">
            <li>
              <t>chunk 0: &lt;u<sub>0</sub>, u<sub>1</sub>, …, u<sub>L-1</sub>&gt;</t>
            </li>
            <li>
              <t>chunk 1: &lt;u<sub>L</sub>, u<sub>L+1</sub>, …, u<sub>2L-1</sub>&gt;</t>
            </li>
            <li>
              <t>…</t>
            </li>
            <li>
              <t>chunk s-1: &lt;u<sub>(s-1)L</sub>, u<sub>(s-1)L+1</sub>, …, u<sub>sL-1</sub>&gt;</t>
            </li>
          </ul>
          <t>If the length of <tt>u</tt> is not divisible by <tt>L</tt>, then the final chunk will be
padded with zeros.</t>
          <t>In the first iteration there will be <tt>s = ceil(4m / L)</tt> chunks, as the original
vectors <tt>u</tt> and <tt>v</tt> have length <tt>4m</tt>. In subsequent iterations there will be
fewer chunks.</t>
          <t>They will interpret each chunk as <tt>L</tt> points lying on a polynomial,
<tt>pᵢ(x)</tt> of degree <tt>L-1</tt>, corresponding to the <tt>x</tt> coordinates <tt>{ 0,
1, …, L-1 }</tt>, that is to say they will interpret them as <tt>{ pᵢ(0),
pᵢ(1), …, pᵢ(L-1) }</tt>.</t>
          <t>The prover (P<sub>=</sub>) and left verifier (P<sub>-</sub>) can find the value of
<tt>pᵢ(x)</tt> for any other value of <tt>x</tt> using Lagrange interpolation.</t>
          <t>The prover (P<sub>=</sub>) uses Lagrange interpolation to compute the values <tt>{
pᵢ(L), pᵢ(L+1), …, pᵢ(2L-2) }</tt>.</t>
          <t>The same process is applied for the vector <tt>v</tt> with the right verifier, (P<sub>+</sub>).</t>
          <t>The prover (P<sub>=</sub>) and the right verifier (P<sub>+</sub>), chunk the vector <tt>v</tt>
into <tt>s</tt> chunks of length <tt>L</tt>.</t>
          <ul spacing="normal">
            <li>
              <t>chunk 0: &lt;v<sub>0</sub>, v<sub>1</sub>, …, v<sub>L-1</sub>&gt;</t>
            </li>
            <li>
              <t>chunk 1: &lt;v<sub>L</sub>, v<sub>L+1</sub>, …, v<sub>2L-1</sub>&gt;</t>
            </li>
            <li>
              <t>…</t>
            </li>
            <li>
              <t>chunk s-1: &lt;v<sub>(s-1)L</sub>, v<sub>(s-1)L+1</sub>, …, v<sub>sL-1</sub>&gt;</t>
            </li>
          </ul>
          <t>As before, if the length of <tt>v</tt> is not a multiple of <tt>L</tt>, the final chunk will
be padded with zeros.</t>
          <t>Each chunk is interpreted as <tt>L</tt> points on a polynomial. From this the values <tt>{
qᵢ(L), qᵢ(L+1), …, qᵢ(2L-2) }</tt> are found using
using Lagrange interpolation.</t>
        </section>
      </section>
      <section anchor="producing-the-zero-knowledge-proof">
        <name>Producing the Zero Knowledge Proof</name>
        <t>In order to prove that <tt>u·v = t</tt>, the prover will compute the value of <tt>2L-1</tt>
points on the polynomial <tt>G(x)</tt>, which is defined as:</t>
        <sourcecode type="pseudocode"><![CDATA[
G(x) = sum(i=1..s, pᵢ(x) · qᵢ(x))
]]></sourcecode>
        <t>The prover computes the values of <tt>{ G(0), G(1), …, G(2L-2) }</tt> by incrementally
aggregating the products of <tt>{ pᵢ(0), pᵢ(1), …,
pᵢ(2L-21) }</tt> and <tt>{ qᵢ(L), qᵢ(L+1), …,
qᵢ(2L-2) }</tt>, for each chunk.</t>
        <t>These <tt>2L-1</tt> points on the polynomial <tt>G(x)</tt> constitute the zero-knowledge proof
that <tt>u·v = t</tt>.</t>
        <t>An equivalent method of proving <tt>u·v = t</tt>, is to show that <tt>sum(i=0..L-1, G(i))
= t</tt>.</t>
        <section anchor="masking-the-zero-knowledge-proof">
          <name>Masking the Zero-Knowledge Proof</name>
          <t>The prover (P<sub>=</sub>), cannot simply send this zero-knowledge proof to the
verifiers, as doing so would release private information. Instead, the prover
produces a two-part additive secret-sharing of these <tt>2L-1</tt> points, sending one
share to each verifier.</t>
          <t>The prover (P<sub>=</sub>) and the right verifier (P<sub>+</sub>) generate one
share using their shared randomness, which means that no communication is
needed.  This share is denoted <tt>G(x)_+</tt>.</t>
          <t>The prover (P<sub>=</sub>) computes the other share via subtraction.  That is,
<tt>G₋(x) = G(x) - G₊(x)</tt>.  This value is sent to the left verifier
(P<sub>-</sub>). Transmitting this share <tt>G(x)_-</tt> involves sending <tt>2L-1</tt> field
values.</t>
        </section>
        <section anchor="validating-the-proof-increment">
          <name>Validating the Proof Increment</name>
          <t>To check that <tt>sum(i=0..L-1, G(i)) = t</tt>, the left verifier (P<sub>-</sub>)
computes:</t>
          <sourcecode type="pseudocode"><![CDATA[
b₋ = t₋ - sum(i=0..L-1, G(i)_-)
]]></sourcecode>
          <t>Similarly, the right verifier (P<sub>+</sub>) computes:</t>
          <sourcecode type="pseudocode"><![CDATA[
b₊ = t₊ - sum(i=0..L-1, G(i)_+)
]]></sourcecode>
          <t>The two verifiers will reveal these values <tt>b₋</tt> and <tt>b₊</tt> to one another, so
that each can reconstruct the full sum, <tt>b = b₋ + b₊</tt>.</t>
          <t>Each confirms that <tt>b</tt> is zero. If it is not, the parties abort and destroy
their shares.</t>
        </section>
        <section anchor="challenge">
          <name>Random Challenge</name>
          <t>Now that the verifiers have confirmed that the proof says that there was no
additive attack, they need to validate that this was indeed a legitimate
zero-knowledge proof.  The prover knows the value of <tt>t</tt>, even if each verifier
only has shares of <tt>t</tt> after the first round.  Therefore, it is trivial for a
prover to falsify <tt>G(x)</tt>.</t>
          <t>To demonstrate that the prover has provided a valid <tt>G(x)</tt>, a random field
element, <tt>r</tt>, is chosen from the range <tt>[L, p)</tt> (that is, a value that is not
part of the proof).  The prover then has to show that the value of <tt>G(r)</tt>
matches what the verifiers hold.  The verifiers could jointly compute this value
using the values of <tt>pᵢ(x)</tt> and <tt>qᵢ(x)</tt>.</t>
          <t>The key requirement in choosing <tt>r</tt> is that the prover cannot influence the
choice.</t>
        </section>
        <section anchor="fiat-shamir-challenge-selection">
          <name>Fiat-Shamir Challenge Selection</name>
          <t>To minimize the rounds of communication, instead of having the verifiers select
this random point, we utilize the Fiat-Shamir transform to produce a
constant-round proof system.</t>
          <t>The prover (P<sub>=</sub>) hashes the zero-knowledge proof shares it has
generated onto a field element as follows:</t>
          <sourcecode type="pseudocode"><![CDATA[
commitment = SHA256(
  concat(
    SHA256([G(x)]_-),
    SHA256([G(x)]_+)
  )
)
r = (bytes2int(commitment[..16]) % (prime - L)) + L
]]></sourcecode>
          <t>This computation does not use the entire output of the hash function, just
enough to ensure that the value of r has minimal bias. For SHA-256 and a prime
field modulo 2<sup>61</sup>-1, the bias is in the order of 2<sup>-67</sup>,
which is negligible.</t>
          <t>The verifiers generate the same point <tt>r</tt> independently. Each verifier only has
access to one set of shares from <tt>G(x)</tt> so they each compute a hash of the shares
they have. They then send that hash to each other, after which they can concatenate
the two hash values and compute the challenge point.</t>
          <t>Note that one verifier does not need to receive their shares of <tt>G(x)</tt> from the
prover, so they are able to compute their hash before even starting any
computation.</t>
          <t>Consequently, though each round depends on communication, the total latency is two rounds. In the first, the prover sends shares of G(x) to the left verifier. Concurrently, the right verifier sends a hash of their shares to the left verifier. In the second round, the left verifier sends a hash of their shares to the right verifier.</t>
          <!-- TODO: this Fiat-Shamir seems worse than an explicit challenge… -->

</section>
        <section anchor="recursive-proof">
          <name>Recursive Proof</name>
          <t>At the end of each round, the prover is left with the task of proving that
<tt>G(r)</tt> is correct based on the random challenge. <tt>r</tt>.</t>
          <t>Recall the definition of <tt>G(x)</tt>:</t>
          <sourcecode type="pseudocode"><![CDATA[
G(x) = sum(i=0..s, pᵢ(x)·qᵢ(x))
]]></sourcecode>
          <t>This is equivalent to providing that <tt>u′ · v′ = G(r)</tt>, where:</t>
          <sourcecode type="pseudocode"><![CDATA[
u′ = <p₀(r), p₁(r), …>
v′ = <q₀(r), q₁(r), …>
]]></sourcecode>
          <t>This is a problem of exactly the same form as the original problem, except that
the length of <tt>u′</tt> and <tt>v′</tt> is now a factor of <tt>L</tt> shorter than the original
length of <tt>u</tt> and <tt>v</tt>.</t>
          <t>The prover (P<sub>=</sub>) and left verifier (P<sub>-</sub>) use Lagrange interpolation
to compute the value of <tt>pᵢ(r)</tt> for all chunks in the range <tt>0..s</tt>
and set this as the new vector <tt>u</tt>.</t>
          <t>Similarly, the prover (P<sub>=</sub>) and right verifier (P<sub>+</sub>) use Lagrange
interpolation to compute the value of <tt>qᵢ(r)</tt> and set this as the new
vector <tt>v</tt>.</t>
          <t>The target value <tt>t</tt> is set to <tt>G(r)</tt>.  The two verifiers do not learn <tt>G(r)</tt>.
Instead, each uses Lagrange interpolation to compute a share of <tt>G(r)</tt>.  That
is:</t>
          <sourcecode type="pseudocode"><![CDATA[
t₋ = lagrange_interpolate(r, [G₋(0), G₋(1), …, G₋(2L-2)])
t₊ = lagrange_interpolate(r, [G₊(0), G₊(1), …, G₊(2L-2)])
]]></sourcecode>
        </section>
        <section anchor="final-iteration">
          <name>The Final Iteration</name>
          <t>The proof proceeds recursively until the length of the vectors <tt>u</tt> and <tt>v</tt> are
strictly less than the compression factor <tt>L</tt>.</t>
          <t>Next, the prover (P<sub>=</sub>) and left verifier (P<sub>-</sub>) jointly
generate a random field value <tt>pₘ</tt> using shared secrets. Similarly, the prover
(P<sub>=</sub>) and right verifier (P<sub>+</sub>) generate a random field value
<tt>qₘ</tt> using shared secrets.</t>
          <t>The prover (P<sub>=</sub>) and left verifier (P<sub>-</sub>) move <tt>u₀</tt> to index
<tt>L-1</tt>. No data will be lost as this replaces a zero value; the length of <tt>u</tt> is
strictly less than <tt>L</tt>.  The value at index 0 is replaced with <tt>pₘ</tt>.</t>
          <t>The prover (P<sub>=</sub>) and right verifier (P<sub>+</sub>) move <tt>v₀</tt>
to index <tt>L-1</tt> and place the value <tt>qₘ</tt> at index 0.</t>
          <t>The prover generates a zero knowledge proof from these polynomials exactly as
before, sending each verifier <tt>2L-1</tt> shares of <tt>G(x)</tt>.  The process of
validation then proceeds differently.</t>
          <t>Firstly, when the verifiers compute their shares of <tt>b</tt>, they ignore the random
value at index 0 of <tt>G(x)</tt>.  That is:</t>
          <sourcecode type="pseudocode"><![CDATA[
b₋ = t₋ - sum(i=1..L-1, G₋(i))
b₊ = t₊ - sum(i=1..L-1, G₊(i))
]]></sourcecode>
          <t>Verifiers confirm that <tt>b₋ + b₊</tt> is zero by exchanging their shares of <tt>b</tt>.</t>
          <t>Finally, the left verifier (P<sub>-</sub>)
computes both <tt>p₀(r)</tt> and <tt>G₋(r)</tt>, right verifier (P<sub>+</sub>)
computes <tt>q₀(r)</tt> and <tt>G₊(r)</tt>, and then the verifiers reveal all of
these values to each other.  They then both verify that:</t>
          <sourcecode type="pseudocode"><![CDATA[
G₋(r) + G₊(r) = p₀(r) · q₀(r)
]]></sourcecode>
          <t>The addition of random masks (<tt>pₘ</tt> and <tt>qₘ</tt>) ensure that revealing <tt>G(r)</tt> in
this way does not reveal anything about the value of the polynomials held by the
other party.  Revealing <tt>q₀(r)</tt>, which was computed from the random values,
only confirms that the prover did not cheat.</t>
        </section>
      </section>
    </section>
    <section anchor="conditions-of-usage">
      <name>Conditions of Usage</name>
      <t>This protocol requires integration into a larger protocol, which will need to:</t>
      <ul spacing="normal">
        <li>
          <t>set or negotiate parameters,</t>
        </li>
        <li>
          <t>provide communication channels,</t>
        </li>
        <li>
          <t>agree on shared secrets, and</t>
        </li>
        <li>
          <t>arrange the multiplications that are to be validated into batches.</t>
        </li>
      </ul>
      <section anchor="recommended-parameters">
        <name>Recommended Parameters</name>
        <t>This document recommends several parameters, which are used in the security
analysis.  Alternative parameters can be used, provided that they meet the
stated requirements.</t>
        <t>For shared secrets, pseudorandom secret sharing <xref target="PRSS"/> is used.  For PRSS
parameters, HPKE <xref target="RFC9180"/> with DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, and
AES-128-GCM is RECOMMENDED, with the same KDF being used for PRSS and AES-128 as
the PRP.</t>
        <t>For validation, the prime field used is modulo the Mersenne prime
2<sup>61</sup>-1 validation.  Any sufficiently large prime can be used, but this
value provides both good performance on 64-bit hardware and useful security
margins for typical batch sizes; see TODO/below for an analysis of the batch
size requirements and security properties that can be obtained by using this
particular prime.</t>
        <t>The Fiat-Shamir transform <xref target="challenge"/> used in the validation proofs can use
SHA-256.  However, any preimage and collision-resistant hash function can be
used provided that it has a enough output entropy to avoid bias in the selected
field value.</t>
      </section>
    </section>
    <section anchor="performance-characteristics">
      <name>Performance Characteristics</name>
      <t>TODO</t>
      <ul spacing="normal">
        <li>
          <t>Communication - number of bits sent/received</t>
        </li>
        <li>
          <t>Computation - how many times you invoke PRSS</t>
        </li>
        <li>
          <t>Vectorization - why it is useful and good</t>
        </li>
        <li>
          <t>How to multiply in parallel - sending and receiving, stalling, etc…</t>
        </li>
        <li>
          <t>Memory requirements
          </t>
          <ul spacing="normal">
            <li>
              <t>Compression factor and choice</t>
            </li>
            <li>
              <t>Trade-offs - time/memory (factor of 64 during generation of r, for Fiat-Shamir version)</t>
            </li>
          </ul>
        </li>
        <li>
          <t>Multiple rounds or Fiat-Shamir</t>
        </li>
      </ul>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <t>TODO</t>
      <ul spacing="normal">
        <li>
          <t>Parameter choice and security margins
          </t>
          <ul spacing="normal">
            <li>
              <t>Talk about trade-off between attack success probability and prime size.</t>
            </li>
            <li>
              <t>Show equation for how many bits of security you get when validating N multiplications</t>
            </li>
          </ul>
        </li>
        <li>
          <t>You can't just use the multiplication protocol without the validation protocol due to the additive attack (explain why)</t>
        </li>
        <li>
          <t>Communication security (authentication)</t>
        </li>
        <li>
          <t>Constant time and implications thereof</t>
        </li>
        <li>
          <t>Fiat-Shamir vs more rounds</t>
        </li>
      </ul>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document has no IANA considerations.</t>
    </section>
  </middle>
  <back>
    <references>
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="PRSS">
          <front>
            <title>High Performance Pseudorandom Secret Sharing (PRSS)</title>
            <author initials="M." surname="Thomson" fullname="Martin Thomson">
              <organization/>
            </author>
            <author initials="B." surname="Savage" fullname="Ben Savage">
              <organization/>
            </author>
            <date year="2024" month="July"/>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-thomson-ppm-prss-00"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <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="FLPCP">
          <front>
            <title>Zero-Knowledge Proofs on Secret-Shared Data via Fully Linear PCPs</title>
            <author fullname="Dan Boneh" initials="D." surname="Boneh">
              <organization/>
            </author>
            <author fullname="Elette Boyle" initials="E." surname="Boyle">
              <organization/>
            </author>
            <author fullname="Henry Corrigan-Gibbs" initials="H." surname="Corrigan-Gibbs">
              <organization/>
            </author>
            <author fullname="Niv Gilboa" initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author fullname="Yuval Ishai" initials="Y." surname="Ishai">
              <organization/>
            </author>
            <date year="2019"/>
          </front>
          <seriesInfo name="Advances in Cryptology – CRYPTO 2019" value="pp. 67-97"/>
          <seriesInfo name="DOI" value="10.1007/978-3-030-26954-8_3"/>
          <seriesInfo name="ISBN" value="[&quot;9783030269531&quot;, &quot;9783030269548&quot;]"/>
          <refcontent>Springer International Publishing</refcontent>
        </reference>
        <reference anchor="BOYLE">
          <front>
            <title>Efficient Fully Secure Computation via Distributed Zero-Knowledge Proofs</title>
            <author fullname="Elette Boyle" initials="E." surname="Boyle">
              <organization/>
            </author>
            <author fullname="Niv Gilboa" initials="N." surname="Gilboa">
              <organization/>
            </author>
            <author fullname="Yuval Ishai" initials="Y." surname="Ishai">
              <organization/>
            </author>
            <author fullname="Ariel Nof" initials="A." surname="Nof">
              <organization/>
            </author>
            <date year="2020"/>
          </front>
          <seriesInfo name="Advances in Cryptology – ASIACRYPT 2020" value="pp. 244-276"/>
          <seriesInfo name="DOI" value="10.1007/978-3-030-64840-4_9"/>
          <seriesInfo name="ISBN" value="[&quot;9783030648398&quot;, &quot;9783030648404&quot;]"/>
          <refcontent>Springer International Publishing</refcontent>
        </reference>
        <reference anchor="BINARY">
          <front>
            <title>Efficient 3PC for binary circuits with application to maliciously-secure DNN inference</title>
            <author fullname="Yun Li" initials="Y." surname="Li">
              <organization/>
            </author>
            <author fullname="Yufei Duan" initials="Y." surname="Duan">
              <organization/>
            </author>
            <author fullname="Zhicong Huang" initials="Z." surname="Huang">
              <organization/>
            </author>
            <author fullname="Cheng Hong" initials="C." surname="Hong">
              <organization/>
            </author>
            <author fullname="Chao Zhang" initials="C." surname="Zhang">
              <organization/>
            </author>
            <author fullname="Yifan Song" initials="Y." surname="Song">
              <organization/>
            </author>
            <date month="August" year="2023"/>
          </front>
          <seriesInfo name="Proceedings of the 32nd USENIX Conference on Security Symposium" value="pp. 5377–5394"/>
          <seriesInfo name="ISBN" value="978-1-939133-37-3"/>
          <refcontent>USENIX Association</refcontent>
        </reference>
        <reference anchor="RFC9180">
          <front>
            <title>Hybrid Public Key Encryption</title>
            <author fullname="R. Barnes" initials="R." surname="Barnes"/>
            <author fullname="K. Bhargavan" initials="K." surname="Bhargavan"/>
            <author fullname="B. Lipp" initials="B." surname="Lipp"/>
            <author fullname="C. Wood" initials="C." surname="Wood"/>
            <date month="February" year="2022"/>
            <abstract>
              <t>This document describes a scheme for hybrid public key encryption (HPKE). This scheme provides a variant of public key encryption of arbitrary-sized plaintexts for a recipient public key. It also includes three authenticated variants, including one that authenticates possession of a pre-shared key and two optional ones that authenticate possession of a key encapsulation mechanism (KEM) private key. HPKE works for any combination of an asymmetric KEM, key derivation function (KDF), and authenticated encryption with additional data (AEAD) encryption function. Some authenticated variants may not be supported by all KEMs. We provide instantiations of the scheme using widely used and efficient primitives, such as Elliptic Curve Diffie-Hellman (ECDH) key agreement, HMAC-based key derivation function (HKDF), and SHA2.</t>
              <t>This document is a product of the Crypto Forum Research Group (CFRG) in the IRTF.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9180"/>
          <seriesInfo name="DOI" value="10.17487/RFC9180"/>
        </reference>
      </references>
    </references>
    <?line 1059?>

<section anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>This work is a direct implementation of the protocols described in <xref target="BINARY"/>,
which builds on a lot of prior academic work on MPC.</t>
    </section>
  </back>
  <!-- ##markdown-source:
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
pyq0jqRHfPFYKqSR78tlcrNy52QjV/dWeVm+wCt8XGE7W/jCe2PGzyNSCxE/
j5ypDlS4IVudCPEl/nml+9VF/y7ydY/E3+GJXSGtO88NPe36bX4p3fbv6I+3
NOC+zdHYxgU0UZ+R30Cj5V8/df0PXP/Hcf/H1/tGOIyGQCe2HahO/FAD+DJs
jce/9Q5aB4PailSyWXF1yIt3uA46ocoO4SDqmOdlvBTJoFYbvhtMZ4/yBlWX
fl+HoJxNvZ7UoJSBhM4Ht9b6hn48tMcw6qhiV/FnCodc6o3w86qFOUHCo6lY
LghjYlrGy7LGe8hgKch3RK+gl/8hhYUOspFy/rfIV5YcAOx8vX9iw0w8eOV2
VpZYNY5utk/O9P5IHch5QUfRgvm+PSbwpruAg/qFUmZaSgPQEvaHI0V/HIiO
zT+jkQVDXhoxeoeA0YwuntgMRftCJb95so4wy5gM0aA09hVq1KXLojvzF/Db
1k05MS4nZwyDx0O7/esxOIC+DgN4kAkQuMdtJMKWhgyCNY7DxUrtqB3xuRrS
3UHaY3R5FiVD/hyedRzzrOMennV8Gc86jnnWcS/POn4nnnXcw7OOL+ZZx12e
dRdVawzMusulAfs6duwr9Rdl8IHwrw7rwhsjfawrcI6T+SyUxvWpA07Q4gFh
Of0YFV9aVHzZQsWXISqSIF6QsCZSUVcQTCQ8ccK+NHZixMBl0NC8IAoTOWwu
8bTi8U6U33vT58APShAEfvxOSA7bOn/LwUXe/U7cNfLdB3GjM41uYHTEOdB+
7uE6lRdbogVPIaJ0uawo20AA52pR8ViWjeqIjSrHNw74tFAInemLzlZFZzvy
91wIscY2zYKhqq+AKttWWWMPpc99q9rBNUxnCUvcyes1UK2TmEWIAyJkVjbc
2efiVDLuNbrgy2U+LOK1bwJdnplwUcmcvo3Zy6XO2iLlYF5SpnsplxcrMHPA
JtDy8uPwTglqBVTfIMq1CG65Ym2NDUUbe5z2vmBG+7RGrtICvrhQqmuWNi+E
1/qPEALe4vfzuJqB1r8QFtaxNBjcFGqXuEQbGn1IeK2YnQFBKWasiePDEpdv
IaLI4FUN+jhL4/dZuYvVavI5Zg4SAyA+kOjPMRHwdDixi7H1caNwSKSYqJZi
MubU+nXWNC7HWwJWNtbSKa4vp0keUOVeTnotziTCmTkt4JHlIVwBb2VmL66I
+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

-->

</rfc>
