ZIP 307: use math markup for the decryption algorithm, and add TODO for ZIP 212/Canopy.

Signed-off-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
Daira Hopwood 2020-06-29 22:23:52 +01:00
parent d229f7b9ce
commit 327746929e
2 changed files with 74 additions and 26 deletions

View File

@ -3,6 +3,7 @@
<head> <head>
<title>ZIP 307: Light Client Protocol for Payment Detection</title> <title>ZIP 307: Light Client Protocol for Payment Detection</title>
<meta charset="utf-8" /> <meta charset="utf-8" />
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js?config=TeX-AMS-MML_HTMLorMML"></script>
<meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="css/style.css"></head> <meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="css/style.css"></head>
<body> <body>
<section> <section>
@ -192,21 +193,56 @@ License: MIT</pre>
<section id="local-processing"><h3><span class="section-heading">Local processing</span><span class="section-anchor"> <a rel="bookmark" href="#local-processing"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3> <section id="local-processing"><h3><span class="section-heading">Local processing</span><span class="section-anchor"> <a rel="bookmark" href="#local-processing"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Given a <code>CompactBlock</code> received in height-sequential order from a proxy server, a light client can process it in four ways:</p> <p>Given a <code>CompactBlock</code> received in height-sequential order from a proxy server, a light client can process it in four ways:</p>
<section id="scanning-for-relevant-transactions"><h4><span class="section-heading">Scanning for relevant transactions</span><span class="section-anchor"> <a rel="bookmark" href="#scanning-for-relevant-transactions"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h4> <section id="scanning-for-relevant-transactions"><h4><span class="section-heading">Scanning for relevant transactions</span><span class="section-anchor"> <a rel="bookmark" href="#scanning-for-relevant-transactions"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h4>
<p>For every <code>CompactOutput</code> in the <code>CompactBlock</code>, the light client can trial-decrypt it against a set of Sapling incoming viewing keys. The procedure for trial-decrypting a <code>CompactOutput</code> (<em>cmu</em>, <em>epk</em>, <em>ciphertext</em>) with an incoming viewing key <em>ivk</em> is a slight deviation from the standard decryption process <a id="id3" class="footnote_reference" href="#protocol-saplingdecryptivk">4</a>:</p> <p>For every <code>CompactOutput</code> in the <code>CompactBlock</code>, the light client can trial-decrypt it against a set of Sapling incoming viewing keys. The procedure for trial-decrypting a <code>CompactOutput</code>
<span class="math">\((\mathtt{cmu}, \mathsf{epk}, \mathsf{ciphertext})\)</span>
with an incoming viewing key
<span class="math">\(\mathsf{ivk}\)</span>
is a slight deviation from the standard decryption process <a id="id3" class="footnote_reference" href="#protocol-saplingdecryptivk">4</a>:</p>
<ul> <ul>
<li>let sharedSecret = KA<sup>Sapling</sup>.Agree(<em>ivk</em>, <em>epk</em>)</li> <li>let
<li>let K<sup>enc</sup> = KDF<sup>Sapling</sup>(sharedSecret, <em>epk</em>)</li> <span class="math">\(\mathsf{sharedSecret} = \mathsf{KA^{Sapling}.Agree}(\mathsf{ivk}, \mathsf{epk})\)</span>
<li>let P<sup>enc</sup> = ChaCha20.Decrypt<sub>K^enc</sub>(<em>ciphertext</em>)</li> </li>
<li>extract <strong>np</strong> = (d, v, rcm) from P<sup>enc</sup></li> <li>let
<li>let rcm = LEOS2IP<sub>256</sub>(rcm) and g<sub>d</sub> = DiversifyHash(d)</li> <span class="math">\(K^{\mathsf{enc}} = \mathsf{KDF^{Sapling}}(\mathsf{sharedSecret}, \mathsf{epk})\)</span>
<li>if rcm &gt;= r<sub>J</sub> or g<sub>d</sub> = ⊥, return ⊥</li> </li>
<li>let pk<sub>d</sub> = KASapling.DerivePublic(ivk, g<sub>d</sub>)</li> <li>let
<li>let cm<sub>u</sub>' = Extract<sub>J^(r)</sub>(NoteCommitSapling<sub>rcm^new</sub>(repr<sub>J</sub>(g<sub>d</sub>), repr<sub>J</sub>(pk<sub>d</sub>), v)).</li> <span class="math">\(P^{\mathsf{enc}} = \mathsf{ChaCha20.Decrypt}_{K^{\mathsf{enc}}}(\mathsf{ciphertext})\)</span>
<li>if LEBS2OSP<sub>256</sub>(cm<sub>u</sub>') != <em>cmu</em> , return ⊥, else return <strong>np</strong>.</li> </li>
<li>extract
<span class="math">\(\mathbf{np} = (\mathsf{d}, \mathsf{v}, \mathsf{rcm})\)</span>
from
<span class="math">\(P^{\mathsf{enc}}\)</span>
</li>
<li>let
<span class="math">\(\mathsf{rcm} = \mathsf{LEOS2IP}_{256}(\mathsf{rcm})\)</span>
and
<span class="math">\(\mathsf{g_d} = \mathsf{DiversifyHash}(\mathsf{d})\)</span>
</li>
<li>if
<span class="math">\(\mathsf{rcm} \geq r_{\mathbb{J}}\)</span>
or
<span class="math">\(\mathsf{g_d} = \bot\)</span>
, return
<span class="math">\(\bot\)</span>
</li>
<li>let
<span class="math">\(\mathsf{pk_d} = \mathsf{KA^{Sapling}.DerivePublic}(\mathsf{ivk}, \mathsf{g_d})\)</span>
</li>
<li>let
<span class="math">\(\mathsf{cm}_u' = \mathsf{Extract}_{\mathbb{J}^{(r)}}(\mathsf{NoteCommit^{Sapling}_{rcm}}(\mathsf{repr}_{\mathbb{J}}(\mathsf{g_d}), \mathsf{repr}_{\mathbb{J}}(\mathsf{pk_d}), \mathsf{v}))\)</span>
.</li>
<li>if
<span class="math">\(\mathsf{LEBS2OSP}_{256}(\mathsf{cm}_u') \neq \mathtt{cmu}\)</span>
, return
<span class="math">\(\bot\)</span>
, else return
<span class="math">\(\mathbf{np}\)</span>
.</li>
</ul> </ul>
<p>TODO: update this for ZIP 212 <a id="id4" class="footnote_reference" href="#zip-0212">8</a>.</p>
</section> </section>
<section id="creating-and-updating-note-witnesses"><h4><span class="section-heading">Creating and updating note witnesses</span><span class="section-anchor"> <a rel="bookmark" href="#creating-and-updating-note-witnesses"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h4> <section id="creating-and-updating-note-witnesses"><h4><span class="section-heading">Creating and updating note witnesses</span><span class="section-anchor"> <a rel="bookmark" href="#creating-and-updating-note-witnesses"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h4>
<p>As <code>CompactBlocks</code> are received in height order, and the transactions within them have their order preserved, the <em>cmu</em> values in each <code>CompactOutput</code> can be sequentially appended to an incremental Merkle tree of depth 32 in order to maintain a local copy of the Sapling note commitment tree. <a id="id4" class="footnote_reference" href="#protocol-merkletree">2</a> This can then be used to create incremental witnesses for each unspent note the light client is tracking. <a id="id5" class="footnote_reference" href="#incremental-witness">9</a> An incremental witness updated to height <code>X</code> corresponds to a Merkle path from the note to the Sapling commitment tree anchor for block <code>X</code>. <a id="id6" class="footnote_reference" href="#protocol-merklepath">3</a></p> <p>As <code>CompactBlocks</code> are received in height order, and the transactions within them have their order preserved, the <em>cmu</em> values in each <code>CompactOutput</code> can be sequentially appended to an incremental Merkle tree of depth 32 in order to maintain a local copy of the Sapling note commitment tree. <a id="id5" class="footnote_reference" href="#protocol-merkletree">2</a> This can then be used to create incremental witnesses for each unspent note the light client is tracking. <a id="id6" class="footnote_reference" href="#incremental-witness">10</a> An incremental witness updated to height <code>X</code> corresponds to a Merkle path from the note to the Sapling commitment tree anchor for block <code>X</code>. <a id="id7" class="footnote_reference" href="#protocol-merklepath">3</a></p>
<p>Let <code>tree</code> be the Sapling note commitment tree at height <code>X-1</code>, and <code>note_witnesses</code> be the incremental witnesses for unspent notes detected up to height <code>X-1</code>. When the <code>CompactBlock</code> at height <code>X</code> is received:</p> <p>Let <code>tree</code> be the Sapling note commitment tree at height <code>X-1</code>, and <code>note_witnesses</code> be the incremental witnesses for unspent notes detected up to height <code>X-1</code>. When the <code>CompactBlock</code> at height <code>X</code> is received:</p>
<ul> <ul>
<li>For each <code>CompactTx</code> in <code>CompactBlock</code>: <li>For each <code>CompactTx</code> in <code>CompactBlock</code>:
@ -231,7 +267,7 @@ License: MIT</pre>
<p>The <code>CompactSpend</code> entries can be checked against known local nullifiers, to for example ensure that a transaction has been received by the network and mined.</p> <p>The <code>CompactSpend</code> entries can be checked against known local nullifiers, to for example ensure that a transaction has been received by the network and mined.</p>
</section> </section>
<section id="block-header-validation"><h4><span class="section-heading">Block header validation</span><span class="section-anchor"> <a rel="bookmark" href="#block-header-validation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h4> <section id="block-header-validation"><h4><span class="section-heading">Block header validation</span><span class="section-anchor"> <a rel="bookmark" href="#block-header-validation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h4>
<p>If the <code>CompactBlock</code> for height <code>X</code> contains a block header, the light client can validate it in a similar way to SPV clients <a id="id7" class="footnote_reference" href="#spv-clients">10</a> by performing the following checks:</p> <p>If the <code>CompactBlock</code> for height <code>X</code> contains a block header, the light client can validate it in a similar way to SPV clients <a id="id8" class="footnote_reference" href="#spv-clients">11</a> by performing the following checks:</p>
<ul> <ul>
<li><code>version &gt;= MIN_BLOCK_VERSION</code></li> <li><code>version &gt;= MIN_BLOCK_VERSION</code></li>
<li><code>prevHash == prevBlock.id.blockHash</code> where <code>prevBlock</code> is the previous <code>CompactBlock</code> received (at height <code>X-1</code>).</li> <li><code>prevHash == prevBlock.id.blockHash</code> where <code>prevBlock</code> is the previous <code>CompactBlock</code> received (at height <code>X-1</code>).</li>
@ -490,10 +526,18 @@ License: MIT</pre>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<table id="protocolbuffers" class="footnote"> <table id="zip-0212" class="footnote">
<tbody> <tbody>
<tr> <tr>
<th>8</th> <th>8</th>
<td><a href="zip-0212">ZIP 212: Allow Recipient to Derive Sapling Ephemeral Secret from Note Plaintext</a></td>
</tr>
</tbody>
</table>
<table id="protocolbuffers" class="footnote">
<tbody>
<tr>
<th>9</th>
<td><a href="https://developers.google.com/protocol-buffers/">Protocol Buffers.</a></td> <td><a href="https://developers.google.com/protocol-buffers/">Protocol Buffers.</a></td>
</tr> </tr>
</tbody> </tbody>
@ -501,7 +545,7 @@ License: MIT</pre>
<table id="incremental-witness" class="footnote"> <table id="incremental-witness" class="footnote">
<tbody> <tbody>
<tr> <tr>
<th>9</th> <th>10</th>
<td><cite>TODO</cite></td> <td><cite>TODO</cite></td>
</tr> </tr>
</tbody> </tbody>
@ -509,7 +553,7 @@ License: MIT</pre>
<table id="spv-clients" class="footnote"> <table id="spv-clients" class="footnote">
<tbody> <tbody>
<tr> <tr>
<th>10</th> <th>11</th>
<td><cite>TODO</cite></td> <td><cite>TODO</cite></td>
</tr> </tr>
</tbody> </tbody>

View File

@ -256,18 +256,21 @@ Scanning for relevant transactions
`````````````````````````````````` ``````````````````````````````````
For every ``CompactOutput`` in the ``CompactBlock``, the light client can trial-decrypt it For every ``CompactOutput`` in the ``CompactBlock``, the light client can trial-decrypt it
against a set of Sapling incoming viewing keys. The procedure for trial-decrypting a against a set of Sapling incoming viewing keys. The procedure for trial-decrypting a
``CompactOutput`` (*cmu*, *epk*, *ciphertext*) with an incoming viewing key *ivk* is a ``CompactOutput`` :math:`(\mathtt{cmu}, \mathsf{epk}, \mathsf{ciphertext})` with an incoming
slight deviation from the standard decryption process [#protocol-saplingdecryptivk]_: viewing key :math:`\mathsf{ivk}` is a slight deviation from the standard decryption process
[#protocol-saplingdecryptivk]_:
- let sharedSecret = KA\ :sup:`Sapling`\ .Agree(*ivk*, *epk*) - let :math:`\mathsf{sharedSecret} = \mathsf{KA^{Sapling}.Agree}(\mathsf{ivk}, \mathsf{epk})`
- let K\ :sup:`enc` = KDF\ :sup:`Sapling`\ (sharedSecret, *epk*) - let :math:`K^{\mathsf{enc}} = \mathsf{KDF^{Sapling}}(\mathsf{sharedSecret}, \mathsf{epk})`
- let P\ :sup:`enc` = ChaCha20.Decrypt\ :sub:`K^enc`\ (*ciphertext*) - let :math:`P^{\mathsf{enc}} = \mathsf{ChaCha20.Decrypt}_{K^{\mathsf{enc}}}(\mathsf{ciphertext})`
- extract **np** = (d, v, rcm) from P\ :sup:`enc` - extract :math:`\mathbf{np} = (\mathsf{d}, \mathsf{v}, \mathsf{rcm})` from :math:`P^{\mathsf{enc}}`
- let rcm = LEOS2IP\ :sub:`256`\ (rcm) and g\ :sub:`d` = DiversifyHash(d) - let :math:`\mathsf{rcm} = \mathsf{LEOS2IP}_{256}(\mathsf{rcm})` and :math:`\mathsf{g_d} = \mathsf{DiversifyHash}(\mathsf{d})`
- if rcm >= r\ :sub:`J` or g\ :sub:`d` = ⊥, return ⊥ - if :math:`\mathsf{rcm} \geq r_{\mathbb{J}}` or :math:`\mathsf{g_d} = \bot`, return :math:`\bot`
- let pk\ :sub:`d` = KASapling.DerivePublic(ivk, g\ :sub:`d`\ ) - let :math:`\mathsf{pk_d} = \mathsf{KA^{Sapling}.DerivePublic}(\mathsf{ivk}, \mathsf{g_d})`
- let cm\ :sub:`u`\ ' = Extract\ :sub:`J^(r)`\ (NoteCommitSapling\ :sub:`rcm^new`\ (repr\ :sub:`J`\ (g\ :sub:`d`\ ), repr\ :sub:`J`\ (pk\ :sub:`d`\ ), v)). - let :math:`\mathsf{cm}_u' = \mathsf{Extract}_{\mathbb{J}^{(r)}}(\mathsf{NoteCommit^{Sapling}_{rcm}}(\mathsf{repr}_{\mathbb{J}}(\mathsf{g_d}), \mathsf{repr}_{\mathbb{J}}(\mathsf{pk_d}), \mathsf{v}))`.
- if LEBS2OSP\ :sub:`256`\ (cm\ :sub:`u`\ ') != *cmu* , return ⊥, else return **np**. - if :math:`\mathsf{LEBS2OSP}_{256}(\mathsf{cm}_u') \neq \mathtt{cmu}`, return :math:`\bot`, else return :math:`\mathbf{np}`.
TODO: update this for ZIP 212 [#zip-0212]_.
Creating and updating note witnesses Creating and updating note witnesses
```````````````````````````````````` ````````````````````````````````````
@ -591,6 +594,7 @@ References
.. [#protocol-notept] `Section 5.5: Encodings of Note Plaintexts and Memo Fields. Zcash Protocol Specification, Version 2020.1.6 <protocol/protocol.pdf#notept>`_ .. [#protocol-notept] `Section 5.5: Encodings of Note Plaintexts and Memo Fields. Zcash Protocol Specification, Version 2020.1.6 <protocol/protocol.pdf#notept>`_
.. [#protocol-spendencoding] `Section 7.3: Encoding of Spend Descriptions. Zcash Protocol Specification, Version 2020.1.6 <protocol/protocol.pdf#spendencoding>`_ .. [#protocol-spendencoding] `Section 7.3: Encoding of Spend Descriptions. Zcash Protocol Specification, Version 2020.1.6 <protocol/protocol.pdf#spendencoding>`_
.. [#protocol-outputencoding] `Section 7.4: Encoding of Output Descriptions. Zcash Protocol Specification, Version 2020.1.6 <protocol/protocol.pdf#outputencoding>`_ .. [#protocol-outputencoding] `Section 7.4: Encoding of Output Descriptions. Zcash Protocol Specification, Version 2020.1.6 <protocol/protocol.pdf#outputencoding>`_
.. [#zip-0212] `ZIP 212: Allow Recipient to Derive Sapling Ephemeral Secret from Note Plaintext <zip-0212.rst>`_
.. [#protocolbuffers] `Protocol Buffers. <https://developers.google.com/protocol-buffers/>`_ .. [#protocolbuffers] `Protocol Buffers. <https://developers.google.com/protocol-buffers/>`_
.. [#incremental-witness] `TODO` .. [#incremental-witness] `TODO`
.. [#spv-clients] `TODO` .. [#spv-clients] `TODO`