diff --git a/.gitignore b/.gitignore
index 58c8a585c..bc00a6a2d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@
*.save
*.save.*
*~
+*.html.temp
.Makefile.uptodate
.zipfilelist.*
diff --git a/Makefile b/Makefile
index 91414311a..7448c3d2a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,7 @@
# Dependencies: see zip-guide.rst and protocol/README.rst
+MARKDOWN_OPTION?=--pandoc
+
.PHONY: all-zips all tag-release protocol all-protocol discard
all-zips: .Makefile.uptodate
echo "$(patsubst zips/%,%,$(sort $(wildcard zips/zip-*.rst) $(wildcard zips/zip-*.md)))" >.zipfilelist.new
@@ -31,30 +33,18 @@ all-specs: all-zips
discard:
git checkout -- 'rendered/*.html' 'README.rst' 'rendered/protocol/*.pdf'
-.Makefile.uptodate: Makefile edithtml.sh
+.Makefile.uptodate: Makefile render.sh
$(MAKE) clean
touch .Makefile.uptodate
-define PROCESSRST
-$(eval TITLE := $(shell echo '$(patsubst zips/%,%,$(basename $<))' | sed -E 's|zip-0{0,3}|ZIP |;s|draft-|Draft |')$(shell grep -E '^(\.\.)?\s*Title: ' $< |sed -E 's|.*Title||'))
-rst2html5 -v --title="$(TITLE)" $< >$@
-./edithtml.sh --rst $@
-endef
-
-define PROCESSMD
-$(eval TITLE := $(shell echo '$(patsubst zips/%,%,$(basename $<))' | sed -E 's|zip-0{0,3}|ZIP |;s|draft-|Draft |')$(shell grep -E '^(\.\.)?\s*Title: ' $< |sed -E 's|.*Title||'))
-pandoc --from=markdown --to=html $< --output=$@
-./edithtml.sh --md $@ "${TITLE}"
-endef
-
-rendered/index.html: README.rst edithtml.sh
- $(PROCESSRST)
+rendered/index.html: README.rst render.sh
+ ./render.sh --rst $< $@
-rendered/%.html: zips/%.rst edithtml.sh
- $(PROCESSRST)
+rendered/%.html: zips/%.rst render.sh
+ ./render.sh --rst $< $@
-rendered/%.html: zips/%.md edithtml.sh
- $(PROCESSMD)
+rendered/%.html: zips/%.md render.sh
+ ./render.sh $(MARKDOWN_OPTION) $< $@
README.rst: .zipfilelist.current .draftfilelist.current makeindex.sh README.template $(wildcard zips/zip-*.rst) $(wildcard zips/zip-*.md) $(wildcard zips/draft-*.rst) $(wildcard zips/draft-*.md)
./makeindex.sh | cat README.template - >README.rst
diff --git a/edithtml.sh b/edithtml.sh
deleted file mode 100755
index 0cdead977..000000000
--- a/edithtml.sh
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/sh
-
-if ! ( ( [ "x$1" = "x--rst" ] && [ $# -eq 2 ] ) || ( [ "x$1" = "x--md" ] && [ $# -eq 3 ] ) ); then
- echo "Usage: edithtml.sh --rst Implementors should note that this ZIP is consistently little-endian (in keeping with the Sapling and Orchard specifications), which is the opposite of BIP 32. We adapt the path notation of BIP 32 2 to describe shielded HD paths, using prime marks (
- \('\)
+ \(\kern-0.1em{}'\!\)
) to indicate hardened derivation (
- \(i' = i + 2^{31}\)
+ \(\!i' = i + 2^{31}\!\)
) as in BIP 44 5: We represent a Sapling extended spending key as
- \((\mathsf{ask, nsk, ovk, dk, c})\)
+ \((\mathsf{ask, nsk, ovk, dk, c})\!\)
, where
\((\mathsf{ask, nsk, ovk})\)
is the normal Sapling expanded spending key,
@@ -211,7 +213,7 @@
\(\mathsf{c}\)
is the chain code. We represent a Sapling extended full viewing key as
- \((\mathsf{ak, nk, ovk, dk, c})\)
+ \((\mathsf{ak, nk, ovk, dk, c})\!\)
, where
\((\mathsf{ak, nk, ovk})\)
is the normal Sapling full viewing key,
@@ -245,40 +247,40 @@
be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes. Note that the master extended key is invalid if
\(\mathsf{ask}_m\)
is
- \(0\)
+ \(0\!\)
, or if the corresponding
\(\mathsf{ivk}\)
derived as specified in 11 is
- \(0\)
+ \(0\!\)
. As in BIP 32, the method for deriving a child extended key, given a parent extended key and an index
- \(i\)
+ \(i\!\)
, depends on the type of key being derived, and whether this is a hardened or non-hardened derivation.
\(\mathsf{CKDsk}((\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)\)
- [^<]*
[^<]*)?)[^<]*
[^<]*)?)
Sapling child key derivation
Deriving a child extended spending key
Note that the child extended key is invalid if \(\mathsf{ask}_i\) is - \(0\) + \(0\!\) , or if the corresponding \(\mathsf{ivk}\) derived as specified in 11 is - \(0\) + \(0\!\) .
\(\mathsf{CKDfvk}((\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})\) -
+ :Note that the child extended key is invalid if @@ -489,7 +491,7 @@ is the zero point of Jubjub, or if the corresponding \(\mathsf{ivk}\) derived as specified in 11 is - \(0\) + \(0\!\) .
This design uses the same technique as non-hardened derivation to obtain a full viewing key with the same spend authority (the private key corresponding to - \(\mathsf{ak}\) + \(\mathsf{ak}\!\) ) as the original, but viewing authority only for internal transfers.
The values of - \(I\) + \(I\!\) , - \(I_\mathsf{nsk}\) + \(I_\mathsf{nsk}\!\) , and \(R\) are the same between deriving a full viewing key, and deriving the corresponding spending key. Both of these derivations are shown in the following diagram:
@@ -544,35 +546,35 @@ is the zero point of Jubjub, or if the corresponding \(\mathsf{ivk_{internal}}\) derived from the internal full viewing key as specified in 11 is - \(0\) + \(0\!\) .The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key - \(\mathsf{dk}\) + \(\mathsf{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:
A valid diversifier \(d_j\) is one for which - \(\mathsf{DiversifyHash^{Sapling}}(d_j) \neq \bot\) + \(\mathsf{DiversifyHash^{Sapling}}(d_j) \neq \bot\!\) . For a given - \(\mathsf{dk}\) + \(\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\) + \(d_j\!\) , where \(j\) is the least nonnegative integer yielding a valid diversifier.
@@ -591,7 +593,7 @@\(\mathsf{MKGh}^\mathsf{Context}(\mathsf{IKM}) \rightarrow (\mathsf{sk}_m, \mathsf{c}_m)\) -
+ :\(\mathsf{CKDh}^\mathsf{Context}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)\) \(\rightarrow (\mathsf{sk}_i, \mathsf{c}_i)\) -
+ :\(\mathsf{CKDsk}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)\) \(\rightarrow (\mathsf{sk}_{i}, \mathsf{c}_i)\) -
+ :The result of applying \(\mathsf{DeriveInternalFVK^{Orchard}}\) to the external full viewing key is the internal full viewing key. The corresponding expanded internal spending key is - \((\mathsf{ask}, \mathsf{nk}, \mathsf{rivk_{internal}})\) - ,
+ \((\mathsf{ask}, \mathsf{nk}, \mathsf{rivk_{internal}})\!\) + .Unlike Sapling internal key derivation, we do not base this internal key derivation procedure on non-hardened derivation, which is not defined for Orchard. We can obtain the desired separation of viewing authority by modifying only the
\(\mathsf{rivk_{internal}}\)
field relative to the external full viewing key, which results in different
- \(\mathsf{dk_{internal}}\)
+ \(\mathsf{dk_{internal}}\!\)
,
\(\mathsf{ivk_{internal}}\)
and
@@ -755,27 +757,27 @@
As with Sapling, we define a mechanism for deterministically deriving a sequence of diversifiers, without leaking how many diversified addresses have already been generated for an account. Unlike Sapling, we do so by deriving a diversifier key directly from the full viewing key, instead of as part of the extended spending key. This means that the full viewing key provides the capability to determine the position of a diversifier within the sequence, which matches the capabilities of a Sapling extended full viewing key but simplifies the key structure. Given an Orchard extended spending key
- \((\mathsf{sk}_i, \mathsf{c}_i)\)
+ \((\mathsf{sk}_i, \mathsf{c}_i)\!\)
: Note that unlike Sapling, all Orchard diversifiers are valid, and thus all possible values of
@@ -799,7 +801,7 @@
\(\mathsf{Arbitrary.MKGDomain} = \texttt{âZcashArbitraryKDâ}\)
Orchard diversifier derivation
\(\mathsf{CKDarb}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)\) \(\rightarrow (\mathsf{sk}_i, \mathsf{c}_i)\) -
+ :Sapling and Orchard key paths have the following three path levels at the top, all of which use hardened derivation:
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\,.\!. 2^{31} - 1 \}\) + \(\{ 0\,..\, 2^{31} - 1 \}\!\) :
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.
@@ -882,23 +884,23 @@ path level as in 5:zcashd version 4.6.0 and later uses this to derive "legacy" Sapling addresses from a mnemonic seed phrase under account - \(\mathtt{0x7FFFFFFF}\) + \(\mathtt{0x7FFFFFFF}\!\) , using hardened derivation for - \(address\_index\) + \(address\_index\!\) .
Orchard supports diversified addresses with the same spending authority (like Sapling). 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 Orchard ZIP 32 derivation MUST support the following path for any account in range - \(\{ 0\,.\!. 2^{31} - 1 \}\) + \(\{ 0\,..\, 2^{31} - 1 \}\!\) :
Furthermore, wallets MUST support generating the default payment address (corresponding to the default diversifier for Orchard) for any account they support. They MAY also support generating a stream of diversified payment addresses for a given account, if they wish to enable users to give a unique address to each recipient.
@@ -914,7 +916,7 @@ (as specified in 18) is given by:It MAY be used to uniquely identify a particular Sapling full viewing key.
@@ -926,7 +928,7 @@ (as specified in 20) is given by:It MAY be used to uniquely identify a particular Orchard full viewing key.
@@ -938,8 +940,8 @@ of a hierarchical deterministic wallet is given by:It MAY be used to uniquely identify a particular hierarchical deterministic wallet.
@@ -951,13 +953,13 @@The following encodings are analogous to the xprv
and xpub
encodings defined in BIP 32 for transparent keys and addresses. Each key type has a raw representation and a Bech32 7 encoding.
A Sapling extended spending key - \((\mathsf{ask, nsk, ovk, dk, c})\) + \((\mathsf{ask, nsk, ovk, dk, c})\!\) , at depth - \(depth\) + \(depth\!\) , with parent full viewing key tag \(parent\_fvk\_tag\) and child number - \(i\) + \(i\!\) , is represented as a byte sequence:
For the master extended spending key, \(depth\) is - \(0\) + \(0\!\) , \(parent\_fvk\_tag\) is 4 zero bytes, and \(i\) is - \(0\) + \(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.
A Sapling extended full viewing key - \((\mathsf{ak, nk, ovk, dk, c})\) + \((\mathsf{ak, nk, ovk, dk, c})\!\) , at depth - \(depth\) + \(depth\!\) , with parent full viewing key tag \(parent\_fvk\_tag\) and child number - \(i\) + \(i\!\) , is represented as a byte sequence:
For the master extended full viewing key, \(depth\) is - \(0\) + \(0\!\) , \(parent\_fvk\_tag\) is 4 zero bytes, and \(i\) is - \(0\) + \(0\!\) .
When encoded as Bech32, the Human-Readable Part is zxviews
for the production network, or zxviewtestsapling
for the test network.
An Orchard extended spending key - \((\mathsf{sk, c})\) + \((\mathsf{sk, c})\!\) , at depth - \(depth\) + \(depth\!\) , with parent full viewing key tag \(parent\_fvk\_tag\) and child number - \(i\) + \(i\!\) , is represented as a byte sequence:
For the master extended spending key, \(depth\) is - \(0\) + \(0\!\) , \(parent\_fvk\_tag\) is 4 zero bytes, and \(i\) is - \(0\) + \(0\!\) .
When encoded as Bech32, the Human-Readable Part is secret-orchard-extsk-main
for Mainnet, or secret-orchard-extsk-test
for Testnet.
We define this encoding for completeness, however given that it includes the capability to derive child spending keys, we expect that most wallets will only expose the regular Orchard spending key encoding to users 21.
@@ -1049,17 +1051,17 @@zxsprout
and zxtestsprout
, formerly specified for Sprout extended spending keys on Mainnet and Testnet respectively.Transactions that have insufficient fees are often not mined. This indeterminism is a source of confusion for users and wallets. Allowing a transaction to set a block height after which it cannot be mined would provide certainty around how long a transaction has to confirm before it is rejected by the network and must be re-sent.
Advantages include optimizing mempool performance by removing transactions that will not be mined, and potentially simplifying bidirectional payment channels by reducing the need to store and compress revocations for past states, since transactions not committed to the chain could expire and become invalid after a period of time.
If the expiry is at block height - \(N\) + \(N\!\!\) , then the transaction must be included in block \(N\) or earlier. Block \(N+1\) will be too late, and the transaction will be removed from the mempool.
The new consensus rule will enforce that the transaction will not be considered valid if included in block of height greater than - \(N\) + \(N\!\!\) , and blocks that include expired transactions will not be considered valid.
We also define the following function:
An active funding stream at a given block height is defined as a funding stream for which the block height is less than its end height, but not less than its start height.
-The funding streams are paid to one of a pre-defined set of recipients, depending on the block height. Each recipient identifier MUST be either the string encoding of a transparent P2SH address or Sapling address (as specified in 6 or [#protocol-saplingpaymentaddrencoding]) to be paid by an output in the coinbase transaction, or the identifier - \(\mathsf{DEFERRED}\_\mathsf{POOL}\) - . The latter, added in the NU6 network upgrade 19, indicates that the value is to be paid to a reserve to be used for development funding, the distribution of which is to be determined via a future ZIP.
+The funding streams are paid to one of a pre-defined set of recipients, depending on the block height. Each recipient identifier MUST be either the string encoding of a transparent P2SH address or Sapling address (as specified in 6 or 7) to be paid by an output in the coinbase transaction, or the identifier + \(\mathsf{DEFERRED\_POOL}\!\) + . The latter, added in the NU6 network upgrade 19, indicates that the value is to be paid to a reserve to be used for development funding, the distribution of which is to be determined via a future ZIP.
Each address is used for at most 1/48th of a halving interval, creating a roughly-monthly sequence of funding periods. The address to be used for a given block height is defined as follows:
-This has the property that all active funding streams change the address they are using on the same block height schedule, aligned to the height of the first halving so that 48 funding periods fit cleanly within a halving interval. This can be leveraged to simplify implementations, by batching the necessary outputs for each funding period.
Below is a visual representation of how stream addresses align with funding periods:
@@ -207,21 +209,21 @@ where \(\mathsf{DeferredFundingStreams}(\mathsf{height})\) is the set of funding streams with recipient identifier - \(\mathsf{DEFERRED}\_\mathsf{POOL}\) + \(\mathsf{DEFERRED\_POOL}\) in the block at height - \(\mathsf{height}\) + \(\mathsf{height}\!\) .The \(\mathsf{ChainValuePoolBalance^{Deferred}}\) chain value pool balance for a given block chain is the sum of the values of payments to - \(\mathsf{DEFERRED}\_\mathsf{POOL}\) + \(\mathsf{DEFERRED\_POOL}\) for transactions in the block chain.
Equivalently, \(\mathsf{ChainValuePoolBalance^{Deferred}}\) for a block chain up to and including height \(\mathsf{height}\) is given by - \(\sum_{\mathsf{h} = 0}^{\mathsf{height}} \mathsf{totalDeferredOutput}(\mathsf{h})\) + \(\sum_{\mathsf{h} = 0}^{\mathsf{height}} \mathsf{totalDeferredOutput}(\mathsf{h})\!\) .
Note: \(\mathsf{totalDeferredOutput}(\mathsf{h})\) @@ -230,18 +232,18 @@ prior to NU6 activation.
Prior to activation of the Canopy network upgrade, the existing consensus rule for payment of the original Founders' Reward is enforced. 10
+Prior to activation of the Canopy network upgrade, the existing consensus rule for payment of the original Founders' Reward is enforced. 10
Once the Canopy network upgrade activates:
OP_HASH160 RedeemScriptHash(height) OP_EQUAL
as the scriptPubKey
.These rules are reproduced in [#protocol-fundingstreams].
+These rules are reproduced in 11.
The effect of the definition of \(\mathsf{ChainValuePoolBalance^{Deferred}}\) above is that payments to the - \(\mathsf{DEFERRED}\_\mathsf{POOL}\) + \(\mathsf{DEFERRED\_POOL}\) cause \(\mathsf{FundingStream[FUND].Value}(\mathsf{height})\) to be added to \(\mathsf{ChainValuePoolBalance^{Deferred}}\) for the block chain including that block.
-For the funding stream definitions to be activated at Canopy and at NU6, see ZIP 214. 17 Funding stream definitions can be added, changed, or deleted in ZIPs associated with subsequent network upgrades, subject to the ZIP process. 12
+For the funding stream definitions to be activated at Canopy and at NU6, see ZIP 214. 17 Funding stream definitions can be added, changed, or deleted in ZIPs associated with subsequent network upgrades, subject to the ZIP process. 12
This proposal was initially deployed with Canopy. 18
-Changes to support deferred funding streams are to be deployed with NU6. 19
+This proposal was initially deployed with Canopy. 18
+Changes to support deferred funding streams are to be deployed with NU6. 19
This proposal intentionally creates what is known as a "bilateral consensus rule change". Use of this mechanism requires that all network participants upgrade their software to a compatible version within the upgrade window. Older software will treat post-upgrade blocks as invalid, and will follow any pre-upgrade consensus branch that persists.
@@ -291,7 +293,7 @@The changes described in this section are to be made in the Zcash Protocol Specification 3, relative to the pre-Blossom specification in [#preblossom-protocol].
Throughout the specification, rename HalvingInterval to PreBlossomHalvingInterval, and rename PoWTargetSpacing to PreBlossomTargetSpacing. These constants retain their values from 2 of 840000 (blocks) and 150 (seconds) respectively.
-In section 2 (Notation), add BlossomActivationHeight and PostBlossomPoWTargetSpacing to the list of integer constants.
-In section 5.3 (Constants), define PostBlossomPoWTargetSpacing := 75 seconds.
-For a given network (production or test), define BlossomActivationHeight as the height at which Blossom activates on that network, as specified in 11.
+Throughout the specification, rename + \(\mathsf{HalvingInterval}\) + to + \(\mathsf{PreBlossomHalvingInterval}\!\) + , and rename + \(\mathsf{PoWTargetSpacing}\) + to + \(\mathsf{PreBlossomTargetSpacing}\!\) + . These constants retain their values from 2 of + \(840000\) + (blocks) and + \(150\) + (seconds) respectively.
+In section 2 (Notation), add + \(\mathsf{BlossomActivationHeight}\) + and + \(\mathsf{PostBlossomPoWTargetSpacing}\) + to the list of integer constants.
+In section 5.3 (Constants), define + \(\mathsf{PostBlossomPoWTargetSpacing} := 75\) + seconds.
+For a given network (production or test), define + \(\mathsf{BlossomActivationHeight}\) + as the height at which Blossom activates on that network, as specified in 11.
In section 7.6.3 (Difficulty adjustment) [later moved to section 7.7.3], make the following changes:
-Define IsBlossomActivated(height) to return true if height ⼠BlossomActivationHeight, otherwise false.
-This specification assumes that BlossomActivationHeight ⼠SlowStartInterval.
+Define + \(\mathsf{IsBlossomActivated}(\mathsf{height})\) + to return true if + \(\mathsf{height} \geq \mathsf{BlossomActivationHeight}\!\) + , otherwise false.
+This specification assumes that + \(\mathsf{BlossomActivationHeight} \geq \mathsf{SlowStartInterval}\!\) + .
Define:
In the same section, redefine PoWTargetSpacing as a function taking a height parameter, as follows:
-Also redefine AveragingWindowTimespan, MinActualTimespan, MaxActualTimespan, ActualTimespanDamped, ActualTimespanBounded, and Threshold as follows:
-In section 7.7 (Calculation of Block Subsidy and Foundersâ Reward) [later moved to section 7.8], redefine the Halving and BlockSubsidy functions as follows:
+In the same section, redefine $mathsf{PoWTargetSpacing} as a function taking a + \(\mathsf{height}\) + parameter, as follows:
+Also redefine + \(\mathsf{AveragingWindowTimespan}\!\) + , + \(\mathsf{MinActualTimespan}\!\) + , + \(\mathsf{MaxActualTimespan}\!\) + , + \(\mathsf{ActualTimespanDamped}\!\) + , + \(\mathsf{ActualTimespanBounded}\!\) + , and + \(\mathsf{Threshold}\) + as follows:
Note: BlossomActivationHeight, PostBlossomHalvingInterval, and PostBlossomTargetSpacing are chosen so that:
+In section 7.7 (Calculation of Block Subsidy and Foundersâ Reward) [later moved to section 7.8], redefine the + \(\mathsf{Halving}\) + and + \(\mathsf{BlockSubsidy}\) + functions as follows:
+Note: + \(\mathsf{BlossomActivationHeight}\!\) + , + \(\mathsf{PostBlossomHalvingInterval}\!\) + , and + \(\mathsf{PostBlossomTargetSpacing}\) + are chosen so that:
In section 7.8 (Payment of Foundersâ Reward) [later moved to section 7.9], define:
-and in the definition of FounderAddressIndex, replace the use of height with FounderAddressAdjustedHeight(height).
+and in the definition of + \(\mathsf{FounderAddressIndex}\!\) + , replace the use of + \(\mathsf{height}\) + with + \(\mathsf{FounderAddressAdjustedHeight}(\mathsf{height})\!\) + .
Also define:
Replace the first note in that section with:
and in the second note, replace SlowStartShift + PreBlossomHalvingInterval - 1 with FoundersRewardLastBlockHeight.
+and in the second note, replace + \(\mathsf{SlowStartShift} + \mathsf{PreBlossomHalvingInterval} - 1\) + with + \(\mathsf{FoundersRewardLastBlockHeight}\!\) + .
The difficulty adjustment parameters PoWAveragingWindow and PoWMedianBlockSpan refer to numbers of blocks, but do not change at Blossom activation. This is because the amount of damping/averaging required is expected to be roughly the same, in terms of the number of blocks, after the change in block target spacing.
-The change in the effective value of PoWTargetSpacing will cause the block spacing to adjust to the new target, at the normal rate for a difficulty adjustment. The results of simulations are consistent with this expected behaviour.
-Note that the change in AveragingWindowTimespan(height) takes effect immediately when calculating the target difficulty starting from the block at the Blossom activation height, even though the difficulty of the preceding PoWAveragingWindow blocks will have been adjusted using the pre-Blossom target spacing. Therefore it is likely that the difficulty adjustment for the first few blocks after activation will be limited by PoWMaxAdjustDown. This is not anticipated to cause any problem.
+The difficulty adjustment parameters + \(\mathsf{PoWAveragingWindow}\) + and + \(\mathsf{PoWMedianBlockSpan}\) + refer to numbers of blocks, but do not change at Blossom activation. This is because the amount of damping/averaging required is expected to be roughly the same, in terms of the number of blocks, after the change in block target spacing.
+The change in the effective value of + \(\mathsf{PoWTargetSpacing}\) + will cause the block spacing to adjust to the new target, at the normal rate for a difficulty adjustment. The results of simulations are consistent with this expected behaviour.
+Note that the change in + \(\mathsf{AveragingWindowTimespan(\mathsf{height})\) + takes effect immediately when calculating the target difficulty starting from the block at the Blossom activation height, even though the difficulty of the preceding + \(\mathsf{PoWAveragingWindow}\) + blocks will have been adjusted using the pre-Blossom target spacing. Therefore it is likely that the difficulty adjustment for the first few blocks after activation will be limited by + \(\mathsf{PoWMaxAdjustDown}\!\) + . This is not anticipated to cause any problem.
On Testnet from block height 299188 onward, the difficulty adjustment algorithm 6 allows minimum-difficulty blocks, as described in 10, when the block time is greater than a given threshold. This specification changes this threshold to be proportional to the block target spacing.
-That is, if the block time of a block at height height ⼠299188 is greater than 6 ¡ PoWTargetSpacing(height) seconds after that of the preceding block, then the block is a minimum-difficulty block. In that case its nBits
field MUST be set to ToCompact(PoWLimit), where PoWLimit is the value defined for Testnet in section 5.3 of the Zcash Protocol Specification 5, and ToCompact is as defined in section 7.7.4 of that specification 7.
That is, if the block time of a block at height
+ \(\mathsf{height} \geq 299188\)
+ is greater than
+ \(6 \cdot \mathsf{PoWTargetSpacing}(\mathsf{height})\)
+ seconds after that of the preceding block, then the block is a minimum-difficulty block. In that case its nBits
field MUST be set to
+ \(\mathsf{ToCompact}(\mathsf{PoWLimit})\!\)
+ , where
+ \(\mathsf{PoWLimit}\)
+ is the value defined for Testnet in section 5.3 of the Zcash Protocol Specification 5, and
+ \(\mathsf{ToCompact}\)
+ is as defined in section 7.7.4 of that specification 7.
Note: a previous revision of this ZIP (and 10) incorrectly said that only the target threshold of minimum-difficulty blocks is affected. In fact the nBits
field is modified as well, and this affects difficulty adjustment for subsequent blocks.
This change does not affect Mainnet.
If pruning is enabled, when zcashd responds to an "getblocks" peer-to-peer message, it will only include blocks that it has on disk, and is likely to still have on disk an hour after responding to the message:
// If pruning, don't inv blocks unless we have on disk and are likely to still have // for some reasonable time window (1 hour) that block relay might require.-
For each block, when estimating whether it will still be on disk after an hour, we take MIN_BLOCKS_TO_KEEP = 288 blocks, minus approximately the number of blocks expected in one hour at the target block spacing as of that block. Around Blossom activation, this might underestimate the number of blocks in the next hour, but given the value of MIN_BLOCKS_TO_KEEP, this is not anticipated to cause any problem.
+For each block, when estimating whether it will still be on disk after an hour, we take MIN_BLOCKS_TO_KEEP = + \(288\) + blocks, minus approximately the number of blocks expected in one hour at the target block spacing as of that block. Around Blossom activation, this might underestimate the number of blocks in the next hour, but given the value of MIN_BLOCKS_TO_KEEP, this is not anticipated to cause any problem.
zcashd uses the EstimateNetHeight
function to estimate the approximate height of the fully synced chain, so that the progress of block download can be displayed to the node operator. This function has been rewritten, simplified, and changed to take account of cases where the time period that needs to be estimated crosses Blossom activation.
This proposal intentionally creates what is known as a "bilateral consensus rule change". Use of this mechanism requires that all network participants upgrade their software to a compatible version within the upgrade window. Older software will treat post-upgrade blocks as invalid, and will follow any pre-upgrade consensus branch that persists.
sizeProofsOrchard |
compactSize |
Length in bytes of proofsOrchard . Value is
- \(2720 + 2272 \cdot \mathtt{nActionsOrchard}\)
+ \(2720 + 2272 \cdot \mathtt{nActionsOrchard}\!\)
. |
valueBalanceSapling
and bindingSigSapling
are present if and only if
- \(\mathtt{nSpendsSapling} + \mathtt{nOutputsSapling} > 0\)
+ \(\mathtt{nSpendsSapling} + \mathtt{nOutputsSapling} > 0\!\)
. If valueBalanceSapling
is not present, then
- \(\mathsf{v^{balanceSapling}}`\)
- is defined to be 0.anchorSapling
is present if and only if
- \(\mathtt{nSpendsSapling} > 0\)
+ \(\mathtt{nSpendsSapling} > 0\!\)
.flagsOrchard
, valueBalanceOrchard
, anchorOrchard
, sizeProofsOrchard
, proofsOrchard
, and bindingSigOrchard
are present if and only if
- \(\mathtt{nActionsOrchard} > 0\)
+ \(\mathtt{nActionsOrchard} > 0\!\)
. If valueBalanceOrchard
is not present, then
\(\mathsf{v^{balanceOrchard}}\)
- is defined to be 0.vSpendProofsSapling
and vSpendAuthSigsSapling
have a 1:1 correspondence to the elements of vSpendsSapling
and MUST be ordered such that the proof or signature at a given index corresponds to the SpendDescriptionV5
at the same index.vOutputProofsSapling
have a 1:1 correspondence to the elements of vOutputsSapling
and MUST be ordered such that the proof at a given index corresponds to the OutputDescriptionV5
at the same index.proofsOrchard
, and the elements of vSpendAuthSigsOrchard
, each have a 1:1 correspondence to the elements of vActionsOrchard
and MUST be ordered such that the proof or signature at a given index corresponds to the OrchardAction
at the same index.enableSpendsOrchard
bit MUST be set to 0
.enableSpendsOrchard
bit MUST be set to
+ \(0\!\)
+ .The encodings of tx_in
, and tx_out
are as in a version 4 transaction (i.e. unchanged from Canopy). The encodings of SpendDescriptionV5
, OutputDescriptionV5
and OrchardAction
are described below. The encoding of Sapling Spends and Outputs has changed relative to prior versions in order to better separate data that describe the effects of the transaction from the proofs of and commitments to those effects, and for symmetry with this separation in the Orchard-related parts of the transaction format.
32
cmu
byte[32]
32
32
cmx
byte[32]
32
ephemeralKey
byte[32]
580
joinSplitPubKey
and joinSplitSig
fields were specified to be present if and only if
- \(\mathtt{nJoinSplit} > 0\)
+ \(\mathtt{nJoinSplit} > 0\!\)
.This Asset Base will be the base point of the value commitment for the specific Custom Asset. Note that the Asset Base of the ZEC Asset will be kept as the original value base point, \(\mathcal{V}^{\mathsf{Orchard}}\!\) @@ -116,27 +118,36 @@
We define the note commitment scheme \(\mathsf{NoteCommit^{OrchardZSA}_{rcm}}\) as follows:
-where \(\mathbb{P}, \ell_{\mathbb{P}}, q_{\mathbb{P}}\) are as defined for the Pallas curve 27, and where - \(\mathsf{NoteCommit^{Orchard}}.\!\mathsf{Trapdoor}\) - and - \(\mathsf{Orchard}.\!\mathsf{Output}\) + \(\mathsf{NoteCommit^{Orchard}.\{Trapdoor, Output\}}\) are as defined in the Zcash protocol specification 17. This note commitment scheme is instantiated using the Sinsemilla Commitment 26 as follows:
-where:
-Note that \(\mathsf{repr}_{\mathbb{P}}\) and @@ -156,7 +167,7 @@ \(\mathsf{NoteCommit^{Orchard}_{rcm}}\) in that for Custom Assets, the Asset Base will be added as an input to the commitment computation. In the case where the Asset is the ZEC Asset, the commitment is computed identically to the Orchard note commitment, without making use of the ZEC Asset Base as an input. As we will see, the nested structure of the Sinsemilla-based commitment 26 allows us to add the Asset Base as a final recursive step.
The note commitment output is still indistinguishable from the original Orchard ZEC note commitments, by definition of the Sinsemilla hash function 24. ZSA note commitments will therefore be added to the same Orchard Note Commitment Tree. In essence, we have:
-This definition can be viewed as a generalization of the Orchard note commitment, and will allow maintaining a single commitment instance for the note commitment, which will be used both for pre-ZSA Orchard and ZSA notes.
where \(\mathsf{v^{net}_{AssetId}} = \mathsf{v^{old}_{AssetId}} - \mathsf{v^{new}_{AssetId}}\) - such that - \(\mathsf{v^{old}_{AssetId}}\) - and - \(\mathsf{v^{new}_{AssetId}}\) - are the values of the old and new notes of Asset Identifier - \(\mathsf{AssetId}\) - respectively,
-- \(\mathsf{AssetBase_{AssetId}}\) - is defined in ZIP 227 5, and
-- \(\mathcal{R}^{\mathsf{Orchard}} := \mathsf{GroupHash^{\mathbb{P}}}(\texttt{"z.cash:Orchard-cv"}, \texttt{"r"})\!\) - , as in the Orchard protocol.
+ such that +For ZEC, we define \(\mathsf{AssetBase}_{\mathsf{AssetId}} := \mathcal{V}^{\mathsf{Orchard}}\) so that the value commitment for ZEC notes is computed identically to the Orchard protocol deployed in NU5 4. As such @@ -203,7 +217,7 @@ ) that is burnt in the transaction, the sender adds to \(\mathsf{assetBurn}\) the tuple - \((\mathsf{AssetBase}, \mathsf{v})\) + \((\mathsf{AssetBase}, \mathsf{v})\!\) , where \(\mathsf{v}\) is the amount of the Custom Asset the sender wants to burn. We denote by @@ -319,7 +333,7 @@ , \(\mathcal{K}^{\mathsf{Orchard}}\) is the Orchard Nullifier Base as defined in 20, and - \(\mathcal{L}^{\mathsf{Orchard}} := \mathsf{GroupHash^{\mathbb{P}}}(\texttt{"z.cash:Orchard"}, \texttt{"L"})\!\) + \(\mathcal{L}^{\mathsf{Orchard}} := \mathsf{GroupHash^{\mathbb{P}}}(\texttt{âz.cash:Orchardâ}, \texttt{âLâ})\!\) .
In the Orchard protocol, since each Action represents an input and an output, the transaction that wants to send one input to multiple outputs must have multiple inputs. The Orchard protocol gives dummy spend notes 18 to the Actions that have not been assigned input notes.
@@ -397,67 +411,52 @@Senders must not be able to change the Asset Base for the output note in a Split Action. We do this via the following constraints:
Define - \(\mathsf{IssueAuthSig}.\!\mathsf{DerivePublic}\; : \; (\mathsf{isk}\; : \; \mathsf{IssueAuthSig}.\!\mathsf{Private}) \to \mathsf{IssueAuthSig}.\!\mathsf{Public}\) + \(\mathsf{IssueAuthSig.DerivePublic} \;{\small âŚ}\; (\mathsf{isk} \;{\small âŚ}\; \mathsf{IssueAuthSig.Private}) \to \mathsf{IssueAuthSig.Public}\) as:
where the \(\textit{PubKey}\) - algorithm is defined in BIP 340 17. Note that the byte representation of + algorithm is defined in BIP 340 18. Note that the byte representation of \(\mathsf{ik}\) is in big-endian order as defined in BIP 340.
It is possible for the \(\textit{PubKey}\) algorithm to fail with very low probability, which means that - \(\mathsf{IssueAuthSig}.\!\mathsf{DerivePublic}\) + \(\mathsf{IssueAuthSig.DerivePublic}\) could return \(\bot\) with very low probability. If this happens, discard the keys and repeat with a different \(\mathsf{isk}\!\) .
-This allows the issuer to use the same wallet it usually uses to transfer Assets, while keeping a disconnect from the other keys. Specifically, this method is aligned with the requirements and motivation of ZIP 32 2. It provides further anonymity and the ability to delegate issuance of an Asset (or in the future, generate a multi-signature protocol) while the rest of the keys remain in the wallet safe.
+This allows the issuer to use the same wallet it usually uses to transfer Assets, while keeping a disconnect from the other keys. Specifically, this method is aligned with the requirements and motivation of ZIP 32 2. It provides further anonymity and the ability to delegate issuance of an Asset (or in the future, generate a multi-signature protocol) while the rest of the keys remain in the wallet safe.
Define - \(\mathsf{AssetDigest_{AssetId}} := \textsf{BLAKE2b-512}(\texttt{"ZSA-Asset-Digest"},\; \mathsf{EncodeAssetId}(\mathsf{AssetId}))\!\) + \(\mathsf{AssetDigest_{AssetId}} := \textsf{BLAKE2b-512}(\texttt{âZSA-Asset-Digestâ},\; \mathsf{EncodeAssetId}(\mathsf{AssetId}))\!\) , where
In the case of the Orchard-ZSA protocol, we define - \(\mathsf{ZSAValueBase}(\mathsf{AssetDigest_{AssetId}}) := \mathsf{GroupHash}^\mathbb{P}(\texttt{"z.cash:OrchardZSA"}, \mathsf{AssetDigest_{AssetId}})\) + \(\mathsf{ZSAValueBase}(\mathsf{AssetDigest_{AssetId}}) := \mathsf{GroupHash}^\mathbb{P}(\texttt{âz.cash:OrchardZSAâ}, \mathsf{AssetDigest_{AssetId}})\) where \(\mathsf{GroupHash}^\mathbb{P}\) - is defined as in 21.
+ is defined as in 22.The relations between the Asset Identifier, Asset Digest, and Asset Base are shown in the following diagram:
We use the notation @@ -359,7 +361,7 @@ \(\mathsf{issued\_assets}(\mathsf{AssetBase}).\!\mathsf{final}\) to access, respectively, the balance and finalization status of the Asset stored in the global state.
It is necessary to ensure that the balance of any issued Custom Asset never becomes negative within a shielded pool, along the lines of ZIP 209 8. However, unlike for the shielded ZEC pools, there is no individual transaction field that directly corresponds to both the issued and burnt amounts for a given Asset. Therefore, we require that all nodes maintain a record of the current amount in circulation for every issued Custom Asset, and update this record at the block boundary based on the issuance and burn transactions within the block. This allows for efficient detection of balance violations for any Asset, in which scenario we specify a consensus rule to reject the block.
+It is necessary to ensure that the balance of any issued Custom Asset never becomes negative within a shielded pool, along the lines of ZIP 209 8. However, unlike for the shielded ZEC pools, there is no individual transaction field that directly corresponds to both the issued and burnt amounts for a given Asset. Therefore, we require that all nodes maintain a record of the current amount in circulation for every issued Custom Asset, and update this record at the block boundary based on the issuance and burn transactions within the block. This allows for efficient detection of balance violations for any Asset, in which scenario we specify a consensus rule to reject the block.
Nodes also need to ensure the rejection of blocks in which issuance of Custom Assets that have been previously finalized. The \(\mathsf{issued\_assets}\) map allows nodes to store whether or not a given Asset has been finalized.
@@ -459,18 +461,18 @@An issuance bundle, IssueBundle
, is the aggregate of all the issuance-related information. Specifically, contains all the issuance actions and the issuer signature on the transaction SIGHASH that validates the issuance itself. It contains the following fields:
vIssueActions
: an array of issuance actions, of type IssueAction
.The issuance bundle is then added within the transaction format as a new bundle. That is, issuance requires the addition of the following information to the transaction format 23.
+The issuance bundle is then added within the transaction format as a new bundle. That is, issuance requires the addition of the following information to the transaction format 24.
17 | +BIP 43: Purpose Field for Deterministic Wallets | +
---|
18 | BIP 340: Schnorr Signatures for secp256k1 |
---|
18 | +19 | Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 2: Notation |
---|
19 | +20 | Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 3.1: Payment Addresses and Keys |
---|
20 | +21 | Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 4.2.3: Orchard Key Components |
---|
21 | +22 | Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.4.9.8: Group Hash into Pallas and Vesta |
---|
22 | +23 | Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.6.4.2: Orchard Raw Payment Addresses |
---|
23 | +24 | Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.1: Transaction Encoding and Consensus |
---|---|---|
- \(issuance\_fee\) + \(\mathsf{issuance\_fee}\) | \(100 \cdot marginal\_fee\) @@ -659,7 +661,7 @@ |
Wallets implementing this specification SHOULD use a conventional fee, viz. - \(zsa\_conventional\_fee\) + \(\mathsf{zsa\_conventional\_fee}\!\) , that is calculated in zatoshis. Additional definitions that are used in the formula for the calculation are in the table below:
- \(nOrchardActions\) + \(\mathsf{nOrchardActions}\) | number | the number of OrchardZSA transfer actions (including ZEC actions) |
- \(nTotalOutputsZsaIssuance\) + \(\mathsf{nTotalOutputsZsaIssuance}\) | number | the total number of OrchardZSA issuance outputs (added across issuance actions) |
- \(nCreateActions\) + \(\mathsf{nCreateActions}\) | number | the number of OrchardZSA issuance actions that issue a Custom Asset that is not present in the Global Issuance State | @@ -694,22 +696,22 @@
The other inputs to this formula are taken from transaction fields defined in the Zcash protocol specification 6 and the global state. They are defined in the Fee calculation section of ZIP 317 12. Note that - \(nOrchardActions\) + \(\mathsf{nOrchardActions}\!\) , that is used in the computation of - \(logical\_actions\) + \(\mathsf{logical\_actions}\!\) , is redefined in the above table, and now combines the actions for native ZEC as well as OrchardZSA transfer actions for Custom Assets.
The formula for the computation of the - \(zsa\_logical\_actions\) + \(\mathsf{zsa\_logical\_actions}\) (with the updated computation of - \(logical\_actions\) + \(\mathsf{logical\_actions}\) as described above) is:
-The formula for the computation of the - \(zsa\_conventional\_fee\) + \(\mathsf{zsa\_conventional\_fee}\) is:
It is not a consensus requirement that fees follow this formula; however, wallets SHOULD create transactions that pay this fee, in order to reduce information leakage, unless overridden by the user.
During transaction construction, each output with memo data is
assigned a 32-byte memo key Kmemo. These keys SHOULD be
+class="math inline">\(\mathsf{K^{memo}}\). These keys SHOULD be
generated randomly, and MUST NOT be used to encrypt more than one memo
within a single transaction. If an output has no memo data, it is
assigned the memo key consisting of 32 0
x
F
F
-bytes.
In note plaintexts of v6-onward transactions, the 512-byte memo field -is replaced by Kmemoâ.
+is replaced by \(\mathsf{K^{memo}}\).The transaction builder generates a 32-byte salt value salt from a CSPRNG. A new salt MUST be -generated for each memo bundle.
+class="math inline">\(\mathsf{salt}\) from a CSPRNG. A new salt +MUST be generated for each memo bundle.The symmetric encryption key for a memo is derived from its Kmemo as follows:
-âââencryption_keyâ=âPRFKmemoexpand([0
x
E
0
]â||âsalt)
The first byte 0
x
E
0
+class="math inline">\(\mathsf{K^{memo}}\) as follows:
\(\hspace{2em}\mathsf{encryption\_key} = +\mathsf{PRF^{expand}_{K^{memo}}}([\mathtt{0xE0}] \,||\, +\mathsf{salt})\)
+The first byte \(\mathtt{0xE0}\) should be added to the documentation of inputs to PRFexpand in § 4.1.2 âPseudo +class="math inline">\(\mathsf{PRF^{expand}}\) in § 4.1.2 âPseudo Random Functionsâ 7.
If the generated key is 32 0
x
F
F
-bytes, the transaction constructor MAY repeat this procedure with a
-different salt, in order to avoid the recipient misinterpreting the
-output as having no memo data. Since that has negligible probability, it
-alternatively MAY omit this check.
Each memo is padded to a multiple of 256 bytes with zeroes, and split into 256-byte chunks. Each memo chunk is encrypted with ChaCha20Poly1305 8 as follows:
âââIETF_AEAD_CHACHA20_POLY1305(encryption_key,ânonce,âmemo_chunk)
-where nonceâ=âI2BEOSP88(counter)â||â[final_chunk]â.
+class="math inline">\(\hspace{2em}\mathsf{IETF\_AEAD\_CHACHA20\_POLY1305}(\mathsf{encryption\_key}, +\mathsf{nonce}, \mathsf{memo\_chunk})\) +where \(\mathsf{nonce} = +\mathsf{I2BEOSP}_{88}(\mathsf{counter}) \,||\, +[\mathsf{final\_chunk}]\).
This is a variant of the STREAM construction 9.
0
x
01
-for the final memo chunk, and 0
x
00
-for all preceding chunks.Finally, the encrypted memo chunks for all memos are combined into a single sequence using an order-preserving shuffle. Memo chunks from @@ -193,8 +196,9 @@
When a recipient decrypts a shielded output, they obtain a memo key
-Kmemo. From this they derive
-encryption_key
as above, and then proceed as follows:
encryption_key
as above, and then proceed as
+follows:
counter = 0
and
final_chunk = 0x00
.fAllPruned
uint8
nonceOrHash
byte[32]
nMemoChunks
compactSize
pruned
byte[
ceiling(n
M
e
m
o
C
h
u
n
k
s
/8)]
]
vMemoChunks
.vMemoChunks
MemoChunk[nMemoChunks]
Change
Each Sapling or Orchard note plaintext (denoted np) -consists of
-âââ(leadByteâ âŚâ đšđ,âdâ âŚâ đš[âd],ârseedâ âŚâ đšđ[đđ],âmemoâ âŚâ đšđ[đđđ])
+class="math inline">\(\mathbf{np}\)) consists of +\(\hspace{2em}(\mathsf{leadByte} \;âŚ\; +\mathbb{B^{Y}}, \mathsf{d} \;âŚ\; \mathbb{B^{[\ell_{\mathsf{d}}]}}, +\mathsf{rseed} \;âŚ\; \mathbb{B^{Y[32]}}, \mathsf{memo} \;âŚ\; +\mathbb{B^{Y[512]}})\)
to
@@ -333,15 +338,17 @@Changes to the version of the transaction in which it will be included; specifically whether that version is pre-v6, or v6-onward.
Each pre-v6 Sapling or Orchard note plaintext (denoted np) -consists of
-âââ(leadByteâ âŚâ đšđ,âdâ âŚâ đš[âd],ârseedâ âŚâ đšđ[đđ],âmemoâ âŚâ đšđ[đđđ])
+class="math inline">\(\mathbf{np}\)) consists of +\(\hspace{2em}(\mathsf{leadByte} \;âŚ\; +\mathbb{B^{Y}}, \mathsf{d} \;âŚ\; \mathbb{B^{[\ell_{\mathsf{d}}]}}, +\mathsf{rseed} \;âŚ\; \mathbb{B^{Y[32]}}, \mathsf{memo} \;âŚ\; +\mathbb{B^{Y[512]}})\)
Each v6-onward Sapling or Orchard note plaintext (denoted np) -consists of
-âââ(leadByteâ âŚâ đšđ,âdâ âŚâ đš[âd],ârseedâ âŚâ đšđ[đđ],âKmemoâ âŚâ đšđ[đđ])
+class="math inline">\(\mathbf{np}\)) consists of +\(\hspace{2em}(\mathsf{leadByte} \;âŚ\; +\mathbb{B^{Y}}, \mathsf{d} \;âŚ\; \mathbb{B^{[\ell_{\mathsf{d}}]}}, +\mathsf{rseed} \;âŚ\; \mathbb{B^{Y[32]}}, \mathsf{K^{memo}} \;âŚ\; +\mathbb{B^{Y[32]}})\)
In § 5.5 âEncodings of Note Plaintexts and Memo Fieldsâ Changes to the
- 8-bit leadByte
-88-bit d
-64-bit v
-256-bit rseed
-32-byte Kmemo
+
+
8-bit \(\mathsf{leadByte}\)
+88-bit \(\mathsf{d}\)
+64-bit \(\mathsf{v}\)
+256-bit \(\mathsf{rseed}\)
+32-byte \(\mathsf{K^{memo}}\)
A value consisting of 32 0
x
F
F
-bytes for Kmemo is used to
-indicate that there is no memo for this note plaintext.
In § 4.7.2 âSending Notes (Sapling)â Changes to the
Add a reference to this ZIP specifying the construction of the
memo bundle and derivation of Kmemo in the case of a v6-onward
-note plaintext.
Change
-Let npâ=â(leadByte,âd,âv,ârseed,âmemo)â.
+Let \(\mathbf{np} = (\mathsf{leadByte}, +\mathsf{d}, \mathsf{v}, \mathsf{rseed}, \mathsf{memo})\).
to
-Let np be the -encoding of a Sapling note plaintext using leadByte, d, -v, rseed, and either memo for a pre-v6 note plaintext or Kmemo for a v6-onward note -plaintext.
+Let \(\mathbf{np}\) be the encoding +of a Sapling note plaintext using \(\mathsf{leadByte}\), \(\mathsf{d}\), \(\mathsf{v}\), \(\mathsf{rseed}\), and either \(\mathsf{memo}\) for a pre-v6 note plaintext +or \(\mathsf{K^{memo}}\) for a +v6-onward note plaintext.
replacing âSaplingâ with Orchard in the case of § 4.7.3.
Change
-Let npâ=â(leadByte,âd,âv,ârseed,âmemo) -be the Sapling or Orchard note plaintext. np is -encoded as defined in § 5.5 âEncodings of Note Plaintexts and Memo -Fieldsâ.
+Let \(\mathbf{np} = (\mathsf{leadByte}, +\mathsf{d}, \mathsf{v}, \mathsf{rseed}, \mathsf{memo})\) be the +Sapling or Orchard note plaintext. \(\mathbf{np}\) is encoded as defined in § +5.5 âEncodings of Note Plaintexts and Memo Fieldsâ.
to
-Let np be the -encoding of the Sapling or Orchard note plaintext (which may be pre-v6 -or v6-onward), as defined in § 5.5 âEncodings of Note Plaintexts and -Memo Fieldsâ.
+Let \(\mathbf{np}\) be the encoding +of the Sapling or Orchard note plaintext (which may be pre-v6 or +v6-onward), as defined in § 5.5 âEncodings of Note Plaintexts and Memo +Fieldsâ.
Add another normative note to that section:
-
- Cenc will be of length -either 580 or 100 bytes, depending on whether np is a -pre-v6 or v6-onward note plaintext.
+- \(\mathsf{C^{enc}}\) will be of +length either 580 or 100 bytes, depending on whether \(\mathbf{np}\) is a pre-v6 or v6-onward note +plaintext.
All of these changes apply identically to Mainnet and Testnet.
@@ -494,39 +504,29 @@- | Memo size | -+ | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Chunk size | +Memo size ⤠256 bytes | +Memo size = 512 bytes | ||||||||||||||||||||||||||||||
Chunk size | -⤠256 bytes | -512 bytes | -||||||||||||||||||||||||||||||
============ | -====================== | -====================== | -||||||||||||||||||||||||||||||
Pre-231 | 20 @ 10240 ( 0.00%) | 20 @ 10240 ( 0.00%) | ||||||||||||||||||||||||||||||
512 | 20 @ 11220 (+ 9.57%) | 20 @ 11220 (+ 9.57%) | ||||||||||||||||||||||||||||||
256 | 40 @ 12200 (+19.14%) | 20 @ 11540 (+12.70%) | ||||||||||||||||||||||||||||||
256 20-out | 20 @ 6100 (-40.43%) | @@ -544,39 +544,29 @@ |
- | Memo size | -+ | ||||||
---|---|---|---|---|---|---|---|---|
Chunk size | +Memo size ⤠256 bytes | +Memo size = 512 bytes | ||||||
Chunk size | -⤠256 bytes | -512 bytes | -||||||
============ | -====================== | -====================== | -||||||
Pre-231 | 20 @ 10240 ( 0.00%) | 20 @ 10240 ( 0.00%) | ||||||
512 | 20 @ 10900 (+ 6.45%) | 20 @ 10900 (+ 6.45%) | ||||||
256 | 40 @ 11560 (+12.89%) | 20 @ 11220 (+ 9.57%) | ||||||
256 20-out | 20 @ 5780 (-43.55%) | @@ -596,21 +586,22 @@ | ||||||
Bytes | Name | Data Type | @@ -114,7 +119,7 @@||||||
8 | burnAmount |
uint64 |
@@ -122,9 +127,9 @@
The burn_amount of a transaction is
-defined to be the value of the burnAmount
field if present,
-and otherwise 0.
The \(\mathsf{burn\_amount}\) of a
+transaction is defined to be the value of the burnAmount
+field if present, and otherwise 0.
Notes:
-[NU7 onward] burn_amount MUST be in -the range {0..MAX_MONEY}.
+[NU7 onward] \(\mathsf{burn\_amount}\) MUST be in the +range \(\{ 0 .. \mathsf{MAX\_MONEY} +\}\).
Relative to the sighash algorithm defined in ZIP 244, the sighash
algorithm that applies to v6 transactions differs by appending the
-encoding of burn_amount to the Common
-Transaction Fields that are the input to the digest in T.1:
-header_digest
\(\mathsf{burn\_amount}\)
+to the Common Transaction Fields that are the input to the digest in
+T.1: header_digest
15:
diff --git a/rendered/zip-0234.html b/rendered/zip-0234.html index 35ada1278..fac4f75ae 100644 --- a/rendered/zip-0234.html +++ b/rendered/zip-0234.html @@ -3,7 +3,9 @@T.1f: burn_amount (8-byte little-endian burn amount)
ZIP 234: Network Sustainability Mechanism: Issuance Smoothing - + + + @@ -35,7 +37,7 @@Terminology
The terms âMainnetâ and âTestnetâ are to be interpreted as described in § 3.12 âMainnet and Testnetâ. 4
-The symbol âââ ââ means +
The symbol â\(\,\cdot\,\)â means multiplication, as described in § 2 âNotationâ. 5
âZEC/TAZâ refers to the native currency of Zcash on a given network, @@ -43,11 +45,12 @@
Terminology
The terms âBlock Subsidyâ, âIssuanceâ, and âBurningâ are to be interpreted as described in ZIP 233. 6
-Let PostBlossomHalvingInterval be as +
Let \(\mathsf{PostBlossomHalvingInterval}\) be as defined in 7.
-MAX_MONEY, as defined in § 5.3 -âConstantsâ \(\mathsf{MAX\_MONEY}\), as defined +in § 5.3 âConstantsâ 8, is the total ZEC/TAZ supply cap measured in zatoshi, corresponding to 21,000,000 ZEC. This is slightly larger than the supply cap for the current issuance mechanism, but is @@ -55,13 +58,13 @@
Terminology
âIssued Supplyâ - The Issued Supply at a given height of a block chain is the total ZEC/TAZ value in all chain value pool balances at that height, as calculated by IssuedSupply(height) defined in § 4.17 âChain -Value Pool Balancesâ. 9
+class="math inline">\(\mathsf{IssuedSupply}(\mathsf{height})\) +defined in § 4.17 âChain Value Pool Balancesâ. 9âMoney Reserveâ - The Money Reserve at a given height of a block chain is the total ZEC/TAZ value remaining to be issued, as calculated -by MAX_MONEYâ ââ IssuedSupply(height)â.
+by \(\mathsf{MAX\_MONEY} - +\mathsf{IssuedSupply}(\mathsf{height})\).Abstract
This ZIP proposes a change to how nodes calculate the block subsidy.
@@ -123,9 +126,10 @@Requirements
Specification
Parameters
--
B
L
O
C
K
_
S
U
B
S
I
D
Y
_
F
R
A
C
T
I
O
N
â=â4126/10_000_000_000â=â0.0000004126+
DEPLOYMENT_BLOCK_HEIGHT
=TBD
\(\mathsf{BLOCK\_SUBSIDY\_FRACTION} = 4126 +/ 10\_000\_000\_000 = 0.0000004126\)
+\(\mathsf{DEPLOYMENT\_BLOCK\_HEIGHT} = +\mathsf{TBD}\)
The block height will be chosen by the following criteria:
- It is after NU7 activation height.
@@ -146,26 +150,30 @@Parameters
calculated up-front). This means with the pre-defined constant parameter approach, issuance will jump up some amount at activation. This amount should be equivalent to all ZEC burnt prior to that height times -B
L
O
C
K
_
S
U
B
S
I
D
Y
_
F
R
A
C
T
I
O
N
. +\(\mathsf{BLOCK\_SUBSIDY\_FRACTION}\). For example, if a total of 100,000 ZEC were burnt prior to the pre-defined constant activation height, then at activation the issuance would be larger than BTC-style issuance by 100_000 -ZECâ â âB
L
O
C
K
_
S
U
B
S
I
D
Y
_
F
R
A
C
T
I
O
N
â, -which we calculate equals 0.04126 ZEC. -This example is chosen to demonstrate that a very large burn amount -(much larger than expected) would elevate issuance by a relatively small -amount. For this reason, we believe a pre-defined constant is a better -approach to achieving Key Objective 6 than a âdynamic latchâ logic -because it is so much simpler to implement and reason about. -MoneyReserveAfter(height)â â= The -value of the Money Reserve after the specified block height.
-Issuance Calculation
-At the
+class="math inline">\(100\_000\textsf{ ZEC} \cdot +\mathsf{BLOCK\_SUBSIDY\_FRACTION}\), which we calculate equals +\(0.04126\) ZEC. This example is chosen +to demonstrate that a very large burn amount (much larger than expected) +would elevate issuance by a relatively small amount. For this reason, we +believe a pre-defined constant is a better approach to achieving Key +Objective 6 than a âdynamic latchâ logic because it is so much simpler +to implement and reason about.DEPLOYMENT_BLOCK_HEIGHT
, nodes should switch from -the current issuance calculation, to the following:BlockSubsidy(height)â=âceiling(
+class="math inline">\(\mathsf{MoneyReserveAfter}(\mathsf{height}) +=\) The value of the Money Reserve after the specified block +height. +B
L
O
C
K
_
S
U
B
S
I
D
Y
_
F
R
A
C
T
I
O
N
â â â MoneyReserveAfter(heightâ ââ 1))Issuance Calculation
+At the \(\mathsf{DEPLOYMENT\_BLOCK\_HEIGHT}\), nodes +should switch from the current issuance calculation, to the +following:
+\(\mathsf{BlockSubsidy}(\mathsf{height}) = +\mathsf{ceiling}(\mathsf{BLOCK\_SUBSIDY\_FRACTION} \cdot +\mathsf{MoneyReserveAfter}(\mathsf{height} - 1))\)
Applicability
All of these changes apply identically to Mainnet and Testnet.
Rationale
@@ -177,20 +185,24 @@Rationale
BLOCK_SUBSIDY_FRACTION
Let IntendedMoneyReserveFractionRemainingAfterFourYearsâ=â0.5â.
-The value 4126/10_000_000_000 -satisfies the approximation within Âą0.002%:
-(1â ââ
+class="math inline">\(\mathsf{IntendedMoneyReserveFractionRemainingAfterFourYears} += 0.5\). +B
L
O
C
K
_
S
U
B
S
I
D
Y
_
F
R
A
C
T
I
O
N
)PostBlossomHalvingIntervalâââIntendedMoneyReserveFractionRemainingAfterFourYearsThe value \(4126 / +10\_000\_000\_000\) satisfies the approximation within \(\pm 0.002\%\):
+\((1 - +\mathsf{BLOCK\_SUBSIDY\_FRACTION})^\mathsf{PostBlossomHalvingInterval} +\approx +\mathsf{IntendedMoneyReserveFractionRemainingAfterFourYears}\)
This implies that after a period of 4 years around half of Money Reserve will have been issued as block subsidies, thus satisfying Requirement 4.
The largest possible value in the Money Reserve is MAX_MONEY, in the theoretically possible case -that all issued funds are burned. If this happened, the largest interim -sum in the block subsidy calculation would be MAX_MONEYâ â â 4126/10_000_000_000â.
+class="math inline">\(\mathsf{MAX\_MONEY}\), in the theoretically +possible case that all issued funds are burned. If this happened, the +largest interim sum in the block subsidy calculation would be \(\mathsf{MAX\_MONEY} \cdot 4126 / +10\_000\_000\_000\).This uses 62.91 bits, which is just under the 63-bit limit for signed twoâs complement 64-bit integer amount types.
The numerator could be brought closer to the limit by using a larger diff --git a/rendered/zip-0235.html b/rendered/zip-0235.html index 4b2213bf9..07a86bd7d 100644 --- a/rendered/zip-0235.html +++ b/rendered/zip-0235.html @@ -3,7 +3,9 @@
ZIP 235: Burn 60% of Transaction Fees - + + + @@ -35,23 +37,24 @@Terminology
The terms âMainnetâ and âTestnetâ are to be interpreted as described in § 3.12 âMainnet and Testnetâ. 4
-The symbol âââ ââ means -multiplication, as described in § 2 âNotationâ. [^protocol-notation]
+The symbol â\(\,\cdot\,\)â means +multiplication, as described in § 2 âNotationâ. 5
âZEC/TAZâ refers to the native currency of Zcash on a given network, i.e. ZEC on Mainnet and TAZ on Testnet.
The terms âBlock Subsidyâ, âIssuanceâ, and âBurningâ are to be -interpreted as described in ZIP 233. 5
+interpreted as described in ZIP 233. 6Abstract
This ZIP proposes to burn 60% of transaction fees, while the remaining 40% is directed as before, providing a deflationary effect, and building the groundwork for long-term support of the Zcash network -via the new block subsidy rules proposed by ZIP 234 6.
+via the new block subsidy rules proposed by ZIP 234 7.Motivation
-ZIP 233 (âNetwork Sustainability Mechanism: Burningâ 7) +
ZIP 233 (âNetwork Sustainability Mechanism: Burningâ 8) describes a method by which ZEC can be burned to support network sustainability.
By introducing a requirement that a certain proportion of transaction @@ -62,8 +65,8 @@
Benefits to the Network
- Network Sustainability: This mechanism involves temporarily reducing the supply of ZEC, similar to asset burning in -Ethereumâs EIP-1559 8, but with long-term sustainability +Ethereumâs EIP-1559 9, but with long-term sustainability benefits, as the burned funds effectively boost future mining rewards, making it an attractive option for current and future Zcash users.
- Incentivizing Transaction Inclusion: By maintaining @@ -98,13 +101,14 @@
Requirements
Specification
Consensus Rule Changes
For a given block, the coinbase transaction MUST have a burn_amount, as defined in 9, -that is greater than or equal to floor(transactionFeesâ â â 6/10)â.
-The version of a coinbase transaction MUST be v6 or later \(\mathsf{burn\_amount}\), as defined in 10.
+role="doc-noteref">10, that is greater than or equal to +\(\mathsf{floor}(\mathsf{transactionFees} +\cdot 6 / 10)\). +The version of a coinbase transaction MUST be v6 or later 11.
Applicability
All of these changes apply identically to Mainnet and Testnet.
Rationale
@@ -117,28 +121,29 @@Rationale
for requiring the coinbase transaction to be v6 or laterThere is no explicit mechanism in prior transaction versions to burn the required funds. Since burn_amountâ=â0 for transaction versions -prior to v6, absent the rule about the coinbase transaction version it -would be technically possible to satisfy the constraint on burn_amount with earlier versions than v6, -but only when transactionFeesâ=â0. That -would introduce a corner case in the transaction consensus rules that is -not useful, since it is expected that the transactionFees will normally be +class="math inline">\(\mathsf{burn\_amount} = 0\) for transaction +versions prior to v6, absent the rule about the coinbase transaction +version it would be technically possible to satisfy the constraint on +\(\mathsf{burn\_amount}\) with earlier +versions than v6, but only when \(\mathsf{transactionFees} = 0\). That would +introduce a corner case in the transaction consensus rules that is not +useful, since it is expected that the \(\mathsf{transactionFees}\) will normally be non-zero.
Estimated impact on miners
Over 100,000 blocks starting at block 2235515, there were 316130 transactions. 60608 of them are categorized as âsandblastingâ transactions. The remaining transactions have an average of 5.46 logical -actions (see ZIP 317 11).
+actions (see ZIP 317 12).The total fees paid to miners from those transactions, assuming the ZIP 317 regime, would be 87.86 ZEC. 100,000 blocks is approximately 3 months of blocks. Extrapolating to a year, we would expect 351.44 ZEC in fees paid to miners over a year.
If 60% of these fees burned, that would be 210.864 ZEC per year. 12
+href="#fn13" class="footnote-ref" id="fnref13" +role="doc-noteref">13Considerations for the Future
If transaction fees were to increase, further modifications can @@ -161,10 +166,10 @@
Considerations for the
The implementation of this ZIP MUST be deployed at the same time or -after ZIP 233 (âNSM: Burningâ 13), and ZIP 234 (âNSM: -Issuance Smoothingâ 14).
+after ZIP 233 (âNSM: Burningâ 14), and ZIP 234 (âNSM: +Issuance Smoothingâ 15).ZIP 233: Network Sustainability
-Mechanism: Burning Zcash Protocol
+Specification, Version 2024.5.1 [NU6]. Section 2: NotationâŠď¸
ZIP 234: Network Sustainability
-Mechanism: Issuance Smoothing ZIP 234: Network Sustainability
+Mechanism: Issuance SmoothingâŠď¸
ZIP 234: Network Sustainability
-Mechanism: Issuance Smoothing ZIP 234: Network Sustainability
+Mechanism: Issuance SmoothingâŠď¸
The nonmalleable transaction identifier specified by this ZIP will be used in the place of the current malleable transaction identifier within the Merkle tree committed to by the hashMerkleRoot
value. However, this change now means that hashMerkleRoot
is not sufficient to fully commit to the transaction data, including witnesses, that appear within the block.
As a consequence, we now need to add a new commitment to the block header. This commitment will be the root of a Merkle tree having leaves that are transaction authorizing data commitments, produced according to the Authorizing Data Commitment part of this specification. The insertion order for this Merkle tree MUST be identical to the insertion order of transaction identifiers into the Merkle tree that is used to construct hashMerkleRoot
, such that a path through this Merkle tree to a transaction identifies the same transaction as that path reaches in the tree rooted at hashMerkleRoot
.
This new commitment is named hashAuthDataRoot
and is the root of a binary Merkle tree of transaction authorizing data commitments having height
- \(\mathsf{ceil(log_2(tx\_count))}\)
+ \(\mathsf{ceil(log_2(tx\_count))}\!\)
, padded with leaves having the "null" hash value [0u8; 32]
. Note that
\(\mathsf{log_2(tx\_count)}\)
is well-defined because
- \(\mathsf{tx\_count} > 0\)
+ \(\mathsf{tx\_count} > 0\!\)
, due to the coinbase transaction in each block. Non-leaf hashes in this tree are BLAKE2b-256 hashes personalized by the string "ZcashAuthDatHash"
.
Changing the block header format to allow space for an additional commitment is somewhat invasive. Instead, the name and meaning of the hashLightClientRoot
field, described in ZIP 221 4, is changed.
hashLightClientRoot
is renamed to hashBlockCommitments
. The value of this hash is the BLAKE2b-256 hash personalized by the string "ZcashBlockCommit"
of the following elements:
The inputs to the signature algorithm are:
The inputs to the verification algorithm are:
The signature MUST be verified as follows:
@@ -212,20 +214,20 @@ \(coinType\) be the 4-byte little-endian encoding of the coin type in its index form, not its hardened form (i.e. 133 for mainnet Zcash).The raw form of a ZIP 304 signature is - \(\mathsf{nf}\,||\,\mathsf{LEBS2OSP}_{256}(\mathsf{repr}_{\mathbb{J}}(\mathsf{rk}))\,||\,zkproof\,||\,spendAuthSig\) + \(\mathsf{nf}\,||\,\mathsf{LEBS2OSP}_{256}(\mathsf{repr}_{\mathbb{J}}(\mathsf{rk}))\,||\,zkproof\,||\,spendAuthSig\!\) , for a total size of 320 bytes.
When encoding a ZIP 304 signature in a human-readable format, implementations SHOULD use standard Base64 for compatibility with the signmessage
and verifymessage
RPC methods in zcashd
. ZIP 304 signatures in this form are 428 bytes. The encoded form is the string
- \(\texttt{"zip304:"}\)
+ \(\texttt{âzip304:â}\)
followed by the result of Base64-encoding 2 the raw form of the signature.
We use a note value of \(1\) zatoshi instead of zero to ensure that the payment address is fully bound to - \(zkproof\) + \(zkproof\!\) . Notes with zero value have certain constraints disabled inside the circuit.
We set \(\mathsf{rcm}\) @@ -287,7 +289,7 @@
The one component that is inherently malleable is - \(zkproof\) + \(zkproof\!\) . The zero-knowledge property of a Groth16 proof implies that anyone can take a valid proof, and re-randomize it to obtain another valid proof with a different encoding. We prevent this by binding the encoding of \(zkproof\) to - \(spendAuthSig\) + \(spendAuthSig\!\) , by including \(zkproof\) in the message digest.
diff --git a/rendered/zip-0307.html b/rendered/zip-0307.html index 07a72407c..eaf3dcc7e 100644 --- a/rendered/zip-0307.html +++ b/rendered/zip-0307.html @@ -3,7 +3,9 @@We also define the following notation here:
@@ -173,12 +175,12 @@ means the sequence of values inclusive of \(a\) and exclusive of - \(b\) + \(b\!\) .Given a payment disclosure - \(\mathsf{pd}\) + \(\mathsf{pd}\!\) , a transaction - \(\mathsf{tx}\) + \(\mathsf{tx}\!\) , and the height of the block in which \(\mathsf{tx}\) was mined (which we assume was verified by the caller), the verifier proceeds as follows:
@@ -385,21 +387,21 @@Payment disclosures that prove Sapling spend authority are not required to reveal a sender address. This is because it is impossible: we can "prove" the transaction came from any of the diversified addresses linked to the spending key. Fundamentally, the "sender" of a transaction is anyone who has access to the corresponding spend authority; in the case of Sapling, a spend authority corresponds to multiple diversified addresses. In situations where a sender address is already known to the verifier of the payment disclosure (or publically), it may still be useful to have the option of linking the payment disclosure to that address.
The types Scalar, Element, and G are defined in 7, as well as the notation for elliptic-curve arithmetic, which uses the additive notation. Note that this notation differs from that used in the Zcash Protocol Specification. For example, G.ScalarMult(P, k)
is used for scalar multiplication, where the protocol spec would use
\([k] P\)
with the group implied by
- \(P\)
+ \(P\!\)
.
An additional per-ciphersuite hash function is used, denote HR(m)
, which receives an arbitrary-sized byte string and returns a Scalar. It is defined concretely in the Ciphersuites section.
G.Order()
.G.Order()
. (This is equivalent to
- \(\mathsf{H}^\circledast(m)\)
+ \(\mathsf{H}^\circledast(m)\!\)
, as defined by the
\(\mathsf{RedJubjub}\)
scheme instantiated in 12.)G.Order()
.G.Order()
. (This is equivalent to
- \(\mathsf{H}^\circledast(m)\)
+ \(\mathsf{H}^\circledast(m)\!\)
, as defined by the
\(\mathsf{RedPallas}\)
scheme instantiated in 12.)R
value from the signature is not influenced by the randomizer so we just need to focus on the z
value (using FROST notation). Recall that z
must equal to r + (c * sk)
, and that each signature share is z_i = (hiding_nonce + (binding_nonce * binding_factor)) +
(lambda_i * c * sk_i)
. The first terms are not influenced by the randomizer so we can only look into the second term of each top-level addition, i.e. c
* sk
must be equal to sum(lambda_i * c * sk_i)
for each participant i
. Under re-randomization these become c * (sk + randomizer)
(see
- \(\mathsf{RedDSA.RandomizedPrivate}\)
+ \(\mathsf{RedDSA.RandomizedPrivate}\!\)
, which refers to the randomizer as
- \(\alpha\)
+ \(\alpha\!\)
) and sum(lambda_i * c * (sk_i + randomizer))
. The latter can be rewritten as c * (sum(lambda_i * sk_i) + randomizer *
sum(lambda_i)
. Since sum(lambda_i * sk_i) == sk
per the Shamir secret sharing mechanism used by FROST, and since sum(lambda_i) == 1
18, we arrive at c * (sk + randomizer)
as required.randomizer_generate
generates randomizer uniformly at random as required by
- \(\mathsf{RedDSA.GenRandom}\)
+ \(\mathsf{RedDSA.GenRandom}\!\)
; and signature generation is compatible with
- \(\mathsf{RedDSA.RandomizedPrivate}\)
+ \(\mathsf{RedDSA.RandomizedPrivate}\!\)
,
- \(\mathsf{RedDSA.RandomizedPublic}\)
+ \(\mathsf{RedDSA.RandomizedPublic}\!\)
,
\(\mathsf{RedDSA.Sign}\)
and
diff --git a/rendered/zip-0316.html b/rendered/zip-0316.html
index 23a70cfb3..594829c81 100644
--- a/rendered/zip-0316.html
+++ b/rendered/zip-0316.html
@@ -3,7 +3,9 @@
The Human-Readable Part is as specified for a Unified Viewing Key in Revisions.
@@ -309,7 +311,7 @@When deriving a UIVK from a UFVK containing Typecodes \(\mathtt{0xE0}\) and/or - \(\mathtt{0xE1}\) + \(\mathtt{0xE1}\!\) , these Metadata Items MUST be retained unmodified in the derived UIVK.
When deriving a Unified Address from a UFVK or UIVK containing a Metadata Item having Typecode - \(\mathtt{0xE0}\) + \(\mathtt{0xE0}\!\) , the derived Unified Address MUST contain a Metadata Item having Typecode \(\mathtt{0xE0}\) such that the Address Expiry Height of the resulting address is less than or equal to the Expiry Height of the viewing key.
When deriving a Unified Address from a UFVK or UIVK containing a Metadata Item having Typecode - \(\mathtt{0xE1}\) + \(\mathtt{0xE1}\!\) , the derived Unified Address MUST contain a Metadata Item having Typecode \(\mathtt{0xE1}\) such that the Address Expiry Time of the resulting address is less than or equal to the Expiry Time of the viewing key.
@@ -467,7 +469,7 @@ be the remaining \(32\) bytes of - \(I_\mathsf{ovk}\) + \(I_\mathsf{ovk}\!\) .Since an external P2PKH FVK encodes the chain code and public key at the Account level, we can derive both external and internal child keys from it, as described in BIP 44 34. It is possible to derive an internal P2PKH FVK from the external P2PKH FVK (i.e. its parent) without having the external spending key, because child derivation at the Change level is non-hardened.
@@ -502,7 +504,7 @@Note: A diversifier index of 0 may not generate a valid Sapling diversifier (with probability - \(1/2\) + \(1/2\!\) ). Some wallets (either prior to the deployment of ZIP 316, in violation of the above requirement, or because they do not include a Sapling component in their UAs) always generate a Transparent P2PKH address at diversifier index 0. Therefore, all Zcash wallets, whether or not they support Unified Addresses, MUST assume that there may be transparent funds associated with diversifier index 0 for each ZIP 32 account, even in cases where the wallet implementation would not generate a Unified Address with that index for a given account. This is necessary to ensure reliable recovery of funds if key material is imported between wallets.
The following derivations are applied to each component IVK using the diversifier index:
We instantiate \(H_i(u)\) by - \(\mathsf{BLAKE2bâ}(8\ell_L)(\texttt{âUA_F4Jumble_Hâ} \,||\,\) + \(\mathsf{BLAKE2bâ}(8\ell_L)(\texttt{âUA\_F4Jumble\_Hâ} \,||\,\) \([i, 0, 0], u),\) with \(\ell_H = 64.\) @@ -656,7 +658,7 @@ as the first \(\ell_R\) bytes of the concatenation of - \([\mathsf{BLAKE2bâ}512(\texttt{âUA_F4Jumble_Gâ} \,||\, [i] \,||\,\) + \([\mathsf{BLAKE2bâ}512(\texttt{âUA\_F4Jumble\_Gâ} \,||\, [i] \,||\,\) \(\mathsf{I2LEOSP}_{16}(j), u) \text{ for } j \text{ from}\) \(0 \text{ up to } \mathsf{ceiling}(\ell_R/\ell_H)-1].\)
@@ -734,7 +736,7 @@ is close to \(c.\) ( - \(b'\) + \(\!b'\) and \(d'\) will not be close to @@ -809,7 +811,7 @@ part of the jumbled encoding three times from a less memory-constrained device. It is essential that the streamed value of \(d\) is the same on each pass, which can be verified using a Message Authentication Code (with key held only by the Consumer) or collision-resistant hash function. After the first pass of - \(d\) + \(d\!\) , the implementation is able to compute \(y;\) after the second pass it is able to compute diff --git a/rendered/zip-0317.html b/rendered/zip-0317.html index bf2e70936..8dab6cbe0 100644 --- a/rendered/zip-0317.html +++ b/rendered/zip-0317.html @@ -3,7 +3,9 @@Let \(min\_actions\) be the minimum number of logical actions that can be used to execute economically relevant transactions that produce change. Due to the aforementioned padding, - \(min\_actions = 2\) + \(min\_actions = 2\!\) .
Having a grace window size greater than \(min\_actions\) would increase the cost to create such a minimal transaction. If the cost we believe that users will tolerate for a minimal transaction is - \(B\) + \(B\!\) , then possible choices of \(marginal\_fee\) are bounded above by - \(B / \max(min\_actions, grace\_actions)\) + \(B / \max(min\_actions, grace\_actions)\!\) . Therefore, the optimal choice of \(grace\_actions\) to maximize the per-logical-action cost of denial-of-service attacks for a given - \(B\) + \(B\!\) , is - \(grace\_actions = min\_actions = 2\) + \(grace\_actions = min\_actions = 2\!\) . This also ensures that a denial-of-service adversary does not gain a significant per-logical-action cost advantage by using transactions with a smaller or larger number of logical actions.
The specified formula calculates the contribution of transparent inputs and outputs based on their total size relative to a typical input or output. Another considered approach was to calculate this contribution simply as - \(\mathsf{max}(transparent\_inputs, transparent\_outputs)\) + \(\mathsf{max}(transparent\_inputs, transparent\_outputs)\!\) . However, this would allow a denial-of-service adversary to create transactions with transparent components containing arbitrarily large scripts.
The chosen values for \(p2pkh\_standard\_input\_size\) @@ -298,7 +300,7 @@ \(unpaid\_actions(tx) = \begin{cases}\mathsf{max}\!\left(0,\, \mathsf{max}(grace\_actions,\, tx.\!logical\_actions) - \mathsf{floor}\!\left(\frac{tx.fee}{marginal\_fee}\right)\right),&\textsf{if }tx\textsf{ is a non-coinbase transaction} \\ 0,&\textsf{if }tx\textsf{ is a coinbase transaction.}\end{cases}\)
Let - \(block\_unpaid\_actions(block) = \sum_{tx \,\in\, block}\, unpaid\_actions(tx)\) + \(block\_unpaid\_actions(block) = \sum_{tx \,\in\, block}\, unpaid\_actions(tx)\!\) .
The following algorithm is RECOMMENDED for constructing a block template from a set of transactions in a node's mempool:
"tex"
.For Testnet addresses, the required lead bytes of a P2PKH address in step 2 are
- \([\mathtt{0x1D}, \mathtt{0x25}]\)
+ \([\mathtt{0x1D}, \mathtt{0x25}]\!\)
, and the "textest"
HRP is used when reencoding in step 3.
A TEX address can be parsed by reversing this encoding, i.e.:
There is some ambiguity in the specification of a transaction's "memory size", allowing implementations to use different approximations. Currently, zcashd uses a size computed by the RecursiveDynamicUsage
function, and zebrad uses the serialized size. This has been changed from a previous version of this ZIP that specified use of the serialized size, to reflect how the implementation in zcashd has worked since it was first deployed 7.
The threshold 10000 for the cost function is chosen so that the size in bytes of a minimal fully shielded Orchard transaction with 2 shielded actions (having a serialized size of 9165 bytes) will fall below the threshold. This has the effect of ensuring that such transactions are not evicted preferentially to typical transparent or Sapling transactions because of their size. This constant has been updated 6 from 4000 to 10000 in parallel with the changes for deployment of ZIP 317 5; the previous value had been chosen based on the typical size of fully shielded Sapling transactions.
The proposed eviction policy differs significantly from that of Bitcoin Core 8, which is primarily fee-based. This reflects differing philosophies about the motivation for fees and the level of fee that legitimate users can reasonably be expected to pay. The proposed eviction weight function does involve a penalty for transactions with a fee lower than the ZIP 317 5 conventional fee, but since there is no further benefit (as far as mempool limiting is concerned) to increasing the fee above the conventional fee value, it creates no pressure toward escalating fees. For transactions with a memory size up to 10000 bytes, this penalty makes a transaction that pays less than the conventional fee five times as likely to be chosen for eviction (because - \(10000 + 40000 = 50000 = 10000 \times 5\) + \(10000 + 40000 = 50000 = 10000 \times 5\!\) ).
The fee penalty is not included in the cost that determines whether the mempool is considered full. This ensures that a DoS attacker does not have an incentive to pay less than the conventional fee in order to cause the mempool to be considered full sooner.
The default value of 80000000 for mempooltxcostlimit
represents no more than 40 blocksâ worth of transactions in the worst case, which is the default expiration height after the Blossom network upgrade 2. It would serve no purpose to make it larger.
After the section Funding streams, a new section is added with the heading "Deferred Development Fund Chain Value Pool Balance" and the following contents:
@@ -63,14 +65,14 @@The \(\mathsf{ChainValuePoolBalance^{Deferred}}\) chain value pool balance for a given block chain is the sum of the values of payments to - \(\mathsf{DEFERRED}\_\mathsf{POOL}\) + \(\mathsf{DEFERRED\_POOL}\) for transactions in the block chain.
Equivalently, \(\mathsf{ChainValuePoolBalance^{Deferred}}\) @@ -97,11 +99,11 @@
After the list of post-Canopy consensus rules, the following paragraphs are added:
--These rules are reproduced in [#protocol-fundingstreams].
+These rules are reproduced in 10.
The effect of the definition of \(\mathsf{ChainValuePoolBalance^{Deferred}}\) above is that payments to the - \(\mathsf{DEFERRED}\_\mathsf{POOL}\) + \(\mathsf{DEFERRED\_POOL}\) cause \(\mathsf{FundingStream[FUND].Value}(\mathsf{height})\) to be added to \(\mathsf{ChainValuePoolBalance^{Deferred}}\) for the block chain including that block.
In the section Deployment 14, the following sentence is added:
+In the section Deployment 14, the following sentence is added:
-Changes to support deferred funding streams are to be deployed with NU6. 15
+Changes to support deferred funding streams are to be deployed with NU6. 15
In section 4.17 Chain Value Pool Balances 5 (which is new in version 2024.5.1 of the protocol specification), include the following:
+In section 4.17 Chain Value Pool Balances 5 (which is new in version 2024.5.1 of the protocol specification), include the following:
Define \(\mathsf{totalDeferredOutput}\) - as in 9.
-Then, consistent with 11, the deferred development fund chain value pool balance for a block chain up to and including height + as in 9.
+Then, consistent with 11, the deferred development fund chain value pool balance for a block chain up to and including height \(\mathsf{height}\) is given by \(\mathsf{ChainValuePoolBalance^{Deferred}}(\mathsf{height}) := \sum_{\mathsf{h} = 0}^{\mathsf{height}} \mathsf{totalDeferredOutput}(\mathsf{h})\!\) @@ -165,7 +167,7 @@
Changes to ZIP 207 -
In section 7.1.2 Transaction Consensus Rules 8, instead of:
+In section 7.1.2 Transaction Consensus Rules 8, instead of:
The total value in zatoshi of transparent outputs from a coinbase transaction, minus \(\mathsf{v^{balanceSapling}}\!\) @@ -176,7 +178,7 @@
Changes to ZIP 207 it will be modified to read:
-For the block at block height - \(\mathsf{height}\) + \(\mathsf{height}\!\) :
- define the "total output value" of its coinbase transaction to be the total value in zatoshi of its transparent outputs, minus @@ -198,8 +200,8 @@
Changes to ZIP 207 [Pre-NU6] The total output value of a coinbase transaction MUST NOT be greater than its total input value.
[NU6 onward] The total output value of a coinbase transaction MUST be equal to its total input value.
Section 7.10 Payment of Funding Streams 10 contains language and definitions copied from ZIP 207; it should be updated to reflect the changes made above.
-The second paragraph of section 1.2 High-level Overview 2 should be updated to take into account the deferred chain value pool. Since that section of the specification is entirely non-normative, we do not give the full wording change here.
+Section 7.10 Payment of Funding Streams 10 contains language and definitions copied from ZIP 207; it should be updated to reflect the changes made above.
+The second paragraph of section 1.2 High-level Overview 2 should be updated to take into account the deferred chain value pool. Since that section of the specification is entirely non-normative, we do not give the full wording change here.
[NU7 onward]
fee
MUST be in the range - \(\{ 0 .. \mathsf{MAX\_MONEY} \}\) + \(\{ 0 .. \mathsf{MAX\_MONEY} \}\!\) .
Let - \(\mathsf{NullSym.}\mathbf{K} := \mathbb{B}^{[256]}\) + \(\mathsf{NullSym.}\mathbf{K} := \mathbb{B}^{[256]}\!\) , - \(\mathsf{NullSym.}\mathbf{P} := \mathbb{B^Y}^{\mathbb{N}}\) + \(\mathsf{NullSym.}\mathbf{P} := \mathbb{B^Y}^{\mathbb{N}}\!\) , and \(\mathsf{NullSym.}\mathbf{C} := \mathbb{B^Y}^{\mathbb{N}}\!\) .
diff --git a/rendered/zip-guide-markdown.html b/rendered/zip-guide-markdown.html index bd3f10743..87cc0679a 100644 --- a/rendered/zip-guide-markdown.html +++ b/rendered/zip-guide-markdown.html @@ -3,7 +3,9 @@ZIP guide-markdown: {Something Short and To the Point} - + + + @@ -126,16 +128,16 @@Comparison of ZIPs to RFCs
places where they are most relevant.
Embedded LaTeX xâ
+â
y is allowed and
-encouraged in ZIPs. The syntax for inline math is
-â:math:
latex
-code`" in reStructuredText or "
latexcode`â
-in Markdown. The rendered HTML will use KaTeX 8,
-which only supports a subset of LaTeX, so you will need to double-check
-that the rendering is as intended.
Embedded LaTeX, e.g. \(x + y\), is
+allowed and encouraged in ZIPs. The syntax for inline math is
+â$latex code$
â in either Markdown or (as a non-standard
+extension) reStructuredText. This syntax does not work in tables for
+reStructuredText; in that case use â:math:`latex code`
â
+instead.
The rendered HTML will use KaTeX 8, which only supports a +subset of LaTeX, so you will need to double-check that the rendering is +as intended.
In general the conventions in the Zcash protocol specification SHOULD be followed. If you find this difficult, donât worry too much about it in initial drafts; the ZIP editors will catch any inconsistencies in diff --git a/rendered/zip-guide.html b/rendered/zip-guide.html index ccc02ec80..04af9b14d 100644 --- a/rendered/zip-guide.html +++ b/rendered/zip-guide.html @@ -3,7 +3,9 @@
Embedded
- \(\LaTeX\)
- is allowed and encouraged in ZIPs. The syntax for inline math is ":math:`latex code`
" in reStructuredText or "$latex code$
" in Markdown. The rendered HTML will use KaTeX 6, which only supports a subset of
+ \(\LaTeX\!\)
+ , e.g.
+ \(x + y\!\)
+ , is allowed and encouraged in ZIPs. The syntax for inline math is "$latex code$
" in either Markdown or (as a non-standard extension) reStructuredText. This syntax does not work in tables for reStructuredText; in that case use ":math:`latex code`
" instead.
The rendered HTML will use KaTeX 6, which only supports a subset of \(\LaTeX\!\) , so you will need to double-check that the rendering is as intended.
In general the conventions in the Zcash protocol specification SHOULD be followed. If you find this difficult, don't worry too much about it in initial drafts; the ZIP editors will catch any inconsistencies in review.
diff --git a/zips/zip-0032.rst b/zips/zip-0032.rst index 69817e5a3..ebf2b6f0c 100644 --- a/zips/zip-0032.rst +++ b/zips/zip-0032.rst @@ -15,7 +15,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 .` +$% 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 =========== @@ -83,64 +83,64 @@ Conventions Most of the notation and functions used in this ZIP are defined in the Zcash protocol specification [#protocol]_. They are reproduced here for convenience: -- :math:`\mathsf{truncate}_k(S)` means the sequence formed from the first :math:`k` elements of :math:`S`. +- $\mathsf{truncate}_k(S)$ means the sequence formed from the first $k$ elements of $S$. -- :math:`a\,||\,b` means the concatenation of sequences :math:`a` then :math:`b`. +- $a\,||\,b$ means the concatenation of sequences $a$ then $b$. -- :math:`[k] P` means scalar multiplication of the elliptic curve point :math:`P` by the scalar :math:`k`. +- $[k] P$ means scalar multiplication of the elliptic curve point $P$ by the scalar $k$. -- :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`. +- $\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$. -- :math:`\mathsf{I2LEBSP}_\ell(k)` is the sequence of :math:`\ell` bits representing :math:`k` in +- $\mathsf{I2LEBSP}_\ell(k)$ is the sequence of $\ell$ bits representing $k$ in little-endian order. -- :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 +- $\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. -- :math:`\mathsf{repr}_\mathbb{J}(P)` is the representation of the Jubjub elliptic curve point :math:`P` +- $\mathsf{repr}_\mathbb{J}(P)$ is the representation of the Jubjub elliptic curve point $P$ as a bit sequence, defined in [#protocol-jubjub]_. -- :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`. +- $\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$. -- :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`. +- $\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$. -- :math:`\mathsf{PRF^{expand}}(\mathsf{sk}, t) :=`:math:`\mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{âZcash_ExpandSeedâ},`:math:`\mathsf{sk}\,||\,t)` +- $\mathsf{PRF^{expand}}(\mathsf{sk}, t) :=$ $\mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{âZcash\_ExpandSeedâ},$ $\mathsf{sk}\,||\,t)$. -- :math:`r_\mathbb{J}` is the order of the Jubjub large prime subgroup. +- $r_\mathbb{J}$ is the order of the Jubjub large prime subgroup. -- :math:`r_\mathbb{P}` is the order of the Pallas curve. +- $r_\mathbb{P}$ is the order of the Pallas curve. -- :math:`\mathsf{ToScalar^{Sapling}}(x) :=`:math:`\mathsf{LEOS2IP}_{512}(x) \pmod{r_\mathbb{J}}`. +- $\mathsf{ToScalar^{Sapling}}(x) :=$ $\mathsf{LEOS2IP}_{512}(x) \pmod{r_\mathbb{J}}$. -- :math:`\mathsf{ToScalar^{Orchard}}(x) :=`:math:`\mathsf{LEOS2IP}_{512}(x) \pmod{r_\mathbb{P}}`. +- $\mathsf{ToScalar^{Orchard}}(x) :=$ $\mathsf{LEOS2IP}_{512}(x) \pmod{r_\mathbb{P}}$. -- :math:`\mathsf{DiversifyHash^{Sapling}}(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 [#protocol-concretediversifyhash]_. +- $\mathsf{DiversifyHash^{Sapling}}(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 [#protocol-concretediversifyhash]_. The following algorithm standardized in [#NIST-SP-800-38G]_ is used: -- :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,`:math:`minlen = 88,`:math:`maxlen = 88`. - It will be used only with the empty string :math:`\texttt{ââ}` as the :math:`tweak`. :math:`x` is a +- $\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: -- :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)`. +- $\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 and Orchard specifications), which is the opposite of BIP 32. -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]_: +We adapt the path notation of BIP 32 [#bip-0032]_ to describe shielded HD paths, using prime marks ($\kern-0.1em{}'$) to +indicate hardened derivation ($\!i' = i + 2^{31}$) as in BIP 44 [#bip-0044]_: -- :math:`\mathsf{CKDfvk}(\mathsf{CKDfvk}(\mathsf{CKDfvk}(m_\mathsf{Sapling}, a), b), c)` is written as :math:`m_\mathsf{Sapling} / a / b / c`. +- $\mathsf{CKDfvk}(\mathsf{CKDfvk}(\mathsf{CKDfvk}(m_\mathsf{Sapling}, a), b), c)$ is written as $m_\mathsf{Sapling} / a / b / c$. Specification: Sapling key derivation @@ -163,110 +163,110 @@ 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 :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 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 :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. +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 -* :math:`\mathsf{EncodeExtSKParts}(\mathsf{ask, nsk, ovk, dk}) :=`:math:`\mathsf{I2LEOSP}_{256}(\mathsf{ask})`:math:`||\,\mathsf{I2LEOSP}_{256}(\mathsf{nsk})`:math:`||\,\mathsf{ovk}`:math:`||\,\mathsf{dk}` -* :math:`\mathsf{EncodeExtFVKParts}(\mathsf{ak, nk, ovk, dk}) :=`:math:`\mathsf{LEBS2OSP}_{256}(\mathsf{repr}_\mathbb{J}(\mathsf{ak}))`:math:`||\,\mathsf{LEBS2OSP}_{256}(\mathsf{repr}_\mathbb{J}(\mathsf{nk}))`:math:`||\,\mathsf{ovk}`:math:`||\,\mathsf{dk}` +* $\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{LEBS2OSP}_{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 :math:`S` be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes. +Let $S$ be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes. -- 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 +- 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 [#protocol-saplingkeycomponents]_: - - :math:`\mathsf{ask}_m = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x00}]))` - - :math:`\mathsf{nsk}_m = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x01}]))` - - :math:`\mathsf{ovk}_m = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x02}]))`. + - $\mathsf{ask}_m = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\mathtt{0x00}]))$ + - $\mathsf{nsk}_m = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\mathtt{0x01}]))$ + - $\mathsf{ovk}_m = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\mathtt{0x02}]))$. -- Calculate :math:`\mathsf{dk}_m` similarly: +- Calculate $\mathsf{dk}_m$ similarly: - - :math:`\mathsf{dk}_m = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x10}]))`. + - $\mathsf{dk}_m = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\mathtt{0x10}]))$. -- 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}`. +- 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}$. -Note that the master extended key is invalid if :math:`\mathsf{ask}_m` is :math:`0`, or if the corresponding -:math:`\mathsf{ivk}` derived as specified in [#protocol-saplingkeycomponents]_ is :math:`0`. +Note that the master extended key is invalid if $\mathsf{ask}_m$ is $0$, or if the corresponding +$\mathsf{ivk}$ derived as specified in [#protocol-saplingkeycomponents]_ is $0$. Sapling child key derivation ---------------------------- -As in BIP 32, the method for deriving a child extended key, given a parent extended key and an index :math:`i`, +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 `````````````````````````````````````` -:math:`\mathsf{CKDsk}((\mathsf{ask}_{par}, \mathsf{nsk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par}, \mathsf{c}_{par}), i)`:math:`\rightarrow (\mathsf{ask}_i, \mathsf{nsk}_i, \mathsf{ovk}_i, \mathsf{dk}_i, \mathsf{c}_i)` +$\mathsf{CKDsk}((\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 :math:`i \geq 2^{31}` (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 :math:`I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\texttt{0x11}]`:math:`||\,\mathsf{EncodeExtSKParts}(\mathsf{ask}_{par}, \mathsf{nsk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par})`:math:`||\,\mathsf{I2LEOSP}_{32}(i))`. + let $I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\mathtt{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}]`:math:`||\,\mathsf{EncodeExtFVKParts}(\mathsf{ak}_{par}, \mathsf{nk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par})`:math:`||\,\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 [#protocol-saplingkeycomponents]_. + let $I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\mathtt{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 [#protocol-saplingkeycomponents]_. -- Split :math:`I` into two 32-byte sequences, :math:`I_L` and :math:`I_R`. -- Let :math:`I_\mathsf{ask} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x13}]))`. -- Let :math:`I_\mathsf{nsk} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x14}]))`. +- Split $I$ into two 32-byte sequences, $I_L$ and $I_R$. +- Let $I_\mathsf{ask} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x13}]))$. +- Let $I_\mathsf{nsk} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x14}]))$. - Return: - - :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}]`:math:`||\,\mathsf{ovk}_{par}))` - - :math:`\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x16}]`:math:`||\,\mathsf{dk}_{par}))` - - :math:`\mathsf{c}_i = I_R`. + - $\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, [\mathtt{0x15}]$ $||\,\mathsf{ovk}_{par}))$ + - $\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x16}]$ $||\,\mathsf{dk}_{par}))$ + - $\mathsf{c}_i = I_R$. -Note that the child extended key is invalid if :math:`\mathsf{ask}_i` is :math:`0`, or if the corresponding -:math:`\mathsf{ivk}` derived as specified in [#protocol-saplingkeycomponents]_ is :math:`0`. +Note that the child extended key is invalid if $\mathsf{ask}_i$ is $0$, or if the corresponding +$\mathsf{ivk}$ derived as specified in [#protocol-saplingkeycomponents]_ is $0$. Deriving a child extended full viewing key `````````````````````````````````````````` -Let :math:`\mathcal{G}^\mathsf{Sapling}` be as defined in [#protocol-concretespendauthsig]_ and -let :math:`\mathcal{H}^\mathsf{Sapling}` be as defined in [#protocol-saplingkeycomponents]_. +Let $\mathcal{G}^\mathsf{Sapling}$ be as defined in [#protocol-concretespendauthsig]_ and +let $\mathcal{H}^\mathsf{Sapling}$ be as defined in [#protocol-saplingkeycomponents]_. -:math:`\mathsf{CKDfvk}((\mathsf{ak}_{par}, \mathsf{nk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par}, \mathsf{c}_{par}), i)`:math:`\rightarrow (\mathsf{ak}_{i}, \mathsf{nk}_{i}, \mathsf{ovk}_{i}, \mathsf{dk}_{i}, \mathsf{c}_{i})` +$\mathsf{CKDfvk}((\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 :math:`i \geq 2^{31}` (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 - :math:`I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\texttt{0x12}]`:math:`||\,\mathsf{EncodeExtFVKParts}(\mathsf{ak}_{par}, \mathsf{nk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par})`:math:`||\,\mathsf{I2LEOSP}_{32}(i))`. + $I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\mathtt{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^{Sapling}}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x13}]))`. -- Let :math:`I_\mathsf{nsk} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x14}]))`. +- Split $I$ into two 32-byte sequences, $I_L$ and $I_R$. +- Let $I_\mathsf{ask} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x13}]))$. +- Let $I_\mathsf{nsk} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x14}]))$. - Return: - - :math:`\mathsf{ak}_i = [I_\mathsf{ask}]\,\mathcal{G}^\mathsf{Sapling} + \mathsf{ak}_{par}` - - :math:`\mathsf{nk}_i = [I_\mathsf{nsk}]\,\mathcal{H}^\mathsf{Sapling} + \mathsf{nk}_{par}` - - :math:`\mathsf{ovk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x15}]`:math:`||\,\mathsf{ovk}_{par}))` - - :math:`\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x16}]`:math:`||\,\mathsf{dk}_{par}))` - - :math:`\mathsf{c}_i = I_R`. + - $\mathsf{ak}_i = [I_\mathsf{ask}]\,\mathcal{G}^\mathsf{Sapling} + \mathsf{ak}_{par}$ + - $\mathsf{nk}_i = [I_\mathsf{nsk}]\,\mathcal{H}^\mathsf{Sapling} + \mathsf{nk}_{par}$ + - $\mathsf{ovk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x15}]$ $||\,\mathsf{ovk}_{par}))$ + - $\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x16}]$ $||\,\mathsf{dk}_{par}))$ + - $\mathsf{c}_i = I_R$. -Note that the child extended key is invalid if :math:`\mathsf{ak}_i` is the zero point of Jubjub, -or if the corresponding :math:`\mathsf{ivk}` derived as specified in [#protocol-saplingkeycomponents]_ -is :math:`0`. +Note that the child extended key is invalid if $\mathsf{ak}_i$ is the zero point of Jubjub, +or if the corresponding $\mathsf{ivk}$ derived as specified in [#protocol-saplingkeycomponents]_ +is $0$. Sapling internal key derivation ------------------------------- @@ -283,39 +283,39 @@ key. Deriving a Sapling internal spending key ```````````````````````````````````````` -Let :math:`(\mathsf{ask}, \mathsf{nsk}, \mathsf{ovk}, \mathsf{dk})` be the external spending key. +Let $(\mathsf{ask}, \mathsf{nsk}, \mathsf{ovk}, \mathsf{dk})$ be the external spending key. -- Derive the corresponding :math:`\mathsf{ak}` and :math:`\mathsf{nk}` as specified in [#protocol-saplingkeycomponents]_. -- Let :math:`I = \textsf{BLAKE2b-256}(\texttt{"Zcash_SaplingInt"}, \mathsf{EncodeExtFVKParts}(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk}))`. -- Let :math:`I_\mathsf{nsk} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I, [\mathtt{0x17}]))`. -- Let :math:`R = \mathsf{PRF^{expand}}(I, [\mathtt{0x18}])`. -- Let :math:`\mathsf{nsk_{internal}} = (I_\mathsf{nsk} + \mathsf{nsk}) \pmod{r_\mathbb{J}}`. -- Split :math:`R` into two 32-byte sequences, :math:`\mathsf{dk_{internal}}` and :math:`\mathsf{ovk_{internal}}`. -- Return the internal spending key as :math:`(\mathsf{ask}, \mathsf{nsk_{internal}}, \mathsf{ovk_{internal}}, \mathsf{dk_{internal}})`. +- Derive the corresponding $\mathsf{ak}$ and $\mathsf{nk}$ as specified in [#protocol-saplingkeycomponents]_. +- Let $I = \textsf{BLAKE2b-256}(\texttt{âZcash\_SaplingIntâ}, \mathsf{EncodeExtFVKParts}(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk}))$. +- Let $I_\mathsf{nsk} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I, [\mathtt{0x17}]))$. +- Let $R = \mathsf{PRF^{expand}}(I, [\mathtt{0x18}])$. +- Let $\mathsf{nsk_{internal}} = (I_\mathsf{nsk} + \mathsf{nsk}) \pmod{r_\mathbb{J}}$. +- Split $R$ into two 32-byte sequences, $\mathsf{dk_{internal}}$ and $\mathsf{ovk_{internal}}$. +- Return the internal spending key as $(\mathsf{ask}, \mathsf{nsk_{internal}}, \mathsf{ovk_{internal}}, \mathsf{dk_{internal}})$. -Note that the child extended key is invalid if :math:`\mathsf{ak}` is the zero point of Jubjub, -or if the corresponding :math:`\mathsf{ivk}` derived as specified in [#protocol-saplingkeycomponents]_ -is :math:`0`. +Note that the child extended key is invalid if $\mathsf{ak}$ is the zero point of Jubjub, +or if the corresponding $\mathsf{ivk}$ derived as specified in [#protocol-saplingkeycomponents]_ +is $0$. Deriving a Sapling internal full viewing key ```````````````````````````````````````````` -Let :math:`\mathcal{H}^\mathsf{Sapling}` be as defined in [#protocol-saplingkeycomponents]_. +Let $\mathcal{H}^\mathsf{Sapling}$ be as defined in [#protocol-saplingkeycomponents]_. -Let :math:`(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk})` be the external full viewing key. +Let $(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk})$ be the external full viewing key. -- Let :math:`I = \textsf{BLAKE2b-256}(\texttt{"Zcash_SaplingInt"}, \mathsf{EncodeExtFVKParts}(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk}))`. -- Let :math:`I_\mathsf{nsk} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I, [\mathtt{0x17}]))`. -- Let :math:`R = \mathsf{PRF^{expand}}(I, [\mathtt{0x18}])`. -- Let :math:`\mathsf{nk_{internal}} = [I_\mathsf{nsk}] \mathcal{H}^\mathsf{Sapling} + \mathsf{nk}`. -- Split :math:`R` into two 32-byte sequences, :math:`\mathsf{dk_{internal}}` and :math:`\mathsf{ovk_{internal}}`. -- Return the internal full viewing key as :math:`(\mathsf{ak}, \mathsf{nk_{internal}}, \mathsf{ovk_{internal}}, \mathsf{dk_{internal}})`. +- Let $I = \textsf{BLAKE2b-256}(\texttt{âZcash\_SaplingIntâ}, \mathsf{EncodeExtFVKParts}(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk}))$. +- Let $I_\mathsf{nsk} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I, [\mathtt{0x17}]))$. +- Let $R = \mathsf{PRF^{expand}}(I, [\mathtt{0x18}])$. +- Let $\mathsf{nk_{internal}} = [I_\mathsf{nsk}] \mathcal{H}^\mathsf{Sapling} + \mathsf{nk}$. +- Split $R$ into two 32-byte sequences, $\mathsf{dk_{internal}}$ and $\mathsf{ovk_{internal}}$. +- Return the internal full viewing key as $(\mathsf{ak}, \mathsf{nk_{internal}}, \mathsf{ovk_{internal}}, \mathsf{dk_{internal}})$. This design uses the same technique as non-hardened derivation to obtain a full viewing key -with the same spend authority (the private key corresponding to :math:`\mathsf{ak}`) as the +with the same spend authority (the private key corresponding to $\mathsf{ak}$) as the original, but viewing authority only for internal transfers. -The values of :math:`I`, :math:`I_\mathsf{nsk}`, and :math:`R` are the same between deriving +The values of $I$, $I_\mathsf{nsk}$, and $R$ are the same between deriving a full viewing key, and deriving the corresponding spending key. Both of these derivations are shown in the following diagram: @@ -331,28 +331,28 @@ are shown in the following diagram: This method of deriving internal keys is applied to external keys that are children of the Account level. It was implemented in `zcashd` as part of support for ZIP 316 [#zip-0316]_. -Note that the internal extended key is invalid if :math:`\mathsf{ak}` is the zero point of Jubjub, -or if the corresponding :math:`\mathsf{ivk_{internal}}` derived from the internal full viewing key -as specified in [#protocol-saplingkeycomponents]_ is :math:`0`. +Note that the internal extended key is invalid if $\mathsf{ak}$ is the zero point of Jubjub, +or if the corresponding $\mathsf{ivk_{internal}}$ derived from the internal full viewing key +as specified in [#protocol-saplingkeycomponents]_ is $0$. Sapling diversifier derivation ------------------------------ -The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key :math:`\mathsf{dk}`. +The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key $\mathsf{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 :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))`. +- 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 :math:`d_j` is one for which :math:`\mathsf{DiversifyHash^{Sapling}}(d_j) \neq \bot`. -For a given :math:`\mathsf{dk}`, approximately half of the possible values of :math:`j` yield valid +A valid diversifier $d_j$ is one for which $\mathsf{DiversifyHash^{Sapling}}(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 :math:`d_j`, where :math:`j` is the +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. @@ -368,47 +368,47 @@ path across multiple contexts). Instantiation ------------- -Let :math:`\mathsf{Context}` be the context in which the hardened-only key derivation process is +Let $\mathsf{Context}$ be the context in which the hardened-only key derivation process is instantiated (e.g. a shielded protocol). We define two context-specific constants: -- :math:`\mathsf{Context.MKGDomain}` is a sequence of 16 bytes, used as a domain separator during +- $\mathsf{Context.MKGDomain}$ is a sequence of 16 bytes, used as a domain separator during master key generation. It SHOULD be disjoint from other domain separators used with BLAKE2b in Zcash protocols. -- :math:`\mathsf{Context.CKDDomain}` is a byte value, used as a domain separator during child key +- $\mathsf{Context.CKDDomain}$ is a byte value, used as a domain separator during child key derivation. This should be tracked as part of the global set of domains defined for - :math:`\mathsf{PRF^{expand}}`. + $\mathsf{PRF^{expand}}$. Hardened-only master key generation ----------------------------------- -Let :math:`\mathsf{IKM}` be an input key material byte sequence, which MUST use an unambiguous encoding +Let $\mathsf{IKM}$ be an input key material byte sequence, which MUST use an unambiguous encoding within the given context, and SHOULD contain at least 256 bits of entropy. It is RECOMMENDED to use a prefix-free encoding, which may require the use of length fields if multiple fields need to be encoded. -:math:`\mathsf{MKGh}^\mathsf{Context}(\mathsf{IKM}) \rightarrow (\mathsf{sk}_m, \mathsf{c}_m)` +$\mathsf{MKGh}^\mathsf{Context}(\mathsf{IKM}) \rightarrow (\mathsf{sk}_m, \mathsf{c}_m)$ : -- Calculate :math:`I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\mathsf{Context.MKGDomain}, \mathsf{IKM})`. -- Split :math:`I` into two 32-byte sequences, :math:`I_L` and :math:`I_R`. -- Use :math:`I_L` as the master secret key :math:`\mathsf{sk}_m`. -- Use :math:`I_R` as the master chain code :math:`\mathsf{c}_m`. -- Return :math:`(\mathsf{sk}_m, \mathsf{c}_m)`. +- Calculate $I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\mathsf{Context.MKGDomain}, \mathsf{IKM})$. +- Split $I$ into two 32-byte sequences, $I_L$ and $I_R$. +- Use $I_L$ as the master secret key $\mathsf{sk}_m$. +- Use $I_R$ as the master chain code $\mathsf{c}_m$. +- Return $(\mathsf{sk}_m, \mathsf{c}_m)$. Hardened-only child key derivation ---------------------------------- -:math:`\mathsf{CKDh}^\mathsf{Context}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)`:math:`\rightarrow (\mathsf{sk}_i, \mathsf{c}_i)` +$\mathsf{CKDh}^\mathsf{Context}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)$ $\rightarrow (\mathsf{sk}_i, \mathsf{c}_i)$ : -- Check whether :math:`i \geq 2^{31}` (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 - :math:`I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\mathsf{Context.CKDDomain}]\,||\,\mathsf{sk}_{par}\,||\,\mathsf{I2LEOSP}_{32}(i))`. + $I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\mathsf{Context.CKDDomain}]\,||\,\mathsf{sk}_{par}\,||\,\mathsf{I2LEOSP}_{32}(i))$. - If not (normal child): return failure. -- Split :math:`I` into two 32-byte sequences, :math:`I_L` and :math:`I_R`. -- Use :math:`I_L` as the child secret key :math:`\mathsf{sk}_i`. -- Use :math:`I_R` as the child chain code :math:`\mathsf{c}_i`. -- Return :math:`(\mathsf{sk}_i, \mathsf{c}_i)`. +- Split $I$ into two 32-byte sequences, $I_L$ and $I_R$. +- Use $I_L$ as the child secret key $\mathsf{sk}_i$. +- Use $I_R$ as the child chain code $\mathsf{c}_i$. +- Return $(\mathsf{sk}_i, \mathsf{c}_i)$. Specification: Orchard key derivation @@ -417,29 +417,29 @@ Specification: Orchard key derivation We only support hardened key derivation for Orchard. We instantiate the hardened key generation process with the following constants: -- :math:`\mathsf{Orchard.MKGDomain} = \texttt{âZcashIP32Orchardâ}` -- :math:`\mathsf{Orchard.CKDDomain} = \texttt{0x81}` +- $\mathsf{Orchard.MKGDomain} = \texttt{âZcashIP32Orchardâ}$ +- $\mathsf{Orchard.CKDDomain} = \mathtt{0x81}$ Orchard extended keys --------------------- -We represent an Orchard extended spending key as :math:`(\mathsf{sk, c}),` where :math:`\mathsf{sk}` -is the normal Orchard spending key (opaque 32 bytes), and :math:`\mathsf{c}` is the chain code. +We represent an Orchard extended spending key as $(\mathsf{sk, c}),$ where $\mathsf{sk}$ +is the normal Orchard spending key (opaque 32 bytes), and $\mathsf{c}$ is the chain code. Orchard master key generation ----------------------------- -Let :math:`S` be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes. +Let $S$ be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes. -- Return :math:`\mathsf{MKGh}^\mathsf{Orchard}(S)` as the master extended spending key - :math:`m_\mathsf{Orchard}`. +- Return $\mathsf{MKGh}^\mathsf{Orchard}(S)$ as the master extended spending key + $m_\mathsf{Orchard}$. Orchard child key derivation ---------------------------- -:math:`\mathsf{CKDsk}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)`:math:`\rightarrow (\mathsf{sk}_{i}, \mathsf{c}_i)` +$\mathsf{CKDsk}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)$ $\rightarrow (\mathsf{sk}_{i}, \mathsf{c}_i)$ : -- Return :math:`\mathsf{CKDh}^\mathsf{Orchard}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)` +- Return $\mathsf{CKDh}^\mathsf{Orchard}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)$ Note that the resulting child spending key may produce an invalid external FVK, as specified in [#protocol-orchardkeycomponents]_, with small probability. The corresponding internal FVK @@ -454,26 +454,26 @@ any external full viewing key we need to be able to derive a single internal ful key that has viewing authority for just internal transfers. We also need to be able to derive the corresponding internal spending key if we have the external spending key. -Let :math:`\mathsf{ask}` be the spend authorizing key if available, and -let :math:`(\mathsf{ak}, \mathsf{nk}, \mathsf{rivk})` be the corresponding external full +Let $\mathsf{ask}$ be the spend authorizing key if available, and +let $(\mathsf{ak}, \mathsf{nk}, \mathsf{rivk})$ be the corresponding external full viewing key, obtained as specified in [#protocol-orchardkeycomponents]_. -Define :math:`\mathsf{DeriveInternalFVK^{Orchard}}(\mathsf{ak}, \mathsf{nk}, \mathsf{rivk})` +Define $\mathsf{DeriveInternalFVK^{Orchard}}(\mathsf{ak}, \mathsf{nk}, \mathsf{rivk})$ as follows: -- Let :math:`K = \mathsf{I2LEBSP}_{256}(\mathsf{rivk})`. -- Let :math:`\mathsf{rivk_{internal}} = \mathsf{ToScalar^{Orchard}}(\mathsf{PRF^{expand}}(K, [\mathtt{0x83}] \,||\, \mathsf{I2LEOSP_{256}}(\mathsf{ak}) \,||\, \mathsf{I2LEOSP_{256}}(\mathsf{nk}))`. -- Return :math:`(\mathsf{ak}, \mathsf{nk}, \mathsf{rivk_{internal}})`. +- Let $K = \mathsf{I2LEBSP}_{256}(\mathsf{rivk})$. +- Let $\mathsf{rivk_{internal}} = \mathsf{ToScalar^{Orchard}}(\mathsf{PRF^{expand}}(K, [\mathtt{0x83}] \,||\, \mathsf{I2LEOSP_{256}}(\mathsf{ak}) \,||\, \mathsf{I2LEOSP_{256}}(\mathsf{nk}))$. +- Return $(\mathsf{ak}, \mathsf{nk}, \mathsf{rivk_{internal}})$. -The result of applying :math:`\mathsf{DeriveInternalFVK^{Orchard}}` to the external full viewing +The result of applying $\mathsf{DeriveInternalFVK^{Orchard}}$ to the external full viewing key is the internal full viewing key. The corresponding expanded internal spending key is -:math:`(\mathsf{ask}, \mathsf{nk}, \mathsf{rivk_{internal}})`, +$(\mathsf{ask}, \mathsf{nk}, \mathsf{rivk_{internal}})$. Unlike `Sapling internal key derivation`_, we do not base this internal key derivation procedure on non-hardened derivation, which is not defined for Orchard. We can obtain the -desired separation of viewing authority by modifying only the :math:`\mathsf{rivk_{internal}}` +desired separation of viewing authority by modifying only the $\mathsf{rivk_{internal}}$ field relative to the external full viewing key, which results in different -:math:`\mathsf{dk_{internal}}`, :math:`\mathsf{ivk_{internal}}` and :math:`\mathsf{ovk_{internal}}` +$\mathsf{dk_{internal}}$, $\mathsf{ivk_{internal}}$ and $\mathsf{ovk_{internal}}$ fields being derived, as specified in [#protocol-orchardkeycomponents]_ and shown in the following diagram: @@ -499,18 +499,18 @@ key. This means that the full viewing key provides the capability to determine t within the sequence, which matches the capabilities of a Sapling extended full viewing key but simplifies the key structure. -Given an Orchard extended spending key :math:`(\mathsf{sk}_i, \mathsf{c}_i)`: +Given an Orchard extended spending key $(\mathsf{sk}_i, \mathsf{c}_i)$: -- Let :math:`(\mathsf{ak}, \mathsf{nk}, \mathsf{rivk})` be the Orchard full viewing key for :math:`\mathsf{sk}_i`. -- Let :math:`K = \mathsf{I2LEBSP}_{256}(\mathsf{rivk})`. -- :math:`\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(K, [\texttt{0x82}] \,||\, \mathsf{I2LEOSP}_{256}(\mathsf{ak}) \,||\, \mathsf{I2LEOSP}_{256}(\mathsf{nk})))`. -- Let :math:`j` be the index of the desired diversifier, in the range :math:`0\,.\!. 2^{88} - 1`. -- :math:`d_{i,j} = \mathsf{FF1}\text{-}\mathsf{AES256.Encrypt}(\mathsf{dk}_i, \texttt{ââ}, \mathsf{I2LEBSP}_{88}(j))`. +- Let $(\mathsf{ak}, \mathsf{nk}, \mathsf{rivk})$ be the Orchard full viewing key for $\mathsf{sk}_i$. +- Let $K = \mathsf{I2LEBSP}_{256}(\mathsf{rivk})$. +- $\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(K, [\mathtt{0x82}] \,||\, \mathsf{I2LEOSP}_{256}(\mathsf{ak}) \,||\, \mathsf{I2LEOSP}_{256}(\mathsf{nk})))$. +- Let $j$ be the index of the desired diversifier, in the range $0\,..\, 2^{88} - 1$. +- $d_{i,j} = \mathsf{FF1}\text{-}\mathsf{AES256.Encrypt}(\mathsf{dk}_i, \texttt{ââ}, \mathsf{I2LEBSP}_{88}(j))$. -Note that unlike Sapling, all Orchard diversifiers are valid, and thus all possible values of :math:`j` yield +Note that unlike Sapling, all Orchard diversifiers are valid, and thus all possible values of $j$ yield valid diversifiers. -The default diversifier for :math:`(\mathsf{sk}_i, \mathsf{c}_i)` is defined to be :math:`d_{i,0}.` +The default diversifier for $(\mathsf{sk}_i, \mathsf{c}_i)$ is defined to be $d_{i,0}.$ Specification: Arbitrary key derivation @@ -521,35 +521,35 @@ existing key material (for example, deriving an arbitrary account-level key), wi ecosystem-wide coordination. The following instantiation of the hardened key generation process may be used for this purpose. -Let :math:`\mathsf{ContextString}` be a globally-unique non-empty sequence of at most 252 bytes +Let $\mathsf{ContextString}$ be a globally-unique non-empty sequence of at most 252 bytes that identifies the desired context. We instantiate the hardened key generation process with the following constants: -- :math:`\mathsf{Arbitrary.MKGDomain} = \texttt{âZcashArbitraryKDâ}` -- :math:`\mathsf{Arbitrary.CKDDomain} = \texttt{0xAB}` +- $\mathsf{Arbitrary.MKGDomain} = \texttt{âZcashArbitraryKDâ}$ +- $\mathsf{Arbitrary.CKDDomain} = \mathtt{0xAB}$ Arbitrary master key generation ------------------------------- -Let :math:`S` be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes. +Let $S$ be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes. The master extended arbitrary key is: -:math:`m_\mathsf{Arbitrary} = \mathsf{MKGh}^\mathsf{Arbitrary}([\mathsf{length}(\mathsf{ContextString})]\,||\,\mathsf{ContextString}\,||\,[\mathsf{length}(S)]\,||\,S)\!`. +$m_\mathsf{Arbitrary} = \mathsf{MKGh}^\mathsf{Arbitrary}([\mathsf{length}(\mathsf{ContextString})]\,||\,\mathsf{ContextString}\,||\,[\mathsf{length}(S)]\,||\,S)$. Arbitrary child key derivation ------------------------------ -:math:`\mathsf{CKDarb}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)`:math:`\rightarrow (\mathsf{sk}_i, \mathsf{c}_i)` +$\mathsf{CKDarb}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)$ $\rightarrow (\mathsf{sk}_i, \mathsf{c}_i)$ : -- Return :math:`\mathsf{CKDh}^\mathsf{Arbitrary}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)\!`. +- Return $\mathsf{CKDh}^\mathsf{Arbitrary}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)$. If the context requires a 64-byte key (for example, to avoid an entropy bottleneck in its particular -subsequent operations), and :math:`i` is the last element of an HD path, the concatenation -:math:`\mathsf{sk}_i\,||\,\mathsf{c}_i` MAY be used as a key. In this case, -:math:`(\mathsf{sk}_i, \mathsf{c}_i)` MUST NOT be given as input to :math:`\mathsf{CKDarb}` (this -is a restatement of the requirement that :math:`i` is the last element of an HD path). +subsequent operations), and $i$ is the last element of an HD path, the concatenation +$\mathsf{sk}_i\,||\,\mathsf{c}_i$ MAY be used as a key. In this case, +$(\mathsf{sk}_i, \mathsf{c}_i)$ MUST NOT be given as input to $\mathsf{CKDarb}$ (this +is a restatement of the requirement that $i$ is the last element of an HD path). Specification: Wallet usage @@ -565,18 +565,18 @@ Key path levels Sapling and Orchard key paths have the following three path levels at the top, all of which use hardened derivation: -- :math:`purpose`: a constant set to :math:`32'` (or :math:`\texttt{0x80000020}`) following the BIP 43 +- $purpose$: a constant set to $32'$ (or $\mathtt{0x80000020}$) following the BIP 43 recommendation. It indicates that the subtree of this node is used according to this specification. -- :math:`coin\_type`: a constant identifying the cryptocurrency that this subtree's keys are used with. For +- $coin\_type$: a constant identifying the cryptocurrency 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 cryptocurrency testnets share :math:`coin\_type` - index :math:`1`. + [#slip-0044]_. Note that in keeping with that document, all cryptocurrency testnets share $coin\_type$ + index $1$. -- :math:`account`: numbered from index :math:`0` in sequentially increasing manner. Defined as in +- $account$: numbered from index $0$ in sequentially increasing manner. Defined as in BIP 44 [#bip-0044]_. -Unlike BIP 44, none of the shielded key paths have a :math:`change` path level. The use of change addresses +Unlike BIP 44, none of the shielded key paths 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 @@ -592,25 +592,25 @@ 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 :math:`\{ 0\,.\!. 2^{31} - 1 \}`: +ZIP 32 derivation MUST support the following path for any account in range $\{ 0\,..\, 2^{31} - 1 \}$: -* :math:`m_\mathsf{Sapling} / purpose' / coin\_type' / account'`. +* $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 :math:`2^{87}` payment addresses, because each +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 :math:`address\_index` path level as in [#bip-0044]_: +they MAY additionally support a non-hardened $address\_index$ path level as in [#bip-0044]_: -* :math:`m_\mathsf{Sapling} / purpose' / coin\_type' / account' / address\_index`. +* $m_\mathsf{Sapling} / purpose' / coin\_type' / account' / address\_index$. `zcashd` version 4.6.0 and later uses this to derive "legacy" Sapling addresses from a mnemonic seed phrase -under account :math:`\mathtt{0x7FFFFFFF}`, using hardened derivation for :math:`address\_index`. +under account $\mathtt{0x7FFFFFFF}$, using hardened derivation for $address\_index$. Orchard key path ---------------- @@ -621,16 +621,16 @@ addresses as needed does not increase the cost of scanning the block chain for r 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 Orchard -ZIP 32 derivation MUST support the following path for any account in range :math:`\{ 0\,.\!. 2^{31} - 1 \}`: +ZIP 32 derivation MUST support the following path for any account in range $\{ 0\,..\, 2^{31} - 1 \}$: -* :math:`m_\mathsf{Orchard} / purpose' / coin\_type' / account'`. +* $m_\mathsf{Orchard} / purpose' / coin\_type' / account'$. Furthermore, wallets MUST support generating the default payment address (corresponding to the default diversifier for Orchard) for any account they support. They MAY also support generating a stream of diversified payment addresses for a given account, if they wish to enable users to give a unique address to each recipient. -Note that a given account can have a maximum of :math:`2^{88}` payment addresses (unlike Sapling, all Orchard +Note that a given account can have a maximum of $2^{88}$ payment addresses (unlike Sapling, all Orchard diversifiers are valid). @@ -640,10 +640,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 :math:`\mathit{FVK}` (as specified +A "Sapling full viewing key fingerprint" of a full viewing key with raw encoding $\mathit{FVK}$ (as specified in [#protocol-saplingfullviewingkeyencoding]_) is given by: -* :math:`\mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{âZcashSaplingFVFPâ}, \mathit{FVK})`. +* $\mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{âZcashSaplingFVFPâ}, \mathit{FVK})$. It MAY be used to uniquely identify a particular Sapling full viewing key. @@ -654,10 +654,10 @@ uniquely identify a particular key. Orchard Full Viewing Key Fingerprints and Tags ---------------------------------------------- -An "Orchard full viewing key fingerprint" of a full viewing key with raw encoding :math:`\mathit{FVK}` (as +An "Orchard full viewing key fingerprint" of a full viewing key with raw encoding $\mathit{FVK}$ (as specified in [#protocol-orchardfullviewingkeyencoding]_) is given by: -* :math:`\mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{âZcashOrchardFVFPâ}, \mathit{FVK})`. +* $\mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{âZcashOrchardFVFPâ}, \mathit{FVK})$. It MAY be used to uniquely identify a particular Orchard full viewing key. @@ -668,9 +668,9 @@ uniquely identify a particular key. Seed Fingerprints ----------------- -A "seed fingerprint" for the master seed :math:`S` of a hierarchical deterministic wallet is given by: +A "seed fingerprint" for the master seed $S$ of a hierarchical deterministic wallet is given by: -* :math:`\mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{âZcash_HD_Seed_FPâ},`:math:`[\mathsf{length}(S)]\,||\,S)`. +* $\mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{âZcash\_HD\_Seed\_FPâ},$ $[\mathsf{length}(S)]\,||\,S)$. It MAY be used to uniquely identify a particular hierarchical deterministic wallet. @@ -691,14 +691,14 @@ and a Bech32 [#bip-0173]_ encoding. Sapling extended spending keys ------------------------------ -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 +A Sapling extended spending key $(\mathsf{ask, nsk, ovk, dk, c})$, at depth $depth$, +with parent full viewing key tag $parent\_fvk\_tag$ and child number $i$, is represented as a byte sequence: -* :math:`\mathsf{I2LEOSP}_{8}(depth)`:math:`||\,parent\_fvk\_tag`:math:`||\,\mathsf{I2LEOSP}_{32}(i)`:math:`||\,\mathsf{c}`:math:`||\,\mathsf{EncodeExtSKParts}(\mathsf{ask, nsk, ovk, dk})`. +* $\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, :math:`depth` is :math:`0`, :math:`parent\_fvk\_tag` is -4 zero bytes, and :math:`i` is :math:`0`. +For the master extended spending key, $depth$ is $0$, $parent\_fvk\_tag$ is +4 zero bytes, and $i$ is $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. @@ -706,14 +706,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 :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 +A Sapling extended full viewing key $(\mathsf{ak, nk, ovk, dk, c})$, at depth $depth$, +with parent full viewing key tag $parent\_fvk\_tag$ and child number $i$, is represented as a byte sequence: -* :math:`\mathsf{I2LEOSP}_{8}(depth)`:math:`||\,parent\_fvk\_tag`:math:`||\,\mathsf{I2LEOSP}_{32}(i)`:math:`||\,\mathsf{c}`:math:`||\,\mathsf{EncodeExtFVKParts}(\mathsf{ak, nk, ovk, dk})`. +* $\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, :math:`depth` is :math:`0`, :math:`parent\_fvk\_tag` -is 4 zero bytes, and :math:`i` is :math:`0`. +For the master extended full viewing key, $depth$ is $0$, $parent\_fvk\_tag$ +is 4 zero bytes, and $i$ is $0$. When encoded as Bech32, the Human-Readable Part is ``zxviews`` for the production network, or ``zxviewtestsapling`` for the test network. @@ -721,13 +721,13 @@ network, or ``zxviewtestsapling`` for the test network. Orchard extended spending keys ------------------------------ -An Orchard extended spending key :math:`(\mathsf{sk, 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: +An Orchard extended spending key $(\mathsf{sk, c})$, at depth $depth$, with parent full viewing +key tag $parent\_fvk\_tag$ and child number $i$, is represented as a byte sequence: -* :math:`\mathsf{I2LEOSP}_{8}(depth)\,||\,parent\_fvk\_tag\,||\,\mathsf{I2LEOSP}_{32}(i)\,||\,\mathsf{c}\,||\,\mathsf{sk}`. +* $\mathsf{I2LEOSP}_{8}(depth)\,||\,parent\_fvk\_tag\,||\,\mathsf{I2LEOSP}_{32}(i)\,||\,\mathsf{c}\,||\,\mathsf{sk}$. -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`. +For the master extended spending key, $depth$ is $0$, $parent\_fvk\_tag$ is +4 zero bytes, and $i$ is $0$. When encoded as Bech32, the Human-Readable Part is ``secret-orchard-extsk-main`` for Mainnet, or ``secret-orchard-extsk-test`` for Testnet. @@ -743,11 +743,11 @@ Values reserved due to previous specification for Sprout The following values were previously used in the specification of hierarchical derivation for Sprout, and therefore SHOULD NOT be used in future Zcash-related specifications: -* the :math:`\mathsf{BLAKE2b}\text{-}\mathsf{512}` personalization :math:`\texttt{âZcashIP32_Sproutâ}`, +* the $\mathsf{BLAKE2b}\text{-}\mathsf{512}$ personalization $\texttt{âZcashIP32\_Sproutâ}$, formerly specified for derivation of the master key of the Sprout tree; -* the :math:`\mathsf{BLAKE2b}\text{-}\mathsf{256}` personalization :math:`\texttt{âZcash_Sprout_AFPâ}`, +* the $\mathsf{BLAKE2b}\text{-}\mathsf{256}$ personalization $\texttt{âZcash\_Sprout\_AFPâ}$, formerly specified for generation of Sprout address fingerprints; -* the :math:`\mathsf{PRF^{expand}}` prefix :math:`\texttt{0x80}`, formerly specified for +* the $\mathsf{PRF^{expand}}$ prefix $\mathtt{0x80}$, formerly specified for Sprout child key derivation; * the Bech32 Human-Readable Parts ``zxsprout`` and ``zxtestsprout``, formerly specified for Sprout extended spending keys on Mainnet and Testnet respectively. diff --git a/zips/zip-0203.rst b/zips/zip-0203.rst index 3d2dbd036..a49f0b349 100644 --- a/zips/zip-0203.rst +++ b/zips/zip-0203.rst @@ -31,12 +31,12 @@ be mined, and potentially simplifying bidirectional payment channels by reducing to store and compress revocations for past states, since transactions not committed to the chain could expire and become invalid after a period of time. -If the expiry is at block height :math:`N`, then the transaction must be included in block -:math:`N` or earlier. Block :math:`N+1` will be too late, and the transaction will be +If the expiry is at block height $N\!$, then the transaction must be included in block +$N$ or earlier. Block $N+1$ will be too late, and the transaction will be removed from the mempool. The new consensus rule will enforce that the transaction will not be considered valid if -included in block of height greater than :math:`N`, and blocks that include expired +included in block of height greater than $N\!$, and blocks that include expired transactions will not be considered valid. diff --git a/zips/zip-0207.rst b/zips/zip-0207.rst index b3719c197..291da0a09 100644 --- a/zips/zip-0207.rst +++ b/zips/zip-0207.rst @@ -89,16 +89,16 @@ Definitions We use the following constants and functions defined in [#protocol-constants]_, [#protocol-diffadjustment]_, [#protocol-subsidies]_, and [#protocol-foundersreward]_: -- :math:`\mathsf{BlossomActivationHeight}` -- :math:`\mathsf{PostBlossomHalvingInterval}` -- :math:`\mathsf{Halving}(\mathsf{height})` -- :math:`\mathsf{BlockSubsidy}(\mathsf{height})` -- :math:`\mathsf{RedeemScriptHash}(\mathsf{height})`. +- $\mathsf{BlossomActivationHeight}$ +- $\mathsf{PostBlossomHalvingInterval}$ +- $\mathsf{Halving}(\mathsf{height})$ +- $\mathsf{BlockSubsidy}(\mathsf{height})$ +- $\mathsf{RedeemScriptHash}(\mathsf{height})$. We also define the following function: -- :math:`\mathsf{HeightForHalving}(\mathsf{halving})`: Smallest :math:`\mathsf{height}` such that - :math:`\mathsf{Halving}(\mathsf{height}) = \mathsf{halving}` +- $\mathsf{HeightForHalving}(\mathsf{halving})$: Smallest $\mathsf{height}$ such that + $\mathsf{Halving}(\mathsf{height}) = \mathsf{halving}$ Funding streams @@ -129,10 +129,10 @@ than its start height. The funding streams are paid to one of a pre-defined set of recipients, depending on the block height. Each recipient identifier MUST be either the string encoding of a transparent P2SH address or Sapling address (as specified in -[#protocol-transparentaddrencoding]_ or [#protocol-saplingpaymentaddrencoding]) +[#protocol-transparentaddrencoding]_ or [#protocol-saplingpaymentaddrencoding]_) to be paid by an output in the coinbase transaction, or the identifier -:math:`\mathsf{DEFERRED}\_\mathsf{POOL}`. The latter, added in the NU6 network -upgrade [#zip-0253]_, indicates that the value is to be paid to a reserve to be +$\mathsf{DEFERRED\_POOL}$. The latter, added in the NU6 network upgrade +[#zip-0253]_, indicates that the value is to be paid to a reserve to be used for development funding, the distribution of which is to be determined via a future ZIP. @@ -142,7 +142,7 @@ given block height is defined as follows: .. math:: - \begin{eqnarray*} + \begin{array}{rcl} \mathsf{AddressChangeInterval} &=& \mathsf{PostBlossomHalvingInterval} / 48 \\ \mathsf{AddressPeriod}(\mathsf{height}) &=& \mathsf{floor}\left( @@ -151,7 +151,7 @@ given block height is defined as follows: \mathsf{FundingStream[FUND].AddressIndex}(\mathsf{height}) &=& \mathsf{AddressPeriod}(\mathsf{height}) - \\&&\hspace{2em} \mathsf{AddressPeriod}(\mathsf{FundingStream[FUND].StartHeight}) \\ \mathsf{FundingStream[FUND].Address}(\mathsf{height}) &=& \mathsf{FundingStream[FUND].Addresses[} \\&&\hspace{2em} \mathsf{FundingStream[FUND].AddressIndex}(\mathsf{height})\mathsf{]} - \end{eqnarray*} + \end{array} This has the property that all active funding streams change the address they are using on the same block height schedule, aligned to the height of the @@ -190,24 +190,24 @@ Deferred Development Fund Chain Value Pool Balance -------------------------------------------------- Full node implementations MUST track an additional -:math:`\mathsf{ChainValuePoolBalance^{Deferred}}` chain value pool balance, +$\mathsf{ChainValuePoolBalance^{Deferred}}$ chain value pool balance, in addition to the Sprout, Sapling, and Orchard chain value pool balances. -Define :math:`\mathsf{totalDeferredOutput}(\mathsf{height}) := \sum_{\mathsf{fs} \in \mathsf{DeferredFundingStreams}(\mathsf{height})} \mathsf{fs.Value}(\mathsf{height})` -where :math:`\mathsf{DeferredFundingStreams}(\mathsf{height})` is the set of -funding streams with recipient identifier :math:`\mathsf{DEFERRED}\_\mathsf{POOL}` -in the block at height :math:`\mathsf{height}`. +Define $\mathsf{totalDeferredOutput}(\mathsf{height}) := \sum_{\mathsf{fs} \in \mathsf{DeferredFundingStreams}(\mathsf{height})} \mathsf{fs.Value}(\mathsf{height})$ +where $\mathsf{DeferredFundingStreams}(\mathsf{height})$ is the set of +funding streams with recipient identifier $\mathsf{DEFERRED\_POOL}$ +in the block at height $\mathsf{height}$. -The :math:`\mathsf{ChainValuePoolBalance^{Deferred}}` chain value pool balance +The $\mathsf{ChainValuePoolBalance^{Deferred}}$ chain value pool balance for a given block chain is the sum of the values of payments to -:math:`\mathsf{DEFERRED}\_\mathsf{POOL}` for transactions in the block chain. +$\mathsf{DEFERRED\_POOL}$ for transactions in the block chain. -Equivalently, :math:`\mathsf{ChainValuePoolBalance^{Deferred}}` for a block -chain up to and including height :math:`\mathsf{height}` is given by -:math:`\sum_{\mathsf{h} = 0}^{\mathsf{height}} \mathsf{totalDeferredOutput}(\mathsf{h})`. +Equivalently, $\mathsf{ChainValuePoolBalance^{Deferred}}$ for a block +chain up to and including height $\mathsf{height}$ is given by +$\sum_{\mathsf{h} = 0}^{\mathsf{height}} \mathsf{totalDeferredOutput}(\mathsf{h})$. -Note: :math:`\mathsf{totalDeferredOutput}(\mathsf{h})` is necessarily -zero for heights :math:`\mathsf{h}` prior to NU6 activation. +Note: $\mathsf{totalDeferredOutput}(\mathsf{h})$ is necessarily +zero for heights $\mathsf{h}$ prior to NU6 activation. Consensus rules @@ -223,17 +223,17 @@ Once the Canopy network upgrade activates: (This would be the case under the preexisting consensus rules for Mainnet, but not for Testnet.) -- In each block with coinbase transaction :math:`\mathsf{cb}` at block height - :math:`\mathsf{height}`, for each funding stream :math:`\mathsf{fs}` +- In each block with coinbase transaction $\mathsf{cb}$ at block height + $\mathsf{height}$, for each funding stream $\mathsf{fs}$ active at that block height with a recipient identifier other than - :math:`\mathsf{DEFERRED}\_\mathsf{POOL}` given by - :math:`\mathsf{fs.Recipient}(\mathsf{height})\!`, - :math:`\mathsf{cb}` \MUST contain at least one output that pays - :math:`\mathsf{fs.Value}(\mathsf{height})` \zatoshi in the prescribed way to + $\mathsf{DEFERRED\_POOL}$ given by + $\mathsf{fs.Recipient}(\mathsf{height})$, + $\mathsf{cb}$ \MUST contain at least one output that pays + $\mathsf{fs.Value}(\mathsf{height})$ zatoshi in the prescribed way to the address represented by that recipient identifier. -- :math:`\mathsf{fs.Recipient}(\mathsf{height})` is defined as - :math:`\mathsf{fs.Recipients_{\,\fs.RecipientIndex}}(\mathsf{height})\!`. +- $\mathsf{fs.Recipient}(\mathsf{height})$ is defined as + $\mathsf{fs.Recipients_{\,fs.RecipientIndex}}(\mathsf{height})$. - The "prescribed way" to pay a transparent P2SH address is to use a standard P2SH script of the form ``OP_HASH160 RedeemScriptHash(height) OP_EQUAL`` as @@ -243,15 +243,15 @@ Once the Canopy network upgrade activates: That is, all Sapling outputs in coinbase transactions (including, but not limited to, outputs for funding streams) MUST have valid note commitments when recovered using a 32-byte array of zeroes as the outgoing viewing key. - In this case the note plaintext lead byte MUST be :math:`\mathbf{0x02}\!`, as + In this case the note plaintext lead byte MUST be $\mathbf{0x02}$, as specified in [#zip-0212]_. -These rules are reproduced in [#protocol-fundingstreams]. +These rules are reproduced in [#protocol-fundingstreams]_. -The effect of the definition of :math:`\mathsf{ChainValuePoolBalance^{Deferred}}` -above is that payments to the :math:`\mathsf{DEFERRED}\_\mathsf{POOL}` cause -:math:`\mathsf{FundingStream[FUND].Value}(\mathsf{height})` to be added to -:math:`\mathsf{ChainValuePoolBalance^{Deferred}}` for the block chain including +The effect of the definition of $\mathsf{ChainValuePoolBalance^{Deferred}}$ +above is that payments to the $\mathsf{DEFERRED\_POOL}$ cause +$\mathsf{FundingStream[FUND].Value}(\mathsf{height})$ to be added to +$\mathsf{ChainValuePoolBalance^{Deferred}}$ for the block chain including that block. For the funding stream definitions to be activated at Canopy and at NU6, see @@ -289,25 +289,25 @@ Reference Implementation References ========== -.. [#BCP14] `Information on BCP 14 â "RFC 2119: Key words for use in RFCs to Indicate Requirement Levels" and "RFC 8174: Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words"\$latex code\$
" in either Markdown or (as a
+non-standard extension) reStructuredText. This syntax does not work in tables for
+reStructuredText; in that case use ":math:\`latex code\`
" instead.
+
+The rendered HTML will use KaTeX [^katex], which only supports a subset of LaTeX,
+so you will need to double-check that the rendering is as intended.
In general the conventions in the Zcash protocol specification SHOULD be followed.
If you find this difficult, don't worry too much about it in initial drafts; the
diff --git a/zips/zip-guide.rst b/zips/zip-guide.rst
index 048594048..ca39e538d 100644
--- a/zips/zip-guide.rst
+++ b/zips/zip-guide.rst
@@ -151,11 +151,13 @@ ZIPs are different from RFCs in the following ways:
Using mathematical notation
---------------------------
-Embedded :math:`\LaTeX` is allowed and encouraged in ZIPs. The syntax for inline
-math is "``:math:`latex code```" in reStructuredText or "``$latex code$``" in
-Markdown. The rendered HTML will use KaTeX [#katex]_, which only supports a subset
-of :math:`\LaTeX\!`, so you will need to double-check that the rendering is as
-intended.
+Embedded $\LaTeX$, e.g. $x + y$, is allowed and encouraged in ZIPs. The syntax for
+inline math is "``\$latex code\$``" in either Markdown or (as a non-standard
+extension) reStructuredText. This syntax does not work in tables for
+reStructuredText; in that case use "``:math:`latex code```" instead.
+
+The rendered HTML will use KaTeX [#katex]_, which only supports a subset of
+$\LaTeX$, so you will need to double-check that the rendering is as intended.
In general the conventions in the Zcash protocol specification SHOULD be followed.
If you find this difficult, don't worry too much about it in initial drafts; the