Terminology
The key words "MUST", "MUST NOT", and "MAY" in this document are to be interpreted as described in RFC 2119.
"Jubjub" refers to the elliptic curve defined in .
@@ -39,33 +43,137 @@ License: MIT
Conventions
Most of the notation and functions used in this ZIP are defined in the Sapling protocol specification . They are reproduced here for convenience:
- - truncatek(S) means the sequence formed from the first k elements of S.
- - a || b means the concatenation of sequences a then b.
- - [k] P means scalar multiplication of the elliptic curve point P by the scalar k.
- - LEOS2IPl(S) is the integer in range {0..2l-1} represented in little-endian order by the byte sequence S of length l/8.
- - I2LEBSPl(k) is the sequence of l bits representing k in little-endian order.
- - LEBS2OSPl(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.
- - repr𝕁(P) is the representation of the Jubjub elliptic curve point P as a bit sequence, defined in .
- - 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.
- - 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.
- - PRFexpand(sk, t) := BLAKE2b-512("Zcash_ExpandSeed", sk || t)
- - r𝕁 is the order of the Jubjub large prime subgroup.
- - ToScalar(x) := LEOS2IP512(x) (mod r𝕁).
- - 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 .
+ -
+ \(\mathsf{truncate}_k(S)\)
+ means the sequence formed from the first
+ \(k\)
+ elements of
+ \(S\)
+ .
+ -
+ \(a\,||\,b\)
+ means the concatenation of sequences
+ \(a\)
+ then
+ \(b\)
+ .
+ -
+ \([k] P\)
+ means scalar multiplication of the elliptic curve point
+ \(P\)
+ by the scalar
+ \(k\)
+ .
+ -
+ \(\mathsf{LEOS2IP}_\ell(S)\)
+ is the integer in range
+ \(\{ 0\,.\!. 2^\ell - 1 \}\)
+ represented in little-endian order by the byte sequence
+ \(S\)
+ of length
+ \(\ell/8\)
+ .
+ -
+ \(\mathsf{I2LEBSP}_\ell(k)\)
+ is the sequence of
+ \(\ell\)
+ bits representing
+ \(k\)
+ in little-endian order.
+ -
+ \(\mathsf{LEBS2OSP}_\ell(B)\)
+ is defined as follows when
+ \(\ell\)
+ 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.
+ -
+ \(\mathsf{repr}_\mathbb{J}(P)\)
+ is the representation of the Jubjub elliptic curve point
+ \(P\)
+ as a bit sequence, defined in .
+ -
+ \(\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
+ \(p\)
+ , and input
+ \(x\)
+ .
+ -
+ \(\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
+ \(p\)
+ , and input
+ \(x\)
+ .
+ -
+ \(\mathsf{PRF^{expand}}(\mathsf{sk}, t) := \mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{“Zcash_ExpandSeed”}, \mathsf{sk}\,||\,t)\)
+
+ -
+ \(r_\mathbb{J}\)
+ is the order of the Jubjub large prime subgroup.
+ -
+ \(\mathsf{ToScalar}(x) := \mathsf{LEOS2IP}_{512}(x) \pmod{r_\mathbb{J}}\)
+ .
+ -
+ \(\mathsf{DiversifyHash}(d)\)
+ maps a diversifier
+ \(d\)
+ to a base point on the Jubjub elliptic curve, or to
+ \(\bot\)
+ if the diversifier is invalid. It is instantiated in .
The following algorithm standardized in 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.
+ -
+ \(\mathsf{FF1}\text{-}\mathsf{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
+ \(\texttt{“”}\)
+ as the
+ \(tweak\)
+ .
+ \(x\)
+ is a sequence of 88 bits, as is the output.
We also define the following conversion function:
- - I2LEOSPl(k) is the byte sequence S of length l/8 representing in little-endian order the integer k in range {0..2l-1}. It is the reverse operation of LEOS2IPl(S).
+ -
+ \(\mathsf{I2LEOSP}_\ell(k)\)
+ is the byte sequence
+ \(S\)
+ of length
+ \(\ell/8\)
+ representing in little-endian order the integer
+ \(k\)
+ in range
+ \(\{ 0\,.\!. 2^\ell - 1 \}\)
+ . It is the reverse operation of
+ \(\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 to describe shielded HD paths, using apostrophes to indicate hardened derivation (i' = i + 231) as in BIP 44 :
+ We adapt the path notation of BIP 32 to describe shielded HD paths, using prime marks (
+ \('\)
+ ) to indicate hardened derivation (
+ \(i' = i + 2^{31}\)
+ ) as in BIP 44 :
- - CDKsk(CDKsk(CDKsk(mSprout, a'), b), c) is written as mSprout / a' / b / c
- - CDKfvk(CDKfvk(CDKfvk(MSapling, a), b), c) is written as MSapling / a / b / c
+ -
+ \(\mathsf{CDKsk}(\mathsf{CDKsk}(\mathsf{CDKsk}(m_\mathsf{Sprout}, a'), b), c)\)
+ is written as
+ \(m_\mathsf{Sprout} / a' / b / c\)
+
+ -
+ \(\mathsf{CDKfvk}(\mathsf{CDKfvk}(\mathsf{CDKfvk}(m_\mathsf{Sapling}, a), b), c)\)
+ is written as
+ \(m_\mathsf{Sapling} / a / b / c\)
+ .
Specification: Sapling key derivation
@@ -75,125 +183,324 @@ License: MIT
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).
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.
- 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 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 spending key as
+ \((\mathsf{ask, nsk, ovk, dk, c})\)
+ , where
+ \((\mathsf{ask, nsk, ovk})\)
+ is the normal Sapling expanded spending key,
+ \(\mathsf{dk}\)
+ is a diversifier key, and
+ \(\mathsf{c}\)
+ is the chain code.
+ We represent a Sapling extended full viewing key as
+ \((\mathsf{ak, nk, ovk, dk, c})\)
+ , where
+ \((\mathsf{ak, nk, ovk})\)
+ is the normal Sapling full viewing key,
+ \(\mathsf{dk}\)
+ is the same diversifier key as above, and
+ \(\mathsf{c}\)
+ is the chain code.
Sapling helper functions
- Define EncodeExtSKParts(ask, nsk, ovk, dk) := I2LEOSP256(ask) || I2LEOSP256(nsk) || ovk || dk.
- Define EncodeExtFVKParts(ak, nk, ovk, dk) := LEBS2OSP256(repr𝕁(ak)) || LEBS2OSP256(repr𝕁(nk)) || ovk || dk.
+ Define
+
+ -
+ \(\mathsf{EncodeExtSKParts}(\mathsf{ask, nsk, ovk, dk}) := \mathsf{I2LEOSP}_{256}(\mathsf{ask})\,||\,\mathsf{I2LEOSP}_{256}(\mathsf{nsk})\,||\,\mathsf{ovk}\,||\,\mathsf{dk}\)
+
+ -
+ \(\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
+ \(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, IL and IR.
- - Use IL as the master spending key skm, and IR as the master chain code cm.
- - Calculate askm, nskm, and ovkm via the standard Sapling derivation :
+
- Calculate
+ \(I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{“ZcashIP32Sapling”}, S)\)
+ .
+ - Split
+ \(I\)
+ into two 32-byte sequences,
+ \(I_L\)
+ and
+ \(I_R\)
+ .
+ - Use
+ \(I_L\)
+ as the master spending key
+ \(\mathsf{sk}_m\)
+ , and
+ \(I_R\)
+ as the master chain code
+ \(\mathsf{c}_m\)
+ .
+ - Calculate
+ \(\mathsf{ask}_m\)
+ ,
+ \(\mathsf{nsk}_m\)
+ , and
+ \(\mathsf{ovk}_m\)
+ via the standard Sapling derivation :
- - askm = ToScalar(PRFexpand(skm, [0x00]))
- - nskm = ToScalar(PRFexpand(skm, [0x01]))
- - ovkm = truncate32(PRFexpand(skm, [0x02]))
+ -
+ \(\mathsf{ask}_m = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x00}]))\)
+
+ -
+ \(\mathsf{nsk}_m = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x01}]))\)
+
+ -
+ \(\mathsf{ovk}_m = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x02}]))\)
+ .
- - Calculate dkm similarly:
+
- Calculate
+ \(\mathsf{dk}_m\)
+ similarly:
- - dkm = truncate32(PRFexpand(skm, [0x10]))
+ -
+ \(\mathsf{dk}_m = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x10}]))\)
+ .
- - Return (askm, nskm, ovkm, dkm, cm) as the master extended spending key mSapling.
+ - Return
+ \((\mathsf{ask}_m, \mathsf{nsk}_m, \mathsf{ovk}_m, \mathsf{dk}_m, \mathsf{c}_m)\)
+ as the master extended spending key
+ \(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, depends on the type of key being derived, and whether this is a hardened or non-hardened derivation.
+ As in BIP 32, the method for deriving a child extended key, given a parent extended key and an index
+ \(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((askpar, nskpar, ovkpar, dkpar, cpar), i) → (aski, nski, ovki, dki, ci)
+
+ \(\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)\)
+
- - Check whether i ≥ 231 (whether the child is a hardened key).
+
- Check whether
+ \(i \geq 2^{31}\)
+ (whether the child is a hardened key).
- - If so (hardened child): let I = PRFexpand(cpar, [0x11] || EncodeExtSKParts(askpar, nskpar, ovkpar, dkpar) || I2LEOSP32(i))
- - If not (normal child): let I = PRFexpand(cpar, [0x12] || EncodeExtFVKParts(akpar, nkpar, ovkpar, dkpar) || I2LEOSP32(i)) where (nkpar, akpar, ovkpar) is the full viewing key derived from (askpar, nskpar, ovkpar) as described in .
+ - If so (hardened child): let
+ \(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
+ \(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
+ \((\mathsf{nk}_{par}, \mathsf{ak}_{par}, \mathsf{ovk}_{par})\)
+ is the full viewing key derived from
+ \((\mathsf{ask}_{par}, \mathsf{nsk}_{par}, \mathsf{ovk}_{par})\)
+ as described in .
- - Split I into two 32-byte sequences, IL and IR.
- - Let Iask = ToScalar(PRFexpand(IL, [0x13]))
- - Let Insk = ToScalar(PRFexpand(IL, [0x14]))
+ - Split
+ \(I\)
+ into two 32-byte sequences,
+ \(I_L\)
+ and
+ \(I_R\)
+ .
+ - Let
+ \(I_\mathsf{ask} = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x13}]))\)
+ .
+ - Let
+ \(I_\mathsf{nsk} = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x14}]))\)
+ .
- Return:
- - aski = (Iask + askpar) (mod r𝕁)
- - nski = (Insk + nskpar) (mod r𝕁)
- - ovki = truncate32(PRFexpand(IL, [0x15] || ovkpar))
- - dki = truncate32(PRFexpand(IL, [0x16] || dkpar))
- - ci = IR
+ -
+ \(\mathsf{ask}_i = (I_\mathsf{ask} + \mathsf{ask}_{par}) \pmod{r_\mathbb{J}}\)
+
+ -
+ \(\mathsf{nsk}_i = (I_\mathsf{nsk} + \mathsf{nsk}_{par}) \pmod{r_\mathbb{J}}\)
+
+ -
+ \(\mathsf{ovk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x15}]\,||\,\mathsf{ovk}_{par}))\)
+
+ -
+ \(\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x16}]\,||\,\mathsf{dk}_{par}))\)
+
+ -
+ \(\mathsf{c}_i = I_R\)
+ .
Deriving a child extended full viewing key
- Let 𝓖 be as defined in and let 𝓗 be as defined in .
- CDKfvk((akpar, nkpar, ovkpar, dkpar, cpar), i) → (aki, nki, ovki, dki, ci)
+ Let
+ \(\mathcal{G}\)
+ be as defined in and let
+ \(\mathcal{H}\)
+ be as defined in .
+
+ \(\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})\)
+
- - Check whether i ≥ 231 (whether the child is a hardened key).
+
- Check whether
+ \(i \geq 2^{31}\)
+ (whether the child is a hardened key).
- - If so (hardened child): return failure
- - If not (normal child): let I = PRFexpand(cpar, [0x12] || EncodeExtFVKParts(akpar, nkpar, ovkpar, dkpar) || I2LEOSP32(i))
+ - If so (hardened child): return failure.
+ - If not (normal child): let
+ \(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 I into two 32-byte sequences, IL and IR.
- - Let Iask = ToScalar(PRFexpand(IL, [0x13]))
- - Let Insk = ToScalar(PRFexpand(IL, [0x14]))
+ - Split
+ \(I\)
+ into two 32-byte sequences,
+ \(I_L\)
+ and
+ \(I_R\)
+ .
+ - Let
+ \(I_\mathsf{ask} = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x13}]))\)
+ .
+ - Let
+ \(I_\mathsf{nsk} = \mathsf{ToScalar}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x14}]))\)
+ .
- Return:
- - aki = [Iask] 𝓖 + akpar
- - nki = [Insk] 𝓗 + nkpar
- - ovki = truncate32(PRFexpand(IL, [0x15] || ovkpar))
- - dki = truncate32(PRFexpand(IL, [0x16] || dkpar))
- - ci = IR
+ -
+ \(\mathsf{ak}_i = [I_\mathsf{ask}]\,\mathcal{G} + \mathsf{ak}_{par}\)
+
+ -
+ \(\mathsf{nk}_i = [I_\mathsf{nsk}]\,\mathcal{H} + \mathsf{nk}_{par}\)
+
+ -
+ \(\mathsf{ovk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x15}]\,||\,\mathsf{ovk}_{par}))\)
+
+ -
+ \(\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x16}]\,||\,\mathsf{dk}_{par}))\)
+
+ -
+ \(\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 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:
+ 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 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 .. 288-1.
- - dj = FF1-AES256.Encrypt(dk, "", I2LEBSP88(j)).
+ - Let
+ \(j\)
+ be the index of the desired diversifier, in the range
+ \(0\,.\!. 2^{88} - 1\)
+ .
+ -
+ \(d_j = \mathsf{FF1}\text{-}\mathsf{AES256.Encrypt}(\mathsf{dk}, \texttt{“”}, \mathsf{I2LEBSP}_{88}(j))\)
+ .
- A valid diversifier dj is one for which DiversifyHash(dj) ≠ ⊥. For a given dk, approximately half of the possible values of j yield valid diversifiers.
- The default diversifier for a Sapling extended key is defined to be dj, where j is the least nonnegative integer yielding a valid diversifier.
+ A valid diversifier
+ \(d_j\)
+ is one for which
+ \(\mathsf{DiversifyHash}(d_j) \neq \bot\)
+ . For a given
+ \(\mathsf{dk}\)
+ , approximately half of the possible values of
+ \(j\)
+ yield valid diversifiers.
+ The default diversifier for a Sapling extended key is defined to be
+ \(d_j\)
+ , where
+ \(j\)
+ is the least nonnegative integer yielding a valid diversifier.
Specification: Sprout key derivation
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.
Sprout extended keys
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.
- We represent a Sprout extended spending key as (ask, c), where ask is the normal Sprout spending key, and c is the chain code.
+ We represent a Sprout extended spending key as
+ \((\mathsf{a_{sk}, c})\)
+ , where
+ \(\mathsf{a_{sk}}\)
+ is the normal Sprout spending key, and
+ \(\mathsf{c}\)
+ is the chain code.
Sprout helper functions
- Let EncodeASK(ask) be the 32-byte encoding of ask in the raw encoding of a Sprout spending key (excluding lead bytes) as specified in .
- 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
+ \(\mathsf{EncodeASK}(\mathsf{a_{sk}})\)
+ be the 32-byte encoding of
+ \(\mathsf{a_{sk}}\)
+ in the raw encoding of a Sprout spending key (excluding lead bytes) as specified in .
+ Let
+ \(\mathsf{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
+ \(\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
+ \(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, IL and IR.
- - Use DecodeASK(IL) as the master spending key ask,m.
- - Use IR as the master chain code cm.
+ - Calculate
+ \(I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{“ZcashIP32_Sprout”}, S)\)
+ .
+ - Split
+ \(I\)
+ into two 32-byte sequences,
+ \(I_L\)
+ and
+ \(I_R\)
+ .
+ - Use
+ \(\mathsf{DecodeASK}(I_L)\)
+ as the master spending key
+ \(\mathsf{a}_{\mathsf{sk},m}\)
+ .
+ - Use
+ \(I_R\)
+ as the master chain code
+ \(\mathsf{c}_m\)
+ .
Sprout child key derivation
- CDKsk((ask,par, cpar), i) → (ask,i, ci)
+
+ \(\mathsf{CDKsk}((\mathsf{a}_{\mathsf{sk},par}, \mathsf{c}_{par}), i) \rightarrow (\mathsf{a}_{\mathsf{sk},i}, \mathsf{c}_i)\)
+
- - Check whether i ≥ 231 (whether the child is a hardened key).
+
- Check whether
+ \(i \geq 2^{31}\)
+ (whether the child is a hardened key).
- - If so (hardened child): let I = PRFexpand(cpar, [0x80] || EncodeASK(ask,par) || I2LEOSP32(i))
- - If not (normal child): return failure
+ - If so (hardened child): let
+ \(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, IL and IR.
- - Use DecodeASK(IL) as the child spending key ask,i.
- - Use IR as the child chain code ci.
+ - Split
+ \(I\)
+ into two 32-byte sequences,
+ \(I_L\)
+ and
+ \(I_R\)
+ .
+ - Use
+ \(\mathsf{DecodeASK}(I_L)\)
+ as the child spending key
+ \(\mathsf{a}_{\mathsf{sk},i}\)
+ .
+ - Use
+ \(I_R\)
+ as the child chain code
+ \(\mathsf{c}_i\)
+ .
@@ -202,48 +509,96 @@ License: MIT
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.
- 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 . Note that in keeping with that document, all cybercoin testnets share coin_type
index 1.
- account
: numbered from index 0 in sequentially increasing manner. Defined as in BIP 44 .
+ -
+ \(purpose\)
+ : a constant set to
+ \(32'\)
+ (or
+ \(\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 compatibility with existing BIP 44 implementations, we use the same constants as defined in SLIP 44 . Note that in keeping with that document, all cybercoin testnets share
+ \(coin\_type\)
+ index
+ \(1\)
+ .
+ -
+ \(account\)
+ : numbered from index
+ \(0\)
+ in sequentially increasing manner. Defined as in BIP 44 .
- 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
+ \(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
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.
- 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..231-1}:
- m_Sapling / purpose' / coin_type' / account'
+ 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^{31} - 1 \}\)
+ :
+
+ -
+ \(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 287 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 :
- m_Sapling / purpose' / coin_type' / account' / address_index
+ Note that a given account can have a maximum of approximately
+ \(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 :
+
+ -
+ \(m_\mathsf{Sapling} / purpose' / coin\_type' / account' / address\_index\)
+ .
+