ZIP 32: use :math: markup for better rendering.

Signed-off-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
Daira Hopwood 2020-04-22 10:24:13 +01:00
parent b9968a3bca
commit 6c6843154d
2 changed files with 688 additions and 257 deletions

View File

@ -3,6 +3,7 @@
<head>
<title>ZIP 32: Shielded Hierarchical Deterministic Wallets</title>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.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>
<body>
<section>
@ -17,6 +18,9 @@ Status: Final
Category: Standards Track
Created: 2018-05-22
License: MIT</pre>
<p>
<span class="math">\(% This ZIP makes heavy use of mathematical markup. If you can see this, you may want to instead view the rendered version at &lt;https://zips.z.cash/zip-0032&gt;.\)</span>
</p>
<section id="terminology"><h2><span class="section-heading">Terminology</span><span class="section-anchor"> <a href="#terminology"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>The key words "MUST", "MUST NOT", and "MAY" in this document are to be interpreted as described in RFC 2119. <a id="id1" class="footnote_reference" href="#rfc2119">1</a></p>
<p>"Jubjub" refers to the elliptic curve defined in <a id="id2" class="footnote_reference" href="#sapling-jubjub">12</a>.</p>
@ -39,33 +43,137 @@ License: MIT</pre>
<section id="conventions"><h2><span class="section-heading">Conventions</span><span class="section-anchor"> <a href="#conventions"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>Most of the notation and functions used in this ZIP are defined in the Sapling protocol specification <a id="id8" class="footnote_reference" href="#sapling-spec">8</a>. They are reproduced here for convenience:</p>
<ul>
<li>truncate<sub>k</sub>(<em>S</em>) means the sequence formed from the first <em>k</em> elements of <em>S</em>.</li>
<li><em>a</em> || <em>b</em> means the concatenation of sequences <em>a</em> then <em>b</em>.</li>
<li>[<em>k</em>] <em>P</em> means scalar multiplication of the elliptic curve point <em>P</em> by the scalar <em>k</em>.</li>
<li>LEOS2IP<sub>l</sub>(<em>S</em>) is the integer in range {0..2<sup>l</sup>-1} represented in little-endian order by the byte sequence <em>S</em> of length <em>l</em>/8.</li>
<li>I2LEBSP<sub>l</sub>(<em>k</em>) is the sequence of <em>l</em> bits representing <em>k</em> in little-endian order.</li>
<li>LEBS2OSP<sub>l</sub>(<em>B</em>) is defined as follows when <em>l</em> is a multiple of 8: convert each group of 8 bits in <em>B</em> to a byte value with the least significant bit first, and concatenate the resulting bytes in the same order as the groups.</li>
<li>repr<sub>𝕁</sub>(<em>P</em>) is the representation of the Jubjub elliptic curve point <em>P</em> as a bit sequence, defined in <a id="id9" class="footnote_reference" href="#sapling-jubjub">12</a>.</li>
<li>BLAKE2b-256(<em>p</em>, <em>x</em>) refers to unkeyed BLAKE2b-256 in sequential mode, with an output digest length of 32 bytes, 16-byte personalization string <em>p</em>, and input <em>x</em>.</li>
<li>BLAKE2b-512(<em>p</em>, <em>x</em>) refers to unkeyed BLAKE2b-512 in sequential mode, with an output digest length of 64 bytes, 16-byte personalization string <em>p</em>, and input <em>x</em>.</li>
<li>PRF<sup>expand</sup>(<em>sk</em>, <em>t</em>) := BLAKE2b-512("Zcash_ExpandSeed", <em>sk</em> || <em>t</em>)</li>
<li><em>r</em><sub>𝕁</sub> is the order of the Jubjub large prime subgroup.</li>
<li>ToScalar(<em>x</em>) := LEOS2IP<sub>512</sub>(<em>x</em>) (mod <em>r</em><sub>𝕁</sub>).</li>
<li>DiversifyHash(<em>d</em>) maps a diversifier <em>d</em> to a base point on the Jubjub elliptic curve, or to ⊥ if the diversifier is invalid. It is instantiated in <a id="id10" class="footnote_reference" href="#sapling-diversifyhash">10</a>.</li>
<li>
<span class="math">\(\mathsf{truncate}_k(S)\)</span>
means the sequence formed from the first
<span class="math">\(k\)</span>
elements of
<span class="math">\(S\)</span>
.</li>
<li>
<span class="math">\(a\,||\,b\)</span>
means the concatenation of sequences
<span class="math">\(a\)</span>
then
<span class="math">\(b\)</span>
.</li>
<li>
<span class="math">\([k] P\)</span>
means scalar multiplication of the elliptic curve point
<span class="math">\(P\)</span>
by the scalar
<span class="math">\(k\)</span>
.</li>
<li>
<span class="math">\(\mathsf{LEOS2IP}_\ell(S)\)</span>
is the integer in range
<span class="math">\(\{ 0\,.\!. 2^\ell - 1 \}\)</span>
represented in little-endian order by the byte sequence
<span class="math">\(S\)</span>
of length
<span class="math">\(\ell/8\)</span>
.</li>
<li>
<span class="math">\(\mathsf{I2LEBSP}_\ell(k)\)</span>
is the sequence of
<span class="math">\(\ell\)</span>
bits representing
<span class="math">\(k\)</span>
in little-endian order.</li>
<li>
<span class="math">\(\mathsf{LEBS2OSP}_\ell(B)\)</span>
is defined as follows when
<span class="math">\(\ell\)</span>
is a multiple of
<span class="math">\(8\)</span>
: convert each group of 8 bits in
<span class="math">\(B\)</span>
to a byte value with the least significant bit first, and concatenate the resulting bytes in the same order as the groups.</li>
<li>
<span class="math">\(\mathsf{repr}_\mathbb{J}(P)\)</span>
is the representation of the Jubjub elliptic curve point
<span class="math">\(P\)</span>
as a bit sequence, defined in <a id="id9" class="footnote_reference" href="#sapling-jubjub">12</a>.</li>
<li>
<span class="math">\(\mathsf{BLAKE2b}\text{-}\mathsf{256}(p, x)\)</span>
refers to unkeyed BLAKE2b-256 in sequential mode, with an output digest length of 32 bytes, 16-byte personalization string
<span class="math">\(p\)</span>
, and input
<span class="math">\(x\)</span>
.</li>
<li>
<span class="math">\(\mathsf{BLAKE2b}\text{-}\mathsf{512}(p, x)\)</span>
refers to unkeyed BLAKE2b-512 in sequential mode, with an output digest length of 64 bytes, 16-byte personalization string
<span class="math">\(p\)</span>
, and input
<span class="math">\(x\)</span>
.</li>
<li>
<span class="math">\(\mathsf{PRF^{expand}}(\mathsf{sk}, t) := \mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{“Zcash_ExpandSeed”}, \mathsf{sk}\,||\,t)\)</span>
</li>
<li>
<span class="math">\(r_\mathbb{J}\)</span>
is the order of the Jubjub large prime subgroup.</li>
<li>
<span class="math">\(\mathsf{ToScalar}(x) := \mathsf{LEOS2IP}_{512}(x) \pmod{r_\mathbb{J}}\)</span>
.</li>
<li>
<span class="math">\(\mathsf{DiversifyHash}(d)\)</span>
maps a diversifier
<span class="math">\(d\)</span>
to a base point on the Jubjub elliptic curve, or to
<span class="math">\(\bot\)</span>
if the diversifier is invalid. It is instantiated in <a id="id10" class="footnote_reference" href="#sapling-diversifyhash">10</a>.</li>
</ul>
<p>The following algorithm standardized in <a id="id11" class="footnote_reference" href="#nist-sp-800-38g">16</a> is used:</p>
<ul>
<li>FF1-AES256.Encrypt(<em>key</em>, <em>tweak</em>, <em>x</em>) refers to the FF1 encryption algorithm using AES with a 256-bit <em>key</em>, and parameters <em>radix</em> = 2, <em>minlen</em> = 88, <em>maxlen</em> = 88. It will be used only with the empty string "" as the <em>tweak</em>. <em>x</em> is a sequence of 88 bits, as is the output.</li>
<li>
<span class="math">\(\mathsf{FF1}\text{-}\mathsf{AES256.Encrypt}(key, tweak, x)\)</span>
refers to the FF1 encryption algorithm using AES with a 256-bit
<span class="math">\(key\)</span>
, and parameters
<span class="math">\(radix = 2, minlen = 88, maxlen = 88\)</span>
. It will be used only with the empty string
<span class="math">\(\texttt{“”}\)</span>
as the
<span class="math">\(tweak\)</span>
.
<span class="math">\(x\)</span>
is a sequence of 88 bits, as is the output.</li>
</ul>
<p>We also define the following conversion function:</p>
<ul>
<li>I2LEOSP<sub>l</sub>(<em>k</em>) is the byte sequence <em>S</em> of length <em>l</em>/8 representing in little-endian order the integer <em>k</em> in range {0..2<sup>l</sup>-1}. It is the reverse operation of LEOS2IP<sub>l</sub>(<em>S</em>).</li>
<li>
<span class="math">\(\mathsf{I2LEOSP}_\ell(k)\)</span>
is the byte sequence
<span class="math">\(S\)</span>
of length
<span class="math">\(\ell/8\)</span>
representing in little-endian order the integer
<span class="math">\(k\)</span>
in range
<span class="math">\(\{ 0\,.\!. 2^\ell - 1 \}\)</span>
. It is the reverse operation of
<span class="math">\(\mathsf{LEOS2IP}_\ell(S)\)</span>
.</li>
</ul>
<p>Implementors should note that this ZIP is consistently little-endian (in keeping with the Sapling specification), which is the opposite of BIP 32.</p>
<p>We adapt the path notation of BIP 32 <a id="id12" class="footnote_reference" href="#bip-0032">2</a> to describe shielded HD paths, using apostrophes to indicate hardened derivation (i' = i + 2<sup>31</sup>) as in BIP 44 <a id="id13" class="footnote_reference" href="#bip-0044">5</a>:</p>
<p>We adapt the path notation of BIP 32 <a id="id12" class="footnote_reference" href="#bip-0032">2</a> to describe shielded HD paths, using prime marks (
<span class="math">\('\)</span>
) to indicate hardened derivation (
<span class="math">\(i' = i + 2^{31}\)</span>
) as in BIP 44 <a id="id13" class="footnote_reference" href="#bip-0044">5</a>:</p>
<ul>
<li>CDKsk(CDKsk(CDKsk(m<sub>Sprout</sub>, a'), b), c) is written as m<sub>Sprout</sub> / a' / b / c</li>
<li>CDKfvk(CDKfvk(CDKfvk(M<sub>Sapling</sub>, a), b), c) is written as M<sub>Sapling</sub> / a / b / c</li>
<li>
<span class="math">\(\mathsf{CDKsk}(\mathsf{CDKsk}(\mathsf{CDKsk}(m_\mathsf{Sprout}, a'), b), c)\)</span>
is written as
<span class="math">\(m_\mathsf{Sprout} / a' / b / c\)</span>
</li>
<li>
<span class="math">\(\mathsf{CDKfvk}(\mathsf{CDKfvk}(\mathsf{CDKfvk}(m_\mathsf{Sapling}, a), b), c)\)</span>
is written as
<span class="math">\(m_\mathsf{Sapling} / a / b / c\)</span>
.</li>
</ul>
</section>
<section id="specification-sapling-key-derivation"><h2><span class="section-heading">Specification: Sapling key derivation</span><span class="section-anchor"> <a href="#specification-sapling-key-derivation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2>
@ -75,125 +183,324 @@ License: MIT</pre>
<li>We derive child Sapling expanded spending keys, rather than Sapling spending keys. This enables us to implement both hardened and non-hardened derivation modes (the latter being incompatible with Sapling spending keys).</li>
<li>We do not derive Sapling public keys directly, as this would prevent the use of diversified addresses. Instead, we derive Sapling full viewing keys, from which payment addresses can be generated. This maintains the trust semantics of BIP 32: someone with access to a BIP 32 extended public key is able to view all transactions involving that address, which a Sapling full viewing key also enables.</li>
</ul>
<p>We represent a Sapling extended spending key as (<em>ask</em>, <em>nsk</em>, <em>ovk</em>, <em>dk</em>, <em>c</em>), where (<em>ask</em>, <em>nsk</em>, <em>ovk</em>) is the normal Sapling expanded spending key, <em>dk</em> is a diversifier key, and <em>c</em> is the chain code.</p>
<p>We represent a Sapling extended full viewing key as (<em>ak</em>, <em>nk</em>, <em>ovk</em>, <em>dk</em>, <em>c</em>), where (<em>ak</em>, <em>nk</em>, <em>ovk</em>) is the normal Sapling full viewing key, <em>dk</em> is the same diversifier key as above, and <em>c</em> is the chain code.</p>
<p>We represent a Sapling extended spending key as
<span class="math">\((\mathsf{ask, nsk, ovk, dk, c})\)</span>
, where
<span class="math">\((\mathsf{ask, nsk, ovk})\)</span>
is the normal Sapling expanded spending key,
<span class="math">\(\mathsf{dk}\)</span>
is a diversifier key, and
<span class="math">\(\mathsf{c}\)</span>
is the chain code.</p>
<p>We represent a Sapling extended full viewing key as
<span class="math">\((\mathsf{ak, nk, ovk, dk, c})\)</span>
, where
<span class="math">\((\mathsf{ak, nk, ovk})\)</span>
is the normal Sapling full viewing key,
<span class="math">\(\mathsf{dk}\)</span>
is the same diversifier key as above, and
<span class="math">\(\mathsf{c}\)</span>
is the chain code.</p>
</section>
<section id="sapling-helper-functions"><h3><span class="section-heading">Sapling helper functions</span><span class="section-anchor"> <a href="#sapling-helper-functions"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Define EncodeExtSKParts(<em>ask</em>, <em>nsk</em>, <em>ovk</em>, <em>dk</em>) := I2LEOSP<sub>256</sub>(<em>ask</em>) || I2LEOSP<sub>256</sub>(<em>nsk</em>) || <em>ovk</em> || <em>dk</em>.</p>
<p>Define EncodeExtFVKParts(<em>ak</em>, <em>nk</em>, <em>ovk</em>, <em>dk</em>) := LEBS2OSP<sub>256</sub>(repr<sub>𝕁</sub>(<em>ak</em>)) || LEBS2OSP<sub>256</sub>(repr<sub>𝕁</sub>(<em>nk</em>)) || <em>ovk</em> || <em>dk</em>.</p>
<p>Define</p>
<ul>
<li>
<span class="math">\(\mathsf{EncodeExtSKParts}(\mathsf{ask, nsk, ovk, dk}) := \mathsf{I2LEOSP}_{256}(\mathsf{ask})\,||\,\mathsf{I2LEOSP}_{256}(\mathsf{nsk})\,||\,\mathsf{ovk}\,||\,\mathsf{dk}\)</span>
</li>
<li>
<span class="math">\(\mathsf{EncodeExtFVKParts}(\mathsf{ak, nk, ovk, dk}) := \mathsf{LEBS2OS}_{256}(\mathsf{repr}_\mathbb{J}(\mathsf{ak}))\,||\,\mathsf{LEBS2OSP}_{256}(\mathsf{repr}_\mathbb{J}(\mathsf{nk}))\,||\,\mathsf{ovk}\,||\,\mathsf{dk}\)</span>
</li>
</ul>
</section>
<section id="sapling-master-key-generation"><h3><span class="section-heading">Sapling master key generation</span><span class="section-anchor"> <a href="#sapling-master-key-generation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Let <em>S</em> be a seed byte sequence of a chosen length, which MUST be at least 32 bytes.</p>
<p>Let
<span class="math">\(S\)</span>
be a seed byte sequence of a chosen length, which MUST be at least 32 bytes.</p>
<ul>
<li>Calculate <em>I</em> = BLAKE2b-512("ZcashIP32Sapling", <em>S</em>).</li>
<li>Split <em>I</em> into two 32-byte sequences, <em>I</em><sub>L</sub> and <em>I</em><sub>R</sub>.</li>
<li>Use <em>I</em><sub>L</sub> as the master spending key <em>sk</em><sub>m</sub>, and <em>I</em><sub>R</sub> as the master chain code <em>c</em><sub>m</sub>.</li>
<li>Calculate <em>ask</em><sub>m</sub>, <em>nsk</em><sub>m</sub>, and <em>ovk</em><sub>m</sub> via the standard Sapling derivation <a id="id14" class="footnote_reference" href="#sapling-key-components">9</a>:
<li>Calculate
<span class="math">\(I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{“ZcashIP32Sapling”}, S)\)</span>
.</li>
<li>Split
<span class="math">\(I\)</span>
into two 32-byte sequences,
<span class="math">\(I_L\)</span>
and
<span class="math">\(I_R\)</span>
.</li>
<li>Use
<span class="math">\(I_L\)</span>
as the master spending key
<span class="math">\(\mathsf{sk}_m\)</span>
, and
<span class="math">\(I_R\)</span>
as the master chain code
<span class="math">\(\mathsf{c}_m\)</span>
.</li>
<li>Calculate
<span class="math">\(\mathsf{ask}_m\)</span>
,
<span class="math">\(\mathsf{nsk}_m\)</span>
, and
<span class="math">\(\mathsf{ovk}_m\)</span>
via the standard Sapling derivation <a id="id14" class="footnote_reference" href="#sapling-key-components">9</a>:
<ul>
<li><em>ask</em><sub>m</sub> = ToScalar(PRF<sup>expand</sup>(<em>sk</em><sub>m</sub>, [0x00]))</li>
<li><em>nsk</em><sub>m</sub> = ToScalar(PRF<sup>expand</sup>(<em>sk</em><sub>m</sub>, [0x01]))</li>
<li><em>ovk</em><sub>m</sub> = truncate<sub>32</sub>(PRF<sup>expand</sup>(<em>sk</em><sub>m</sub>, [0x02]))</li>
<li>
<span class="math">\(\mathsf{ask}_m = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x00}]))\)</span>
</li>
<li>
<span class="math">\(\mathsf{nsk}_m = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x01}]))\)</span>
</li>
<li>
<span class="math">\(\mathsf{ovk}_m = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x02}]))\)</span>
.</li>
</ul>
</li>
<li>Calculate <em>dk</em><sub>m</sub> similarly:
<li>Calculate
<span class="math">\(\mathsf{dk}_m\)</span>
similarly:
<ul>
<li><em>dk</em><sub>m</sub> = truncate<sub>32</sub>(PRF<sup>expand</sup>(<em>sk</em><sub>m</sub>, [0x10]))</li>
<li>
<span class="math">\(\mathsf{dk}_m = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x10}]))\)</span>
.</li>
</ul>
</li>
<li>Return (<em>ask</em><sub>m</sub>, <em>nsk</em><sub>m</sub>, <em>ovk</em><sub>m</sub>, <em>dk</em><sub>m</sub>, <em>c</em><sub>m</sub>) as the master extended spending key <em>m</em><sub>Sapling</sub>.</li>
<li>Return
<span class="math">\((\mathsf{ask}_m, \mathsf{nsk}_m, \mathsf{ovk}_m, \mathsf{dk}_m, \mathsf{c}_m)\)</span>
as the master extended spending key
<span class="math">\(m_\mathsf{Sapling}\)</span>
.</li>
</ul>
</section>
<section id="sapling-child-key-derivation"><h3><span class="section-heading">Sapling child key derivation</span><span class="section-anchor"> <a href="#sapling-child-key-derivation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>As in BIP 32, the method for deriving a child extended key, given a parent extended key and an index <em>i</em>, depends on the type of key being derived, and whether this is a hardened or non-hardened derivation.</p>
<p>As in BIP 32, the method for deriving a child extended key, given a parent extended key and an index
<span class="math">\(i\)</span>
, depends on the type of key being derived, and whether this is a hardened or non-hardened derivation.</p>
<section id="deriving-a-child-extended-spending-key"><h4><span class="section-heading">Deriving a child extended spending key</span><span class="section-anchor"> <a href="#deriving-a-child-extended-spending-key"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h4>
<p>CDKsk((<em>ask</em><sub>par</sub>, <em>nsk</em><sub>par</sub>, <em>ovk</em><sub>par</sub>, <em>dk</em><sub>par</sub>, <em>c</em><sub>par</sub>), <em>i</em>) → (<em>ask</em><sub>i</sub>, <em>nsk</em><sub>i</sub>, <em>ovk</em><sub>i</sub>, <em>dk</em><sub>i</sub>, <em>c</em><sub>i</sub>)</p>
<p>
<span class="math">\(\mathsf{CDKsk}((\mathsf{ask}_{par}, \mathsf{nsk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par}, \mathsf{c}_{par}), i) \rightarrow (\mathsf{ask}_i, \mathsf{nsk}_i, \mathsf{ovk}_i, \mathsf{dk}_i, \mathsf{c}_i)\)</span>
</p>
<ul>
<li>Check whether <em>i</em> ≥ 2<sup>31</sup> (whether the child is a hardened key).
<li>Check whether
<span class="math">\(i \geq 2^{31}\)</span>
(whether the child is a hardened key).
<ul>
<li>If so (hardened child): let <em>I</em> = PRF<sup>expand</sup>(<em>c</em><sub>par</sub>, [0x11] || EncodeExtSKParts(<em>ask</em><sub>par</sub>, <em>nsk</em><sub>par</sub>, <em>ovk</em><sub>par</sub>, <em>dk</em><sub>par</sub>) || I2LEOSP<sub>32</sub>(<em>i</em>))</li>
<li>If not (normal child): let <em>I</em> = PRF<sup>expand</sup>(<em>c</em><sub>par</sub>, [0x12] || EncodeExtFVKParts(<em>ak</em><sub>par</sub>, <em>nk</em><sub>par</sub>, <em>ovk</em><sub>par</sub>, <em>dk</em><sub>par</sub>) || I2LEOSP<sub>32</sub>(<em>i</em>)) where (<em>nk</em><sub>par</sub>, <em>ak</em><sub>par</sub>, <em>ovk</em><sub>par</sub>) is the full viewing key derived from (<em>ask</em><sub>par</sub>, <em>nsk</em><sub>par</sub>, <em>ovk</em><sub>par</sub>) as described in <a id="id15" class="footnote_reference" href="#sapling-key-components">9</a>.</li>
<li>If so (hardened child): let
<span class="math">\(I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\texttt{0x11}]\,||\,\mathsf{EncodeExtSKParts}(\mathsf{ask}_{par}, \mathsf{nsk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par})\,||\,\mathsf{I2LEOSP}_{32}(i))\)</span>
.</li>
<li>If not (normal child): let
<span class="math">\(I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\texttt{0x12}]\,||\,\mathsf{EncodeExtFVKParts}(\mathsf{ak}_{par}, \mathsf{nk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par})\,||\,\mathsf{I2LEOSP}_{32}(i))\)</span>
where
<span class="math">\((\mathsf{nk}_{par}, \mathsf{ak}_{par}, \mathsf{ovk}_{par})\)</span>
is the full viewing key derived from
<span class="math">\((\mathsf{ask}_{par}, \mathsf{nsk}_{par}, \mathsf{ovk}_{par})\)</span>
as described in <a id="id15" class="footnote_reference" href="#sapling-key-components">9</a>.</li>
</ul>
</li>
<li>Split <em>I</em> into two 32-byte sequences, <em>I</em><sub>L</sub> and <em>I</em><sub>R</sub>.</li>
<li>Let <em>I</em><sub>ask</sub> = ToScalar(PRF<sup>expand</sup>(<em>I</em><sub>L</sub>, [0x13]))</li>
<li>Let <em>I</em><sub>nsk</sub> = ToScalar(PRF<sup>expand</sup>(<em>I</em><sub>L</sub>, [0x14]))</li>
<li>Split
<span class="math">\(I\)</span>
into two 32-byte sequences,
<span class="math">\(I_L\)</span>
and
<span class="math">\(I_R\)</span>
.</li>
<li>Let
<span class="math">\(I_\mathsf{ask} = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x13}]))\)</span>
.</li>
<li>Let
<span class="math">\(I_\mathsf{nsk} = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x14}]))\)</span>
.</li>
<li>Return:
<ul>
<li><em>ask</em><sub>i</sub> = (<em>I</em><sub>ask</sub> + <em>ask</em><sub>par</sub>) (mod <em>r</em><sub>𝕁</sub>)</li>
<li><em>nsk</em><sub>i</sub> = (<em>I</em><sub>nsk</sub> + <em>nsk</em><sub>par</sub>) (mod <em>r</em><sub>𝕁</sub>)</li>
<li><em>ovk</em><sub>i</sub> = truncate<sub>32</sub>(PRF<sup>expand</sup>(<em>I</em><sub>L</sub>, [0x15] || <em>ovk</em><sub>par</sub>))</li>
<li><em>dk</em><sub>i</sub> = truncate<sub>32</sub>(PRF<sup>expand</sup>(<em>I</em><sub>L</sub>, [0x16] || <em>dk</em><sub>par</sub>))</li>
<li><em>c</em><sub>i</sub> = <em>I</em><sub>R</sub></li>
<li>
<span class="math">\(\mathsf{ask}_i = (I_\mathsf{ask} + \mathsf{ask}_{par}) \pmod{r_\mathbb{J}}\)</span>
</li>
<li>
<span class="math">\(\mathsf{nsk}_i = (I_\mathsf{nsk} + \mathsf{nsk}_{par}) \pmod{r_\mathbb{J}}\)</span>
</li>
<li>
<span class="math">\(\mathsf{ovk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x15}]\,||\,\mathsf{ovk}_{par}))\)</span>
</li>
<li>
<span class="math">\(\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x16}]\,||\,\mathsf{dk}_{par}))\)</span>
</li>
<li>
<span class="math">\(\mathsf{c}_i = I_R\)</span>
.</li>
</ul>
</li>
</ul>
</section>
<section id="deriving-a-child-extended-full-viewing-key"><h4><span class="section-heading">Deriving a child extended full viewing key</span><span class="section-anchor"> <a href="#deriving-a-child-extended-full-viewing-key"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h4>
<p>Let 𝓖 be as defined in <a id="id16" class="footnote_reference" href="#sapling-spendauthsig">11</a> and let 𝓗 be as defined in <a id="id17" class="footnote_reference" href="#sapling-key-components">9</a>.</p>
<p>CDKfvk((<em>ak</em><sub>par</sub>, <em>nk</em><sub>par</sub>, <em>ovk</em><sub>par</sub>, <em>dk</em><sub>par</sub>, <em>c</em><sub>par</sub>), <em>i</em>) → (<em>ak</em><sub>i</sub>, <em>nk</em><sub>i</sub>, <em>ovk</em><sub>i</sub>, <em>dk</em><sub>i</sub>, <em>c</em><sub>i</sub>)</p>
<p>Let
<span class="math">\(\mathcal{G}\)</span>
be as defined in <a id="id16" class="footnote_reference" href="#sapling-spendauthsig">11</a> and let
<span class="math">\(\mathcal{H}\)</span>
be as defined in <a id="id17" class="footnote_reference" href="#sapling-key-components">9</a>.</p>
<p>
<span class="math">\(\mathsf{CDKfvk}((\mathsf{ak}_{par}, \mathsf{nk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par}, \mathsf{c}_{par}), i) \rightarrow (\mathsf{ak}_{i}, \mathsf{nk}_{i}, \mathsf{ovk}_{i}, \mathsf{dk}_{i}, \mathsf{c}_{i})\)</span>
</p>
<ul>
<li>Check whether <em>i</em> ≥ 2<sup>31</sup> (whether the child is a hardened key).
<li>Check whether
<span class="math">\(i \geq 2^{31}\)</span>
(whether the child is a hardened key).
<ul>
<li>If so (hardened child): return failure</li>
<li>If not (normal child): let <em>I</em> = PRF<sup>expand</sup>(<em>c</em><sub>par</sub>, [0x12] || EncodeExtFVKParts(<em>ak</em><sub>par</sub>, <em>nk</em><sub>par</sub>, <em>ovk</em><sub>par</sub>, <em>dk</em><sub>par</sub>) || I2LEOSP<sub>32</sub>(<em>i</em>))</li>
<li>If so (hardened child): return failure.</li>
<li>If not (normal child): let
<span class="math">\(I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\texttt{0x12}]\,||\,\mathsf{EncodeExtFVKParts}(\mathsf{ak}_{par}, \mathsf{nk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par})\,||\,\mathsf{I2LEOSP}_{32}(i))\)</span>
.</li>
</ul>
</li>
<li>Split <em>I</em> into two 32-byte sequences, <em>I</em><sub>L</sub> and <em>I</em><sub>R</sub>.</li>
<li>Let <em>I</em><sub>ask</sub> = ToScalar(PRF<sup>expand</sup>(<em>I</em><sub>L</sub>, [0x13]))</li>
<li>Let <em>I</em><sub>nsk</sub> = ToScalar(PRF<sup>expand</sup>(<em>I</em><sub>L</sub>, [0x14]))</li>
<li>Split
<span class="math">\(I\)</span>
into two 32-byte sequences,
<span class="math">\(I_L\)</span>
and
<span class="math">\(I_R\)</span>
.</li>
<li>Let
<span class="math">\(I_\mathsf{ask} = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x13}]))\)</span>
.</li>
<li>Let
<span class="math">\(I_\mathsf{nsk} = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x14}]))\)</span>
.</li>
<li>Return:
<ul>
<li><em>ak</em><sub>i</sub> = [<em>I</em><sub>ask</sub>] 𝓖 + <em>ak</em><sub>par</sub></li>
<li><em>nk</em><sub>i</sub> = [<em>I</em><sub>nsk</sub>] 𝓗 + <em>nk</em><sub>par</sub></li>
<li><em>ovk</em><sub>i</sub> = truncate<sub>32</sub>(PRF<sup>expand</sup>(<em>I</em><sub>L</sub>, [0x15] || <em>ovk</em><sub>par</sub>))</li>
<li><em>dk</em><sub>i</sub> = truncate<sub>32</sub>(PRF<sup>expand</sup>(<em>I</em><sub>L</sub>, [0x16] || <em>dk</em><sub>par</sub>))</li>
<li><em>c</em><sub>i</sub> = <em>I</em><sub>R</sub></li>
<li>
<span class="math">\(\mathsf{ak}_i = [I_\mathsf{ask}]\,\mathcal{G} + \mathsf{ak}_{par}\)</span>
</li>
<li>
<span class="math">\(\mathsf{nk}_i = [I_\mathsf{nsk}]\,\mathcal{H} + \mathsf{nk}_{par}\)</span>
</li>
<li>
<span class="math">\(\mathsf{ovk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x15}]\,||\,\mathsf{ovk}_{par}))\)</span>
</li>
<li>
<span class="math">\(\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x16}]\,||\,\mathsf{dk}_{par}))\)</span>
</li>
<li>
<span class="math">\(\mathsf{c}_i = I_R\)</span>
.</li>
</ul>
</li>
</ul>
</section>
</section>
<section id="diversifier-derivation"><h3><span class="section-heading">Diversifier derivation</span><span class="section-anchor"> <a href="#diversifier-derivation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key <em>dk</em>. To prevent the diversifier leaking how many diversified addresses have already been generated for an account, we make the sequence of diversifiers pseudorandom and uncorrelated to that of any other account. In order to reach the maximum possible diversifier range without running into repetitions due to the birthday bound, we use FF1-AES256 as a Pseudo-Random Permutation as follows:</p>
<p>The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key
<span class="math">\(dk\)</span>
. To prevent the diversifier leaking how many diversified addresses have already been generated for an account, we make the sequence of diversifiers pseudorandom and uncorrelated to that of any other account. In order to reach the maximum possible diversifier range without running into repetitions due to the birthday bound, we use FF1-AES256 as a Pseudo-Random Permutation as follows:</p>
<ul>
<li>Let <em>j</em> be the index of the desired diversifier, in the range 0 .. 2<sup>88</sup>-1.</li>
<li><em>d</em><sub>j</sub> = FF1-AES256.Encrypt(<em>dk</em>, "", I2LEBSP<sub>88</sub>(<em>j</em>)).</li>
<li>Let
<span class="math">\(j\)</span>
be the index of the desired diversifier, in the range
<span class="math">\(0\,.\!. 2^{88} - 1\)</span>
.</li>
<li>
<span class="math">\(d_j = \mathsf{FF1}\text{-}\mathsf{AES256.Encrypt}(\mathsf{dk}, \texttt{“”}, \mathsf{I2LEBSP}_{88}(j))\)</span>
.</li>
</ul>
<p>A valid diversifier <em>d</em><sub>j</sub> is one for which DiversifyHash(<em>d</em><sub>j</sub>) ≠ ⊥. For a given <em>dk</em>, approximately half of the possible values of <em>j</em> yield valid diversifiers.</p>
<p>The default diversifier for a Sapling extended key is defined to be <em>d</em><sub>j</sub>, where <em>j</em> is the least nonnegative integer yielding a valid diversifier.</p>
<p>A valid diversifier
<span class="math">\(d_j\)</span>
is one for which
<span class="math">\(\mathsf{DiversifyHash}(d_j) \neq \bot\)</span>
. For a given
<span class="math">\(\mathsf{dk}\)</span>
, approximately half of the possible values of
<span class="math">\(j\)</span>
yield valid diversifiers.</p>
<p>The default diversifier for a Sapling extended key is defined to be
<span class="math">\(d_j\)</span>
, where
<span class="math">\(j\)</span>
is the least nonnegative integer yielding a valid diversifier.</p>
</section>
</section>
<section id="specification-sprout-key-derivation"><h2><span class="section-heading">Specification: Sprout key derivation</span><span class="section-anchor"> <a href="#specification-sprout-key-derivation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>For completeness, we define a system for deriving a tree of Sprout key components. It is unlikely that this will garner much usage once Sapling activates, but is presented for those users who may require it.</p>
<section id="sprout-extended-keys"><h3><span class="section-heading">Sprout extended keys</span><span class="section-anchor"> <a href="#sprout-extended-keys"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Due to the way Sprout keys are constructed and used, it is not possible to derive incoming viewing keys or payment addresses in parallel with spending keys. Nor is it possible to implement non-hardened derivation. We therefore only define and derive Sprout extended spending keys.</p>
<p>We represent a Sprout extended spending key as (<em>a</em><sub>sk</sub>, <em>c</em>), where <em>a</em><sub>sk</sub> is the normal Sprout spending key, and <em>c</em> is the chain code.</p>
<p>We represent a Sprout extended spending key as
<span class="math">\((\mathsf{a_{sk}, c})\)</span>
, where
<span class="math">\(\mathsf{a_{sk}}\)</span>
is the normal Sprout spending key, and
<span class="math">\(\mathsf{c}\)</span>
is the chain code.</p>
</section>
<section id="sprout-helper-functions"><h3><span class="section-heading">Sprout helper functions</span><span class="section-anchor"> <a href="#sprout-helper-functions"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Let EncodeASK(<em>a</em><sub>sk</sub>) be the 32-byte encoding of <em>a</em><sub>sk</sub> in the raw encoding of a Sprout spending key (excluding lead bytes) as specified in <a id="id18" class="footnote_reference" href="#sprout-spending-keys">15</a>.</p>
<p>Let DecodeASK(<em>ASK</em>) be the result of clearing the 4 most significant bits of the first byte of <em>ASK</em>, and decoding the 32-byte result according to the inverse of EncodeASK.</p>
<p>Let
<span class="math">\(\mathsf{EncodeASK}(\mathsf{a_{sk}})\)</span>
be the 32-byte encoding of
<span class="math">\(\mathsf{a_{sk}}\)</span>
in the raw encoding of a Sprout spending key (excluding lead bytes) as specified in <a id="id18" class="footnote_reference" href="#sprout-spending-keys">15</a>.</p>
<p>Let
<span class="math">\(\mathsf{DecodeASK}(ASK)\)</span>
be the result of clearing the 4 most significant bits of the first byte of
<span class="math">\(ASK\)</span>
, and decoding the 32-byte result according to the inverse of
<span class="math">\(\mathsf{EncodeASK}\)</span>
.</p>
</section>
<section id="sprout-master-key-generation"><h3><span class="section-heading">Sprout master key generation</span><span class="section-anchor"> <a href="#sprout-master-key-generation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Let <em>S</em> be a seed byte sequence of a chosen length, which MUST be at least 32 bytes.</p>
<p>Let
<span class="math">\(S\)</span>
be a seed byte sequence of a chosen length, which MUST be at least 32 bytes.</p>
<ul>
<li>Calculate <em>I</em> = BLAKE2b-512("ZcashIP32_Sprout", <em>S</em>).</li>
<li>Split <em>I</em> into two 32-byte sequences, I<sub>L</sub> and I<sub>R</sub>.</li>
<li>Use DecodeASK(<em>I</em><sub>L</sub>) as the master spending key a<sub>sk,m</sub>.</li>
<li>Use <em>I</em><sub>R</sub> as the master chain code <em>c</em><sub>m</sub>.</li>
<li>Calculate
<span class="math">\(I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{“ZcashIP32_Sprout”}, S)\)</span>
.</li>
<li>Split
<span class="math">\(I\)</span>
into two 32-byte sequences,
<span class="math">\(I_L\)</span>
and
<span class="math">\(I_R\)</span>
.</li>
<li>Use
<span class="math">\(\mathsf{DecodeASK}(I_L)\)</span>
as the master spending key
<span class="math">\(\mathsf{a}_{\mathsf{sk},m}\)</span>
.</li>
<li>Use
<span class="math">\(I_R\)</span>
as the master chain code
<span class="math">\(\mathsf{c}_m\)</span>
.</li>
</ul>
</section>
<section id="sprout-child-key-derivation"><h3><span class="section-heading">Sprout child key derivation</span><span class="section-anchor"> <a href="#sprout-child-key-derivation"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>CDKsk((<em>a</em><sub>sk,par</sub>, <em>c</em><sub>par</sub>), <em>i</em>) → (<em>a</em><sub>sk,i</sub>, <em>c</em><sub>i</sub>)</p>
<p>
<span class="math">\(\mathsf{CDKsk}((\mathsf{a}_{\mathsf{sk},par}, \mathsf{c}_{par}), i) \rightarrow (\mathsf{a}_{\mathsf{sk},i}, \mathsf{c}_i)\)</span>
</p>
<ul>
<li>Check whether <em>i</em> ≥ 2<sup>31</sup> (whether the child is a hardened key).
<li>Check whether
<span class="math">\(i \geq 2^{31}\)</span>
(whether the child is a hardened key).
<ul>
<li>If so (hardened child): let <em>I</em> = PRF<sup>expand</sup>(<em>c</em><sub>par</sub>, [0x80] || EncodeASK(<em>a</em><sub>sk,par</sub>) || I2LEOSP<sub>32</sub>(<em>i</em>))</li>
<li>If not (normal child): return failure</li>
<li>If so (hardened child): let
<span class="math">\(I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\texttt{0x80}]\,||\,\mathsf{EncodeASK}(\mathsf{a}_{\mathsf{sk},par})\,||\,\mathsf{I2LEOSP}_{32}(i))\)</span>
.</li>
<li>If not (normal child): return failure.</li>
</ul>
</li>
<li>Split <em>I</em> into two 32-byte sequences, <em>I</em><sub>L</sub> and <em>I</em><sub>R</sub>.</li>
<li>Use DecodeASK(<em>I</em><sub>L</sub>) as the child spending key a<sub>sk,i</sub>.</li>
<li>Use <em>I</em><sub>R</sub> as the child chain code <em>c</em><sub>i</sub>.</li>
<li>Split
<span class="math">\(I\)</span>
into two 32-byte sequences,
<span class="math">\(I_L\)</span>
and
<span class="math">\(I_R\)</span>
.</li>
<li>Use
<span class="math">\(\mathsf{DecodeASK}(I_L)\)</span>
as the child spending key
<span class="math">\(\mathsf{a}_{\mathsf{sk},i}\)</span>
.</li>
<li>Use
<span class="math">\(I_R\)</span>
as the child chain code
<span class="math">\(\mathsf{c}_i\)</span>
.</li>
</ul>
</section>
</section>
@ -202,48 +509,96 @@ License: MIT</pre>
<section id="key-path-levels"><h3><span class="section-heading">Key path levels</span><span class="section-anchor"> <a href="#key-path-levels"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Both Sprout and Sapling key paths have the following three path levels at the top, all of which use hardened derivation:</p>
<ul>
<li><code>purpose</code>: a constant set to 32' (or 0x80000020) following the BIP 43 recommendation. It indicates that the subtree of this node is used according to this specification.</li>
<li><code>coin_type</code>: a constant identifying the cybercoin that this subtree's keys are used with. For compatibility with existing BIP 44 implementations, we use the same constants as defined in SLIP 44 <a id="id20" class="footnote_reference" href="#slip-0044">6</a>. Note that in keeping with that document, all cybercoin testnets share <code>coin_type</code> index 1.</li>
<li><code>account</code>: numbered from index 0 in sequentially increasing manner. Defined as in BIP 44 <a id="id21" class="footnote_reference" href="#bip-0044">5</a>.</li>
<li>
<span class="math">\(purpose\)</span>
: a constant set to
<span class="math">\(32'\)</span>
(or
<span class="math">\(\texttt{0x80000020}\)</span>
) following the BIP 43 recommendation. It indicates that the subtree of this node is used according to this specification.</li>
<li>
<span class="math">\(coin\_type\)</span>
: a constant identifying the cybercoin that this subtree's keys are used with. For compatibility with existing BIP 44 implementations, we use the same constants as defined in SLIP 44 <a id="id20" class="footnote_reference" href="#slip-0044">6</a>. Note that in keeping with that document, all cybercoin testnets share
<span class="math">\(coin\_type\)</span>
index
<span class="math">\(1\)</span>
.</li>
<li>
<span class="math">\(account\)</span>
: numbered from index
<span class="math">\(0\)</span>
in sequentially increasing manner. Defined as in BIP 44 <a id="id21" class="footnote_reference" href="#bip-0044">5</a>.</li>
</ul>
<p>Unlike BIP 44, neither Sprout nor Sapling have a <cite>change</cite> path level. The use of change addresses in Bitcoin is a (failed) attempt to increase the difficulty of tracking users on the transaction graph, by segregating external and internal address usage. Shielded addresses are never publicly visible in transactions, which means that sending change back to the originating address is indistinguishable from using a change address.</p>
<p>Unlike BIP 44, neither Sprout nor Sapling have a
<span class="math">\(change\)</span>
path level. The use of change addresses in Bitcoin is a (failed) attempt to increase the difficulty of tracking users on the transaction graph, by segregating external and internal address usage. Shielded addresses are never publicly visible in transactions, which means that sending change back to the originating address is indistinguishable from using a change address.</p>
</section>
<section id="sapling-key-path"><h3><span class="section-heading">Sapling key path</span><span class="section-anchor"> <a href="#sapling-key-path"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Sapling provides a mechanism to allow the efficient creation of diversified payment addresses with the same spending authority. A group of such addresses shares the same full viewing key and incoming viewing key, and so creating as many unlinkable addresses as needed does not increase the cost of scanning the block chain for relevant transactions.</p>
<p>The above key path levels include an account identifier, which in all user interfaces is represented as a "bucket of funds" under the control of a single spending authority. Therefore, wallets implementing Sapling ZIP 32 derivation MUST support the following path for any account in range {0..2<sup>31</sup>-1}:</p>
<pre>m_Sapling / purpose' / coin_type' / account'</pre>
<p>The above key path levels include an account identifier, which in all user interfaces is represented as a "bucket of funds" under the control of a single spending authority. Therefore, wallets implementing Sapling ZIP 32 derivation MUST support the following path for any account in range
<span class="math">\(\{ 0\,.\!. 2^{31} - 1 \}\)</span>
:</p>
<ul>
<li>
<span class="math">\(m_\mathsf{Sapling} / purpose' / coin\_type' / account'\)</span>
.</li>
</ul>
<p>Furthermore, wallets MUST support generating the default payment address (corresponding to the default diversifier as defined above) for any account they support. They MAY also support generating a stream of payment addresses for a given account, if they wish to maintain the user experience of giving a unique address to each recipient.</p>
<p>Note that a given account can have a maximum of approximately 2<sup>87</sup> payment addresses, because each diversifier has around a 50% chance of being invalid.</p>
<p>If in certain circumstances a wallet needs to derive independent spend authorities within a single account, they MAY additionally support a non-hardened <code>address_index</code> path level as in <a id="id22" class="footnote_reference" href="#bip-0044">5</a>:</p>
<pre>m_Sapling / purpose' / coin_type' / account' / address_index</pre>
<p>Note that a given account can have a maximum of approximately
<span class="math">\(2^{87}\)</span>
payment addresses, because each diversifier has around a 50% chance of being invalid.</p>
<p>If in certain circumstances a wallet needs to derive independent spend authorities within a single account, they MAY additionally support a non-hardened
<span class="math">\(address\_index\)</span>
path level as in <a id="id22" class="footnote_reference" href="#bip-0044">5</a>:</p>
<ul>
<li>
<span class="math">\(m_\mathsf{Sapling} / purpose' / coin\_type' / account' / address\_index\)</span>
.</li>
</ul>
</section>
<section id="sprout-key-path"><h3><span class="section-heading">Sprout key path</span><span class="section-anchor"> <a href="#sprout-key-path"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Wallets implementing Sprout ZIP 32 derivation MUST support the following path:</p>
<pre>m_Sprout / purpose' / coin_type' / account' / address_index</pre>
<ul>
<li>
<span class="math">\(m_\mathsf{Sprout} / purpose' / coin\_type' / account' / address\_index\)</span>
.</li>
</ul>
</section>
</section>
<section id="specification-fingerprints-and-tags"><h2><span class="section-heading">Specification: Fingerprints and Tags</span><span class="section-anchor"> <a href="#specification-fingerprints-and-tags"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<section id="sapling-full-viewing-key-fingerprints-and-tags"><h3><span class="section-heading">Sapling Full Viewing Key Fingerprints and Tags</span><span class="section-anchor"> <a href="#sapling-full-viewing-key-fingerprints-and-tags"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>A "Sapling full viewing key fingerprint" of a full viewing key with raw encoding <em>FVK</em> (as specified in <a id="id23" class="footnote_reference" href="#sapling-full-viewing-keys">14</a>) is given by:</p>
<blockquote>
<p>BLAKE2b-256("ZcashSaplingFVFP", <em>FVK</em>)</p>
</blockquote>
<p>A "Sapling full viewing key fingerprint" of a full viewing key with raw encoding
<span class="math">\(FVK\)</span>
(as specified in <a id="id23" class="footnote_reference" href="#sapling-full-viewing-keys">14</a>) is given by:</p>
<ul>
<li>
<span class="math">\(\mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{“ZcashSaplingFVFP”}, FVK)\)</span>
.</li>
</ul>
<p>It MAY be used to uniquely identify a particular Sapling full viewing key.</p>
<p>A "Sapling full viewing key tag" is the first 4 bytes of the corresponding Sapling full viewing key fingerprint. It is intended for optimizing performance of key lookups, and MUST NOT be assumed to uniquely identify a particular key.</p>
</section>
<section id="sprout-address-fingerprints-and-tags"><h3><span class="section-heading">Sprout Address Fingerprints and Tags</span><span class="section-anchor"> <a href="#sprout-address-fingerprints-and-tags"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>A "Sprout address fingerprint" of a Sprout payment address with raw encoding <em>ADDR</em> (as specified in <a id="id24" class="footnote_reference" href="#sprout-shielded-addresses">13</a>, including the lead bytes) is given by:</p>
<blockquote>
<p>BLAKE2b-256("Zcash_Sprout_AFP", <em>ADDR</em>)</p>
</blockquote>
<p>A "Sprout address fingerprint" of a Sprout payment address with raw encoding
<span class="math">\(ADDR\)</span>
(as specified in <a id="id24" class="footnote_reference" href="#sprout-shielded-addresses">13</a>, including the lead bytes) is given by:</p>
<ul>
<li>
<span class="math">\(\mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{“Zcash_Sprout_AFP”}, ADDR)\)</span>
.</li>
</ul>
<p>It MAY be used to uniquely identify a particular Sprout payment address.</p>
<p>A "Sprout address tag" is the first 4 bytes of the corresponding Sprout address fingerprint. It is intended for optimizing performance of address lookups, and MUST NOT be assumed to uniquely identify a particular address.</p>
</section>
<section id="seed-fingerprints"><h3><span class="section-heading">Seed Fingerprints</span><span class="section-anchor"> <a href="#seed-fingerprints"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>A "seed fingerprint" for the master seed <em>S</em> of a hierarchical deterministic wallet is given by:</p>
<blockquote>
<p>BLAKE2b-256("Zcash_HD_Seed_FP", <em>S</em>)</p>
</blockquote>
<p>A "seed fingerprint" for the master seed
<span class="math">\(S\)</span>
of a hierarchical deterministic wallet is given by:</p>
<ul>
<li>
<span class="math">\(\mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{“Zcash_HD_Seed_FP”}, S)\)</span>
.</li>
</ul>
<p>It MAY be used to uniquely identify a particular hierarchical deterministic wallet.</p>
<p>No corresponding short tag is defined.</p>
</section>
@ -251,27 +606,87 @@ License: MIT</pre>
<section id="specification-key-encodings"><h2><span class="section-heading">Specification: Key Encodings</span><span class="section-anchor"> <a href="#specification-key-encodings"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>The following encodings are analogous to the <code>xprv</code> and <code>xpub</code> encodings defined in BIP 32 for transparent keys and addresses. Each key type has a raw representation and a Bech32 <a id="id25" class="footnote_reference" href="#bip-0173">7</a> encoding.</p>
<section id="sapling-extended-spending-keys"><h3><span class="section-heading">Sapling extended spending keys</span><span class="section-anchor"> <a href="#sapling-extended-spending-keys"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>A Sapling extended spending key (<em>ask</em>, <em>nsk</em>, <em>ovk</em>, <em>dk</em>, <em>c</em>), at depth <em>depth</em>, with parent full viewing key tag <em>parent_fvk_tag</em> and child number <em>i</em>, is represented as a byte sequence:</p>
<blockquote>
<p>I2LEOSP<sub>8</sub>(<em>depth</em>) || <em>parent_fvk_tag</em> || I2LEOSP<sub>32</sub>(<em>i</em>) || <em>c</em> || EncodeExtSKParts(<em>ask</em>, <em>nsk</em>, <em>ovk</em>, <em>dk</em>)</p>
</blockquote>
<p>For the master extended spending key, <em>depth</em> is 0, <em>parent_fvk_tag</em> is 4 zero bytes, and <em>i</em> is 0.</p>
<p>A Sapling extended spending key
<span class="math">\((\mathsf{ask, nsk, ovk, dk, c})\)</span>
, at depth
<span class="math">\(depth\)</span>
, with parent full viewing key tag
<span class="math">\(parent\_fvk\_tag\)</span>
and child number
<span class="math">\(i\)</span>
, is represented as a byte sequence:</p>
<ul>
<li>
<span class="math">\(\mathsf{I2LEOSP}_{8}(depth)\,||\,parent\_fvk\_tag\,||\,\mathsf{I2LEOSP}_{32}(i)\,||\,\mathsf{c}\,||\,\mathsf{EncodeExtSKParts}(\mathsf{ask, nsk, ovk, dk})\)</span>
.</li>
</ul>
<p>For the master extended spending key,
<span class="math">\(depth\)</span>
is
<span class="math">\(0\)</span>
,
<span class="math">\(parent\_fvk\_tag\)</span>
is 4 zero bytes, and
<span class="math">\(i\)</span>
is
<span class="math">\(0\)</span>
.</p>
<p>When encoded as Bech32, the Human-Readable Part is <code>secret-extended-key-main</code> for the production network, or <code>secret-extended-key-test</code> for the test network.</p>
</section>
<section id="sapling-extended-full-viewing-keys"><h3><span class="section-heading">Sapling extended full viewing keys</span><span class="section-anchor"> <a href="#sapling-extended-full-viewing-keys"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>A Sapling extended full viewing key (<em>ak</em>, <em>nk</em>, <em>ovk</em>, <em>dk</em>, <em>c</em>), at depth <em>depth</em>, with parent full viewing key tag <em>parent_fvk_tag</em> and child number <em>i</em>, is represented as a byte sequence:</p>
<blockquote>
<p>I2LEOSP<sub>8</sub>(<em>depth</em>) || <em>parent_fvk_tag</em> || I2LEOSP<sub>32</sub>(<em>i</em>) || <em>c</em> || EncodeExtFVKParts(<em>ak</em>, <em>nk</em>, <em>ovk</em>, <em>dk</em>)</p>
</blockquote>
<p>For the master extended full viewing key, <em>depth</em> is 0, <em>parent_fvk_tag</em> is 4 zero bytes, and <em>i</em> is 0.</p>
<p>A Sapling extended full viewing key
<span class="math">\((\mathsf{ak, nk, ovk, dk, c})\)</span>
, at depth
<span class="math">\(depth\)</span>
, with parent full viewing key tag
<span class="math">\(parent\_fvk\_tag\)</span>
and child number
<span class="math">\(i\)</span>
, is represented as a byte sequence:</p>
<ul>
<li>
<span class="math">\(\mathsf{I2LEOSP}_{8}(depth)\,||\,parent\_fvk\_tag\,||\,\mathsf{I2LEOSP}_{32}(i)\,||\,\mathsf{c}\,||\,\mathsf{EncodeExtFVKParts}(\mathsf{ak, nk, ovk, dk})\)</span>
.</li>
</ul>
<p>For the master extended full viewing key,
<span class="math">\(depth\)</span>
is
<span class="math">\(0\)</span>
,
<span class="math">\(parent\_fvk\_tag\)</span>
is 4 zero bytes, and
<span class="math">\(i\)</span>
is
<span class="math">\(0\)</span>
.</p>
<p>When encoded as Bech32, the Human-Readable Part is <code>zxviews</code> for the production network, or <code>zxviewtestsapling</code> for the test network.</p>
</section>
<section id="sprout-extended-spending-keys"><h3><span class="section-heading">Sprout extended spending keys</span><span class="section-anchor"> <a href="#sprout-extended-spending-keys"><img width="24" height="24" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>A Sprout extended spending key (<em>a</em><sub>sk</sub>, <em>c</em>), at depth <em>depth</em>, with parent address tag <em>parent_addr_tag</em> and child number <em>i</em>, is represented as a byte sequence:</p>
<blockquote>
<p>I2LEOSP<sub>8</sub>(<em>depth</em>) || <em>parent_addr_tag</em> || I2LEOSP<sub>32</sub>(<em>i</em>) || <em>c</em> || EncodeASK(<em>a</em><sub>sk</sub>)</p>
</blockquote>
<p>For the master extended spending key, <em>depth</em> is 0, <em>parent_addr_tag</em> is 4 zero bytes, and <em>i</em> is 0.</p>
<p>A Sprout extended spending key
<span class="math">\((\mathsf{a_{sk}, c})\)</span>
, at depth
<span class="math">\(depth\)</span>
, with parent address tag
<span class="math">\(parent\_addr\_tag\)</span>
and child number
<span class="math">\(i\)</span>
, is represented as a byte sequence:</p>
<ul>
<li>
<span class="math">\(\mathsf{I2LEOSP}_{8}(depth)\,||\,parent\_addr\_tag\,||\,\mathsf{I2LEOSP}_{32}(i)\,||\,\mathsf{c}\,||\,\mathsf{EncodeASK}(\mathsf{a_{sk}})\)</span>
.</li>
</ul>
<p>For the master extended spending key,
<span class="math">\(depth\)</span>
is
<span class="math">\(0\)</span>
,
<span class="math">\(parent\_addr\_tag\)</span>
is 4 zero bytes, and
<span class="math">\(i\)</span>
is
<span class="math">\(0\)</span>
.</p>
<p>When encoded as Bech32, the Human-Readable Part is <code>zxsprout</code> for the production network, or <code>zxtestsprout</code> for the test network. Sprout extended spending keys are encoded using Bech32 even though other Sprout keys and addresses are encoded using Base58Check.</p>
</section>
</section>

View File

@ -12,6 +12,7 @@
Created: 2018-05-22
License: MIT
:math:`% This ZIP makes heavy use of mathematical markup. If you can see this, you may want to instead view the rendered version at <https://zips.z.cash/zip-0032>.`
Terminology
===========
@ -65,58 +66,61 @@ Conventions
Most of the notation and functions used in this ZIP are defined in the Sapling protocol specification
[#sapling-spec]_. They are reproduced here for convenience:
- truncate\ :sub:`k`\ (*S*) means the sequence formed from the first *k* elements of *S*.
- :math:`\mathsf{truncate}_k(S)` means the sequence formed from the first :math:`k` elements of :math:`S`.
- *a* || *b* means the concatenation of sequences *a* then *b*.
- :math:`a\,||\,b` means the concatenation of sequences :math:`a` then :math:`b`.
- [*k*] *P* means scalar multiplication of the elliptic curve point *P* by the scalar *k*.
- :math:`[k] P` means scalar multiplication of the elliptic curve point :math:`P` by the scalar :math:`k`.
- LEOS2IP\ :sub:`l`\ (*S*) is the integer in range {0..2\ :sup:`l`\ -1} represented in little-endian order
by the byte sequence *S* of length *l*/8.
- :math:`\mathsf{LEOS2IP}_\ell(S)` is the integer in range :math:`\{ 0\,.\!. 2^\ell - 1 \}` represented in
little-endian order by the byte sequence :math:`S` of length :math:`\ell/8`.
- I2LEBSP\ :sub:`l`\ (*k*) is the sequence of *l* bits representing *k* in little-endian order.
- :math:`\mathsf{I2LEBSP}_\ell(k)` is the sequence of :math:`\ell` bits representing :math:`k` in
little-endian order.
- LEBS2OSP\ :sub:`l`\ (*B*) is defined as follows when *l* is a multiple of 8: convert each group of 8 bits
in *B* to a byte value with the least significant bit first, and concatenate the resulting bytes in the
same order as the groups.
- :math:`\mathsf{LEBS2OSP}_\ell(B)` is defined as follows when :math:`\ell` is a multiple of :math:`8`:
convert each group of 8 bits in :math:`B` to a byte value with the least significant bit first, and
concatenate the resulting bytes in the same order as the groups.
- repr\ :sub:`𝕁`\ (*P*) is the representation of the Jubjub elliptic curve point *P* as a bit sequence,
defined in [#sapling-jubjub]_.
- :math:`\mathsf{repr}_\mathbb{J}(P)` is the representation of the Jubjub elliptic curve point :math:`P`
as a bit sequence, defined in [#sapling-jubjub]_.
- BLAKE2b-256(*p*, *x*) refers to unkeyed BLAKE2b-256 in sequential mode, with an output digest length of
32 bytes, 16-byte personalization string *p*, and input *x*.
- :math:`\mathsf{BLAKE2b}\text{-}\mathsf{256}(p, x)` refers to unkeyed BLAKE2b-256 in sequential mode,
with an output digest length of 32 bytes, 16-byte personalization string :math:`p`, and input :math:`x`.
- BLAKE2b-512(*p*, *x*) refers to unkeyed BLAKE2b-512 in sequential mode, with an output digest length of
64 bytes, 16-byte personalization string *p*, and input *x*.
- :math:`\mathsf{BLAKE2b}\text{-}\mathsf{512}(p, x)` refers to unkeyed BLAKE2b-512 in sequential mode,
with an output digest length of 64 bytes, 16-byte personalization string :math:`p`, and input :math:`x`.
- PRF\ :sup:`expand`\ (*sk*, *t*) := BLAKE2b-512("Zcash_ExpandSeed", *sk* || *t*)
- :math:`\mathsf{PRF^{expand}}(\mathsf{sk}, t) := \mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{“Zcash_ExpandSeed”}, \mathsf{sk}\,||\,t)`
- *r*\ :sub:`𝕁` \ is the order of the Jubjub large prime subgroup.
- :math:`r_\mathbb{J}` is the order of the Jubjub large prime subgroup.
- ToScalar(*x*) := LEOS2IP\ :sub:`512`\ (*x*) (mod *r*\ :sub:`𝕁`\ ).
- :math:`\mathsf{ToScalar}(x) := \mathsf{LEOS2IP}_{512}(x) \pmod{r_\mathbb{J}}`.
- DiversifyHash(*d*) maps a diversifier *d* to a base point on the Jubjub elliptic curve, or to ⊥ if the
diversifier is invalid. It is instantiated in [#sapling-diversifyhash]_.
- :math:`\mathsf{DiversifyHash}(d)` maps a diversifier :math:`d` to a base point on the Jubjub elliptic
curve, or to :math:`\bot` if the diversifier is invalid. It is instantiated in [#sapling-diversifyhash]_.
The following algorithm standardized in [#NIST-SP-800-38G]_ is used:
- FF1-AES256.Encrypt(*key*, *tweak*, *x*) refers to the FF1 encryption algorithm using AES with a
256-bit *key*, and parameters *radix* = 2, *minlen* = 88, *maxlen* = 88. It will be used only with
the empty string "" as the *tweak*. *x* is a sequence of 88 bits, as is the output.
- :math:`\mathsf{FF1}\text{-}\mathsf{AES256.Encrypt}(key, tweak, x)` refers to the FF1 encryption algorithm
using AES with a 256-bit :math:`key`, and parameters :math:`radix = 2, minlen = 88, maxlen = 88`.
It will be used only with the empty string :math:`\texttt{“”}` as the :math:`tweak`. :math:`x` is a
sequence of 88 bits, as is the output.
We also define the following conversion function:
- I2LEOSP\ :sub:`l`\ (*k*) is the byte sequence *S* of length *l*/8 representing in little-endian order the
integer *k* in range {0..2\ :sup:`l`\ -1}. It is the reverse operation of LEOS2IP\ :sub:`l`\ (*S*).
- :math:`\mathsf{I2LEOSP}_\ell(k)` is the byte sequence :math:`S` of length :math:`\ell/8` representing in
little-endian order the integer :math:`k` in range :math:`\{ 0\,.\!. 2^\ell - 1 \}`. It is the reverse
operation of :math:`\mathsf{LEOS2IP}_\ell(S)`.
Implementors should note that this ZIP is consistently little-endian (in keeping with the Sapling
specification), which is the opposite of BIP 32.
We adapt the path notation of BIP 32 [#bip-0032]_ to describe shielded HD paths, using apostrophes to
indicate hardened derivation (i' = i + 2\ :sup:`31`\ ) as in BIP 44 [#bip-0044]_:
We adapt the path notation of BIP 32 [#bip-0032]_ to describe shielded HD paths, using prime marks (:math:`'`) to
indicate hardened derivation (:math:`i' = i + 2^{31}`) as in BIP 44 [#bip-0044]_:
- CDKsk(CDKsk(CDKsk(m\ :sub:`Sprout`\ , a'), b), c) is written as m\ :sub:`Sprout` / a' / b / c
- CDKfvk(CDKfvk(CDKfvk(M\ :sub:`Sapling`\ , a), b), c) is written as M\ :sub:`Sapling` / a / b / c
- :math:`\mathsf{CDKsk}(\mathsf{CDKsk}(\mathsf{CDKsk}(m_\mathsf{Sprout}, a'), b), c)` is written as :math:`m_\mathsf{Sprout} / a' / b / c`
- :math:`\mathsf{CDKfvk}(\mathsf{CDKfvk}(\mathsf{CDKfvk}(m_\mathsf{Sapling}, a), b), c)` is written as :math:`m_\mathsf{Sapling} / a / b / c`.
Specification: Sapling key derivation
@ -139,110 +143,118 @@ keys in BIP 32 do not map cleanly to Sapling's key components. We take the follo
the trust semantics of BIP 32: someone with access to a BIP 32 extended public key is able to view all
transactions involving that address, which a Sapling full viewing key also enables.
We represent a Sapling extended spending key as (*ask*, *nsk*, *ovk*, *dk*, *c*), where (*ask*, *nsk*, *ovk*)
is the normal Sapling expanded spending key, *dk* is a diversifier key, and *c* is the chain code.
We represent a Sapling extended spending key as :math:`(\mathsf{ask, nsk, ovk, dk, c})`, where
:math:`(\mathsf{ask, nsk, ovk})` is the normal Sapling expanded spending key, :math:`\mathsf{dk}` is a
diversifier key, and :math:`\mathsf{c}` is the chain code.
We represent a Sapling extended full viewing key as (*ak*, *nk*, *ovk*, *dk*, *c*), where (*ak*, *nk*, *ovk*)
is the normal Sapling full viewing key, *dk* is the same diversifier key as above, and *c* is the chain code.
We represent a Sapling extended full viewing key as :math:`(\mathsf{ak, nk, ovk, dk, c})`, where
:math:`(\mathsf{ak, nk, ovk})` is the normal Sapling full viewing key, :math:`\mathsf{dk}` is the same
diversifier key as above, and :math:`\mathsf{c}` is the chain code.
Sapling helper functions
------------------------
Define EncodeExtSKParts(*ask*, *nsk*, *ovk*, *dk*) := I2LEOSP\ :sub:`256`\ (*ask*) || I2LEOSP\ :sub:`256`\ (*nsk*) || *ovk* || *dk*.
Define
Define EncodeExtFVKParts(*ak*, *nk*, *ovk*, *dk*) := LEBS2OSP\ :sub:`256`\ (repr\ :sub:`𝕁`\ (*ak*)) || LEBS2OSP\ :sub:`256`\ (repr\ :sub:`𝕁`\ (*nk*)) || *ovk* || *dk*.
* :math:`\mathsf{EncodeExtSKParts}(\mathsf{ask, nsk, ovk, dk}) := \mathsf{I2LEOSP}_{256}(\mathsf{ask})\,||\,\mathsf{I2LEOSP}_{256}(\mathsf{nsk})\,||\,\mathsf{ovk}\,||\,\mathsf{dk}`
* :math:`\mathsf{EncodeExtFVKParts}(\mathsf{ak, nk, ovk, dk}) := \mathsf{LEBS2OS}_{256}(\mathsf{repr}_\mathbb{J}(\mathsf{ak}))\,||\,\mathsf{LEBS2OSP}_{256}(\mathsf{repr}_\mathbb{J}(\mathsf{nk}))\,||\,\mathsf{ovk}\,||\,\mathsf{dk}`
Sapling master key generation
-----------------------------
Let *S* be a seed byte sequence of a chosen length, which MUST be at least 32 bytes.
Let :math:`S` be a seed byte sequence of a chosen length, which MUST be at least 32 bytes.
- Calculate *I* = BLAKE2b-512("ZcashIP32Sapling", *S*).
- Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ .
- Use *I*\ :sub:`L` as the master spending key *sk*\ :sub:`m`\ , and *I*\ :sub:`R` as the master chain code
*c*\ :sub:`m`\ .
- Calculate *ask*\ :sub:`m`\ , *nsk*\ :sub:`m`\ , and *ovk*\ :sub:`m` via the standard Sapling derivation
[#sapling-key-components]_:
- Calculate :math:`I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{“ZcashIP32Sapling”}, S)`.
- Split :math:`I` into two 32-byte sequences, :math:`I_L` and :math:`I_R`.
- Use :math:`I_L` as the master spending key :math:`\mathsf{sk}_m`, and :math:`I_R` as the master chain code
:math:`\mathsf{c}_m`.
- Calculate :math:`\mathsf{ask}_m`, :math:`\mathsf{nsk}_m`, and :math:`\mathsf{ovk}_m` via the standard
Sapling derivation [#sapling-key-components]_:
- *ask*\ :sub:`m` = ToScalar(PRF\ :sup:`expand`\ (*sk*\ :sub:`m`\ , [0x00]))
- *nsk*\ :sub:`m` = ToScalar(PRF\ :sup:`expand`\ (*sk*\ :sub:`m`\ , [0x01]))
- *ovk*\ :sub:`m` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*sk*\ :sub:`m`\ , [0x02]))
- :math:`\mathsf{ask}_m = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x00}]))`
- :math:`\mathsf{nsk}_m = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x01}]))`
- :math:`\mathsf{ovk}_m = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x02}]))`.
- Calculate *dk*\ :sub:`m` similarly:
- Calculate :math:`\mathsf{dk}_m` similarly:
- *dk*\ :sub:`m` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*sk*\ :sub:`m`\ , [0x10]))
- :math:`\mathsf{dk}_m = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x10}]))`.
- Return (*ask*\ :sub:`m`\ , *nsk*\ :sub:`m`\ , *ovk*\ :sub:`m`\ , *dk*\ :sub:`m`\ , *c*\ :sub:`m`\ ) as the
master extended spending key *m*\ :sub:`Sapling`\ .
- Return :math:`(\mathsf{ask}_m, \mathsf{nsk}_m, \mathsf{ovk}_m, \mathsf{dk}_m, \mathsf{c}_m)` as the
master extended spending key :math:`m_\mathsf{Sapling}`.
Sapling child key derivation
----------------------------
As in BIP 32, the method for deriving a child extended key, given a parent extended key and an index *i*,
As in BIP 32, the method for deriving a child extended key, given a parent extended key and an index :math:`i`,
depends on the type of key being derived, and whether this is a hardened or non-hardened derivation.
Deriving a child extended spending key
``````````````````````````````````````
CDKsk((*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ , *c*\ :sub:`par`\ ), *i*) →
(*ask*\ :sub:`i`\ , *nsk*\ :sub:`i`\ , *ovk*\ :sub:`i`\ , *dk*\ :sub:`i`\ , *c*\ :sub:`i`\ )
- Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key).
:math:`\mathsf{CDKsk}((\mathsf{ask}_{par}, \mathsf{nsk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par}, \mathsf{c}_{par}), i) \rightarrow (\mathsf{ask}_i, \mathsf{nsk}_i, \mathsf{ovk}_i, \mathsf{dk}_i, \mathsf{c}_i)`
- If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x11] || EncodeExtSKParts(*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*))
- If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || EncodeExtFVKParts(*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*))
where (*nk*\ :sub:`par`\ , *ak*\ :sub:`par`\ , *ovk*\ :sub:`par`\ ) is the full viewing key derived from
(*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ ) as described in [#sapling-key-components]_.
- Check whether :math:`i \geq 2^{31}` (whether the child is a hardened key).
- Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ .
- Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x13]))
- Let *I*\ :sub:`nsk` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x14]))
- If so (hardened child):
let :math:`I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\texttt{0x11}]\,||\,\mathsf{EncodeExtSKParts}(\mathsf{ask}_{par}, \mathsf{nsk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par})\,||\,\mathsf{I2LEOSP}_{32}(i))`.
- If not (normal child):
let :math:`I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\texttt{0x12}]\,||\,\mathsf{EncodeExtFVKParts}(\mathsf{ak}_{par}, \mathsf{nk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par})\,||\,\mathsf{I2LEOSP}_{32}(i))`
where :math:`(\mathsf{nk}_{par}, \mathsf{ak}_{par}, \mathsf{ovk}_{par})` is the full viewing key derived from
:math:`(\mathsf{ask}_{par}, \mathsf{nsk}_{par}, \mathsf{ovk}_{par})` as described in [#sapling-key-components]_.
- Split :math:`I` into two 32-byte sequences, :math:`I_L` and :math:`I_R`.
- Let :math:`I_\mathsf{ask} = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x13}]))`.
- Let :math:`I_\mathsf{nsk} = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x14}]))`.
- Return:
- *ask*\ :sub:`i` = (*I*\ :sub:`ask` + *ask*\ :sub:`par`) (mod *r*\ :sub:`𝕁`\ )
- *nsk*\ :sub:`i` = (*I*\ :sub:`nsk` + *nsk*\ :sub:`par`) (mod *r*\ :sub:`𝕁`\ )
- *ovk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x15] || *ovk*\ :sub:`par`\ ))
- *dk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x16] || *dk*\ :sub:`par`\ ))
- *c*\ :sub:`i` = *I*\ :sub:`R`
- :math:`\mathsf{ask}_i = (I_\mathsf{ask} + \mathsf{ask}_{par}) \pmod{r_\mathbb{J}}`
- :math:`\mathsf{nsk}_i = (I_\mathsf{nsk} + \mathsf{nsk}_{par}) \pmod{r_\mathbb{J}}`
- :math:`\mathsf{ovk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x15}]\,||\,\mathsf{ovk}_{par}))`
- :math:`\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x16}]\,||\,\mathsf{dk}_{par}))`
- :math:`\mathsf{c}_i = I_R`.
Deriving a child extended full viewing key
``````````````````````````````````````````
Let 𝓖 be as defined in [#sapling-spendauthsig]_ and let 𝓗 be as defined in [#sapling-key-components]_.
CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ , *c*\ :sub:`par`\ ), *i*) →
(*ak*\ :sub:`i`\ , *nk*\ :sub:`i`\ , *ovk*\ :sub:`i`\ , *dk*\ :sub:`i`\ , *c*\ :sub:`i`\ )
Let :math:`\mathcal{G}` be as defined in [#sapling-spendauthsig]_ and let :math:`\mathcal{H}` be as defined
in [#sapling-key-components]_.
- Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key).
:math:`\mathsf{CDKfvk}((\mathsf{ak}_{par}, \mathsf{nk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par}, \mathsf{c}_{par}), i) \rightarrow (\mathsf{ak}_{i}, \mathsf{nk}_{i}, \mathsf{ovk}_{i}, \mathsf{dk}_{i}, \mathsf{c}_{i})`
- If so (hardened child): return failure
- If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || EncodeExtFVKParts(*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*))
- Check whether :math:`i \geq 2^{31}` (whether the child is a hardened key).
- Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ .
- Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x13]))
- Let *I*\ :sub:`nsk` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x14]))
- If so (hardened child): return failure.
- If not (normal child): let
:math:`I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\texttt{0x12}]\,||\,\mathsf{EncodeExtFVKParts}(\mathsf{ak}_{par}, \mathsf{nk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par})\,||\,\mathsf{I2LEOSP}_{32}(i))`.
- Split :math:`I` into two 32-byte sequences, :math:`I_L` and :math:`I_R`.
- Let :math:`I_\mathsf{ask} = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x13}]))`.
- Let :math:`I_\mathsf{nsk} = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x14}]))`.
- Return:
- *ak*\ :sub:`i` = [*I*\ :sub:`ask`\ ] 𝓖 + *ak*\ :sub:`par`
- *nk*\ :sub:`i` = [*I*\ :sub:`nsk`\ ] 𝓗 + *nk*\ :sub:`par`
- *ovk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x15] || *ovk*\ :sub:`par`\ ))
- *dk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x16] || *dk*\ :sub:`par`\ ))
- *c*\ :sub:`i` = *I*\ :sub:`R`
- :math:`\mathsf{ak}_i = [I_\mathsf{ask}]\,\mathcal{G} + \mathsf{ak}_{par}`
- :math:`\mathsf{nk}_i = [I_\mathsf{nsk}]\,\mathcal{H} + \mathsf{nk}_{par}`
- :math:`\mathsf{ovk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x15}]\,||\,\mathsf{ovk}_{par}))`
- :math:`\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x16}]\,||\,\mathsf{dk}_{par}))`
- :math:`\mathsf{c}_i = I_R`.
Diversifier derivation
----------------------
The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key *dk*. To prevent the
diversifier leaking how many diversified addresses have already been generated for an account, we make the
The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key :math:`dk`. To prevent
the diversifier leaking how many diversified addresses have already been generated for an account, we make the
sequence of diversifiers pseudorandom and uncorrelated to that of any other account. In order to reach the
maximum possible diversifier range without running into repetitions due to the birthday bound, we use
FF1-AES256 as a Pseudo-Random Permutation as follows:
- Let *j* be the index of the desired diversifier, in the range 0 .. 2\ :sup:`88`\ -1.
- *d*\ :sub:`j` = FF1-AES256.Encrypt(*dk*, "", I2LEBSP\ :sub:`88`\ (*j*)).
- Let :math:`j` be the index of the desired diversifier, in the range :math:`0\,.\!. 2^{88} - 1`.
- :math:`d_j = \mathsf{FF1}\text{-}\mathsf{AES256.Encrypt}(\mathsf{dk}, \texttt{“”}, \mathsf{I2LEBSP}_{88}(j))`.
A valid diversifier *d*\ :sub:`j` is one for which DiversifyHash(*d*\ :sub:`j`) ≠ ⊥.
For a given *dk*, approximately half of the possible values of *j* yield valid diversifiers.
A valid diversifier :math:`d_j` is one for which :math:`\mathsf{DiversifyHash}(d_j) \neq \bot`.
For a given :math:`\mathsf{dk}`, approximately half of the possible values of :math:`j` yield valid
diversifiers.
The default diversifier for a Sapling extended key is defined to be *d*\ :sub:`j`\ , where *j* is the
The default diversifier for a Sapling extended key is defined to be :math:`d_j`, where :math:`j` is the
least nonnegative integer yielding a valid diversifier.
@ -259,41 +271,42 @@ Due to the way Sprout keys are constructed and used, it is not possible to deriv
payment addresses in parallel with spending keys. Nor is it possible to implement non-hardened derivation.
We therefore only define and derive Sprout extended spending keys.
We represent a Sprout extended spending key as (*a*\ :sub:`sk`\ , *c*), where *a*\ :sub:`sk` is the normal
Sprout spending key, and *c* is the chain code.
We represent a Sprout extended spending key as :math:`(\mathsf{a_{sk}, c})`, where :math:`\mathsf{a_{sk}}`
is the normal Sprout spending key, and :math:`\mathsf{c}` is the chain code.
Sprout helper functions
-----------------------
Let EncodeASK(*a*\ :sub:`sk`) be the 32-byte encoding of *a*\ :sub:`sk` in the raw encoding of a Sprout
spending key (excluding lead bytes) as specified in [#sprout-spending-keys]_.
Let :math:`\mathsf{EncodeASK}(\mathsf{a_{sk}})` be the 32-byte encoding of :math:`\mathsf{a_{sk}}` in the
raw encoding of a Sprout spending key (excluding lead bytes) as specified in [#sprout-spending-keys]_.
Let DecodeASK(*ASK*) be the result of clearing the 4 most significant bits of the first byte of *ASK*,
and decoding the 32-byte result according to the inverse of EncodeASK.
Let :math:`\mathsf{DecodeASK}(ASK)` be the result of clearing the 4 most significant bits of the first byte
of :math:`ASK`, and decoding the 32-byte result according to the inverse of :math:`\mathsf{EncodeASK}`.
Sprout master key generation
----------------------------
Let *S* be a seed byte sequence of a chosen length, which MUST be at least 32 bytes.
Let :math:`S` be a seed byte sequence of a chosen length, which MUST be at least 32 bytes.
- Calculate *I* = BLAKE2b-512("ZcashIP32_Sprout", *S*).
- Split *I* into two 32-byte sequences, I\ :sub:`L` and I\ :sub:`R`\ .
- Use DecodeASK(*I*\ :sub:`L`\ ) as the master spending key a\ :sub:`sk,m`\ .
- Use *I*\ :sub:`R` as the master chain code *c*\ :sub:`m`\ .
- Calculate :math:`I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{“ZcashIP32_Sprout”}, S)`.
- Split :math:`I` into two 32-byte sequences, :math:`I_L` and :math:`I_R`.
- Use :math:`\mathsf{DecodeASK}(I_L)` as the master spending key :math:`\mathsf{a}_{\mathsf{sk},m}`.
- Use :math:`I_R` as the master chain code :math:`\mathsf{c}_m`.
Sprout child key derivation
---------------------------
CDKsk((*a*\ :sub:`sk,par`\ , *c*\ :sub:`par`\ ), *i*) → (*a*\ :sub:`sk,i`\ , *c*\ :sub:`i`\ )
:math:`\mathsf{CDKsk}((\mathsf{a}_{\mathsf{sk},par}, \mathsf{c}_{par}), i) \rightarrow (\mathsf{a}_{\mathsf{sk},i}, \mathsf{c}_i)`
- Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key).
- Check whether :math:`i \geq 2^{31}` (whether the child is a hardened key).
- If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x80] || EncodeASK(*a*\ :sub:`sk,par`\ ) || I2LEOSP\ :sub:`32`\ (*i*))
- If not (normal child): return failure
- If so (hardened child): let
:math:`I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\texttt{0x80}]\,||\,\mathsf{EncodeASK}(\mathsf{a}_{\mathsf{sk},par})\,||\,\mathsf{I2LEOSP}_{32}(i))`.
- If not (normal child): return failure.
- Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ .
- Use DecodeASK(*I*\ :sub:`L`\ ) as the child spending key a\ :sub:`sk,i`\ .
- Use *I*\ :sub:`R` as the child chain code *c*\ :sub:`i`\ .
- Split :math:`I` into two 32-byte sequences, :math:`I_L` and :math:`I_R`.
- Use :math:`\mathsf{DecodeASK}(I_L)` as the child spending key :math:`\mathsf{a}_{\mathsf{sk},i}`.
- Use :math:`I_R` as the child chain code :math:`\mathsf{c}_i`.
Specification: Wallet usage
@ -309,19 +322,22 @@ Key path levels
Both Sprout and Sapling key paths have the following three path levels at the top, all of which use hardened
derivation:
- ``purpose``: a constant set to 32' (or 0x80000020) following the BIP 43 recommendation. It indicates that
the subtree of this node is used according to this specification.
- :math:`purpose`: a constant set to :math:`32'` (or :math:`\texttt{0x80000020}`) following the BIP 43
recommendation. It indicates that the subtree of this node is used according to this specification.
- ``coin_type``: a constant identifying the cybercoin that this subtree's keys are used with. For
- :math:`coin\_type`: a constant identifying the cybercoin that this subtree's keys are used with. For
compatibility with existing BIP 44 implementations, we use the same constants as defined in SLIP 44
[#slip-0044]_. Note that in keeping with that document, all cybercoin testnets share ``coin_type`` index 1.
[#slip-0044]_. Note that in keeping with that document, all cybercoin testnets share :math:`coin\_type`
index :math:`1`.
- ``account``: numbered from index 0 in sequentially increasing manner. Defined as in BIP 44 [#bip-0044]_.
- :math:`account`: numbered from index :math:`0` in sequentially increasing manner. Defined as in
BIP 44 [#bip-0044]_.
Unlike BIP 44, neither Sprout nor Sapling have a `change` path level. The use of change addresses in Bitcoin
is a (failed) attempt to increase the difficulty of tracking users on the transaction graph, by segregating
external and internal address usage. Shielded addresses are never publicly visible in transactions, which
means that sending change back to the originating address is indistinguishable from using a change address.
Unlike BIP 44, neither Sprout nor Sapling have a :math:`change` path level. The use of change addresses in
Bitcoin is a (failed) attempt to increase the difficulty of tracking users on the transaction graph, by
segregating external and internal address usage. Shielded addresses are never publicly visible in
transactions, which means that sending change back to the originating address is indistinguishable from
using a change address.
Sapling key path
----------------
@ -333,29 +349,29 @@ relevant transactions.
The above key path levels include an account identifier, which in all user interfaces is represented as a
"bucket of funds" under the control of a single spending authority. Therefore, wallets implementing Sapling
ZIP 32 derivation MUST support the following path for any account in range {0..2\ :sup:`31`\ -1}::
ZIP 32 derivation MUST support the following path for any account in range :math:`\{ 0\,.\!. 2^{31} - 1 \}`:
m_Sapling / purpose' / coin_type' / account'
* :math:`m_\mathsf{Sapling} / purpose' / coin\_type' / account'`.
Furthermore, wallets MUST support generating the default payment address (corresponding to the default
diversifier as defined above) for any account they support. They MAY also support generating a stream of
payment addresses for a given account, if they wish to maintain the user experience of giving a unique
address to each recipient.
Note that a given account can have a maximum of approximately 2\ :sup:`87` payment addresses, because each
Note that a given account can have a maximum of approximately :math:`2^{87}` payment addresses, because each
diversifier has around a 50% chance of being invalid.
If in certain circumstances a wallet needs to derive independent spend authorities within a single account,
they MAY additionally support a non-hardened ``address_index`` path level as in [#bip-0044]_::
they MAY additionally support a non-hardened :math:`address\_index` path level as in [#bip-0044]_:
m_Sapling / purpose' / coin_type' / account' / address_index
* :math:`m_\mathsf{Sapling} / purpose' / coin\_type' / account' / address\_index`.
Sprout key path
---------------
Wallets implementing Sprout ZIP 32 derivation MUST support the following path::
Wallets implementing Sprout ZIP 32 derivation MUST support the following path:
m_Sprout / purpose' / coin_type' / account' / address_index
* :math:`m_\mathsf{Sprout} / purpose' / coin\_type' / account' / address\_index`.
Specification: Fingerprints and Tags
@ -364,10 +380,10 @@ Specification: Fingerprints and Tags
Sapling Full Viewing Key Fingerprints and Tags
----------------------------------------------
A "Sapling full viewing key fingerprint" of a full viewing key with raw encoding *FVK* (as specified
A "Sapling full viewing key fingerprint" of a full viewing key with raw encoding :math:`FVK` (as specified
in [#sapling-full-viewing-keys]_) is given by:
BLAKE2b-256("ZcashSaplingFVFP", *FVK*)
* :math:`\mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{“ZcashSaplingFVFP”}, FVK)`.
It MAY be used to uniquely identify a particular Sapling full viewing key.
@ -378,10 +394,10 @@ uniquely identify a particular key.
Sprout Address Fingerprints and Tags
------------------------------------
A "Sprout address fingerprint" of a Sprout payment address with raw encoding *ADDR* (as specified in
A "Sprout address fingerprint" of a Sprout payment address with raw encoding :math:`ADDR` (as specified in
[#sprout-shielded-addresses]_, including the lead bytes) is given by:
BLAKE2b-256("Zcash_Sprout_AFP", *ADDR*)
* :math:`\mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{“Zcash_Sprout_AFP”}, ADDR)`.
It MAY be used to uniquely identify a particular Sprout payment address.
@ -392,9 +408,9 @@ a particular address.
Seed Fingerprints
-----------------
A "seed fingerprint" for the master seed *S* of a hierarchical deterministic wallet is given by:
A "seed fingerprint" for the master seed :math:`S` of a hierarchical deterministic wallet is given by:
BLAKE2b-256("Zcash_HD_Seed_FP", *S*)
* :math:`\mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{“Zcash_HD_Seed_FP”}, S)`.
It MAY be used to uniquely identify a particular hierarchical deterministic wallet.
@ -412,14 +428,14 @@ and a Bech32 [#bip-0173]_ encoding.
Sapling extended spending keys
------------------------------
A Sapling extended spending key (*ask*, *nsk*, *ovk*, *dk*, *c*), at depth *depth*,
with parent full viewing key tag *parent_fvk_tag* and child number *i*, is
A Sapling extended spending key :math:`(\mathsf{ask, nsk, ovk, dk, c})`, at depth :math:`depth`,
with parent full viewing key tag :math:`parent\_fvk\_tag` and child number :math:`i`, is
represented as a byte sequence:
I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || EncodeExtSKParts(*ask*, *nsk*, *ovk*, *dk*)
* :math:`\mathsf{I2LEOSP}_{8}(depth)\,||\,parent\_fvk\_tag\,||\,\mathsf{I2LEOSP}_{32}(i)\,||\,\mathsf{c}\,||\,\mathsf{EncodeExtSKParts}(\mathsf{ask, nsk, ovk, dk})`.
For the master extended spending key, *depth* is 0, *parent_fvk_tag* is 4 zero bytes,
and *i* is 0.
For the master extended spending key, :math:`depth` is :math:`0`, :math:`parent\_fvk\_tag` is
4 zero bytes, and :math:`i` is :math:`0`.
When encoded as Bech32, the Human-Readable Part is ``secret-extended-key-main``
for the production network, or ``secret-extended-key-test`` for the test network.
@ -427,14 +443,14 @@ for the production network, or ``secret-extended-key-test`` for the test network
Sapling extended full viewing keys
----------------------------------
A Sapling extended full viewing key (*ak*, *nk*, *ovk*, *dk*, *c*), at depth *depth*,
with parent full viewing key tag *parent_fvk_tag* and child number *i*, is
A Sapling extended full viewing key :math:`(\mathsf{ak, nk, ovk, dk, c})`, at depth :math:`depth`,
with parent full viewing key tag :math:`parent\_fvk\_tag` and child number :math:`i`, is
represented as a byte sequence:
I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || EncodeExtFVKParts(*ak*, *nk*, *ovk*, *dk*)
* :math:`\mathsf{I2LEOSP}_{8}(depth)\,||\,parent\_fvk\_tag\,||\,\mathsf{I2LEOSP}_{32}(i)\,||\,\mathsf{c}\,||\,\mathsf{EncodeExtFVKParts}(\mathsf{ak, nk, ovk, dk})`.
For the master extended full viewing key, *depth* is 0, *parent_fvk_tag* is 4 zero bytes,
and *i* is 0.
For the master extended full viewing key, :math:`depth` is :math:`0`, :math:`parent\_fvk\_tag`
is 4 zero bytes, and :math:`i` is :math:`0`.
When encoded as Bech32, the Human-Readable Part is ``zxviews`` for the production
network, or ``zxviewtestsapling`` for the test network.
@ -442,14 +458,14 @@ network, or ``zxviewtestsapling`` for the test network.
Sprout extended spending keys
-----------------------------
A Sprout extended spending key (*a*\ :sub:`sk`\ , *c*), at depth *depth*, with
parent address tag *parent_addr_tag* and child number *i*, is represented as a
A Sprout extended spending key :math:`(\mathsf{a_{sk}, c})`, at depth :math:`depth`, with
parent address tag :math:`parent\_addr\_tag` and child number :math:`i`, is represented as a
byte sequence:
I2LEOSP\ :sub:`8`\ (*depth*) || *parent_addr_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || EncodeASK(*a*\ :sub:`sk`\ )
* :math:`\mathsf{I2LEOSP}_{8}(depth)\,||\,parent\_addr\_tag\,||\,\mathsf{I2LEOSP}_{32}(i)\,||\,\mathsf{c}\,||\,\mathsf{EncodeASK}(\mathsf{a_{sk}})`.
For the master extended spending key, *depth* is 0, *parent_addr_tag* is 4 zero bytes,
and *i* is 0.
For the master extended spending key, :math:`depth` is :math:`0`, :math:`parent\_addr\_tag`
is 4 zero bytes, and :math:`i` is :math:`0`.
When encoded as Bech32, the Human-Readable Part is ``zxsprout`` for the production
network, or ``zxtestsprout`` for the test network. Sprout extended spending keys