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 " - echo " or: edithtml.sh --md " - exit -fi - -if ! [ -f "$2" ]; then - echo File not found: "$2" - exit -fi - -if [ "x$1" = "x--rst" ]; then - sed -i.sedbak 's|</head>|<meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="css/style.css"></head>|' $2 - sed -i.sedbak 's|http://cdn.mathjax.org/mathjax/latest/MathJax.js|https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js|' $2 -else - cat - "$2" >"$2".prefix <<EOF -<!DOCTYPE html> -<html> -<head> - <title>$3 - - - - - -EOF - cat "$2.prefix" - >"$2" < - -EOF - rm -f "$2".prefix -fi - -sed -i.sedbak 's|Protocol Specification|Protocol Specification|g' "$2" -sed -i.sedbak 's|\s*(dark mode version)||g' "$2" - -sed -i.sedbak 's|||g' "$2" -sed -i.sedbak 's|||g' "$2" -sed -i.sedbak 's|<\(https:[^&]*\)>|\<\1\>|g' "$2" - -sed -i.sedbak 's|src="../rendered/|src="|g' "$2" -sed -i.sedbak 's|\s*.?\s*([^<]*(?:[^<]*[^<]*)?)|
\3 |g' "$2" - -rm -f rendered/*.sedbak diff --git a/render.sh b/render.sh new file mode 100755 index 000000000..f312aed6d --- /dev/null +++ b/render.sh @@ -0,0 +1,90 @@ +#!/bin/bash + +set -euo pipefail + +if ! ( ( [ "x$1" = "x--rst" ] || [ "x$1" = "x--pandoc" ] || [ "x$1" = "x--mmd" ] ) && [ $# -eq 3 ] ); then + cat - < + +--rst render reStructuredText using rst2html5 +--pandoc render Markdown using pandoc +--mmd render Markdown using multimarkdown +EndOfUsage + exit +fi + +inputfile="$2" +outputfile="$3" + +if ! [ -f "${inputfile}" ]; then + echo "File not found: ${inputfile}" + exit +fi + +if [ "x$1" = "x--rst" ]; then + filetype='.rst' +else + filetype='.md' +fi +title="$(basename -s ${filetype} ${inputfile} | sed -E 's|zip-0{0,3}|ZIP |; s|draft-|Draft |')$(grep -E '^(\.\.)?\s*Title: ' ${inputfile} |sed -E 's|.*Title||')" +echo " ${title}" + +Math1='<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+" crossorigin="anonymous">' +Math2='<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js" integrity="sha384-7zkQWkzuo3B5mTepMUcHkMB5jZaolc2xDwL6VFqjFALcbeS9Ggm/Yr2r3Dy4lfFg" crossorigin="anonymous"></script>' +Math3='<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous" onload="renderMathInElement(document.body);"></script>' +ViewAndStyle='<meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="css/style.css">' + +cat <( + if [ "x$1" = "x--rst" ]; then + # These are basic regexps so \+ is needed, not +. + # We use the Unicode 💲 character to move an escaped $ out of the way, + # which is much easier than trying to handle escapes within a capture. + + cat "${inputfile}" \ + | sed 's|[\][$]|💲|g; + s|[$]\([^$]\+\)[$]\([.,:;!?)-]\)|:math:`\1\\!`\2|g; + s|[$]\([^$]\+\)[$]|:math:`\1`|g; + s|💲|$|g' \ + | rst2html5 -v --title="${title}" - \ + | sed "s|<script src=\"http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML\"></script>|${Math1}\n ${Math2}\n ${Math3}|; + s|</head>|${ViewAndStyle}</head>|" + else + if [ "x$1" = "x--pandoc" ]; then + # Not actually MathJax. KaTeX is compatible if we use the right headers. + pandoc --mathjax --from=markdown --to=html "${inputfile}" --output="${outputfile}.temp" + else + multimarkdown ${inputfile} -o "${outputfile}.temp" + fi + + # Both pandoc and multimarkdown just output the HTML body. + echo "<!DOCTYPE html>" + echo "<html>" + echo "<head>" + echo " <title>${title}" + echo " " + if grep -q -E 'class="math( inline)?"' "${outputfile}.temp"; then + echo " ${Math1}" + echo " ${Math2}" + echo " ${Math3}" + fi + echo " ${ViewAndStyle}" + echo "" + echo "" + cat "${outputfile}.temp" + rm -f "${outputfile}.temp" + echo "" + echo "" + fi +) \ +| sed \ +'s|Protocol Specification|Protocol Specification|g; + s|\s*(dark mode version)||g; + s|||g; + s|||g; + s|<\(https:[^&]*\)>|\<\1\>|g; + s|src="../rendered/|src="|g; + s|\s*.?\s*([^<]*(?:[^<]*[^<]*)?)|
\3 |g' \ +> "${outputfile}" diff --git a/rendered/css/style.css b/rendered/css/style.css index 9cf20f050..d3d22b1ec 100644 --- a/rendered/css/style.css +++ b/rendered/css/style.css @@ -296,28 +296,18 @@ pre { font-size: 0.9375rem; } -span.math { - transform: scale(1, 1.03); - -moz-transform: scale(1, 1.03); - -ms-transform: scale(1, 1.03); - -webkit-transform: scale(1, 1.03); - -o-transform: scale(1, 1.03); - font-size: 0.97rem; +.katex { + font-size: 1.21em; } div.math { - transform: scale(1.3, 1.339); - -moz-transform: scale(1.3, 1.339); - -ms-transform: scale(1.3, 1.339); - -webkit-transform: scale(1.3, 1.339); - -o-transform: scale(1.3, 1.339); + transform: scale(1.42, 1.42); display: block; overflow-x: auto; overflow-y: hidden; margin: 2.6rem 1rem 2.6rem 1rem; text-align: center; padding: 0; - font-size: 0.97rem; } a, a:visited { @@ -344,12 +334,76 @@ span.section-heading:hover + span { opacity: 1; } -a.footnote_reference::before { +a.footnote_reference::before, a.footnote-ref::before { content: "["; } -a.footnote_reference::after { + +a.footnote_reference::after, a.footnote-ref::after { + content: "]"; +} + +/* {{{ rst-specific */ +#references table, #references th, #references td { + border: 0 none transparent; + font-size: 1.125rem; +} + +#references table { + margin-left: 0; + margin-bottom: 0; +} + +#references th { + padding-left: 0; + width: 1.9em; + text-align: right; +} + +#references th::before { + content: "["; +} + +#references th::after { content: "]"; } +/* }}} rst-specific */ + +/* {{{ md-specific */ +a.footnote-ref sup { + vertical-align: baseline; + font-size: 100%; +} + +/* pandoc only, not multimarkdown */ +#footnotes ol { + margin-top: -3ex; +} + +.footnotes li { + margin-top: -0.8ex; + margin-left: 1em; + list-style-type: md-references; +} + +.footnotes ::marker { + font-weight: 600; + font-size: 1.125rem; +} + +.footnotes hr { + display: none; +} + +.footnote-back::before { + content: " "; +} + +@counter-style md-references { + system: extends decimal; + prefix: "["; + suffix: "]     "; +} +/* }}} md-specific */ strong, b { font-family: 'robotomedium',Arial,Helvetica Neue,Helvetica,sans-serif; @@ -361,7 +415,6 @@ hr { margin: 1.875rem 0; } - table { border-collapse: collapse; border: 0 none transparent; @@ -399,22 +452,6 @@ td:first-child { padding-bottom: 0.4rem; } -#references table, #references th, #references td { - border: 0 none transparent; - font-size: 1.125rem; -} - -#references table { - margin-bottom: 0; -} - -#references th::before { - content: "["; -} -#references th::after { - content: "]"; -} - @media (max-width: 576px) { table:not(.footnote) { display: block; diff --git a/rendered/zip-0032.html b/rendered/zip-0032.html index 432702ad2..d4dd53635 100644 --- a/rendered/zip-0032.html +++ b/rendered/zip-0032.html @@ -3,7 +3,9 @@ ZIP 32: Shielded Hierarchical Deterministic Wallets - + + +
@@ -59,30 +61,30 @@ means the sequence formed from the first \(k\) elements of - \(S\) + \(S\!\) .
  • \(a\,||\,b\) means the concatenation of sequences \(a\) then - \(b\) + \(b\!\) .
  • \([k] P\) means scalar multiplication of the elliptic curve point \(P\) by the scalar - \(k\) + \(k\!\) .
  • \(\mathsf{LEOS2IP}_\ell(S)\) is the integer in range - \(\{ 0\,.\!. 2^\ell - 1 \}\) + \(\{ 0\,..\, 2^\ell - 1 \}\) represented in little-endian order by the byte sequence \(S\) of length - \(\ell/8\) + \(\ell/8\!\) .
  • \(\mathsf{I2LEBSP}_\ell(k)\) @@ -96,7 +98,7 @@ is defined as follows when \(\ell\) is a multiple of - \(8\) + \(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.
  • @@ -108,22 +110,22 @@
  • \(\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\) + \(p\!\) , and input - \(x\) + \(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\) + \(p\!\) , and input - \(x\) + \(x\!\) .
  • \(\mathsf{PRF^{expand}}(\mathsf{sk}, t) :=\) - \(\mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{“Zcash_ExpandSeed”},\) - \(\mathsf{sk}\,||\,t)\) -
  • + \(\mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{“Zcash\_ExpandSeed”},\) + \(\mathsf{sk}\,||\,t)\!\) + .
  • \(r_\mathbb{J}\) is the order of the Jubjub large prime subgroup.
  • @@ -132,11 +134,11 @@ is the order of the Pallas curve.
  • \(\mathsf{ToScalar^{Sapling}}(x) :=\) - \(\mathsf{LEOS2IP}_{512}(x) \pmod{r_\mathbb{J}}\) + \(\mathsf{LEOS2IP}_{512}(x) \pmod{r_\mathbb{J}}\!\) .
  • \(\mathsf{ToScalar^{Orchard}}(x) :=\) - \(\mathsf{LEOS2IP}_{512}(x) \pmod{r_\mathbb{P}}\) + \(\mathsf{LEOS2IP}_{512}(x) \pmod{r_\mathbb{P}}\!\) .
  • \(\mathsf{DiversifyHash^{Sapling}}(d)\) @@ -151,15 +153,15 @@
  • \(\mathsf{FF1}\text{-}\mathsf{AES256.Encrypt}(key, tweak, x)\) refers to the FF1 encryption algorithm using AES with a 256-bit - \(key\) + \(key\!\) , and parameters \(radix = 2,\) \(minlen = 88,\) - \(maxlen = 88\) + \(maxlen = 88\!\) . It will be used only with the empty string \(\texttt{“”}\) as the - \(tweak\) + \(tweak\!\) . \(x\) is a sequence of 88 bits, as is the output.
  • @@ -175,22 +177,22 @@ representing in little-endian order the integer \(k\) in range - \(\{ 0\,.\!. 2^\ell - 1 \}\) + \(\{ 0\,..\, 2^\ell - 1 \}\!\) . It is the reverse operation of - \(\mathsf{LEOS2IP}_\ell(S)\) + \(\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 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:

    • \(\mathsf{CKDfvk}(\mathsf{CKDfvk}(\mathsf{CKDfvk}(m_\mathsf{Sapling}, a), b), c)\) is written as - \(m_\mathsf{Sapling} / a / b / c\) + \(m_\mathsf{Sapling} / a / b / c\!\) .
    @@ -202,7 +204,7 @@
  • We do not derive Sapling public keys directly, as this would prevent the use of diversified addresses. Instead, we derive Sapling full viewing keys, from which payment addresses can be generated. This maintains the trust semantics of BIP 32: someone with access to a BIP 32 extended public key is able to view all transactions involving that address, which a Sapling full viewing key also enables.
  • We represent a Sapling extended spending key as - \((\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.

    • Calculate - \(I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{“ZcashIP32Sapling”}, S)\) + \(I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{“ZcashIP32Sapling”}, S)\!\) .
    • Split \(I\) into two 32-byte sequences, \(I_L\) and - \(I_R\) + \(I_R\!\) .
    • Use \(I_L\) as the master spending key - \(\mathsf{sk}_m\) + \(\mathsf{sk}_m\!\) , and \(I_R\) as the master chain code - \(\mathsf{c}_m\) + \(\mathsf{c}_m\!\) .
    • Calculate - \(\mathsf{ask}_m\) + \(\mathsf{ask}_m\!\) , - \(\mathsf{nsk}_m\) + \(\mathsf{nsk}_m\!\) , and \(\mathsf{ovk}_m\) via the standard Sapling derivation 11:
      • - \(\mathsf{ask}_m = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\texttt{0x00}]))\) + \(\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, [\texttt{0x01}]))\) + \(\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, [\texttt{0x02}]))\) + \(\mathsf{ovk}_m = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\mathtt{0x02}]))\!\) .
    • @@ -287,47 +289,47 @@ similarly:
      • - \(\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 \((\mathsf{ask}_m, \mathsf{nsk}_m, \mathsf{ovk}_m, \mathsf{dk}_m, \mathsf{c}_m)\) as the master extended spending key - \(m_\mathsf{Sapling}\) + \(m_\mathsf{Sapling}\!\) .

    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\!\) .

    Sapling child key derivation

    As in BIP 32, the method for deriving a child extended key, given a parent extended key and an index - \(i\) + \(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

    \(\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 \(i \geq 2^{31}\) (whether the child is a hardened key).
      • If so (hardened child): let - \(I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\texttt{0x11}]\) + \(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))\) + \(||\,\mathsf{I2LEOSP}_{32}(i))\!\) .
      • If not (normal child): let - \(I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\texttt{0x12}]\) + \(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 @@ -342,13 +344,13 @@ into two 32-byte sequences, \(I_L\) and - \(I_R\) + \(I_R\!\) .
      • Let - \(I_\mathsf{ask} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x13}]))\) + \(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, [\texttt{0x14}]))\) + \(I_\mathsf{nsk} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x14}]))\!\) .
      • Return:
          @@ -359,15 +361,15 @@ \(\mathsf{nsk}_i = (I_\mathsf{nsk} + \mathsf{nsk}_{par}) \pmod{r_\mathbb{J}}\)
        • - \(\mathsf{ovk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x15}]\) + \(\mathsf{ovk}_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, [\texttt{0x16}]\) + \(\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x16}]\) \(||\,\mathsf{dk}_{par}))\)
        • - \(\mathsf{c}_i = I_R\) + \(\mathsf{c}_i = I_R\!\) .
      • @@ -375,11 +377,11 @@

        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\!\) .

    Deriving a child extended full viewing key

    @@ -391,7 +393,7 @@

    \(\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 \(i \geq 2^{31}\) @@ -399,9 +401,9 @@
      • If so (hardened child): return failure.
      • If not (normal child): let - \(I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\texttt{0x12}]\) + \(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))\) + \(||\,\mathsf{I2LEOSP}_{32}(i))\!\) .
    • @@ -410,13 +412,13 @@ into two 32-byte sequences, \(I_L\) and - \(I_R\) + \(I_R\!\) .
    • Let - \(I_\mathsf{ask} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x13}]))\) + \(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, [\texttt{0x14}]))\) + \(I_\mathsf{nsk} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x14}]))\!\) .
    • Return:
        @@ -427,15 +429,15 @@ \(\mathsf{nk}_i = [I_\mathsf{nsk}]\,\mathcal{H}^\mathsf{Sapling} + \mathsf{nk}_{par}\)
      • - \(\mathsf{ovk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\texttt{0x15}]\) + \(\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, [\texttt{0x16}]\) + \(\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x16}]\) \(||\,\mathsf{dk}_{par}))\)
      • - \(\mathsf{c}_i = I_R\) + \(\mathsf{c}_i = I_R\!\) .
    • @@ -445,7 +447,7 @@ is the zero point of Jubjub, or if the corresponding \(\mathsf{ivk}\) derived as specified in 11 is - \(0\) + \(0\!\) .

    @@ -462,26 +464,26 @@ \(\mathsf{nk}\) as specified in 11.
  • Let - \(I = \textsf{BLAKE2b-256}(\texttt{"Zcash_SaplingInt"}, \mathsf{EncodeExtFVKParts}(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk}))\) + \(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}]))\) + \(I_\mathsf{nsk} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I, [\mathtt{0x17}]))\!\) .
  • Let - \(R = \mathsf{PRF^{expand}}(I, [\mathtt{0x18}])\) + \(R = \mathsf{PRF^{expand}}(I, [\mathtt{0x18}])\!\) .
  • Let - \(\mathsf{nsk_{internal}} = (I_\mathsf{nsk} + \mathsf{nsk}) \pmod{r_\mathbb{J}}\) + \(\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}}\) + \(\mathsf{ovk_{internal}}\!\) .
  • Return the internal spending key as - \((\mathsf{ask}, \mathsf{nsk_{internal}}, \mathsf{ovk_{internal}}, \mathsf{dk_{internal}})\) + \((\mathsf{ask}, \mathsf{nsk_{internal}}, \mathsf{ovk_{internal}}, \mathsf{dk_{internal}})\!\) .
  • 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\!\) .

    Deriving a Sapling internal full viewing key

    @@ -501,35 +503,35 @@ be the external full viewing key.

    • Let - \(I = \textsf{BLAKE2b-256}(\texttt{"Zcash_SaplingInt"}, \mathsf{EncodeExtFVKParts}(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk}))\) + \(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}]))\) + \(I_\mathsf{nsk} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I, [\mathtt{0x17}]))\!\) .
    • Let - \(R = \mathsf{PRF^{expand}}(I, [\mathtt{0x18}])\) + \(R = \mathsf{PRF^{expand}}(I, [\mathtt{0x18}])\!\) .
    • Let - \(\mathsf{nk_{internal}} = [I_\mathsf{nsk}] \mathcal{H}^\mathsf{Sapling} + \mathsf{nk}\) + \(\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}}\) + \(\mathsf{ovk_{internal}}\!\) .
    • Return the internal full viewing key as - \((\mathsf{ak}, \mathsf{nk_{internal}}, \mathsf{ovk_{internal}}, \mathsf{dk_{internal}})\) + \((\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 - \(\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\!\) .

    Sapling diversifier derivation

    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:

    • Let \(j\) be the index of the desired diversifier, in the range - \(0\,.\!. 2^{88} - 1\) + \(0\,..\, 2^{88} - 1\!\) .
    • - \(d_j = \mathsf{FF1}\text{-}\mathsf{AES256.Encrypt}(\mathsf{dk}, \texttt{“”}, \mathsf{I2LEBSP}_{88}(j))\) + \(d_j = \mathsf{FF1}\text{-}\mathsf{AES256.Encrypt}(\mathsf{dk}, \texttt{“”}, \mathsf{I2LEBSP}_{88}(j))\!\) .

    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{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 - \(\mathsf{PRF^{expand}}\) + \(\mathsf{PRF^{expand}}\!\) .
  • @@ -601,30 +603,30 @@ 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.

    \(\mathsf{MKGh}^\mathsf{Context}(\mathsf{IKM}) \rightarrow (\mathsf{sk}_m, \mathsf{c}_m)\) -

    + :

    • Calculate - \(I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\mathsf{Context.MKGDomain}, \mathsf{IKM})\) + \(I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\mathsf{Context.MKGDomain}, \mathsf{IKM})\!\) .
    • Split \(I\) into two 32-byte sequences, \(I_L\) and - \(I_R\) + \(I_R\!\) .
    • Use \(I_L\) as the master secret key - \(\mathsf{sk}_m\) + \(\mathsf{sk}_m\!\) .
    • Use \(I_R\) as the master chain code - \(\mathsf{c}_m\) + \(\mathsf{c}_m\!\) .
    • Return - \((\mathsf{sk}_m, \mathsf{c}_m)\) + \((\mathsf{sk}_m, \mathsf{c}_m)\!\) .
    @@ -632,14 +634,14 @@

    \(\mathsf{CKDh}^\mathsf{Context}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)\) \(\rightarrow (\mathsf{sk}_i, \mathsf{c}_i)\) -

    + :

    • Check whether \(i \geq 2^{31}\) (whether the child is a hardened key).
      • If so (hardened child): let - \(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.
      @@ -649,20 +651,20 @@ into two 32-byte sequences, \(I_L\) and - \(I_R\) + \(I_R\!\) .
    • Use \(I_L\) as the child secret key - \(\mathsf{sk}_i\) + \(\mathsf{sk}_i\!\) .
    • Use \(I_R\) as the child chain code - \(\mathsf{c}_i\) + \(\mathsf{c}_i\!\) .
    • Return - \((\mathsf{sk}_i, \mathsf{c}_i)\) + \((\mathsf{sk}_i, \mathsf{c}_i)\!\) .
    @@ -674,7 +676,7 @@ \(\mathsf{Orchard.MKGDomain} = \texttt{“ZcashIP32Orchard”}\)
  • - \(\mathsf{Orchard.CKDDomain} = \texttt{0x81}\) + \(\mathsf{Orchard.CKDDomain} = \mathtt{0x81}\)
  • Orchard extended keys

    @@ -694,7 +696,7 @@
  • Return \(\mathsf{MKGh}^\mathsf{Orchard}(S)\) as the master extended spending key - \(m_\mathsf{Orchard}\) + \(m_\mathsf{Orchard}\!\) .
  • @@ -702,7 +704,7 @@

    \(\mathsf{CKDsk}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)\) \(\rightarrow (\mathsf{sk}_{i}, \mathsf{c}_i)\) -

    + :

    • Return \(\mathsf{CKDh}^\mathsf{Orchard}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)\) @@ -722,24 +724,24 @@ as follows:

      • Let - \(K = \mathsf{I2LEBSP}_{256}(\mathsf{rivk})\) + \(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}))\) + \(\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}})\) + \((\mathsf{ak}, \mathsf{nk}, \mathsf{rivk_{internal}})\!\) .

      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 @@

      Orchard diversifier derivation

      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)\!\) :

      • Let \((\mathsf{ak}, \mathsf{nk}, \mathsf{rivk})\) be the Orchard full viewing key for - \(\mathsf{sk}_i\) + \(\mathsf{sk}_i\!\) .
      • Let - \(K = \mathsf{I2LEBSP}_{256}(\mathsf{rivk})\) + \(K = \mathsf{I2LEBSP}_{256}(\mathsf{rivk})\!\) .
      • - \(\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(K, [\texttt{0x82}] \,||\, \mathsf{I2LEOSP}_{256}(\mathsf{ak}) \,||\, \mathsf{I2LEOSP}_{256}(\mathsf{nk})))\) + \(\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\) + \(0\,..\, 2^{88} - 1\!\) .
      • - \(d_{i,j} = \mathsf{FF1}\text{-}\mathsf{AES256.Encrypt}(\mathsf{dk}_i, \texttt{“”}, \mathsf{I2LEBSP}_{88}(j))\) + \(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 @@ -799,7 +801,7 @@ \(\mathsf{Arbitrary.MKGDomain} = \texttt{“ZcashArbitraryKD”}\)

    • - \(\mathsf{Arbitrary.CKDDomain} = \texttt{0xAB}\) + \(\mathsf{Arbitrary.CKDDomain} = \mathtt{0xAB}\)

    Arbitrary master key generation

    @@ -815,7 +817,7 @@

    \(\mathsf{CKDarb}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)\) \(\rightarrow (\mathsf{sk}_i, \mathsf{c}_i)\) -

    + :

    • Return \(\mathsf{CKDh}^\mathsf{Arbitrary}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)\!\) @@ -840,21 +842,21 @@

      Sapling and Orchard key paths have the following three path levels at the top, all of which use hardened derivation:

      • - \(purpose\) + \(purpose\!\) : a constant set to \(32'\) (or - \(\texttt{0x80000020}\) + \(\mathtt{0x80000020}\!\) ) following the BIP 43 recommendation. It indicates that the subtree of this node is used according to this specification.
      • - \(coin\_type\) + \(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 6. Note that in keeping with that document, all cryptocurrency testnets share \(coin\_type\) index - \(1\) + \(1\!\) .
      • - \(account\) + \(account\!\) : numbered from index \(0\) in sequentially increasing manner. Defined as in BIP 44 5.
      • @@ -866,11 +868,11 @@

        Sapling key path

        Sapling provides a mechanism to allow the efficient creation of diversified payment addresses with the same spending authority. A group of such addresses shares the same full viewing key and incoming viewing key, and so creating as many unlinkable addresses as needed does not increase the cost of scanning the block chain for relevant transactions.

        The above key path levels include an account identifier, which in all user interfaces is represented as a "bucket of funds" under the control of a single spending authority. Therefore, wallets implementing Sapling ZIP 32 derivation MUST support the following path for any account in range - \(\{ 0\,.\!. 2^{31} - 1 \}\) + \(\{ 0\,..\, 2^{31} - 1 \}\!\) :

        • - \(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.

        @@ -882,23 +884,23 @@ path level as in 5:

        • - \(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 - \(\mathtt{0x7FFFFFFF}\) + \(\mathtt{0x7FFFFFFF}\!\) , using hardened derivation for - \(address\_index\) + \(address\_index\!\) .

        Orchard key path

        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 \}\!\) :

        • - \(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.

        @@ -914,7 +916,7 @@ (as specified in 18) is given by:

        • - \(\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.

        @@ -926,7 +928,7 @@ (as specified in 20) is given by:

        • - \(\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.

        @@ -938,8 +940,8 @@ of a hierarchical deterministic wallet is given by:

        • - \(\mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{“Zcash_HD_Seed_FP”},\) - \([\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.

        @@ -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.

        Sapling extended spending keys

        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:

        • @@ -965,31 +967,31 @@ \(||\,parent\_fvk\_tag\) \(||\,\mathsf{I2LEOSP}_{32}(i)\) \(||\,\mathsf{c}\) - \(||\,\mathsf{EncodeExtSKParts}(\mathsf{ask, nsk, ovk, dk})\) + \(||\,\mathsf{EncodeExtSKParts}(\mathsf{ask, nsk, ovk, dk})\!\) .

        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.

        Sapling extended full viewing keys

        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:

        • @@ -997,47 +999,47 @@ \(||\,parent\_fvk\_tag\) \(||\,\mathsf{I2LEOSP}_{32}(i)\) \(||\,\mathsf{c}\) - \(||\,\mathsf{EncodeExtFVKParts}(\mathsf{ak, nk, ovk, dk})\) + \(||\,\mathsf{EncodeExtFVKParts}(\mathsf{ak, nk, ovk, dk})\!\) .

        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.

        Orchard extended spending keys

        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:

        • - \(\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, \(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 @@
      • the \(\mathsf{BLAKE2b}\text{-}\mathsf{512}\) personalization - \(\texttt{“ZcashIP32_Sprout”}\) + \(\texttt{“ZcashIP32\_Sprout”}\!\) , formerly specified for derivation of the master key of the Sprout tree;
      • the \(\mathsf{BLAKE2b}\text{-}\mathsf{256}\) personalization - \(\texttt{“Zcash_Sprout_AFP”}\) + \(\texttt{“Zcash\_Sprout\_AFP”}\!\) , formerly specified for generation of Sprout address fingerprints;
      • the \(\mathsf{PRF^{expand}}\) prefix - \(\texttt{0x80}\) + \(\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/rendered/zip-0203.html b/rendered/zip-0203.html index 074d62c7d..26ef4083e 100644 --- a/rendered/zip-0203.html +++ b/rendered/zip-0203.html @@ -3,7 +3,9 @@ ZIP 203: Transaction Expiry - + + +
      @@ -22,14 +24,14 @@

      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.

      Specification

      diff --git a/rendered/zip-0207.html b/rendered/zip-0207.html index 6be0e0d5d..88ced65b0 100644 --- a/rendered/zip-0207.html +++ b/rendered/zip-0207.html @@ -3,7 +3,9 @@ ZIP 207: Funding Streams - + + +
      @@ -59,13 +61,13 @@ \(\mathsf{BlockSubsidy}(\mathsf{height})\)
    • - \(\mathsf{RedeemScriptHash}(\mathsf{height})\) + \(\mathsf{RedeemScriptHash}(\mathsf{height})\!\) .

    We also define the following function:

    • - \(\mathsf{HeightForHalving}(\mathsf{halving})\) + \(\mathsf{HeightForHalving}(\mathsf{halving})\!\) : Smallest \(\mathsf{height}\) such that @@ -82,11 +84,11 @@ \frac{\mathsf{BlockSubsidy}(\mathsf{height}) \,\cdot\, \mathsf{FundingStream[FUND].ValueNumerator}}{\mathsf{FundingStream[FUND].ValueDenominator}} \right)\)

      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:

      -
      \(\begin{eqnarray*} +
      \(\begin{array}{rcl} \mathsf{AddressChangeInterval} &=& \mathsf{PostBlossomHalvingInterval} / 48 \\ \mathsf{AddressPeriod}(\mathsf{height}) &=& \mathsf{floor}\left( @@ -95,7 +97,7 @@ \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 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.

    Consensus rules

    -

    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:

      -
    • The existing consensus rule for payment of the Founders' Reward 10 is no longer active. (This would be the case under the preexisting consensus rules for Mainnet, but not for Testnet.)
    • +
    • The existing consensus rule for payment of the Founders' Reward 10 is no longer active. (This would be the case under the preexisting consensus rules for Mainnet, but not for Testnet.)
    • In each block with coinbase transaction \(\mathsf{cb}\) at block height - \(\mathsf{height}\) + \(\mathsf{height}\!\) , for each funding stream \(\mathsf{fs}\) active at that block height with a recipient identifier other than - \(\mathsf{DEFERRED}\_\mathsf{POOL}\) + \(\mathsf{DEFERRED\_POOL}\) given by \(\mathsf{fs.Recipient}(\mathsf{height})\!\) , @@ -252,29 +254,29 @@
    • \(\mathsf{fs.Recipient}(\mathsf{height})\) is defined as - \(\mathsf{fs.Recipients_{\,\fs.RecipientIndex}}(\mathsf{height})\!\) + \(\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 the scriptPubKey.
    • -
    • The "prescribed way" to pay a Sapling address is as defined in 16. 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 +
    • The "prescribed way" to pay a Sapling address is as defined in 16. 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 \(\mathbf{0x02}\!\) - , as specified in 15.
    • + , as specified in 15.
    -

    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

    Deployment

    -

    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

    Backward compatibility

    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 @@ 1 - 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" <https://www.rfc-editor.org/info/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" @@ -299,7 +301,7 @@ 2 - Zcash Protocol Specification, Version 2024.5.1 or later <protocol/protocol.pdf> + Zcash Protocol Specification, Version 2024.5.1 or later @@ -307,7 +309,7 @@ 3 - Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 3.10: Block Subsidy and Founders' Reward <protocol/protocol.pdf#subsidyconcepts> + Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 3.10: Block Subsidy and Founders' Reward @@ -315,7 +317,7 @@ 4 - Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 3.12: Mainnet and Testnet <protocol/protocol.pdf#networks> + Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 3.12: Mainnet and Testnet @@ -323,7 +325,7 @@ 5 - Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.3: Constants <protocol/protocol.pdf#constants> + Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.3: Constants @@ -331,7 +333,7 @@ 6 - Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.6.1.1: Transparent Addresses <protocol/protocol.pdf#transparentaddrencoding> + Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.6.1.1: Transparent Addresses @@ -339,7 +341,7 @@ 7 - Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.6.3.1: Sapling Payment Addresses <protocol/protocol.pdf#saplingpaymentaddrencoding> + Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.6.3.1: Sapling Payment Addresses @@ -347,7 +349,7 @@ 8 - Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.7.3: Difficulty adjustment <protocol/protocol.pdf#diffadjustment> + Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.7.3: Difficulty adjustment @@ -355,7 +357,7 @@ 9 - Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.8: Calculation of Block Subsidy, Funding Streams, and Founders' Reward <protocol/protocol.pdf#subsidies> + Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.8: Calculation of Block Subsidy, Funding Streams, and Founders' Reward @@ -363,7 +365,7 @@ 10 - Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.9: Payment of Founders' Reward <protocol/protocol.pdf#foundersreward> + Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.9: Payment of Founders' Reward @@ -371,7 +373,7 @@ 11 - Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.10: Payment of Funding Streams <protocol/protocol.pdf#fundingstreams> + Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.10: Payment of Funding Streams @@ -379,7 +381,7 @@ 12 - ZIP 0: ZIP Process <zip-0000.rst> + ZIP 0: ZIP Process @@ -387,7 +389,7 @@ 13 - ZIP 200: Network Upgrade Mechanism <zip-0200.rst> + ZIP 200: Network Upgrade Mechanism @@ -395,7 +397,7 @@ 14 - ZIP 208: Shorter Block Target Spacing <zip-0208.rst> + ZIP 208: Shorter Block Target Spacing @@ -403,7 +405,7 @@ 15 - ZIP 212: Allow Recipient to Derive Sapling Ephemeral Secret from Note Plaintext <zip-0212.rst> + ZIP 212: Allow Recipient to Derive Sapling Ephemeral Secret from Note Plaintext @@ -411,7 +413,7 @@ 16 - ZIP 213: Shielded Coinbase <zip-0213.rst> + ZIP 213: Shielded Coinbase @@ -419,7 +421,7 @@ 17 - ZIP 214: Consensus rules for a Zcash Development Fund <zip-0214.rst> + ZIP 214: Consensus rules for a Zcash Development Fund @@ -427,7 +429,7 @@ 18 - ZIP 251: Deployment of the Canopy Network Upgrade <zip-0251.rst> + ZIP 251: Deployment of the Canopy Network Upgrade @@ -435,7 +437,7 @@ 19 - ZIP 253: Deployment of the NU6 Network Upgrade <zip-0253.rst> + ZIP 253: Deployment of the NU6 Network Upgrade @@ -443,7 +445,7 @@ 20 - ZIP 1014: Establishing a Dev Fund for ECC, ZF, and Major Grants <zip-1014.rst> + ZIP 1014: Establishing a Dev Fund for ECC, ZF, and Major Grants @@ -451,7 +453,7 @@ 21 - ZIP 1015: Block Subsidy Allocation for Non-Direct Development Funding <zip-1015.rst> + ZIP 1015: Block Subsidy Allocation for Non-Direct Development Funding @@ -459,7 +461,7 @@ 22 - ZIP 2001: Lockbox Funding Streams <zip-2001.rst> + ZIP 2001: Lockbox Funding Streams diff --git a/rendered/zip-0208.html b/rendered/zip-0208.html index 4d4a014bc..b3734d244 100644 --- a/rendered/zip-0208.html +++ b/rendered/zip-0208.html @@ -3,6 +3,9 @@ ZIP 208: Shorter Block Target Spacing + + +
    @@ -38,81 +41,181 @@

    Specification

    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].

    Consensus changes

    -

    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:

      -
    • BlossomPoWTargetSpacingRatio := PreBlossomPoWTargetSpacing / PostBlossomPoWTargetSpacing
    • -
    • PostBlossomHalvingInterval := floor(PreBlossomHalvingInterval ¡ BlossomPoWTargetSpacingRatio).
    • -
    -

    In the same section, redefine PoWTargetSpacing as a function taking a height parameter, as follows:

    -
      -
    • PoWTargetSpacing(height) := -
        -
      • PreBlossomPoWTargetSpacing, if not IsBlossomActivated(height)
      • -
      • PostBlossomPoWTargetSpacing, otherwise.
      • -
      +
    • + \(\mathsf{BlossomPoWTargetSpacingRatio} := \mathsf{PreBlossomPoWTargetSpacing} / \mathsf{PostBlossomPoWTargetSpacing}\)
    • +
    • + \(\mathsf{PostBlossomHalvingInterval} := \mathsf{floor}(\mathsf{PreBlossomHalvingInterval} \cdot \mathsf{BlossomPoWTargetSpacingRatio})\!\) + .
    -

    Also redefine AveragingWindowTimespan, MinActualTimespan, MaxActualTimespan, ActualTimespanDamped, ActualTimespanBounded, and Threshold as follows:

    -
      -
    • add a height parameter to each of these functions that does not already have one;
    • -
    • ensure that each reference to any of these values, or to PoWTargetSpacing, are replaced with a function call passing the height parameter.
    • -
    -

    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:

    +
    \(\mathsf{PoWTargetSpacing}(\mathsf{height}) := + \begin{cases} + \mathsf{PreBlossomPoWTargetSpacing}, &\!\!\text{if not } \mathsf{IsBlossomActivated}(\mathsf{height}) \\ + \mathsf{PostBlossomPoWTargetSpacing} &\!\!\text{otherwise} + \end{cases}\)
    +

    Also redefine + \(\mathsf{AveragingWindowTimespan}\!\) + , + \(\mathsf{MinActualTimespan}\!\) + , + \(\mathsf{MaxActualTimespan}\!\) + , + \(\mathsf{ActualTimespanDamped}\!\) + , + \(\mathsf{ActualTimespanBounded}\!\) + , and + \(\mathsf{Threshold}\) + as follows:

      -
    • Halving(height) := -
        -
      • floor((height - SlowStartShift) / PreBlossomHalvingInterval), if not IsBlossomActivated(height)
      • -
      • floor((BlossomActivationHeight - SlowStartShift) / PreBlossomHalvingInterval + (height - BlossomActivationHeight) / PostBlossomHalvingInterval), otherwise
      • -
      -
    • -
    • BlockSubsidy(height) := -
        -
      • SlowStartRate ¡ height, if height < SlowStartInterval / 2
      • -
      • SlowStartRate ¡ (height + 1), if SlowStartInterval / 2 ≤ height and height < SlowStartInterval
      • -
      • floor(MaxBlockSubsidy / 2Halving(*height*)), if SlowStartInterval ≤ height and not IsBlossomActivated(height)
      • -
      • floor(MaxBlockSubsidy / (BlossomPoWTargetSpacingRatio ¡ 2Halving(*height*))), otherwise
      • -
      -
    • +
    • add a + \(\mathsf{height}\) + parameter to each of these functions that does not already have one;
    • +
    • ensure that each reference to any of these values, or to + \(\mathsf{PoWTargetSpacing}\!\) + , are replaced with a function call passing the + \(\mathsf{height}\) + parameter.
    -

    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:

    +
    \(\mathsf{Halving}(\mathsf{height}) := + \begin{cases} + \mathsf{floor}((\mathsf{height} - \mathsf{SlowStartShift}) / \mathsf{PreBlossomHalvingInterval}), &\!\!\text{if not } \mathsf{IsBlossomActivated}(\mathsf{height}) \\ + \mathsf{floor}((\mathsf{BlossomActivationHeight} - \mathsf{SlowStartShift}) / \mathsf{PreBlossomHalvingInterval} & \\ + \hspace{1em}+\; (\mathsf{height} - \mathsf{BlossomActivationHeight}) / \mathsf{PostBlossomHalvingInterval}) &\!\!\text{otherwise} + \end{cases}\)
    +
    \(\mathsf{BlockSubsidy}(\mathsf{height}) := + \begin{cases} + \mathsf{SlowStartRate} \cdot \mathsf{height}, &\!\!\text{if } \mathsf{height} < \mathsf{SlowStartInterval} / 2 \\ + \mathsf{SlowStartRate} \cdot (\mathsf{height} + 1), &\!\!\text{if } \mathsf{SlowStartInterval} / 2 \leq \mathsf{height} \text{ and } \mathsf{height} < \mathsf{SlowStartInterval} \\ + \mathsf{floor}(\mathsf{MaxBlockSubsidy} / 2^{\mathsf{Halving}(\mathsf{height})}), &\!\!\text{if } \mathsf{SlowStartInterval} \leq \mathsf{height} \text{ and not } \mathsf{IsBlossomActivated}(\mathsf{height}) \\ + \mathsf{floor}(\mathsf{MaxBlockSubsidy} / & \\ + \hspace{1em}(\mathsf{BlossomPoWTargetSpacingRatio} \cdot 2^{\mathsf{Halving}(\mathsf{height})})) &\!\!\text{otherwise} + \end{cases}\)
    +

    Note: + \(\mathsf{BlossomActivationHeight}\!\) + , + \(\mathsf{PostBlossomHalvingInterval}\!\) + , and + \(\mathsf{PostBlossomTargetSpacing}\) + are chosen so that:

      -
    • (BlossomActivationHeight - SlowStartShift) / PreBlossomHalvingInterval + (height - BlossomActivationHeight) / PostBlossomHalvingInterval) is exactly 1 for some integer height.
    • -
    • MaxBlockSubsidy / (BlossomPoWTargetSpacingRatio ¡ 2Halving(*height*)) is an integer for the next few periods.
    • +
    • + \((\mathsf{BlossomActivationHeight} - \mathsf{SlowStartShift}) / \mathsf{PreBlossomHalvingInterval}\hspace{-3em}\) + \(\hspace{3em}+\; (\mathsf{height} - \mathsf{BlossomActivationHeight}) / \mathsf{PostBlossomHalvingInterval}\) + is exactly + \(1\) + for some integer + \(\mathsf{height}\!\) + .
    • +
    • + \(\mathsf{MaxBlockSubsidy} / (\mathsf{BlossomPoWTargetSpacingRatio} \cdot 2^{\mathsf{Halving}(\mathsf{height})})\) + is an integer for the next few periods.

    In section 7.8 (Payment of Founders’ Reward) [later moved to section 7.9], define:

    -
      -
    • FounderAddressAdjustedHeight(height) := -
        -
      • height, if not IsBlossomActivated(height)
      • -
      • BlossomActivationHeight + floor((height - BlossomActivationHeight) / BlossomPoWTargetSpacingRatio), otherwise
      • -
      -
    • -
    -

    and in the definition of FounderAddressIndex, replace the use of height with FounderAddressAdjustedHeight(height).

    +
    \(\mathsf{FounderAddressAdjustedHeight}(\mathsf{height}) := + \begin{cases} + \mathsf{height}, &\!\!\text{if not } \mathsf{IsBlossomActivated}(\mathsf{height}) \\ + \mathsf{BlossomActivationHeight} + \mathsf{floor}((\mathsf{height} - \mathsf{BlossomActivationHeight}) / \\ + \hspace{1em}\mathsf{BlossomPoWTargetSpacingRatio}) &\!\!\text{otherwise} + \end{cases}\)
    +

    and in the definition of + \(\mathsf{FounderAddressIndex}\!\) + , replace the use of + \(\mathsf{height}\) + with + \(\mathsf{FounderAddressAdjustedHeight}(\mathsf{height})\!\) + .

    Also define:

      -
    • FoundersRewardLastBlockHeight := max({ height ⦂ N | Halving(height) < 1 })
    • +
    • + \(\mathsf{FoundersRewardLastBlockHeight} := \mathsf{max}(\{ \mathsf{height} \;{\small ⦂}\; \mathbb{N} | \mathsf{Halving}(\mathsf{height}) < 1 \})\) +

    Replace the first note in that section with:

      -
    • No Founders’ Reward is required to be paid for height > FoundersRewardLastBlockHeight (i.e. after the first halving), or for height = 0 (i.e. the genesis block).
    • +
    • No Founders’ Reward is required to be paid for + \(\mathsf{height} > \mathsf{FoundersRewardLastBlockHeight}\) + (i.e. after the first halving), or for + \(\mathsf{height} = 0\) + (i.e. the genesis block).
    -

    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}\!\) + .

    Effect on difficulty adjustment

    -

    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.

    Minimum difficulty blocks on Testnet

    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.

    @@ -162,7 +265,9 @@

    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.

    Estimation of fully synced chain height

    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.

    @@ -200,7 +305,9 @@

    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.

    Reference Implementation

    -

    https://github.com/zcash/zcash/pull/4025

    +

    References

    diff --git a/rendered/zip-0212.html b/rendered/zip-0212.html index 2c755bc84..846588b62 100644 --- a/rendered/zip-0212.html +++ b/rendered/zip-0212.html @@ -3,7 +3,9 @@ ZIP 212: Allow Recipient to Derive Ephemeral Secret from Note Plaintext - + + +
    diff --git a/rendered/zip-0215.html b/rendered/zip-0215.html index 4fe952bc9..215315187 100644 --- a/rendered/zip-0215.html +++ b/rendered/zip-0215.html @@ -3,7 +3,9 @@ ZIP 215: Explicitly Defining and Modifying Ed25519 Validation Rules - + + +
    @@ -43,7 +45,7 @@ MUST represent an integer \(S\) less than - \(\ell\) + \(\ell\!\) ;
  • The group equation \([8][S]B = [8]R + [8][k]A\) @@ -61,12 +63,12 @@ and \(\underline{R}\) are canonical encodings; in other words, the integer encoding the - \(y\) + \(y\!\) -coordinate of the points may be unreduced modulo - \(2^{255}-19\) + \(2^{255}-19\!\) .

    Note: the alternate validation equation - \([S]B = R + [k]A\) + \([S]B = R + [k]A\!\) , allowed by RFC 8032, MUST NOT be used.

  • Rationale

    diff --git a/rendered/zip-0216.html b/rendered/zip-0216.html index 52bc7adab..32d031186 100644 --- a/rendered/zip-0216.html +++ b/rendered/zip-0216.html @@ -3,7 +3,9 @@ ZIP 216: Require Canonical Jubjub Point Encodings - + + +
    @@ -38,14 +40,14 @@ -coordinate zero:

    • - \((0, 1)\) + \((0, 1)\!\) , which is the identity;
    • - \((0, -1)\) + \((0, -1)\!\) , which is a point of order two.

    Each of these has a single non-canonical encoding in which the value of the sign bit is - \(1\) + \(1\!\) .

    This creates a consensus issue because (unlike other non-canonical point encodings that are rejected) either of the above encodings can be decoded, and then re-encoded to a different encoding. For example, if a non-canonical encoding appeared in a transaction field, then node implementations that store points internally as abstract curve points, and used those to derive transaction IDs, would derive different IDs than nodes which store transactions as bytes (such as zcashd).

    This issue is not known to cause any security vulnerability, beyond the risk of consensus incompatibility. In fact, for some of the fields that would otherwise be affected, the issue does not occur because there are already consensus rules that prohibit small-order points, and this incidentally prohibits non-canonical encodings.

    @@ -53,25 +55,25 @@

    Specification

    Let - \(\mathsf{abst}_{\mathbb{J}}\) + \(\mathsf{abst}_{\mathbb{J}}\!\) , - \(\mathsf{repr}_{\mathbb{J}}\) + \(\mathsf{repr}_{\mathbb{J}}\!\) , and \(q_{\mathbb{J}}\) be as defined in 6.

    Define a non-canonical compressed encoding of a Jubjub point to be a sequence of \(256\) bits, - \(b\) + \(b\!\) , such that \(\mathsf{abst}_{\mathbb{J}}(b) \neq \bot\) and - \(\mathsf{repr_{\mathbb{J}}}\big(\mathsf{abst}_{\mathbb{J}}(b)\big) \neq b\) + \(\mathsf{repr_{\mathbb{J}}}\big(\mathsf{abst}_{\mathbb{J}}(b)\big) \neq b\!\) .

    Non-normative note: There are two such bit sequences, \(\mathsf{I2LEOSP}_{\ell_{\mathbb{J}}}(2^{255} + 1)\) and - \(\mathsf{I2LEOSP}_{\ell_{\mathbb{J}}}(2^{255} + q_{\mathbb{J}} - 1)\) + \(\mathsf{I2LEOSP}_{\ell_{\mathbb{J}}}(2^{255} + q_{\mathbb{J}} - 1)\!\) . The Sapling protocol uses little-endian ordering when converting between bit and byte sequences, so the first of these sequences corresponds to a \(\mathtt{0x01}\) byte, followed by @@ -110,7 +112,7 @@

    • - \(\mathsf{pk}\star_{\mathsf{d}}\) + \(\mathsf{pk}\star_{\mathsf{d}}\!\) .
    @@ -136,20 +138,20 @@ \(\mathtt{cv}\)
  • - \(\mathtt{ephemeralKey}\) + \(\mathtt{ephemeralKey}\!\) .
  • These fields cannot by consensus contain small-order points. All of the points with non-canonical encodings are small-order.

    Implementations MAY choose to reject non-canonical encodings of the above four fields early in decoding of a transaction. This eliminates the risk that parts of the transaction could be re-serialized from their internal representation to a different byte sequence than in the original transaction, e.g. when calculating transaction IDs.

    In addition, Sapling addresses and full viewing keys MUST be considered invalid when imported if they contain non-canonical Jubjub point encodings, or encodings of points that are not in the prime-order subgroup - \(\mathbb{J}^{(r)}\) + \(\mathbb{J}^{(r)}\!\) . These requirements MAY be enforced in advance of NU5 activation.

    In Sapling addresses 8:

    • the encoding of - \(\mathsf{pk_d}\) + \(\mathsf{pk_d}\!\) .
    @@ -157,14 +159,14 @@
    • the encoding of - \(\mathsf{ak}\) + \(\mathsf{ak}\!\) .

    ( \(\mathsf{ak}\) also MUST NOT encode the zero point - \(\mathcal{O}_{\mathbb{J}}\) + \(\mathcal{O}_{\mathbb{J}}\!\) .)

    The above is intended to be a complete list of the places where compressed encodings of Jubjub points occur in the Zcash consensus protocol and in plaintext, address, or key formats.

    @@ -178,22 +180,22 @@

    The necessary checks are very simple and do not require cryptographic operations, therefore the performance impact will be negligible.

    The public inputs of Jubjub points to the Spend circuit ( - \(\mathsf{rk}\) + \(\!\mathsf{rk}\) and - \(\mathsf{cv^{old}}\) + \(\mathsf{cv^{old}}\!\) ) and Output circuit ( - \(\mathsf{cv^{new}}\) + \(\!\mathsf{cv^{new}}\) and - \(\mathsf{epk}\) + \(\mathsf{epk}\!\) ) are not affected because they are represented in affine coordinates as elements of the correct field ( - \(\mathbb{F}_{r_\mathbb{S}} = \mathbb{F}_{q_\mathbb{J}}\) + \(\!\mathbb{F}_{r_\mathbb{S}} = \mathbb{F}_{q_\mathbb{J}}\!\) ), and so no issue of encoding canonicity arises.

    Encodings of elliptic curve points on Curve25519, BN-254 - \(\mathbb{G}_1\) + \(\mathbb{G}_1\!\) , BN-254 - \(\mathbb{G}_2\) + \(\mathbb{G}_2\!\) , BLS12-381 - \(\mathbb{G}_1\) + \(\mathbb{G}_1\!\) , and BLS12-381 \(\mathbb{G}_2\) are not affected.

    diff --git a/rendered/zip-0221.html b/rendered/zip-0221.html index a4e119e7b..400295cfc 100644 --- a/rendered/zip-0221.html +++ b/rendered/zip-0221.html @@ -3,7 +3,9 @@ ZIP 221: FlyClient - Consensus-Layer Changes - + + +
    @@ -25,13 +27,13 @@
    A client that is not a full participant in the network of Zcash peers. It can send and receive payments, but does not store or validate a copy of the block chain.
    High probability
    An event occurs with high probability if it occurs with probability - \(1-O(1/2^\lambda)\) + \(1-O(1/2^\lambda)\!\) , where \(\lambda\) is a security parameter.
    Negligible probability
    An event occurs with negligible probability if it occurs with probability - \(O(1/2^\lambda)\) + \(O(1/2^\lambda)\!\) , where \(\lambda\) is the security parameter.
    @@ -46,7 +48,7 @@

    An MMR is a Merkle tree which allows for efficient appends, proofs, and verifications. Informally, appending data to an MMR consists of creating a new leaf and then iteratively merging neighboring subtrees with the same size. This takes at most \(\log(n)\) operations and only requires knowledge of the previous subtree roots, of which there are fewer than - \(\log(n)\) + \(\log(n)\!\) .

    (example adapted from 6) To illustrate this, consider a list of 11 leaves. We first construct the biggest perfect binary subtrees possible by joining any balanced sibling trees that are the same size. We do this starting from the left to the right, adding a parent as soon as 2 children exist. This leaves us with three subtrees ("mountains") of altitudes 3, 1, and 0:

       /\
    @@ -122,7 +124,7 @@
                  be the altitude of a given node. We can easily jump to the node's right sibling (if it has one) by adding
                     \(2^{h+1} - 1\)
                  to its position, and its left child (if it has one) by subtracting
    -                \(2^h\)
    +                \(2^h\!\)
                 . This allows us to efficiently find the subtree roots ("peaks") of the mountains.

    Once we have the positions of the mountain peaks, we "bag" them using the following algorithm:

      @@ -162,14 +164,14 @@

      The protocol requires that an MMR that commits to the inclusion of all blocks since the preceding network upgrade \((B_x, \ldots, B_{n-1})\) is formed for each block - \(B_n\) + \(B_n\!\) . The root \(M_n\) of the MMR MUST be included in the header of - \(B_n\) + \(B_n\!\) .

      ( - \(x\) + \(\!x\) is the activation height of the preceding network upgrade.)

      FlyClient reduces the number of block headers needed for light client verification of a valid chain, from linear (as in the current reference protocol) to logarithmic in block chain length. This verification is correct with high probability. It also allows creation of subtree proofs, so light clients need only check blocks later than the most recently verified block index. Following that, verification of a transaction inclusion within that block follows the usual reference protocol 13.

      A smaller proof size could enable the verification of Zcash SPV Proofs in block-chain protocols such as Ethereum, enabling efficient cross-chain communication and pegs. It also reduces bandwidth and storage requirements for resource-limited clients like mobile or IoT devices.

      @@ -184,14 +186,14 @@ of \(B_n\) to be the last network upgrade activation height in the chain that is less than - \(n\) + \(n\!\) . (For this definition, block height \(0\) is considered to be the height of a network upgrade activation. The preceding network upgrade height of the genesis block is undefined.)

      The leaves of the MMR at block \(B_n\) are hash commitments to the header data and metadata of each previous block - \(B_x, \ldots, B_{n-1}\) + \(B_x, \ldots, B_{n-1}\!\) , where \(x\) is defined as above. We extend the standard MMR to allow metadata to propagate upwards through the tree by either summing the metadata of both children, or inheriting the metadata of a specific child as necessary. This allows us to create efficient proofs of selected properties of a range of blocks without transmitting the entire range of blocks or headers.

      @@ -209,7 +211,7 @@
    1. For clarity, in a given consensus branch, the hashSubtreeCommitment field of leaf \(n-1\) is precisely equal to the hashPrevBlock field in the header of the block at height - \(x+n\) + \(x+n\!\) , where \(x\) is the network upgrade activation height of that consensus branch.
    2. @@ -286,7 +288,7 @@
      Leaf node
      The protocol-defined work of the block: - \(\mathsf{floor}(2^{256} / (\mathsf{ToTarget}(\mathsf{nBits}) + 1))\) + \(\mathsf{floor}(2^{256} / (\mathsf{ToTarget}(\mathsf{nBits}) + 1))\!\) . 4
      Internal or root node
      @@ -462,9 +464,9 @@

    Incremental push and pop (pseudocode)

    With each new block - \(B_n\) + \(B_n\!\) , we append a new MMR leaf node corresponding to block - \(B_{n-1}\) + \(B_{n-1}\!\) . The append operation is detailed below in pseudocode (adapted from 2):

    def get_peaks(node: ZcashMMRNode) -> List[ZcashMMRNode]:
         peaks: List[ZcashMMRNode] = []
    @@ -600,7 +602,7 @@
                                 
    • This commitment serves the same purpose as hashFinalSaplingRoot in current Sapling semantics.
    • However, because the MMR tree commits to blocks - \(B_x \ldots B_{n-1}\) + \(B_x \ldots B_{n-1}\!\) , the latest commitment will describe the final treestate of the previous block, rather than the current block.
    • Concretely: block 500 currently commits to the final treestate of block 500 in its header. With this ZIP, block 500 will commit to all roots up to block 499, but not the final root of block 500.
    • We feel this is an acceptable tradeoff. Using the most recent treestate as a transaction anchor is already unsafe in reorgs. Clients should never use the most recent treestate to generate transactions, so it is acceptable to delay commitment by one block.
    • @@ -631,7 +633,7 @@

      The calculation of hashChainHistoryRoot is not well-defined for the genesis block, since then \(n = 0\) and there is no block - \(B_{n-1}\) + \(B_{n-1}\!\) . Also, in the case of chains that activate this ZIP after genesis (including Zcash Mainnet and Testnet), the hashChainHistoryRoot of the activation block would commit to the whole previous epoch if a special case were not made. It would be impractical to calculate this commitment all at once, and so we specify that hashLightClientRoot is set to all zero bytes for that block instead. The hash of the final Sapling note commitment tree root for the activation block will not be encoded in that block, but will be committed to one block later in the hashLatestSaplingRoot field of the MMR root commitment.

    diff --git a/rendered/zip-0224.html b/rendered/zip-0224.html index 211d87e21..e88a49eec 100644 --- a/rendered/zip-0224.html +++ b/rendered/zip-0224.html @@ -3,7 +3,9 @@ ZIP 224: Orchard Shielded Protocol - + + +
    @@ -49,13 +51,13 @@
  • Vesta is used as the "circuit curve"; its scalar field (being the base field of Pallas) is the "word" type over which the circuit is implemented (c/f BLS12-381).
  • We use the "simplified SWU" algorithm to define an infallible - \(\mathsf{GroupHash}\) + \(\mathsf{GroupHash}\!\) , instead of the fallible BLAKE2s-based mechanism used for Sapling. It is intended to follow (version 10 of) the IETF hash-to-curve Internet Draft 33 (but the protocol specification takes precedence in the case of any discrepancy).

    The presence of the curve cycle is an explicit design choice. This proposal only uses half of the cycle (Pallas being an embedded curve of Vesta); the full cycle is expected to be leveraged by future protocol updates.

    • Curve specifications: 15
    • - \(\mathsf{GroupHash}\) + \(\mathsf{GroupHash}\!\) : 16
    • Supporting evidence: 34
    @@ -101,7 +103,7 @@
  • \(\mathsf{ovk}\) is derived from - \(\mathsf{fvk}\) + \(\mathsf{fvk}\!\) , instead of being a component of the spending key.
  • All diversifiers now result in valid payment addresses.
  • @@ -117,10 +119,10 @@

    Notes

    Orchard notes have the structure - \((addr, v, \rho, \psi, \mathsf{rcm}).\) - \(\rho\) + \((addr, v, \text{ρ}, \text{φ}, \mathsf{rcm}).\) + \(\text{ρ}\) is set to the nullifier of the spent note in the same action, which ensures it is unique. - \(\psi\) + \(\text{φ}\) and \(\mathsf{rcm}\) are derived from a random seed (as with Sapling after ZIP 212 30).

    @@ -131,7 +133,7 @@

    Nullifiers

    Nullifiers for Orchard notes are computed as:

    - \(\mathsf{nf} = [F_{\mathsf{nk}}(\rho) + \psi \pmod{p}] \mathcal{G} + \mathsf{cm}\) + \(\mathsf{nf} = [F_{\mathsf{nk}}(\text{ρ}) + \text{φ} \pmod{p}] \,\mathcal{G} + \mathsf{cm}\)

    where \(F\) diff --git a/rendered/zip-0225.html b/rendered/zip-0225.html index 1ab6b9415..2d381715d 100644 --- a/rendered/zip-0225.html +++ b/rendered/zip-0225.html @@ -3,7 +3,9 @@ ZIP 225: Version 5 Transaction Format - + + +

    @@ -212,7 +214,9 @@
    • enableSpendsOrchard
    • enableOutputsOrchard
    • -
    • The remaining bits are set to 0.
    • +
    • The remaining bits are set to + \(0\!\) + .
    @@ -235,7 +239,7 @@
    @@ -260,22 +264,28 @@
    sizeProofsOrchard compactSize Length in bytes of proofsOrchard. Value is - \(2720 + 2272 \cdot \mathtt{nActionsOrchard}\) + \(2720 + 2272 \cdot \mathtt{nActionsOrchard}\!\) .
    • The fields 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.
    • + \(\mathsf{v^{balanceSapling}}\) + is defined to be + \(0\!\) + .
    • The field anchorSapling is present if and only if - \(\mathtt{nSpendsSapling} > 0\) + \(\mathtt{nSpendsSapling} > 0\!\) .
    • The fields 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.
    • + is defined to be + \(0\!\) + .
    • The elements of 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.
    • The elements of 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.
    • The proofs aggregated in 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.
    • -
    • For coinbase transactions, the enableSpendsOrchard bit MUST be set to 0.
    • +
    • For coinbase transactions, the 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.

    @@ -333,7 +343,9 @@ 32 cmu byte[32] - The u-coordinate of the note commitment for the output note. + The + \(u\!\) + -coordinate of the note commitment for the output note. 32 @@ -390,13 +402,15 @@ 32 cmx byte[32] - The x-coordinate of the note commitment for the output note. + The + \(x\!\) + -coordinate of the note commitment for the output note. 32 ephemeralKey byte[32] - An encoding of an ephemeral Pallas public key + An encoding of an ephemeral Pallas public key. 580 @@ -460,7 +474,7 @@
    • The joinSplitPubKey and joinSplitSig fields were specified to be present if and only if - \(\mathtt{nJoinSplit} > 0\) + \(\mathtt{nJoinSplit} > 0\!\) .
    diff --git a/rendered/zip-0226.html b/rendered/zip-0226.html index 7482eed04..bd3e83f33 100644 --- a/rendered/zip-0226.html +++ b/rendered/zip-0226.html @@ -3,7 +3,9 @@ ZIP 226: Transfer and Burn of Zcash Shielded Assets - + + +
    @@ -83,7 +85,7 @@ , which is a global byte string (scoped across all future versions of Zcash). From this Asset description and the issuance validating key of the issuer, the specific Asset Identifier, \(\mathsf{AssetId}\!\) , the Asset Digest, and the Asset Base ( - \(\mathsf{AssetBase}\!\) + \(\!\mathsf{AssetBase}\!\) ) are derived as defined in ZIP 227 5.

    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:

    -
    \(\mathsf{NoteCommit}^{\mathsf{OrchardZSA}} : \mathsf{NoteCommit}^{\mathsf{Orchard}}.\!\mathsf{Trapdoor} \times \mathbb{B}^{[\ell_{\mathbb{P}}]} \times \mathbb{B}^{[\ell_{\mathbb{P}}]} \times \{0 .. 2^{\ell_{\mathsf{value}}} - 1\} \times \mathbb{F}_{q_{\mathbb{P}}} \times \mathbb{F}_{q_{\mathbb{P}}} \times \mathbb{P}^* \to \mathsf{NoteCommit}^{\mathsf{Orchard}}.\!\mathsf{Output}\)
    +
      +
    • + \(\mathsf{NoteCommit}^{\mathsf{OrchardZSA}} : \mathsf{NoteCommit^{Orchard}.Trapdoor}\hspace{-1em}\) + \(\hspace{1em}\times\, \mathbb{B}^{[\ell_{\mathbb{P}}]}\hspace{-1em}\) + \(\hspace{1em}\times\, \mathbb{B}^{[\ell_{\mathbb{P}}]}\hspace{-1em}\) + \(\hspace{1em}\times\, \{0 .. 2^{\ell_{\mathsf{value}}} - 1\}\hspace{-1em}\) + \(\hspace{1em}\times\, \mathbb{F}_{q_{\mathbb{P}}}\hspace{-1em}\) + \(\hspace{1em}\times\, \mathbb{F}_{q_{\mathbb{P}}}\hspace{-1em}\) + \(\hspace{1em}\times\, \mathbb{P}^* \to \mathsf{NoteCommit^{Orchard}.Output}\) +
    • +

    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:

    -
    \(\begin{align} -\mathsf{NoteCommit^{OrchardZSA}_{rcm}}(\mathsf{g_d}\star, \mathsf{pk_d}\star, \mathsf{v}, \text{ρ}, \text{ψ}, \mathsf{AssetBase}) -:= \begin{cases} - \mathsf{NoteCommit^{Orchard}_{rcm}}(\mathsf{g_d}\star, \mathsf{pk_d}\star, \mathsf{v}, \text{ρ}, \text{ψ}), &\text{if } \mathsf{AssetBase} = \mathcal{V}^{\mathsf{Orchard}} \\ - \mathsf{cm_{ZSA}} &\text{otherwise} - \end{cases} -\end{align}\)
    +
    \(\mathsf{NoteCommit^{OrchardZSA}_{rcm}}(\mathsf{g_d}\star, \mathsf{pk_d}\star, \mathsf{v}, \text{ρ}, \text{ψ}, \mathsf{AssetBase}) := + \begin{cases} + \mathsf{NoteCommit^{Orchard}_{rcm}}(\mathsf{g_d}\star, \mathsf{pk_d}\star, \mathsf{v}, \text{ρ}, \text{ψ}), &\!\!\text{if } \mathsf{AssetBase} = \mathcal{V}^{\mathsf{Orchard}} \\ + \mathsf{cm_{ZSA}} &\!\!\text{otherwise} + \end{cases}\)

    where:

    -
    \(\begin{align} -\mathsf{cm_{ZSA}} :=&\;\;\mathsf{SinsemillaHashToPoint}(\texttt{"z.cash:ZSA-NoteCommit-M"}, \\ -&\;\;\;\;\;\mathsf{g_{d}\star} \,||\, \mathsf{pk_{d}\star} \,||\, \mathsf{I2LEBSP_{64}(v)} \,||\, \mathsf{I2LEBSP}_{\ell^{\mathsf{Orchard}}_{\mathsf{base}}}(\text{ρ}) \,||\, \mathsf{I2LEBSP}_{\ell^{\mathsf{Orchard}}_{\mathsf{base}}}(\text{ψ}) \,||\, \mathsf{asset\_base}) \\ -&\;\;+\;\;[\mathsf{rcm}]\,\mathsf{GroupHash}^{\mathbb{P}}(\texttt{"z.cash:Orchard-NoteCommit-r"}, \texttt{""}) -\end{align}\)
    +
      +
    • + \(\mathsf{cm_{ZSA}} := \mathsf{SinsemillaHashToPoint}(\texttt{“z.cash:ZSA-NoteCommit-M”},\hspace{-6em}\) + \(\hspace{6em}\mathsf{g_{d}\star} \,||\, \mathsf{pk_{d}\star} \,||\, \mathsf{I2LEBSP_{64}(v)} \,||\, \mathsf{I2LEBSP}_{\ell^{\mathsf{Orchard}}_{\mathsf{base}}}(\text{ρ})\hspace{-6em}\) + \(\hspace{6em}\,||\, \mathsf{I2LEBSP}_{\ell^{\mathsf{Orchard}}_{\mathsf{base}}}(\text{ψ}) \,||\, \mathsf{asset\_base})\hspace{-4em}\) + \(\hspace{4em}\,+\; [\mathsf{rcm}]\,\mathsf{GroupHash}^{\mathbb{P}}(\texttt{“z.cash:Orchard-NoteCommit-r”}, \texttt{“”})\) +
    • +

    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:

    -
    \(\mathsf{NoteCommit^{OrchardZSA}_{rcm}}(\mathsf{repr}_{\mathbb{P}}(\mathsf{g_d}), \mathsf{repr}_{\mathbb{P}}(\mathsf{pk_d}), \mathsf{v}, \text{ρ}, \text{ψ}, \mathsf{AssetBase}) \in \mathsf{NoteCommit^{Orchard}}.\!\mathsf{Output}\)
    +
    \(\mathsf{NoteCommit^{OrchardZSA}_{rcm}}(\mathsf{repr}_{\mathbb{P}}(\mathsf{g_d}), \mathsf{repr}_{\mathbb{P}}(\mathsf{pk_d}), \mathsf{v}, \text{ρ}, \text{ψ}, \mathsf{AssetBase}) \in \mathsf{NoteCommit^{Orchard}.Output}\)

    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.

    @@ -165,19 +176,22 @@
    \(\mathsf{cv^{net}} := \mathsf{ValueCommit^{OrchardZSA}_{rcv}}(\mathsf{AssetBase_{AssetId}}, \mathsf{v^{net}_{AssetId}}) = [\mathsf{v^{net}_{AssetId}}]\,\mathsf{AssetBase_{AssetId}} + [\mathsf{rcv}]\,\mathcal{R}^{\mathsf{Orchard}}\)

    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

    +
      +
    • + \(\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.
    • +

    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”})\!\) .

    Rationale for Split Notes

    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 @@

    The

    Asset Identifier Consistency for Split Actions

    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:

      -
    • -
      -
      The Value Commitment Integrity should be changed:
      -
      -
        -
      • Replace the input note value by a generic value, - \(\mathsf{v}'\!\) - , as - \(\mathsf{cv^{net}} = \mathsf{ValueCommit_rcv^{OrchardZSA}}(\mathsf{AssetBase_{AssetId}}, \mathsf{v}' - \mathsf{v^{new}})\) -
      • -
      -
      -
      +
    • The Value Commitment Integrity should be changed: +
        +
      • Replace the input note value by a generic value, + \(\mathsf{v}'\!\) + , as + \(\mathsf{cv^{net}} = \mathsf{ValueCommit_rcv^{OrchardZSA}}(\mathsf{AssetBase_{AssetId}}, \mathsf{v}' - \mathsf{v^{new}})\) +
      • +
    • -
    • -
      -
      Add a boolean - \(\mathsf{split\_flag}\) - variable as an auxiliary witness. This variable is to be activated +
    • Add a boolean + \(\mathsf{split\_flag}\) + variable as an auxiliary witness. This variable is to be activated + \(\mathsf{split\_flag} = 1\) + if the Action in question has a Split Input and + \(\mathsf{split\_flag} = 0\) + if the Action is actually spending an input note: +
        +
      • If + \(\mathsf{split\_flag} = 1\) + then constrain + \(\mathsf{v}' = 0\) + otherwise constrain + \(\mathsf{v}' = \mathsf{v^{old}}\) + from the auxiliary input.
      • +
      • If \(\mathsf{split\_flag} = 1\) - if the Action in question has a Split Input and - \(\mathsf{split\_flag} = 0\) - if the Action is actually spending an input note:
    • -
      -
        -
      • If - \(\mathsf{split\_flag} = 1\) - then constrain - \(\mathsf{v}' = 0\) - otherwise constrain - \(\mathsf{v}' = \mathsf{v^{old}}\) - from the auxiliary input.
      • -
      • If - \(\mathsf{split\_flag} = 1\) - then constrain - \(\mathsf{is\_native\_asset} = 0\) - because split notes are only available for Custom Assets.
      • -
      -
      -
      + then constrain + \(\mathsf{is\_native\_asset} = 0\) + because split notes are only available for Custom Assets.
    • +
    -
  • -
    -
    The Merkle Path Validity should check the existence of the note commitment as usual (and not like with dummy notes):
    -
    -
      -
    • Check for all notes except dummy notes that - \((\mathsf{path}, \mathsf{pos})\) - is a valid Merkle path of depth - \(\mathsf{MerkleDepth^{Orchard}}\!\) - , from - \(\mathsf{cm^{old}}\) - to the anchor - \(\mathsf{rt^{Orchard}}\!\) - .
    • -
    • The new constraint is - \(\underbrace{(\mathsf{v^{old}} = 0 \land \mathsf{is\_native\_asset} = 1)}_\text{It is a dummy note} \lor \underbrace{(\mathsf{Valid\,Merkle\,Path})}_\text{The Merkle Path is valid}\!\) - .
    • -
    -
    -
    +
  • The Merkle Path Validity should check the existence of the note commitment as usual (and not like with dummy notes): +
      +
    • Check for all notes except dummy notes that + \((\mathsf{path}, \mathsf{pos})\) + is a valid Merkle path of depth + \(\mathsf{MerkleDepth^{Orchard}}\!\) + , from + \(\mathsf{cm^{old}}\) + to the anchor + \(\mathsf{rt^{Orchard}}\!\) + .
    • +
    • The new constraint is + \(\underbrace{(\mathsf{v^{old}} = 0 \land \mathsf{is\_native\_asset} = 1)}_\text{It is a dummy note} \lor \underbrace{(\mathsf{Valid\,Merkle\,Path})}_\text{The Merkle Path is valid}\!\) + .
    • +
  • The Nullifier Integrity will be changed to prevent the identification of notes as defined in the Split Notes section.
  • diff --git a/rendered/zip-0227.html b/rendered/zip-0227.html index 1231e710a..d236295e6 100644 --- a/rendered/zip-0227.html +++ b/rendered/zip-0227.html @@ -3,7 +3,9 @@ ZIP 227: Issuance of Zcash Shielded Assets - + + +
    @@ -73,7 +75,7 @@

    Specification: Issuance Keys and Issuance Authorization Signature Scheme

    -

    The Orchard-ZSA Protocol adds the following keys to the key components 19 20:

    +

    The Orchard-ZSA Protocol adds the following keys to the key components 20 21:

    1. The issuance authorizing key, denoted as \(\mathsf{isk}\!\) @@ -90,7 +92,7 @@

      Issuance Authorization Signature Scheme

      We instantiate the issuance authorization signature scheme \(\mathsf{IssueAuthSig}\) - as a BIP-340 Schnorr signature over the secp256k1 curve. The signing and validation algorithms, signature encoding, and public key encoding MUST follow BIP 340 17.

      + as a BIP-340 Schnorr signature over the secp256k1 curve. The signing and validation algorithms, signature encoding, and public key encoding MUST follow BIP 340 18.

      Batch verification MAY be used. Precomputation MAY be used if and only if it produces equivalent results; for example, for a given verification key \(pk\) and @@ -102,16 +104,16 @@ signature scheme are as follows:

      • - \(\mathsf{IssueAuthSig}.\!\mathsf{Message} = \mathbb{B}^{\mathbb{Y}^{[\mathbb{N}]}}\) + \(\mathsf{IssueAuthSig.Message} = \mathbb{B}^{\mathbb{Y}^{[\mathbb{N}]}}\)
      • - \(\mathsf{IssueAuthSig}.\!\mathsf{Signature} = \mathbb{B}^{\mathbb{Y}^{[64]}} \cup \{\bot\}\) + \(\mathsf{IssueAuthSig.Signature} = \mathbb{B}^{\mathbb{Y}^{[64]}} \cup \{\bot\}\)
      • - \(\mathsf{IssueAuthSig}.\!\mathsf{Public} = \mathbb{B}^{\mathbb{Y}^{[32]}} \cup \{\bot\}\) + \(\mathsf{IssueAuthSig.Public} = \mathbb{B}^{\mathbb{Y}^{[32]}} \cup \{\bot\}\)
      • - \(\mathsf{IssueAuthSig}.\!\mathsf{Private} = \mathbb{B}^{\mathbb{Y}^{[32]}}\) + \(\mathsf{IssueAuthSig.Private} = \mathbb{B}^{\mathbb{Y}^{[32]}}\)

      where @@ -120,7 +122,7 @@ \(k\) bytes, and \(\mathbb{B}^{\mathbb{Y}^{[\mathbb{N}]}}\) - denotes the type of byte sequences of arbitrary length, as defined in the Zcash protocol specification 18.

      + denotes the type of byte sequences of arbitrary length, as defined in the Zcash protocol specification 19.

      The issuance authorizing key generation algorithm and the issuance validating key derivation algorithm are defined in the Issuance Key Derivation section, while the corresponding signing and validation algorithms are defined in the Issuance Authorization Signing and Validation section.

      Issuance Key Derivation

      @@ -130,10 +132,10 @@ context, we define the following constants:

      • - \(\mathsf{Issuance.\!MKGDomain} := \texttt{"ZcashSA_Issue_V1"}\) + \(\mathsf{Issuance.MKGDomain} := \texttt{“ZcashSA\_Issue\_V1”}\)
      • - \(\mathsf{Issuance.\!CKDDomain} := \mathtt{0x81}\!\) + \(\mathsf{Issuance.CKDDomain} := \mathtt{0x81}\)

      Let @@ -144,18 +146,18 @@

      We use hardened-only child key derivation as defined in ZIP 32 4 for the issuance authorizing key.

      \(\mathsf{CKDsk}((\mathsf{sk}_{par},\mathsf{c}_{par}), i) \rightarrow (\mathsf{sk}_{i}, \mathsf{c}_{i})\) -

      + :

      • Return - \(\mathsf{CKDh}^{\mathsf{Issuance}}((\mathsf{sk}_{par},\mathsf{c}_{par}), i)\!\) + \(\mathsf{CKDh}^{\mathsf{Issuance}}((\mathsf{sk}_{par},\mathsf{c}_{par}), i)\)

      We use the notation of ZIP 32 6 for shielded HD paths, and define the issuance authorizing key path as - \(m_{\mathsf{Issuance}} / \mathit{purpose}' / \mathit{coin\_type}' / \mathit{account}'\!\) - . We fix the path levels as follows:

      + \(m_{\mathsf{Issuance}} / \mathit{purpose}' / \mathit{coin\_type}' / \mathit{account}'.\) + We fix the path levels as follows:

      • - \(\mathit{purpose}\) + \(\mathit{purpose}\!\) : a constant set to \(227\) (i.e. @@ -166,12 +168,12 @@ \(227'\) (or \(\mathtt{0x800000e3}\!\) - ) following the BIP 43 recommendation.
      • + ) following the BIP 43 recommendation. 17
      • - \(\mathit{coin\_type}\) - : Defined as in ZIP 32 5.
      • + \(\mathit{coin\_type}\!\) + : Defined as in ZIP 32 5.
      • - \(\mathit{account}\) + \(\mathit{account}\!\) : fixed to index \(0\!\) .
      • @@ -184,7 +186,7 @@

      Derivation of issuance validating key

      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:

      • @@ -200,24 +202,24 @@

      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.

    Issuance Authorization Signing and Validation

    Define - \(\mathsf{IssueAuthSig}.\!\mathsf{Sign}\; : \; (\mathsf{isk}\; : \; \mathsf{IssueAuthSig}.\!\mathsf{Private}) \times (M\; : \; \mathsf{IssueAuthSig}.\!\mathsf{Message}) \to \mathsf{IssueAuthSig}.\!\mathsf{Signature}\) + \(\mathsf{IssueAuthSig.Sign} \;{\small ⦂}\; (\mathsf{isk} \;{\small ⦂}\; \mathsf{IssueAuthSig.Private}) \times (M \;{\small ⦂}\; \mathsf{IssueAuthSig.Message}) \to \mathsf{IssueAuthSig.Signature}\) as:

    • Let the auxiliary data @@ -238,13 +240,13 @@ \(\mathsf{Sign}\) algorithm is defined in BIP 340 and \(a\) - denotes the auxiliary data used in BIP 340 17. Note that - \(\mathsf{IssueAuthSig}.\!\mathsf{Sign}\) + denotes the auxiliary data used in BIP 340 18. Note that + \(\mathsf{IssueAuthSig.Sign}\) could return \(\bot\) with very low probability.

      Define - \(\mathsf{IssueAuthSig}.\!\mathsf{Validate}\; : \; (\mathsf{ik}\; : \; \mathsf{IssueAuthSig}.\!\mathsf{Public}) \times (M\; : \; \mathsf{IssueAuthSig}.\!\mathsf{Message}) \times (\text{σ}\; : \; \mathsf{IssueAuthSig}.\!\mathsf{Signature}) \to \mathbb{B}\) + \(\mathsf{IssueAuthSig.Validate} \;{\small ⦂}\; (\mathsf{ik} \;{\small ⦂}\; \mathsf{IssueAuthSig.Public}) \times (M \;{\small ⦂}\; \mathsf{IssueAuthSig.Message}) \times (\text{σ} \;{\small ⦂}\; \mathsf{IssueAuthSig.Signature}) \to \mathbb{B}\) as:

      • Return @@ -262,7 +264,7 @@

      where the \(\mathsf{Verify}\) - algorithm is defined in BIP 340 17.

      + algorithm is defined in BIP 340 18.

    Specification: Asset Identifier

    @@ -290,7 +292,7 @@ be the issuance validating key of the issuer, a public key used to verify the signature on the issuance transaction's SIGHASH.

    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

    • @@ -304,10 +306,10 @@ \(\mathsf{AssetBase_{AssetId}} := \mathsf{ZSAValueBase}(\mathsf{AssetDigest_{AssetId}})\)

      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:

      @@ -331,7 +333,7 @@

      A map, \(\mathsf{issued\_assets}\!\) , from the Asset Base, - \(\mathsf{AssetBase}\) + \(\mathsf{AssetBase}\!\) , to a tuple \((\mathsf{balance}, \mathsf{final})\!\) , for every Asset that has been issued up until the block boundary. For each Asset:

      @@ -350,7 +352,7 @@ for any Asset cannot be changed from \(1\) to - \(0\) + \(0\!\) .

    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.

    Rationale for Global Issuance 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:

    • - \(\mathsf{ik}\) + \(\mathsf{ik}\!\) : the issuance validating key, that allows the validators to verify that the \(\mathsf{AssetId}\) is properly associated with the issuer.
    • vIssueActions: an array of issuance actions, of type IssueAction.
    • - \(\mathsf{issueAuthSig}\) + \(\mathsf{issueAuthSig}\!\) : the signature of the transaction SIGHASH, signed by the issuance authorizing key, \(\mathsf{isk}\!\) , that validates the issuance.
    -

    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.

    @@ -537,7 +539,7 @@ \(\mathsf{finalize} = 1\!\) ).
  • for each recipient - \(i\) + \(i\!\) :
    • generate a ZSA output note that includes the Asset Base. For an Orchard-ZSA note this is @@ -570,7 +572,7 @@ , on the SIGHASH transaction hash, \(\mathsf{SigHash}\!\) , by invoking - \(\mathsf{IssueAuthSig}.\!\mathsf{Validate}(\mathsf{ik}, \mathsf{SigHash}, \mathsf{issueAuthSig})\!\) + \(\mathsf{IssueAuthSig.Validate}(\mathsf{ik}, \mathsf{SigHash}, \mathsf{issueAuthSig})\!\) .

    For each IssueAction in IssueBundle:

    @@ -607,14 +609,14 @@
    • compute the note commitment as \(\mathsf{cm} = \mathsf{NoteCommit^{OrchardZSA}_{rcm}}(\mathsf{repr}_{\mathbb{P}}(\mathsf{g_d}), \mathsf{repr}_{\mathbb{P}}(\mathsf{pk_d}), \mathsf{v}, \text{ρ}, \text{ψ}, \mathsf{AssetBase})\) - as defined in the Note Structure and Commitment section of ZIP 226 11.
    • + as defined in the Note Structure and Commitment section of ZIP 226 11.
    • Add \(\mathsf{cm}\) to the Merkle tree of note commitments.
    • Increase the value of \(\mathsf{issued\_assets(AssetBase).balance}\) by the value of the note, - \(\mathsf{v}\) + \(\mathsf{v}\!\) .
  • @@ -653,7 +655,7 @@
    • By using the \(\mathsf{finalize}\) - boolean and the burning mechanism defined in 10, issuers can control the supply production of any Asset associated to their issuer keys. For example, + boolean and the burning mechanism defined in 10, issuers can control the supply production of any Asset associated to their issuer keys. For example,
      • by setting \(\mathsf{finalize} = 1\) @@ -689,7 +691,7 @@

        TxId Digest - Issuance

        -

        This section details the construction of the subtree of hashes in the transaction digest that corresponds to issuance transaction data. Details of the overall changes to the transaction digest due to the Orchard-ZSA protocol can be found in ZIP 226 12. As in ZIP 244 13, the digests are all personalized BLAKE2b-256 hashes, and in cases where no elements are available for hashing, a personalized hash of the empty byte array is used.

        +

        This section details the construction of the subtree of hashes in the transaction digest that corresponds to issuance transaction data. Details of the overall changes to the transaction digest due to the Orchard-ZSA protocol can be found in ZIP 226 12. As in ZIP 244 13, the digests are all personalized BLAKE2b-256 hashes, and in cases where no elements are available for hashing, a personalized hash of the empty byte array is used.

        A new issuance transaction digest algorithm is defined that constructs the subtree of the transaction digest tree of hashes for the issuance portion of a transaction. Each branch of the subtree will correspond to a specific subset of issuance transaction data. The overall structure of the hash is as follows; each name referenced here will be described in detail below:

        issuance_digest
         ├── issue_actions_digest
        @@ -725,7 +727,7 @@
                                 

        In case the transaction has no Issue Notes, ''issue_notes_digest'' is:

        BLAKE2b-256("ZTxIdIAcNoteHash", [])
        T.5a.i.1: recipient
        -

        This is the raw encoding of an Orchard shielded payment address as defined in the protocol specification 22.

        +

        This is the raw encoding of an Orchard shielded payment address as defined in the protocol specification 23.

        T.5a.i.2: value

        Note value encoded as little-endian 8-byte representation of 64-bit unsigned integer (e.g. u64 in Rust) raw value.

        @@ -759,7 +761,7 @@

        Signature Digest

        -

        The per-input transaction digest algorithm to generate the signature digest in ZIP 244 14 is modified so that a signature digest is produced for each transparent input, each Sapling input, each Orchard action, and additionally for each Issuance Action. For Issuance Actions, this algorithm has the exact same output as the transaction digest algorithm, thus the txid may be signed directly.

        +

        The per-input transaction digest algorithm to generate the signature digest in ZIP 244 14 is modified so that a signature digest is produced for each transparent input, each Sapling input, each Orchard action, and additionally for each Issuance Action. For Issuance Actions, this algorithm has the exact same output as the transaction digest algorithm, thus the txid may be signed directly.

        The overall structure of the hash is as follows. We highlight the changes for the Orchard-ZSA protocol via the [ADDED FOR ZSA] text label, and we omit the descriptions of the sections that do not change for the Orchard-ZSA protocol:

        signature_digest
         ├── header_digest
        @@ -774,14 +776,14 @@
         S.3: sapling_digest         (32-byte hash output)
         S.4: orchard_digest         (32-byte hash output)
         S.5: issuance_digest        (32-byte hash output)  [ADDED FOR ZSA]
        -

        The personalization field remains the same as in ZIP 244 13.

        +

        The personalization field remains the same as in ZIP 244 13.

        S.5: issuance_digest

        Identical to that specified for the transaction identifier.

        Authorizing Data Commitment

        -

        The transaction digest algorithm defined in ZIP 244 15 which commits to the authorizing data of a transaction is modified by the Orchard-ZSA protocol to have the following structure. We highlight the changes for the Orchard-ZSA protocol via the [ADDED FOR ZSA] text label, and we omit the descriptions of the sections that do not change for the Orchard-ZSA protocol:

        +

        The transaction digest algorithm defined in ZIP 244 15 which commits to the authorizing data of a transaction is modified by the Orchard-ZSA protocol to have the following structure. We highlight the changes for the Orchard-ZSA protocol via the [ADDED FOR ZSA] text label, and we omit the descriptions of the sections that do not change for the Orchard-ZSA protocol:

        auth_digest
         ├── transparent_scripts_digest
         ├── sapling_auth_digest
        @@ -822,7 +824,7 @@
                         

      Bridging Assets

      -

      For bridging purposes, the secure method of off-boarding Assets is to burn an Asset with the burning mechanism in ZIP 226 10. Users should be aware of issuers that demand the Assets be sent to a specific address on the Zcash chain to be redeemed elsewhere, as this may not reflect the real reserve value of the specific Wrapped Asset.

      +

      For bridging purposes, the secure method of off-boarding Assets is to burn an Asset with the burning mechanism in ZIP 226 10. Users should be aware of issuers that demand the Assets be sent to a specific address on the Zcash chain to be redeemed elsewhere, as this may not reflect the real reserve value of the specific Wrapped Asset.

      Other Considerations

      @@ -836,7 +838,7 @@ in order to properly keep track of the total supply for different Asset Identifiers. This is useful for wallets and other applications that need to keep track of the total supply of Assets.

      Fee Structures

      -

      The fee mechanism described in this ZIP will follow the mechanism described in ZIP 317 16.

      +

      The fee mechanism described in this ZIP will follow the mechanism described in ZIP 317 16.

      Test Vectors

      @@ -982,10 +984,18 @@
    - +
    + + + +
    17BIP 43: Purpose Field for Deterministic Wallets
    + + + + @@ -993,7 +1003,7 @@
    18 BIP 340: Schnorr Signatures for secp256k1
    - + @@ -1001,7 +1011,7 @@
    1819 Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 2: Notation
    - + @@ -1009,7 +1019,7 @@
    1920 Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 3.1: Payment Addresses and Keys
    - + @@ -1017,7 +1027,7 @@
    2021 Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 4.2.3: Orchard Key Components
    - + @@ -1025,7 +1035,7 @@
    2122 Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.4.9.8: Group Hash into Pallas and Vesta
    - + @@ -1033,7 +1043,7 @@
    2223 Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.6.4.2: Orchard Raw Payment Addresses
    - + diff --git a/rendered/zip-0230.html b/rendered/zip-0230.html index 53ec3ae06..80f3a8a6b 100644 --- a/rendered/zip-0230.html +++ b/rendered/zip-0230.html @@ -3,7 +3,9 @@ ZIP 230: Version 6 Transaction Format - + + +
    @@ -327,7 +329,7 @@
  • The fields valueBalanceSapling and bindingSigSapling are present if and only if \(\mathtt{nSpendsSapling} + \mathtt{nOutputsSapling} > 0\!\) . If valueBalanceSapling is not present, then - \(\mathsf{v^{balanceSapling}}`\) + \(\mathsf{v^{balanceSapling}}\) is defined to be \(0\!\) .
  • @@ -650,7 +652,7 @@
    2324 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:

    @@ -672,21 +674,21 @@ @@ -694,22 +696,22 @@
    - \(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

    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:

    -
    \(zsa\_logical\_actions = logical\_actions \;+ nTotalOutputsZsaIssuance\)
    +
    \(\mathsf{zsa\_logical\_actions} = \mathsf{logical\_actions} \;+ \mathsf{nTotalOutputsZsaIssuance}\)

    The formula for the computation of the - \(zsa\_conventional\_fee\) + \(\mathsf{zsa\_conventional\_fee}\) is:

    \(\begin{array}{rcl} - zsa\_conventional\_fee &=& marginal\_fee \cdot \mathsf{max}(grace\_actions, zsa\_logical\_actions) \;+ \\ - & & issuance\_fee \cdot nCreateActions + \mathsf{zsa\_conventional\_fee} &=& \mathsf{marginal\_fee} \cdot \mathsf{max}(\mathsf{grace\_actions}, \mathsf{zsa\_logical\_actions}) \;+ \\ + & & \mathsf{issuance\_fee} \cdot \mathsf{nCreateActions} \end{array}\)

    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.

    Rationale for OrchardZSA Fee calculation

    diff --git a/rendered/zip-0231.html b/rendered/zip-0231.html index 1fc75b6b6..208c1eed2 100644 --- a/rendered/zip-0231.html +++ b/rendered/zip-0231.html @@ -3,7 +3,9 @@ ZIP 231: Memo Bundles - + + + @@ -130,53 +132,54 @@

    Memo bundle

    Memo encryption

    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 0xFF -bytes.

    +class="math inline">\(\mathtt{0xFF}\) 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([0xE0] || salt)

    -

    The first byte 0xE0 +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 0xFF -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.

    +class="math inline">\(\mathtt{0xFF}\) 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.

      -
    • counter is a big-endian chunk -counter starting at zero and incrementing by one for each subsequent -chunk within a particular memo.
    • -
    • final_chunk is the byte 0x01 -for the final memo chunk, and 0x00 -for all preceding chunks.
    • +
    • \(\mathsf{counter}\) is a +big-endian chunk counter starting at zero and incrementing by one for +each subsequent chunk within a particular memo.
    • +
    • \(\mathsf{final\_chunk}\) is the +byte \(\mathtt{0x01}\) for the final +memo chunk, and \(\mathtt{0x00}\) 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 @@

    Memo encryption

    ]

    Memo decryption

    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:

    +\(\mathsf{K^{memo}}\). From this they +derive encryption_key as above, and then proceed as +follows:

    • Set counter = 0 and final_chunk = 0x00.
    • @@ -231,7 +235,7 @@

      Encoding in transactions

      - + Bytes Name Data Type @@ -239,33 +243,33 @@

      Encoding in transactions

      - + 1 fAllPruned uint8 1 if all chunks have been pruned, otherwise 0. - + 32 nonceOrHash byte[32] The nonce for deriving encryption keys, or the overall hash. - + † varies nMemoChunks compactSize The number of memo chunks. - + † varies pruned byte[ceiling(nMemoChunks/8)] +class="math inline">\(\mathsf{ceiling}(\mathtt{nMemoChunks}/8)\)] Bitflags indicating the type of each entry in vMemoChunks. - + † varies vMemoChunks MemoChunk[nMemoChunks] @@ -322,10 +326,11 @@

      Changes to the
    • 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 0xFF -bytes for Kmemo is used to -indicate that there is no memo for this note plaintext.

    +class="math inline">\(\mathtt{0xFF}\) bytes for \(\mathsf{K^{memo}}\) is used to indicate +that there is no memo for this note plaintext.

    In § 4.7.2 ‘Sending Notes (Sapling)’ Changes to the

    @@ -423,28 +433,26 @@

    Changes to the
    • 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.
    @@ -455,15 +463,17 @@

    Changes to the class="footnote-ref" id="fnref16" role="doc-noteref">16:

      -
    • Replace memo ⦂ 𝔹𝕐[𝟝𝟙𝟚] -with memoOrKey.
    • -
    • Specify that the type of memoOrKey -is 𝔹𝕐[𝟝𝟙𝟚] when decrypting a +
    • Replace \(\mathsf{memo} \;⦂\; +\mathbb{B^{Y[512]}}\) with \(\mathsf{memoOrKey}\).
    • +
    • Specify that the type of \(\mathsf{memoOrKey}\) is \(\mathbb{B^{Y[512]}}\) when decrypting a pre-v6 note ciphertext, or 𝔹𝕐[𝟛𝟚] when decrypting a v6-onward -note ciphertext. In the latter case, it is used as Kmemo to decrypt the memo bundle -as described in Memo bundle.
    • +class="math inline">\(\mathbb{B^{Y[32]}}\) when decrypting a +v6-onward note ciphertext. In the latter case, it is used as \(\mathsf{K^{memo}}\) to decrypt the memo +bundle as described in Memo bundle.

    Applicability

    All of these changes apply identically to Mainnet and Testnet.

    @@ -494,39 +504,29 @@

    Memo chunk size

    is:

    - - - - + + + + - - - - - - - - - - - + - + - + - + @@ -544,39 +544,29 @@

    Memo key size

    size overhead becomes:

    Memo size
    Chunk sizeMemo size ≤ 256 bytesMemo size = 512 bytes
    Chunk size≤ 256 bytes512 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%)
    - - - - + + + + - - - - - - - - - - - + - + - + - + @@ -596,21 +586,22 @@

    Memo key size

    keys.

    Encryption format

    -

    Including a per-transaction salt in -the derivation of encryptionkey gives protection +

    Including a per-transaction \(\mathsf{salt}\) in the derivation of \(\mathsf{encryption_key}\) gives protection against accidental (or intentional) reuse of Kmemo reuse across multiple +class="math inline">\(\mathsf{K^{memo}}\) reuse across multiple transactions. We do not protect against Kmemo reuse within a transaction; -it is up to the transaction builder to ensure that the same Kmemo is not used to encrypt two -different memos (and if they did so, normal clients would either never -observe the second memo, or would decrypt parts of each memo and get a -nonsensical and potentially insecure “spliced” memo).

    +class="math inline">\(\mathsf{K^{memo}}\) reuse within a +transaction; it is up to the transaction builder to ensure that the same +\(\mathsf{K^{memo}}\) is not used to +encrypt two different memos (and if they did so, normal clients would +either never observe the second memo, or would decrypt parts of each +memo and get a nonsensical and potentially insecure “spliced” memo).

    We do not include commitments to the shielded outputs in the -derivation of encryptionkey -for two reasons:

    +derivation of \(\mathsf{encryption_key}\) for two +reasons:

    • It would force the transaction builder to fully define all shielded outputs before encrypting the memos, which might prevent potential use @@ -620,7 +611,7 @@

      Encryption format

      transaction with a memo bundle and no shielded outputs, as there may be use cases for, e.g. a fully-transparent transaction with encrypted memo, or a ZSA issuance transaction with exposed memo data using a well-known -Kmemo.
    • +\(\mathsf{K^{memo}}\).

    Pruned encoding

    The separation of memo data from note data, and the new ability to diff --git a/rendered/zip-0233.html b/rendered/zip-0233.html index 0c1b530e9..4f8188360 100644 --- a/rendered/zip-0233.html +++ b/rendered/zip-0233.html @@ -3,7 +3,9 @@ ZIP 233: Network Sustainability Mechanism: Burning - + + + @@ -45,8 +47,8 @@

    Terminology

    conflict between this and issuance as defined in ZIP 227.]

    “Burning” - The method by which ZEC/TAZ becomes unavailable for circulation on the network.

    -

    MAX_MONEY, as defined in § 5.3 -‘Constants’ \(\mathsf{MAX\_MONEY}\), as defined +in § 5.3 ‘Constants’ 5, 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 @@ -66,9 +68,10 @@

    Motivation

    1. Long Term Consensus Sustainability: By enabling the burning of funds, the network gains the ability to create “headroom” -between the chain value and MAX_MONEY. -This lays necessary groundwork for extending the block subsidy system, -which currently has a clear final end date.
    2. +between the chain value and \(\mathsf{MAX\_MONEY}\). This lays necessary +groundwork for extending the block subsidy system, which currently has a +clear final end date.
    3. Benefits to ZEC Holders: Burning funds reduces the supply of ZEC, benefiting network users in proportion to their holdings without requiring them to opt into any scheme, introducing extra risk, @@ -76,19 +79,21 @@

      Motivation

    Specification

    Burn amount

    -

    Each transaction gains a burn_amount -property, specifying the value in zatoshis that is burned when the -transaction is mined. The burned value subtracts from the remaining -value in the “transparent transaction value pool” as described in § 3.4 -‘Transactions and Treestates’ 8.

    -

    burn_amount does not result in an -output being produced in any chain value pool, and therefore from the -point at which the transaction is applied to the global chain state, -burn_amount is subtracted from the -issued supply. It is unavailable for circulation on the network at least -through to the end of the block in which the transaction is mined. ZIP -234 Each transaction gains a \(\mathsf{burn\_amount}\) property, +specifying the value in zatoshis that is burned when the transaction is +mined. The burned value subtracts from the remaining value in the +“transparent transaction value pool” as described in § 3.4 ‘Transactions +and Treestates’ 8.

    +

    \(\mathsf{burn\_amount}\) does not +result in an output being produced in any chain value pool, and +therefore from the point at which the transaction is applied to the +global chain state, \(\mathsf{burn\_amount}\) is subtracted from +the issued supply. It is unavailable for circulation on the network at +least through to the end of the block in which the transaction is mined. +ZIP 234 9 specifies a potential mechanism by which the burned funds would again become available.

    Changes to ZIP 230 Changes to ZIP 230

    - + @@ -114,7 +119,7 @@

    Changes to ZIP 230

    - + @@ -122,9 +127,9 @@

    Changes to ZIP 230

    Memo size
    Chunk sizeMemo size ≤ 256 bytesMemo size = 512 bytes
    Chunk size≤ 256 bytes512 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%)
    Bytes Name Data Type
    8 burnAmount uint64
    -

    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:

    • If both this ZIP and ZIP 2002 are selected for inclusion in the same @@ -145,17 +150,19 @@

      Changes to the class="footnote-ref" id="fnref13" role="doc-noteref">13, add:

      -

      [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} +\}\).

      Modifications relative to ZIP 244 14

      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:

      T.1f: burn_amount (8-byte little-endian burn amount)
      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 @@ 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

      -

      BLOCK_SUBSIDY_FRACTION = 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 -BLOCK_SUBSIDY_FRACTION. +\(\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 ⋅ 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.

        -

        MoneyReserveAfter(height)  = The -value of the Money Reserve after the specified block height.

        -

        Issuance Calculation

        -

        At the DEPLOYMENT_BLOCK_HEIGHT, nodes should switch from -the current issuance calculation, to the following:

        +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.

        BlockSubsidy(height) = ceiling(BLOCK_SUBSIDY_FRACTION ⋅ MoneyReserveAfter(height − 1))

        +class="math inline">\(\mathsf{MoneyReserveAfter}(\mathsf{height}) +=\) The value of the Money Reserve after the specified block +height.

        +

        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 − BLOCK_SUBSIDY_FRACTION)PostBlossomHalvingInterval ≈ IntendedMoneyReserveFractionRemainingAfterFourYears

      +class="math inline">\(\mathsf{IntendedMoneyReserveFractionRemainingAfterFourYears} += 0.5\).

      +

      The 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. 6

      Abstract

      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

      1. 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.
      2. 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 later

    There 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">13

    Considerations for the Future

    If transaction fees were to increase, further modifications can @@ -161,10 +166,10 @@

    Considerations for the

    Deployment

    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).

    References

    @@ -186,37 +191,40 @@

    References

    Specification, Version 2024.5.1 [NU6]. Section 3.12: Mainnet and Testnet↩︎

    -
  • ZIP 233: Network Sustainability -Mechanism: Burning

    Zcash Protocol +Specification, Version 2024.5.1 [NU6]. Section 2: Notation↩︎

  • +
  • ZIP 233: Network Sustainability +Mechanism: Burning↩︎

  • -
  • ZIP 234: Network Sustainability -Mechanism: Issuance Smoothing

    ZIP 234: Network Sustainability +Mechanism: Issuance Smoothing↩︎

  • -
  • ZIP 233: Network Sustainability -Mechanism: Burning

    ZIP 233: Network Sustainability +Mechanism: Burning↩︎

  • -
  • EIP-1559: Fee market -change for ETH 1.0 chain↩︎

  • -
  • ZIP 233: Network Sustainability -Mechanism: Burning

    ZIP 233: Network Sustainability +Mechanism: Burning↩︎

  • -
  • ZIP 230: Version 6 Transaction -Format

    ZIP 230: Version 6 Transaction +Format↩︎

  • -
  • ZIP 317: Proportional Transfer -Fee Mechanism

    ZIP 317: Proportional Transfer +Fee Mechanism↩︎

  • -
  • GitHub repository -eigerco/zsf-fee-estimator↩︎

  • -
  • ZIP 233: Network Sustainability -Mechanism: Burning

    ZIP 233: Network Sustainability +Mechanism: Burning↩︎

  • -
  • ZIP 234: Network Sustainability -Mechanism: Issuance Smoothing

    ZIP 234: Network Sustainability +Mechanism: Issuance Smoothing↩︎

  • diff --git a/rendered/zip-0244.html b/rendered/zip-0244.html index e607a6d65..538b63d65 100644 --- a/rendered/zip-0244.html +++ b/rendered/zip-0244.html @@ -3,7 +3,9 @@ ZIP 244: Transaction Identifier Non-Malleability - + + +
    @@ -391,11 +393,11 @@

    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:

    diff --git a/rendered/zip-0253.html b/rendered/zip-0253.html index 6aff55a18..49a248e2f 100644 --- a/rendered/zip-0253.html +++ b/rendered/zip-0253.html @@ -3,7 +3,6 @@ ZIP 253: Deployment of the NU6 Network Upgrade - diff --git a/rendered/zip-0254.html b/rendered/zip-0254.html index 072b4ac87..4a7091e92 100644 --- a/rendered/zip-0254.html +++ b/rendered/zip-0254.html @@ -3,7 +3,6 @@ ZIP 254: Deployment of the NU7 Network Upgrade - diff --git a/rendered/zip-0304.html b/rendered/zip-0304.html index 453038ad0..0adfd5ac9 100644 --- a/rendered/zip-0304.html +++ b/rendered/zip-0304.html @@ -3,7 +3,9 @@ ZIP 304: Sapling Address Signatures - + + +
    @@ -52,11 +54,11 @@ \(\mathsf{PRF}^\mathsf{nfSapling}_\mathsf{nk}(ρ)\) 10
  • - \(\mathsf{SpendAuthSig.RandomizePrivate}(Îą, \mathsf{sk})\) + \(\mathsf{SpendAuthSig.RandomizePrivate}(Îą, \mathsf{sk})\!\) , - \(\mathsf{SpendAuthSig.RandomizePublic}(Îą, \mathsf{vk})\) + \(\mathsf{SpendAuthSig.RandomizePublic}(Îą, \mathsf{vk})\!\) , - \(\mathsf{SpendAuthSig.Sign}(\mathsf{sk}, m)\) + \(\mathsf{SpendAuthSig.Sign}(\mathsf{sk}, m)\!\) , and \(\mathsf{SpendAuthSig.Verify}(\mathsf{vk}, m, σ)\) 11
  • @@ -74,7 +76,7 @@ means the concatenation of sequences \(a\) then - \(b\) + \(b\!\) .
  • \(\mathsf{repr}_\mathbb{J}(P)\) @@ -84,9 +86,9 @@
  • \(\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\) + \(p\!\) , and input - \(x\) + \(x\!\) .
  • @@ -107,7 +109,7 @@
  • A fake Sapling note with a value of \(1\) zatoshi and - \(\mathsf{rcm} = 0\) + \(\mathsf{rcm} = 0\!\) .
  • A Sapling commitment tree that is empty except for the commitment for the fake note.
  • @@ -115,10 +117,10 @@

    The inputs to the signature algorithm are:

    • The payment address - \((\mathsf{d}, \mathsf{pk_d})\) + \((\mathsf{d}, \mathsf{pk_d})\!\) ,
    • Its corresponding expanded spending key - \((\mathsf{ask}, \mathsf{nsk}, \mathsf{ovk})\) + \((\mathsf{ask}, \mathsf{nsk}, \mathsf{ovk})\!\) ,
    • The SLIP-44 15 coin type, and
    • The message @@ -131,17 +133,17 @@ \((\mathsf{ak}, \mathsf{nk}, \mathsf{ovk})\) from the expanded spending key.
    • Let - \(\mathsf{g_d} = \mathsf{DiversifyHash}(\mathsf{d})\) + \(\mathsf{g_d} = \mathsf{DiversifyHash}(\mathsf{d})\!\) .
    • Let - \(\mathsf{cm} = \mathsf{NoteCommit}^\mathsf{Sapling}_0(\mathsf{repr}_\mathbb{J}(\mathsf{g_d}), \mathsf{repr}_\mathbb{J}(\mathsf{pk_d}), 1)\) + \(\mathsf{cm} = \mathsf{NoteCommit}^\mathsf{Sapling}_0(\mathsf{repr}_\mathbb{J}(\mathsf{g_d}), \mathsf{repr}_\mathbb{J}(\mathsf{pk_d}), 1)\!\) .
    • Let \(\mathsf{rt}\) be the root of a Merkle tree with depth \(\mathsf{MerkleDepth}^\mathsf{Sapling}\) and hashing function - \(\mathsf{MerkleCRH}^\mathsf{Sapling}\) + \(\mathsf{MerkleCRH}^\mathsf{Sapling}\!\) , containing \(\mathsf{cm}\) at position 0, and @@ -150,45 +152,45 @@
    • Let \(path\) be the Merkle path from position 0 to - \(\mathsf{rt}\) + \(\mathsf{rt}\!\) . 4
    • Let - \(\mathsf{cv} = \mathsf{ValueCommit}_0(1)\) + \(\mathsf{cv} = \mathsf{ValueCommit}_0(1)\!\) .
      • This is a constant and may be pre-computed.
    • Let - \(\mathsf{nf} = \mathsf{PRF}^\mathsf{nfSapling}_{\mathsf{repr}_\mathbb{J}(\mathsf{nk})}(\mathsf{repr}_\mathbb{J}(\mathsf{MixingPedersenHash}(\mathsf{cm}, 0)))\) + \(\mathsf{nf} = \mathsf{PRF}^\mathsf{nfSapling}_{\mathsf{repr}_\mathbb{J}(\mathsf{nk})}(\mathsf{repr}_\mathbb{J}(\mathsf{MixingPedersenHash}(\mathsf{cm}, 0)))\!\) .
    • Select a random - \(Îą\) + \(Îą\!\) .
    • Let - \(\mathsf{rk} = \mathsf{SpendAuthSig.RandomizePublic}(Îą, \mathsf{ak})\) + \(\mathsf{rk} = \mathsf{SpendAuthSig.RandomizePublic}(Îą, \mathsf{ak})\!\) .
    • Let \(zkproof\) be the byte sequence representation of a Sapling spend proof with primary input \((\mathsf{rt}, \mathsf{cv}, \mathsf{nf}, \mathsf{rk})\) and auxiliary input - \((path, 0, \mathsf{g_d}, \mathsf{pk_d}, 1, 0, \mathsf{cm}, 0, Îą, \mathsf{ak}, \mathsf{nsk})\) + \((path, 0, \mathsf{g_d}, \mathsf{pk_d}, 1, 0, \mathsf{cm}, 0, Îą, \mathsf{ak}, \mathsf{nsk})\!\) . 5
    • Let - \(\mathsf{rsk} = \mathsf{SpendAuthSig.RandomizePrivate}(Îą, \mathsf{ask})\) + \(\mathsf{rsk} = \mathsf{SpendAuthSig.RandomizePrivate}(Îą, \mathsf{ask})\!\) .
    • Let \(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).
    • Let - \(digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZIP304Signed"}\,||\,coinType, zkproof\,||\,msg)\) + \(digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{“ZIP304Signed”}\,||\,coinType, zkproof\,||\,msg)\!\) .
    • Let - \(spendAuthSig = \mathsf{SpendAuthSig.Sign}(\mathsf{rsk}, digest)\) + \(spendAuthSig = \mathsf{SpendAuthSig.Sign}(\mathsf{rsk}, digest)\!\) .
    • Return - \((\mathsf{nf}, \mathsf{rk}, zkproof, spendAuthSig)\) + \((\mathsf{nf}, \mathsf{rk}, zkproof, spendAuthSig)\!\) .
    @@ -196,14 +198,14 @@

    The inputs to the verification algorithm are:

    • The payment address - \((\mathsf{d}, \mathsf{pk_d})\) + \((\mathsf{d}, \mathsf{pk_d})\!\) ,
    • The SLIP-44 15 coin type,
    • The message \(msg\) that is claimed to be signed, and
    • The ZIP 304 signature - \((\mathsf{nf}, \mathsf{rk}, zkproof, spendAuthSig)\) + \((\mathsf{nf}, \mathsf{rk}, zkproof, spendAuthSig)\!\) .

    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).
  • Let - \(digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZIP304Signed"}\,||\,coinType, zkproof\,||\,msg)\) + \(digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{“ZIP304Signed”}\,||\,coinType, zkproof\,||\,msg)\!\) .
  • If - \(\mathsf{SpendAuthSig.Verify}(\mathsf{rk}, digest, spendAuthSig) = 0\) + \(\mathsf{SpendAuthSig.Verify}(\mathsf{rk}, digest, spendAuthSig) = 0\!\) , return false.
  • Let - \(\mathsf{cm} = \mathsf{NoteCommit}^\mathsf{Sapling}_0(\mathsf{repr}_\mathbb{J}(\mathsf{DiversifyHash}(\mathsf{d})), \mathsf{repr}_\mathbb{J}(\mathsf{pk_d}), 1)\) + \(\mathsf{cm} = \mathsf{NoteCommit}^\mathsf{Sapling}_0(\mathsf{repr}_\mathbb{J}(\mathsf{DiversifyHash}(\mathsf{d})), \mathsf{repr}_\mathbb{J}(\mathsf{pk_d}), 1)\!\) .
  • Let \(\mathsf{rt}\) be the root of a Merkle tree with depth \(\mathsf{MerkleDepth}^\mathsf{Sapling}\) and hashing function - \(\mathsf{MerkleCRH}^\mathsf{Sapling}\) + \(\mathsf{MerkleCRH}^\mathsf{Sapling}\!\) , containing \(\mathsf{cm}\) at position 0, and @@ -234,10 +236,10 @@
  • Let \(path\) be the Merkle path from position 0 to - \(\mathsf{rt}\) + \(\mathsf{rt}\!\) . 4
  • Let - \(\mathsf{cv} = \mathsf{ValueCommit}_0(1)\) + \(\mathsf{cv} = \mathsf{ValueCommit}_0(1)\!\) .
    • This is a constant and may be pre-computed.
    • @@ -246,17 +248,17 @@
    • Decode and verify \(zkproof\) as a Sapling spend proof with primary input - \((\mathsf{rt}, \mathsf{cv}, \mathsf{nf}, \mathsf{rk})\) + \((\mathsf{rt}, \mathsf{cv}, \mathsf{nf}, \mathsf{rk})\!\) . 5 If verification fails, return false.
    • Return true.
  • Signature encoding

    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.

    @@ -265,7 +267,7 @@

    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 @@

  • \(\mathsf{nf}\) is a binary public input to - \(zkproof\) + \(zkproof\!\) .
  • \(\mathsf{rk}\) @@ -297,11 +299,11 @@
  • RedJubjub signatures are themselves non-malleable.
  • 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 @@ ZIP 307: Light Client Protocol for Payment Detection - + + +
    @@ -207,7 +209,7 @@ \(\mathsf{epk} = \mathsf{abst}_{\mathbb{J}}(\mathtt{ephemeralKey})\)
  • if - \(\mathsf{epk} = \bot\) + \(\mathsf{epk} = \bot\!\) , return \(\bot\)
  • @@ -226,7 +228,7 @@ \(P^{\mathsf{enc}}\)
  • [Pre-Canopy] if - \(\mathsf{leadByte} \neq 0x01\) + \(\mathsf{leadByte} \neq 0x01\!\) , return \(\bot\)
  • @@ -236,14 +238,14 @@
  • [Canopy onward] if \(\mathsf{height} < \mathsf{CanopyActivationHeight} + \mathsf{ZIP212GracePeriod}\) and - \(\mathsf{leadByte} \not\in \{ \mathtt{0x01}, \mathtt{0x02} \}\) + \(\mathsf{leadByte} \not\in \{ \mathtt{0x01}, \mathtt{0x02} \}\!\) , return \(\bot\)
  • [Canopy onward] if \(\mathsf{height} < \mathsf{CanopyActivationHeight} + \mathsf{ZIP212GracePeriod}\) and - \(\mathsf{leadByte} \neq \mathtt{0x02}\) + \(\mathsf{leadByte} \neq \mathtt{0x02}\!\) , return \(\bot\)
  • @@ -258,19 +260,19 @@
  • if \(\mathsf{rcm} \geq r_{\mathbb{J}}\) or - \(\mathsf{g_d} = \bot\) + \(\mathsf{g_d} = \bot\!\) , return \(\bot\)
  • [Canopy onward] if - \(\mathsf{leadByte} \neq \mathtt{0x01}\) + \(\mathsf{leadByte} \neq \mathtt{0x01}\!\) :
    • \(\mathsf{esk} = \mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([4]))\)
    • if - \(\mathsf{repr}_{\mathbb{J}}(\mathsf{KA^{Sapling}.DerivePublic}(\mathsf{esk}, \mathsf{g_d})) \neq \mathtt{ephemeralKey}\) + \(\mathsf{repr}_{\mathbb{J}}(\mathsf{KA^{Sapling}.DerivePublic}(\mathsf{esk}, \mathsf{g_d})) \neq \mathtt{ephemeralKey}\!\) , return \(\bot\)
    • @@ -280,15 +282,15 @@ \(\mathsf{pk_d} = \mathsf{KA^{Sapling}.DerivePublic}(\mathsf{ivk}, \mathsf{g_d})\)
    • let - \(\mathsf{cm}_u' = \mathsf{Extract}_{\mathbb{J}^{(r)}}(\mathsf{NoteCommit^{Sapling}_{rcm}}(\mathsf{repr}_{\mathbb{J}}(\mathsf{g_d}), \mathsf{repr}_{\mathbb{J}}(\mathsf{pk_d}), \mathsf{v}))\) + \(\mathsf{cm}_u' = \mathsf{Extract}_{\mathbb{J}^{(r)}}(\mathsf{NoteCommit^{Sapling}_{rcm}}(\mathsf{repr}_{\mathbb{J}}(\mathsf{g_d}), \mathsf{repr}_{\mathbb{J}}(\mathsf{pk_d}), \mathsf{v}))\!\) .
    • if - \(\mathsf{LEBS2OSP}_{256}(\mathsf{cm}_u') \neq \mathtt{cmu}\) + \(\mathsf{LEBS2OSP}_{256}(\mathsf{cm}_u') \neq \mathtt{cmu}\!\) , return \(\bot\)
    • return - \(\mathbf{np}\) + \(\mathbf{np}\!\) .
  • diff --git a/rendered/zip-0311.html b/rendered/zip-0311.html index cfec0a94b..98bbd6107 100644 --- a/rendered/zip-0311.html +++ b/rendered/zip-0311.html @@ -3,7 +3,9 @@ ZIP 311: Zcash Payment Disclosures - + + +
    @@ -142,9 +144,9 @@ \(\mathsf{DiversifyHash}(\mathsf{d})\) 7
  • - \(\mathsf{SpendAuthSig.RandomizePrivate}(Îą, \mathsf{sk})\) + \(\mathsf{SpendAuthSig.RandomizePrivate}(Îą, \mathsf{sk})\!\) , - \(\mathsf{SpendAuthSig.Sign}(\mathsf{sk}, m)\) + \(\mathsf{SpendAuthSig.Sign}(\mathsf{sk}, m)\!\) , and \(\mathsf{SpendAuthSig.Verify}(\mathsf{vk}, m, σ)\) 8
  • @@ -156,14 +158,14 @@ means scalar multiplication of the elliptic curve point \(P\) by the scalar - \(k\) + \(k\!\) .
  • \(\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\) + \(p\!\) , and input - \(x\) + \(x\!\) .
  • We also define the following notation here:

    @@ -173,12 +175,12 @@ means the sequence of values inclusive of \(a\) and exclusive of - \(b\) + \(b\!\) .
  • \(\mathsf{length}(a)\) means the length of the sequence - \(a\) + \(a\!\) .
  • @@ -189,17 +191,17 @@
  • txid: Transaction id for the transaction tx being disclosed.
  • msg: A message field, which could contain a challenge value from the party to whom the payment disclosure is directed.
  • - \(\mathsf{transparentInputs}\) + \(\mathsf{transparentInputs}\!\) : A sequence of the transparent inputs for which we are proving spend authority \([0..\mathsf{length}(\mathsf{tx.vin})]\)
    • - \(\mathsf{index}\) + \(\mathsf{index}\!\) : An index into - \(\mathsf{tx.vin}\) + \(\mathsf{tx.vin}\!\) .
    • - \(\mathsf{sig}\) + \(\mathsf{sig}\!\) : A BIP 322 signature. 9
      • TODO: zcashd currently only supports the legacy format defined in BIP 322. We may want to backport full BIP 322 support before having transparent input support in this ZIP, to ensure it does what we need.
      • @@ -209,23 +211,23 @@
    • - \(\mathsf{saplingSpends}\) + \(\mathsf{saplingSpends}\!\) : A sequence of the Sapling Spends for which we are proving spend authority \([0..\mathsf{length}(\mathsf{tx.shieldedSpends})]\)
      • - \(\mathsf{index}\) + \(\mathsf{index}\!\) : An index into - \(\mathsf{tx.shieldedSpends}\) + \(\mathsf{tx.shieldedSpends}\!\) .
      • - \(\mathsf{cv}\) + \(\mathsf{cv}\!\) : A value commitment to the spent note.
      • - \(\mathsf{rk}\) + \(\mathsf{rk}\!\) : A randomized public key linked to the spent note.
      • - \(\mathsf{zkproof_{spend}}\) + \(\mathsf{zkproof_{spend}}\!\) : A Sapling spend proof.
      • [Optional] A payment address proof addr_proof:
          @@ -235,10 +237,10 @@ \(\mathsf{pk_d} = [\mathsf{ivk}] \mathsf{DiversifyHash}(\mathsf{d})\)
        • - \(\mathsf{nullifier_{addr}}\) + \(\mathsf{nullifier_{addr}}\!\) : A nullifier for a ZIP 304 fake note. 11
        • - \(\mathsf{zkproof_{addr}}\) + \(\mathsf{zkproof_{addr}}\!\) : A Sapling spend proof.
      • @@ -248,17 +250,17 @@
    • - \(\mathsf{saplingOutputs}\) + \(\mathsf{saplingOutputs}\!\) : A sequence of the Sapling Outputs that we are disclosing \([0..\mathsf{length}(\mathsf{tx.shieldedOutputs})]\)
      • - \(\mathsf{index}\) + \(\mathsf{index}\!\) : An index into - \(\mathsf{tx.shieldedOutputs}\) + \(\mathsf{tx.shieldedOutputs}\!\) .
      • - \(\mathsf{ock}\) + \(\mathsf{ock}\!\) : The outgoing cipher key that allows this output to be recovered. 5
    • @@ -282,19 +284,19 @@
      • A Sapling spend index.
      • Its corresponding expanded spending key - \((\mathsf{ask}, \mathsf{nsk}, \mathsf{ovk})\) + \((\mathsf{ask}, \mathsf{nsk}, \mathsf{ovk})\!\) .
      • [Optional] An associated payment address - \((\mathsf{d}, \mathsf{pk_d})\) + \((\mathsf{d}, \mathsf{pk_d})\!\) .
    • A sequence of transparent input tuples (which may be empty) containing:
      • - \(\mathsf{index}\) + \(\mathsf{index}\!\) : An index into - \(\mathsf{tx.vin}\) + \(\mathsf{tx.vin}\!\) .
      • The inputs to a BIP 322 signature (excluding message_data).
      @@ -306,7 +308,7 @@
    • For each Sapling spend index:
      • Create a Sapling spend proof for the note that was spent in - \(\mathsf{tx.shieldedSpends[index]}\) + \(\mathsf{tx.shieldedSpends[index]}\!\) , using the same anchor, to obtain \((\mathsf{cv}, \mathsf{rk}, \mathsf{zkproof_{spend}})\) as well as the random @@ -327,21 +329,21 @@
    • Construct an unsigned payment disclosure from the disclosed Sapling outputs, and the above data for the Sapling spends and transparent inputs. Define the encoding of this as - \(unsignedPaymentDisclosure\) + \(unsignedPaymentDisclosure\!\) .
    • For each Sapling spend index:
      • Let - \(\mathsf{rsk} = \mathsf{SpendAuthSig.RandomizePrivate}(\alpha, \mathsf{ask})\) + \(\mathsf{rsk} = \mathsf{SpendAuthSig.RandomizePrivate}(\alpha, \mathsf{ask})\!\) .
      • Let \(coinType\) be the 4-byte little-endian encoding of the SLIP 44 coin type in its index form, not its hardened form (i.e. 133 for mainnet Zcash).
      • Let - \(digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZIP311Signed"}\,||\,coinType, unsignedPaymentDisclosure)\) + \(digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{“ZIP311Signed”}\,||\,coinType, unsignedPaymentDisclosure)\!\) .
      • Let - \(spendAuthSig = \mathsf{SpendAuthSig.Sign}(\mathsf{rsk}, digest)\) + \(spendAuthSig = \mathsf{SpendAuthSig.Sign}(\mathsf{rsk}, digest)\!\) .
    • @@ -355,9 +357,9 @@

      Verifying a payment disclosure

      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 @@
    • For every \(\mathsf{output}\) in - \(\mathsf{pd.saplingOutputs}\) + \(\mathsf{pd.saplingOutputs}\!\) , \(\mathsf{output.index}\) only occurs once.
    • For every \(\mathsf{spend}\) in - \(\mathsf{pd.saplingSpends}\) + \(\mathsf{pd.saplingSpends}\!\) , \(\mathsf{spend.index}\) only occurs once.
    • For every \(\mathsf{input}\) in - \(\mathsf{pd.transparentInputs}\) + \(\mathsf{pd.transparentInputs}\!\) , \(\mathsf{input.index}\) only occurs once.
    • @@ -410,21 +412,21 @@
    • For every \(\mathsf{output}\) in - \(\mathsf{pd.saplingOutputs}\) + \(\mathsf{pd.saplingOutputs}\!\) , \(\mathsf{output.index} < \mathsf{length}(\mathsf{tx.shieldedOutputs})\)
    • For every \(\mathsf{spend}\) in - \(\mathsf{pd.saplingSpends}\) + \(\mathsf{pd.saplingSpends}\!\) , \(\mathsf{spend.index} < \mathsf{length}(\mathsf{tx.shieldedSpends})\)
    • For every \(\mathsf{input}\) in - \(\mathsf{pd.transparentInputs}\) + \(\mathsf{pd.transparentInputs}\!\) , \(\mathsf{input.index} < \mathsf{length}(\mathsf{tx.vin})\)
    • @@ -442,21 +444,21 @@ \(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).
    • Let - \(digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZIP311Signed"}\,||\,coinType, unsignedPaymentDisclosure)\) + \(digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{“ZIP311Signed”}\,||\,coinType, unsignedPaymentDisclosure)\!\) .
    • For every \(\mathsf{spend}\) in - \(\mathsf{pd.saplingSpends}\) + \(\mathsf{pd.saplingSpends}\!\) :
      • If - \(\mathsf{SpendAuthSig.Verify}(\mathsf{spend.rk}, digest, \mathsf{spend.spendAuthSig}) = 0\) + \(\mathsf{SpendAuthSig.Verify}(\mathsf{spend.rk}, digest, \mathsf{spend.spendAuthSig}) = 0\!\) , return false.
      • [Optional] If a payment address proof \(\mathsf{addrProof}\) is present in - \(\mathsf{spend}\) + \(\mathsf{spend}\!\) , verify \((\mathsf{addrProof.nullifier_{addr}}, \mathsf{spend.rk}, \mathsf{addrProof.zkproof_{addr}})\) as a ZIP 304 proof for @@ -486,7 +488,7 @@
      • For every \(\mathsf{input}\) in - \(\mathsf{pd.transparentInputs}\) + \(\mathsf{pd.transparentInputs}\!\) :
        • TODO: BIP 322 verification.
        • @@ -495,15 +497,15 @@
        • For every \(\mathsf{output}\) in - \(\mathsf{pd.saplingOutputs}\) + \(\mathsf{pd.saplingOutputs}\!\) :
          • Recover the Sapling note in \(\mathsf{tx.shieldedOutputs}[\mathsf{output.index}]\) via the process specified in 6 with inputs - \((height, \mathsf{output.ock})\) + \((height, \mathsf{output.ock})\!\) . If recovery returns - \(\bot\) + \(\bot\!\) , return false.
        • @@ -526,7 +528,7 @@ of \(\bot\) for a specific Sapling output, then they are unable to subsequently create a payment disclosure that discloses that output. This maintains the semantics of - \(\mathsf{ovk}\) + \(\mathsf{ovk}\!\) , in that the sender explicitly chose to lose the capability to recover that output.

          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.

    • diff --git a/rendered/zip-0312.html b/rendered/zip-0312.html index f69ad06eb..6471e4b61 100644 --- a/rendered/zip-0312.html +++ b/rendered/zip-0312.html @@ -3,7 +3,9 @@ ZIP 312: FROST for Spend Authorization Multisignatures - + + +
      @@ -71,7 +73,7 @@

      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.

      Key Generation

      @@ -80,7 +82,7 @@ 14 is the particular key that must be used in the context of this ZIP. Note that the \(\mathsf{ask}\) is usually derived from the spending key - \(\mathsf{sk}\) + \(\mathsf{sk}\!\) , though that is not required. Not doing so allows using distributed key generation, since the key it generates is unpredictable. Note however that not deriving \(\mathsf{ask}\) from @@ -170,7 +172,7 @@
      • H1(m): Implemented by computing BLAKE2b-512("FROST_RedJubjubR", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo G.Order().
      • H2(m): Implemented by computing BLAKE2b-512("Zcash_RedJubjubH", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo G.Order(). (This is equivalent to - \(\mathsf{H}^\circledast(m)\) + \(\mathsf{H}^\circledast(m)\!\) , as defined by the \(\mathsf{RedJubjub}\) scheme instantiated in 12.)
      • @@ -211,7 +213,7 @@
        • H1(m): Implemented by computing BLAKE2b-512("FROST_RedPallasR", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo G.Order().
        • H2(m): Implemented by computing BLAKE2b-512("Zcash_RedPallasH", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo G.Order(). (This is equivalent to - \(\mathsf{H}^\circledast(m)\) + \(\mathsf{H}^\circledast(m)\!\) , as defined by the \(\mathsf{RedPallas}\) scheme instantiated in 12.)
        • @@ -232,10 +234,10 @@ function specified in 12:

          • The FROST signature, when split into R and S in the first step of - \(\mathsf{RedDSA.Validate}\) + \(\mathsf{RedDSA.Validate}\!\) , must yield the values expected by the function. This is ensured by defining SerializeElement and SerializeScalar in each ciphersuite to yield those values.
          • The challenge c used during FROST signing must be equal to the challenge c computed during - \(\mathsf{RedDSA.Validate}\) + \(\mathsf{RedDSA.Validate}\!\) . This requires defining the ciphersuite H2 function as the \(\mathsf{H}^\circledast(m)\) Zcash function in the ciphersuites, and making sure its input will be the same. Fortunately FROST and Zcash use the same input order (R, public key, message) so we just need to make sure that SerializeElement (used to compute the encoded public key before passing to the hash function) matches what @@ -252,17 +254,17 @@
          • The re-randomization must be done in each signature share generation, such that the aggregated signature must be valid under verification with the randomized public key. The 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.
          • The re-randomization procedure must be exactly the same as in 12 to ensure that re-randomized keys are uniformly distributed and signatures are unlinkable. This is also true; observe that 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 @@ ZIP 316: Unified Addresses and Unified Viewing Keys - + + +
            @@ -270,7 +272,7 @@ is the encoding of \((\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk})\) given by - \(\mathsf{EncodeExtFVKParts}(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk})\) + \(\mathsf{EncodeExtFVKParts}(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk})\!\) , where \(\mathsf{EncodeExtFVKParts}\) is defined in 15. This SHOULD be derived from the Extended Full Viewing Key at the Account level of the ZIP 32 hierarchy.
          • @@ -289,11 +291,11 @@ Both of these are encodings of the chain code and public key \((\mathsf{c}, \mathsf{pk})\) given by - \(\mathsf{c}\,||\,\mathsf{ser_P}(\mathsf{pk})\) + \(\mathsf{c}\,||\,\mathsf{ser_P}(\mathsf{pk})\!\) . (This is the same as the last 65 bytes of the extended public key format defined in section “Serialization format” of BIP 32 31.) However, the FVK uses the key at the Account level, i.e. at path - \(m / 44' / coin\_type' / account'\) + \(m / 44' / coin\_type' / account'\!\) , while the IVK uses the external (non-change) child key at the Change level, i.e. at path - \(m / 44' / coin\_type' / account' / 0\) + \(m / 44' / coin\_type' / account' / 0\!\) .

          The Human-Readable Part is as specified for a Unified Viewing Key in Revisions.

          @@ -309,7 +311,7 @@
        • A Revision 0 Unified Address or Unified Viewing Key MUST contain at least one shielded Item (Typecodes \(\mathtt{0x02}\) and - \(\mathtt{0x03}\) + \(\mathtt{0x03}\!\) ). This requirement is dropped for Revision 1 UA/UVKs; however, a Revision 1 UA/UVK MUST contain at least one non-Metadata Item.
        • The \(\mathtt{typecode}\) @@ -401,15 +403,15 @@

          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 @@
      • There are no additional constraints on an Orchard diversifier index.

      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:

        @@ -542,7 +544,7 @@ and last \(m\) characters, up to some bound on - \(n+m\) + \(n+m\!\) );
      • is controlled by the adversary (for concreteness, the adversary knows at least one of the private keys of the constituent Addresses).
      • @@ -646,7 +648,7 @@

        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 @@ ZIP 317: Proportional Transfer Fee Mechanism - + + +
        @@ -211,27 +213,27 @@

        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.

        Transparent Contribution

        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:

          @@ -308,7 +310,7 @@
        1. For each transaction \(tx\) in the mempool, calculate - \(tx.\!weight\_ratio = \mathsf{min}\!\left(\frac{\mathsf{max}(1,\, tx.fee)}{conventional\_fee(tx)},\, weight\_ratio\_cap\right)\!\) + \(tx.\!weight\_ratio = \mathsf{min}\!\left(\frac{\mathsf{max}(1,\, tx.fee)}{conventional\_fee(tx)},\, weight\_ratio\_cap\right)\) and add the transaction to the set of candidate transactions.
        2. Repeat while there is any candidate transaction that pays at least the conventional fee:
            @@ -380,7 +382,7 @@ rather than just \(tx.\!fee\) avoids needing to define "with probability in direct proportion to its - \(weight\_ratio\!\) + \(weight\_ratio\) " for the case where all remaining candidate transactions would have \(weight\_ratio = 0\!\) .

            diff --git a/rendered/zip-0320.html b/rendered/zip-0320.html index 0094e0110..1932b0d0a 100644 --- a/rendered/zip-0320.html +++ b/rendered/zip-0320.html @@ -3,7 +3,9 @@ ZIP 320: Defining an Address Type to which funds can only be sent from Transparent Addresses - + + +
            @@ -58,12 +60,12 @@
            1. Decode the address to a byte sequence using the Base58Check decoding algorithm 13.
            2. If the length of the resulting byte sequence is not 22 bytes or if its two-byte address prefix is not - \([\mathtt{0x1C}, \mathtt{0xB8}]\) + \([\mathtt{0x1C}, \mathtt{0xB8}]\!\) , return an error. Otherwise, let the validating key hash be the remaining 20 bytes of the sequence after removing the two-byte address prefix.
            3. Reencode the 20-byte validating key hash using the Bech32m encoding defined in 15 with the human-readable prefix (HRP) "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.:

              diff --git a/rendered/zip-0324.html b/rendered/zip-0324.html index 2816bce7c..47003b631 100644 --- a/rendered/zip-0324.html +++ b/rendered/zip-0324.html @@ -3,7 +3,9 @@ ZIP 324: URI-Encapsulated Payments - + + +
              diff --git a/rendered/zip-0401.html b/rendered/zip-0401.html index aaec293e4..b35caa570 100644 --- a/rendered/zip-0401.html +++ b/rendered/zip-0401.html @@ -3,7 +3,9 @@ ZIP 401: Addressing Mempool Denial-of-Service - + + +
              @@ -64,7 +66,7 @@

              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.

              diff --git a/rendered/zip-1011.html b/rendered/zip-1011.html index e62e1debf..2aac65bcd 100644 --- a/rendered/zip-1011.html +++ b/rendered/zip-1011.html @@ -3,7 +3,9 @@ ZIP 1011: Decentralize the Dev Fee - + + +
              diff --git a/rendered/zip-2001.html b/rendered/zip-2001.html index 9ab6478b2..48717be1c 100644 --- a/rendered/zip-2001.html +++ b/rendered/zip-2001.html @@ -3,7 +3,9 @@ ZIP 2001: Lockbox Funding Streams - + + +
              @@ -50,7 +52,7 @@

              Changes to ZIP 207 Each element of \(\mathsf{fs.Recipients}\) MUST represent either a transparent P2SH address as specified in 6, or a Sapling shielded payment address as specified in 7, or the identifier - \(\mathsf{DEFERRED}\_\mathsf{POOL}\!\) + \(\mathsf{DEFERRED\_POOL}\!\) .

              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 @@

              Changes to ZIP 207 \(\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}\!\) .

              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 @@

              Changes to ZIP 207 In each block with coinbase transaction \(\mathsf{cb}\) at block height - \(\mathsf{height}\) + \(\mathsf{height}\!\) , for each funding stream \(\mathsf{fs}\) active at that block height with a recipient identifier other than - \(\mathsf{DEFERRED}\_\mathsf{POOL}\) + \(\mathsf{DEFERRED\_POOL}\) given by \(\mathsf{fs.Recipient}(\mathsf{height})\!\) , @@ -118,29 +120,29 @@

              Changes to ZIP 207

              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

              Changes to the Zcash Protocol Specification

              -

              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}\!\) :

              -

              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.

              References

              diff --git a/rendered/zip-2002.html b/rendered/zip-2002.html index 7a1d7978a..735a2f679 100644 --- a/rendered/zip-2002.html +++ b/rendered/zip-2002.html @@ -3,7 +3,9 @@ ZIP 2002: Explicit Fees - + + +
              @@ -70,7 +72,7 @@

              Changes to ZIP 230 In § 7.1 ‘Transaction Encoding and Consensus’ 5, add:

              [NU7 onward] fee MUST be in the range - \(\{ 0 .. \mathsf{MAX\_MONEY} \}\) + \(\{ 0 .. \mathsf{MAX\_MONEY} \}\!\) .

              diff --git a/rendered/zip-2004.html b/rendered/zip-2004.html index a7dec2693..aa570297d 100644 --- a/rendered/zip-2004.html +++ b/rendered/zip-2004.html @@ -3,7 +3,9 @@ ZIP 2004: Remove the dependency of consensus on note encryption - + + +
              @@ -44,9 +46,9 @@ and add the following text:

              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.

      Using mathematical notation

      -

      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 @@ ZIP guide: {Something Short and To the Point} - + + +

      @@ -78,8 +80,11 @@

      Using mathematical notation

      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" ` -.. [#protocol] `Zcash Protocol Specification, Version 2024.5.1 or later ` -.. [#protocol-subsidyconcepts] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 3.10: Block Subsidy and Founders' Reward ` -.. [#protocol-networks] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 3.12: Mainnet and Testnet ` -.. [#protocol-constants] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.3: Constants ` -.. [#protocol-transparentaddrencoding] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.6.1.1: Transparent Addresses ` -.. [#protocol-saplingpaymentaddrencoding] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.6.3.1: Sapling Payment Addresses ` -.. [#protocol-diffadjustment] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.7.3: Difficulty adjustment ` -.. [#protocol-subsidies] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.8: Calculation of Block Subsidy, Funding Streams, and Founders' Reward ` -.. [#protocol-foundersreward] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.9: Payment of Founders' Reward ` -.. [#protocol-fundingstreams] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.10: Payment of Funding Streams ` -.. [#zip-0000] `ZIP 0: ZIP Process ` -.. [#zip-0200] `ZIP 200: Network Upgrade Mechanism ` -.. [#zip-0208] `ZIP 208: Shorter Block Target Spacing ` -.. [#zip-0212] `ZIP 212: Allow Recipient to Derive Sapling Ephemeral Secret from Note Plaintext ` -.. [#zip-0213] `ZIP 213: Shielded Coinbase ` -.. [#zip-0214] `ZIP 214: Consensus rules for a Zcash Development Fund ` -.. [#zip-0251] `ZIP 251: Deployment of the Canopy Network Upgrade ` -.. [#zip-0253] `ZIP 253: Deployment of the NU6 Network Upgrade ` -.. [#zip-1014] `ZIP 1014: Establishing a Dev Fund for ECC, ZF, and Major Grants ` -.. [#zip-1015] `ZIP 1015: Block Subsidy Allocation for Non-Direct Development Funding ` -.. [#zip-2001] `ZIP 2001: Lockbox Funding Streams ` +.. [#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" `_ +.. [#protocol] `Zcash Protocol Specification, Version 2024.5.1 or later `_ +.. [#protocol-subsidyconcepts] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 3.10: Block Subsidy and Founders' Reward `_ +.. [#protocol-networks] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 3.12: Mainnet and Testnet `_ +.. [#protocol-constants] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.3: Constants `_ +.. [#protocol-transparentaddrencoding] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.6.1.1: Transparent Addresses `_ +.. [#protocol-saplingpaymentaddrencoding] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 5.6.3.1: Sapling Payment Addresses `_ +.. [#protocol-diffadjustment] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.7.3: Difficulty adjustment `_ +.. [#protocol-subsidies] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.8: Calculation of Block Subsidy, Funding Streams, and Founders' Reward `_ +.. [#protocol-foundersreward] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.9: Payment of Founders' Reward `_ +.. [#protocol-fundingstreams] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 7.10: Payment of Funding Streams `_ +.. [#zip-0000] `ZIP 0: ZIP Process `_ +.. [#zip-0200] `ZIP 200: Network Upgrade Mechanism `_ +.. [#zip-0208] `ZIP 208: Shorter Block Target Spacing `_ +.. [#zip-0212] `ZIP 212: Allow Recipient to Derive Sapling Ephemeral Secret from Note Plaintext `_ +.. [#zip-0213] `ZIP 213: Shielded Coinbase `_ +.. [#zip-0214] `ZIP 214: Consensus rules for a Zcash Development Fund `_ +.. [#zip-0251] `ZIP 251: Deployment of the Canopy Network Upgrade `_ +.. [#zip-0253] `ZIP 253: Deployment of the NU6 Network Upgrade `_ +.. [#zip-1014] `ZIP 1014: Establishing a Dev Fund for ECC, ZF, and Major Grants `_ +.. [#zip-1015] `ZIP 1015: Block Subsidy Allocation for Non-Direct Development Funding `_ +.. [#zip-2001] `ZIP 2001: Lockbox Funding Streams `_ diff --git a/zips/zip-0208.rst b/zips/zip-0208.rst index cf9840f27..bfd02e4e9 100644 --- a/zips/zip-0208.rst +++ b/zips/zip-0208.rst @@ -71,112 +71,123 @@ The changes described in this section are to be made in the Zcash Protocol Speci Consensus changes ----------------- -Throughout the specification, rename HalvingInterval to PreBlossomHalvingInterval, -and rename PoWTargetSpacing to PreBlossomTargetSpacing. These constants retain -their values from [#preblossom-protocol]_ of 840000 (blocks) and 150 (seconds) -respectively. +Throughout the specification, rename $\mathsf{HalvingInterval}$ to $\mathsf{PreBlossomHalvingInterval}$, +and rename $\mathsf{PoWTargetSpacing}$ to $\mathsf{PreBlossomTargetSpacing}$. These constants retain +their values from [#preblossom-protocol]_ of $840000$ (blocks) and $150$ (seconds) respectively. -In section 2 (Notation), add BlossomActivationHeight and PostBlossomPoWTargetSpacing +In section 2 (Notation), add $\mathsf{BlossomActivationHeight}$ and $\mathsf{PostBlossomPoWTargetSpacing}$ to the list of integer constants. -In section 5.3 (Constants), define PostBlossomPoWTargetSpacing := 75 seconds. +In section 5.3 (Constants), define $\mathsf{PostBlossomPoWTargetSpacing} := 75$ seconds. -For a given network (production or test), define BlossomActivationHeight as the +For a given network (production or test), define $\mathsf{BlossomActivationHeight}$ as the height at which Blossom activates on that network, as specified in [#zip-0206]_. 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. +Define $\mathsf{IsBlossomActivated}(\mathsf{height})$ to return true if +$\mathsf{height} \geq \mathsf{BlossomActivationHeight}$, otherwise false. -This specification assumes that BlossomActivationHeight ≥ SlowStartInterval. +This specification assumes that $\mathsf{BlossomActivationHeight} \geq \mathsf{SlowStartInterval}$. Define: -- BlossomPoWTargetSpacingRatio := PreBlossomPoWTargetSpacing / PostBlossomPoWTargetSpacing -- PostBlossomHalvingInterval := floor(PreBlossomHalvingInterval · BlossomPoWTargetSpacingRatio). +- $\mathsf{BlossomPoWTargetSpacingRatio} := \mathsf{PreBlossomPoWTargetSpacing} / \mathsf{PostBlossomPoWTargetSpacing}$ +- $\mathsf{PostBlossomHalvingInterval} := \mathsf{floor}(\mathsf{PreBlossomHalvingInterval} \cdot \mathsf{BlossomPoWTargetSpacingRatio})$. -In the same section, redefine PoWTargetSpacing as a function taking a *height* -parameter, as follows: +In the same section, redefine $\mathsf{PoWTargetSpacing} as a function taking a +$\mathsf{height}$ parameter, as follows: -- PoWTargetSpacing(*height*) := +.. math:: + \mathsf{PoWTargetSpacing}(\mathsf{height}) := + \begin{cases} + \mathsf{PreBlossomPoWTargetSpacing}, &\!\!\text{if not } \mathsf{IsBlossomActivated}(\mathsf{height}) \\ + \mathsf{PostBlossomPoWTargetSpacing} &\!\!\text{otherwise} + \end{cases} - - PreBlossomPoWTargetSpacing, if not IsBlossomActivated(*height*) - - PostBlossomPoWTargetSpacing, otherwise. +Also redefine $\mathsf{AveragingWindowTimespan}$, $\mathsf{MinActualTimespan}$, $\mathsf{MaxActualTimespan}$, +$\mathsf{ActualTimespanDamped}$, $\mathsf{ActualTimespanBounded}$, and $\mathsf{Threshold}$ as follows: -Also redefine AveragingWindowTimespan, MinActualTimespan, MaxActualTimespan, -ActualTimespanDamped, ActualTimespanBounded, and Threshold as follows: - -- add a *height* parameter to each of these functions that does not already +- add a $\mathsf{height}$ parameter to each of these functions that does not already have one; -- ensure that each reference to any of these values, or to PoWTargetSpacing, - are replaced with a function call passing the *height* parameter. +- ensure that each reference to any of these values, or to $\mathsf{PoWTargetSpacing}$, + are replaced with a function call passing the $\mathsf{height}$ parameter. 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: - -- Halving(*height*) := - - - floor((*height* - SlowStartShift) / PreBlossomHalvingInterval), if not IsBlossomActivated(*height*) - - floor((BlossomActivationHeight - SlowStartShift) / PreBlossomHalvingInterval + (*height* - BlossomActivationHeight) / PostBlossomHalvingInterval), otherwise - -- BlockSubsidy(*height*) := - - - SlowStartRate · *height*, if *height* < SlowStartInterval / 2 - - SlowStartRate · (*height* + 1), if SlowStartInterval / 2 ≤ *height* and *height* < SlowStartInterval - - floor(MaxBlockSubsidy / 2\ :sup:`Halving(*height*)`\ ), if SlowStartInterval ≤ *height* and not IsBlossomActivated(*height*) - - floor(MaxBlockSubsidy / (BlossomPoWTargetSpacingRatio · 2\ :sup:`Halving(*height*)`\ )), otherwise - -Note: BlossomActivationHeight, PostBlossomHalvingInterval, and PostBlossomTargetSpacing are chosen so that: - -- (BlossomActivationHeight - SlowStartShift) / PreBlossomHalvingInterval + (*height* - BlossomActivationHeight) / PostBlossomHalvingInterval) - is exactly 1 for some integer *height*. -- MaxBlockSubsidy / (BlossomPoWTargetSpacingRatio · 2\ :sup:`Halving(*height*)`\ ) +to section 7.8], redefine the $\mathsf{Halving}$ and $\mathsf{BlockSubsidy}$ functions as follows: + +.. math:: + \mathsf{Halving}(\mathsf{height}) := + \begin{cases} + \mathsf{floor}((\mathsf{height} - \mathsf{SlowStartShift}) / \mathsf{PreBlossomHalvingInterval}), &\!\!\text{if not } \mathsf{IsBlossomActivated}(\mathsf{height}) \\ + \mathsf{floor}((\mathsf{BlossomActivationHeight} - \mathsf{SlowStartShift}) / \mathsf{PreBlossomHalvingInterval} & \\ + \hspace{1em}+\; (\mathsf{height} - \mathsf{BlossomActivationHeight}) / \mathsf{PostBlossomHalvingInterval}) &\!\!\text{otherwise} + \end{cases} + +.. math:: + \mathsf{BlockSubsidy}(\mathsf{height}) := + \begin{cases} + \mathsf{SlowStartRate} \cdot \mathsf{height}, &\!\!\text{if } \mathsf{height} < \mathsf{SlowStartInterval} / 2 \\ + \mathsf{SlowStartRate} \cdot (\mathsf{height} + 1), &\!\!\text{if } \mathsf{SlowStartInterval} / 2 \leq \mathsf{height} \text{ and } \mathsf{height} < \mathsf{SlowStartInterval} \\ + \mathsf{floor}(\mathsf{MaxBlockSubsidy} / 2^{\mathsf{Halving}(\mathsf{height})}), &\!\!\text{if } \mathsf{SlowStartInterval} \leq \mathsf{height} \text{ and not } \mathsf{IsBlossomActivated}(\mathsf{height}) \\ + \mathsf{floor}(\mathsf{MaxBlockSubsidy} / & \\ + \hspace{1em}(\mathsf{BlossomPoWTargetSpacingRatio} \cdot 2^{\mathsf{Halving}(\mathsf{height})})) &\!\!\text{otherwise} + \end{cases} + +Note: $\mathsf{BlossomActivationHeight}$, $\mathsf{PostBlossomHalvingInterval}$, and $\mathsf{PostBlossomTargetSpacing}$ are chosen so that: + +- $(\mathsf{BlossomActivationHeight} - \mathsf{SlowStartShift}) / \mathsf{PreBlossomHalvingInterval}\hspace{-3em}$ + $\hspace{3em}+\; (\mathsf{height} - \mathsf{BlossomActivationHeight}) / \mathsf{PostBlossomHalvingInterval}$ + is exactly $1$ for some integer $\mathsf{height}$. +- $\mathsf{MaxBlockSubsidy} / (\mathsf{BlossomPoWTargetSpacingRatio} \cdot 2^{\mathsf{Halving}(\mathsf{height})})$ is an integer for the next few periods. In section 7.8 (Payment of Founders’ Reward) [later moved to section 7.9], define: -- FounderAddressAdjustedHeight(*height*) := - - - *height*, if not IsBlossomActivated(*height*) - - BlossomActivationHeight + floor((*height* - BlossomActivationHeight) / BlossomPoWTargetSpacingRatio), otherwise +.. math:: + \mathsf{FounderAddressAdjustedHeight}(\mathsf{height}) := + \begin{cases} + \mathsf{height}, &\!\!\text{if not } \mathsf{IsBlossomActivated}(\mathsf{height}) \\ + \mathsf{BlossomActivationHeight} + \mathsf{floor}((\mathsf{height} - \mathsf{BlossomActivationHeight}) / \\ + \hspace{1em}\mathsf{BlossomPoWTargetSpacingRatio}) &\!\!\text{otherwise} + \end{cases} -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: -- FoundersRewardLastBlockHeight := max({ *height* ⦂ N | Halving(*height*) < 1 }) +- $\mathsf{FoundersRewardLastBlockHeight} := \mathsf{max}(\{ \mathsf{height} \;{\small ⦂}\; \mathbb{N} | \mathsf{Halving}(\mathsf{height}) < 1 \})$ Replace the first note in that section with: -- No Founders’ Reward is required to be paid for *height* > FoundersRewardLastBlockHeight - (i.e. after the first halving), or for *height* = 0 (i.e. the genesis block). +- No Founders’ Reward is required to be paid for $\mathsf{height} > \mathsf{FoundersRewardLastBlockHeight}$ + (i.e. after the first halving), or for $\mathsf{height} = 0$ (i.e. the genesis block). -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}$. Effect on difficulty adjustment ------------------------------- -The difficulty adjustment parameters PoWAveragingWindow and PoWMedianBlockSpan +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 PoWTargetSpacing will cause the block +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 AveragingWindowTimespan(height) takes effect +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 -PoWAveragingWindow blocks will have been adjusted using the pre-Blossom target +$\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 PoWMaxAdjustDown. This is not +few blocks after activation will be limited by $\mathsf{PoWMaxAdjustDown}$. This is not anticipated to cause any problem. @@ -189,12 +200,13 @@ On Testnet from block height 299188 onward, the difficulty adjustment algorithm 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 [#protocol-constants]_, and -ToCompact is as defined in section 7.7.4 of that specification [#protocol-nbits]_. +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 +[#protocol-constants]_, and $\mathsf{ToCompact}$ is as defined in section 7.7.4 of that +specification [#protocol-nbits]_. Note: a previous revision of this ZIP (and [#zip-0205]_) incorrectly said that only the target threshold of minimum-difficulty blocks is affected. In fact @@ -324,7 +336,7 @@ an hour after responding to the message:: // 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 +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. @@ -388,7 +400,7 @@ pre-upgrade consensus branch that persists. Reference Implementation ======================== -https://github.com/zcash/zcash/pull/4025 +* https://github.com/zcash/zcash/pull/4025 References diff --git a/zips/zip-0212.rst b/zips/zip-0212.rst index 0669e8f60..93ce9dc67 100644 --- a/zips/zip-0212.rst +++ b/zips/zip-0212.rst @@ -19,17 +19,17 @@ in all capitals. The following functions are defined in the Zcash Protocol Specification [#protocol]_ according to the type (Sapling or Orchard) of note plaintext being processed: -* let :math:`\mathsf{ToScalar}` be - :math:`\mathsf{ToScalar^{Sapling}}` defined in section 4.2.2 [#protocol-saplingkeycomponents]_ or - :math:`\mathsf{ToScalar^{Orchard}}` defined in section 4.2.3 [#protocol-orchardkeycomponents]_; -* let :math:`\mathsf{DiversifyHash}` be - :math:`\mathsf{DiversifyHash^{Sapling}}` or :math:`\mathsf{DiversifyHash^{Orchard}}` +* let $\mathsf{ToScalar}$ be + $\mathsf{ToScalar^{Sapling}}$ defined in section 4.2.2 [#protocol-saplingkeycomponents]_ or + $\mathsf{ToScalar^{Orchard}}$ defined in section 4.2.3 [#protocol-orchardkeycomponents]_; +* let $\mathsf{DiversifyHash}$ be + $\mathsf{DiversifyHash^{Sapling}}$ or $\mathsf{DiversifyHash^{Orchard}}$ defined in section 5.4.1.6 [#protocol-concretediversifyhash]_; -* let :math:`\mathsf{KA}` be - :math:`\mathsf{KA^{Sapling}}` defined in section 5.4.5.3 [#protocol-concretesaplingkeyagreement]_ or - :math:`\mathsf{KA^{Orchard}}` defined in section 5.4.5.5 [#protocol-concreteorchardkeyagreement]_; -* let :math:`\mathsf{NoteCommit}` be - :math:`\mathsf{NoteCommit^{Sapling}}` or :math:`\mathsf{NoteCommit^{Orchard}}` +* let $\mathsf{KA}$ be + $\mathsf{KA^{Sapling}}$ defined in section 5.4.5.3 [#protocol-concretesaplingkeyagreement]_ or + $\mathsf{KA^{Orchard}}$ defined in section 5.4.5.5 [#protocol-concreteorchardkeyagreement]_; +* let $\mathsf{NoteCommit}$ be + $\mathsf{NoteCommit^{Sapling}}$ or $\mathsf{NoteCommit^{Orchard}}$ defined in section 4.1.8 [#protocol-abstractcommit]_. @@ -54,28 +54,28 @@ allows users to maintain many payment addresses without paying additional overhead during blockchain scanning. The feature works by allowing payment addresses to become a tuple -:math:`(\mathsf{pk_d}, \mathsf{d})` of a public key :math:`\mathsf{pk_d}` and -:math:`88\!`-bit diversifier :math:`\mathsf{d}` such that -:math:`\mathsf{pk_d} = [\mathsf{ivk}]\, \mathsf{DiversifyHash}(\mathsf{d})` for -some incoming viewing key :math:`\mathsf{ivk}\!`. The hash function -:math:`\mathsf{DiversifyHash}(\mathsf{d})` maps from a diversifier to prime-order +$(\mathsf{pk_d}, \mathsf{d})$ of a public key $\mathsf{pk_d}$ and +$88$-bit diversifier $\mathsf{d}$ such that +$\mathsf{pk_d} = [\mathsf{ivk}]\, \mathsf{DiversifyHash}(\mathsf{d})$ for +some incoming viewing key $\mathsf{ivk}$. The hash function +$\mathsf{DiversifyHash}(\mathsf{d})$ maps from a diversifier to prime-order elements of the Jubjub or Pallas elliptic curve. It is possible for a user -to choose many :math:`\mathsf{d}` to create several distinct and unlinkable +to choose many $\mathsf{d}$ to create several distinct and unlinkable payment addresses of this form. In order to make a payment to a Sapling or Orchard address, an ephemeral secret -:math:`\mathsf{esk}` is sampled by the sender and an ephemeral public key -:math:`\mathsf{epk} = [\mathsf{esk}]\, \mathsf{DiversifyHash}(\mathsf{d})` is +$\mathsf{esk}$ is sampled by the sender and an ephemeral public key +$\mathsf{epk} = [\mathsf{esk}]\, \mathsf{DiversifyHash}(\mathsf{d})$ is included in the Output or Action description. Then, a shared Diffie-Hellman secret is computed by the sender as -:math:`\mathsf{KA.Agree}(\mathsf{esk}, \mathsf{pk_d})\!`. The recipient can -recover this shared secret without knowledge of the particular :math:`\mathsf{d}` -by computing :math:`\mathsf{KA.Agree}(\mathsf{ivk}, \mathsf{epk})\!`. This shared +$\mathsf{KA.Agree}(\mathsf{esk}, \mathsf{pk_d})$. The recipient can +recover this shared secret without knowledge of the particular $\mathsf{d}$ +by computing $\mathsf{KA.Agree}(\mathsf{ivk}, \mathsf{epk})$. This shared secret is then used as part of note decryption. -Naïvely, the recipient cannot know which :math:`(\mathsf{pk_d}, \mathsf{d})` +Naïvely, the recipient cannot know which $(\mathsf{pk_d}, \mathsf{d})$ was used to compute the shared secret, but the sender is asked to include the -:math:`\mathsf{d}` within the note plaintext to reconstruct the note. However, +$\mathsf{d}$ within the note plaintext to reconstruct the note. However, if the recipient has more than one known address, an attacker could use a different payment address to perform secret exchange and, by observing the behavior of the recipient, link the two diversified addresses together. (This @@ -84,9 +84,9 @@ Sapling protocol.) In order to prevent this attack before activation of this ZIP, the protocol forced the sender to prove knowledge of the discrete logarithm of -:math:`\mathsf{epk}` with respect to the -:math:`\mathsf{g_d} = \mathsf{DiversifyHash}(\mathsf{d})` included within the -note commitment. This :math:`\mathsf{g_d}` is determined by :math:`\mathsf{d}` +$\mathsf{epk}$ with respect to the +$\mathsf{g_d} = \mathsf{DiversifyHash}(\mathsf{d})$ included within the +note commitment. This $\mathsf{g_d}$ is determined by $\mathsf{d}$ and recomputed during note decryption, and so either the note decryption will fail, or the sender will be unable to produce the proof that requires knowledge of the discrete logarithm. @@ -95,19 +95,19 @@ However, the latter proof was part of the Sapling Output statement, and so relied on the soundness of the underlying Groth16 zk-SNARK — hence on relatively strong cryptographic assumptions and a trusted setup. It is preferable to force the sender to transfer sufficient information in the note plaintext to allow -deriving :math:`\mathsf{esk}\!`, so that, during note decryption, the recipient -can check that :math:`\mathsf{epk} = [\mathsf{esk}]\, \mathsf{g_d}` for the -expected :math:`\mathsf{g_d}\!`, and ignore the payment as invalid otherwise. +deriving $\mathsf{esk}$, so that, during note decryption, the recipient +can check that $\mathsf{epk} = [\mathsf{esk}]\, \mathsf{g_d}$ for the +expected $\mathsf{g_d}$, and ignore the payment as invalid otherwise. For Sapling, this forms a line of defense in the case that soundness of the zk-SNARK does not hold. For Orchard, this check is essential because (for -efficiency and simplicity) :math:`\mathsf{epk} = [\mathsf{esk}]\, \mathsf{g_d}` +efficiency and simplicity) $\mathsf{epk} = [\mathsf{esk}]\, \mathsf{g_d}$ is *not* checked in the Action statement. -Merely sending :math:`\mathsf{esk}` to the recipient in the note plaintext would +Merely sending $\mathsf{esk}$ to the recipient in the note plaintext would require us to enlarge the note plaintext, but also would compromise the proof of IND-CCA2 security for in-band secret distribution. We avoid both of these -concerns by using a key derivation to obtain both :math:`\mathsf{esk}` and -:math:`\mathsf{rcm}\!`. +concerns by using a key derivation to obtain both $\mathsf{esk}$ and +$\mathsf{rcm}$. Specification @@ -121,17 +121,17 @@ Specification Please note that prior versions of the protocol specification (2022.3.8 and earlier) were inconsistent with this ZIP regarding the - domain separators for :math:`\mathsf{PRF^{expand}}` used to derive - :math:`\mathsf{rcm}` and :math:`\mathsf{esk}\!`. The protocol + domain separators for $\mathsf{PRF^{expand}}$ used to derive + $\mathsf{rcm}$ and $\mathsf{esk}$. The protocol specification diverged from the deployed implementations for Sapling, and this ZIP previously (before December 2023) diverged from the deployed implementations for Orchard. Pseudo random functions (PRFs) are defined in section 4.1.2 of the Zcash Protocol Specification [#protocol-abstractprfs]_. We will be adapting -:math:`\mathsf{PRF^{expand}}` for the purposes of this ZIP. This function is -keyed by a 256-bit key :math:`\mathsf{sk}` and takes an arbitrary length byte -sequence as input, returning a :math:`64\!`-byte sequence as output. +$\mathsf{PRF^{expand}}$ for the purposes of this ZIP. This function is +keyed by a 256-bit key $\mathsf{sk}$ and takes an arbitrary length byte +sequence as input, returning a $64$-byte sequence as output. Changes to Sapling and Orchard Note plaintexts ---------------------------------------------- @@ -139,22 +139,22 @@ Changes to Sapling and Orchard Note plaintexts Note plaintext encodings are specified in section 5.5 of the Zcash Protocol Specification [#protocol-notept]_. Before activation of this ZIP, the encoding of a Sapling note plaintext required that the first byte take the form -:math:`\mathtt{0x01}\!`, indicating the version of the note plaintext. In -addition, a :math:`256\!`-bit :math:`\mathsf{rcm}` field exists within the +$\mathtt{0x01}$, indicating the version of the note plaintext. In +addition, a $256$-bit $\mathsf{rcm}$ field exists within the note plaintext and encoding. Following the activation of this ZIP, senders of Sapling or Orchard notes MUST use the following note plaintext format: -* The first byte of the encoding MUST take the form :math:`\mathtt{0x02}` +* The first byte of the encoding MUST take the form $\mathtt{0x02}$ (representing the new note plaintext version). -* The field :math:`\mathsf{rcm}` of the encoding is renamed to - :math:`\mathsf{rseed}\!`. This field :math:`\mathsf{rseed}` of the Sapling +* The field $\mathsf{rcm}$ of the encoding is renamed to + $\mathsf{rseed}$. This field $\mathsf{rseed}$ of the Sapling or Orchard note plaintext no longer takes the type of - :math:`\mathsf{NoteCommit.Trapdoor}` (as it did for Sapling) but instead - is a :math:`32\!`-byte sequence. + $\mathsf{NoteCommit.Trapdoor}$ (as it did for Sapling) but instead + is a $32$-byte sequence. -The requirement that the former :math:`\mathsf{rcm}` field be a scalar of the +The requirement that the former $\mathsf{rcm}$ field be a scalar of the Jubjub elliptic curve, when interpreted as a little endian integer, is removed from descriptions of note plaintexts in the Zcash Protocol Specification. @@ -166,34 +166,34 @@ Protocol Specification for Sapling [#protocol-saplingsend]_ and section 4.7.3 for Orchard [#protocol-orchardsend]_. In addition, the process of encrypting a note is described in section 4.19.1 of the Zcash Protocol Specification [#protocol-saplingandorchardencrypt]_. Prior to activation of this ZIP, the -sender sampled :math:`\mathsf{rcm^{new}}` and the ephemeral private key -:math:`\mathsf{esk}` uniformly at random during this process. +sender sampled $\mathsf{rcm^{new}}$ and the ephemeral private key +$\mathsf{esk}$ uniformly at random during this process. After the activation of this ZIP, the sender MUST instead sample a uniformly -random :math:`32\!`-byte sequence :math:`\mathsf{rseed}\!`. The note plaintext takes -:math:`\mathsf{rseed}` in place of :math:`\mathsf{rcm^{new}}\!`. +random $32$-byte sequence $\mathsf{rseed}$. The note plaintext takes +$\mathsf{rseed}$ in place of $\mathsf{rcm^{new}}$. For Sapling: -* :math:`\mathsf{rcm^{new}}` MUST be derived as the output of - :math:`\mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([4]))\!`. -* :math:`\mathsf{esk}` MUST be derived as the output of - :math:`\mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([5]))\!`. +* $\mathsf{rcm^{new}}$ MUST be derived as the output of + $\mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([4]))$. +* $\mathsf{esk}$ MUST be derived as the output of + $\mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([5]))$. For Orchard: -* :math:`\mathsf{rcm^{new}}` MUST be derived as the output of - :math:`\mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([5] \,||\, \underline{\text{ρ}}))\!`. -* :math:`\mathsf{esk}` MUST be derived as the output of - :math:`\mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([4] \,||\, \underline{\text{ρ}}))\!`. -* :math:`\text{φ}` MUST be derived as the output of - :math:`\mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([9] \,||\, \underline{\text{ρ}}))\!`. +* $\mathsf{rcm^{new}}$ MUST be derived as the output of + $\mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([5] \,||\, \underline{\text{ρ}}))$. +* $\mathsf{esk}$ MUST be derived as the output of + $\mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([4] \,||\, \underline{\text{ρ}}))$. +* $\text{φ}$ MUST be derived as the output of + $\mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([9] \,||\, \underline{\text{ρ}}))$. -where :math:`\underline{\text{ρ}} = \mathsf{I2LEOSP}_{256}(\mathsf{nf^{old}}` from the same Action description :math:`\!)\!`. +where $\underline{\text{ρ}} = \mathsf{I2LEOSP}_{256}(\mathsf{nf^{old}}$ from the same Action description $\!)$. .. note:: - The domain separators :math:`[4]` and :math:`[5]` used in the input to - :math:`\mathsf{PRF^{expand}_{rseed}}` are swapped for Orchard relative to + The domain separators $[4]$ and $[5]$ used in the input to + $\mathsf{PRF^{expand}_{rseed}}$ are swapped for Orchard relative to Sapling. This was due to an oversight and there is no good reason for it. The specified domain separators were corrected to match the deployed @@ -209,7 +209,7 @@ The process of receiving notes in Sapling is described in sections 4.19.2 and [#protocol-decryptovk]_ There is a "grace period" of 32256 blocks starting from the block at which this -ZIP activates, during which note plaintexts with lead byte :math:`\mathtt{0x01}` +ZIP activates, during which note plaintexts with lead byte $\mathtt{0x01}$ MUST still be accepted. Let ActivationHeight be the activation height of this ZIP, and let @@ -226,12 +226,12 @@ viewing key) is able to decrypt a note plaintext, it performs the following check on the plaintext lead byte, based on the height of the containing transaction: -* If the height is less than ActivationHeight, then only :math:`\mathtt{0x01}` +* If the height is less than ActivationHeight, then only $\mathtt{0x01}$ is accepted as the plaintext lead byte. * If the height is at least ActivationHeight and less than GracePeriodEndHeight, - then either :math:`\mathtt{0x01}` or :math:`\mathtt{0x02}` is accepted as the + then either $\mathtt{0x01}$ or $\mathtt{0x02}$ is accepted as the plaintext lead byte. -* If the height is at least GracePeriodEndHeight, then only :math:`\mathtt{0x02}` +* If the height is at least GracePeriodEndHeight, then only $\mathtt{0x02}$ is accepted as the plaintext lead byte. If the plaintext lead byte is not accepted then the note MUST be discarded. @@ -239,13 +239,13 @@ However, if an implementation decrypted the note from a mempool transaction and it was accepted at that time, but it is later mined in a block after the end of the grace period, then it MAY be retained. -A note plaintext with lead byte :math:`\mathtt{0x02}` contains a field -:math:`\mathsf{rseed}` that is a :math:`32\!`-byte sequence rather than a scalar -value :math:`\mathsf{rcm}\!`. The recipient, during decryption and in any later -contexts, will derive :math:`\mathsf{rcm}` using :math:`\mathsf{PRF^{expand}_{rseed}}` +A note plaintext with lead byte $\mathtt{0x02}$ contains a field +$\mathsf{rseed}$ that is a $32$-byte sequence rather than a scalar +value $\mathsf{rcm}$. The recipient, during decryption and in any later +contexts, will derive $\mathsf{rcm}$ using $\mathsf{PRF^{expand}_{rseed}}$ in the same way as the sender, as described in `Changes to the process of sending Sapling or Orchard notes`_. -Further, the recipient MUST derive :math:`\mathsf{esk}` as described in that -section and check that :math:`\mathsf{epk} = [\mathsf{esk}]\, \mathsf{g_d}\!`, +Further, the recipient MUST derive $\mathsf{esk}$ as described in that +section and check that $\mathsf{epk} = [\mathsf{esk}]\, \mathsf{g_d}$, failing decryption if this check is not satisfied. Consensus rule change for coinbase transactions @@ -253,14 +253,14 @@ Consensus rule change for coinbase transactions After the activation of this ZIP, any Sapling output of a coinbase transaction that is decrypted to a note plaintext as specified in [#zip-0213]_, MUST have -note plaintext lead byte equal to :math:`\mathtt{0x02}\!`. +note plaintext lead byte equal to $\mathtt{0x02}$. This applies even during the “grace period”, and also applies to funding stream outputs [#zip-0207]_ sent to shielded payment addresses, if there are any. Since NU5 activates after the end of the grace period [#zip-0252]_, Orchard outputs will always require a note plaintext lead byte equal to -:math:`\mathtt{0x02}\!`. +$\mathtt{0x02}$. Rationale @@ -276,16 +276,16 @@ Acting differently here would be confusing for users that have previously been told that "privacy does not depend on zk-SNARK soundness" or similar claims. It would have been possible to infringe on the length of the ``memo`` field and -ask the sender to provide :math:`\mathsf{esk}` within the existing note plaintext +ask the sender to provide $\mathsf{esk}$ within the existing note plaintext without modifying the transaction format, but this would have harmed users who -have come to expect a :math:`512\!`-byte memo field to be available to them. +have come to expect a $512$-byte memo field to be available to them. Changes to the memo field length should be considered in a broader context than changes made for cryptographic purposes. It would be possible to transmit a signature of knowledge of a correct -:math:`\mathsf{esk}` rather than :math:`\mathsf{esk}` itself, but this appears +$\mathsf{esk}$ rather than $\mathsf{esk}$ itself, but this appears to be an unnecessary complication and is likely slower than just supplying -:math:`\mathsf{esk}\!`. +$\mathsf{esk}$. The grace period is intended to mitigate loss-of-funds risk due to non-conformant sending wallet implementations. The intention is that during the @@ -294,13 +294,13 @@ are still sending plaintexts according to the old specification, and cajole their developers to make the required updates. For the avoidance of doubt, such wallets are non-conformant because it is a "MUST" requirement to *immediately* switch to sending note plaintexts with lead byte -:math:`\mathtt{0x02}` (and the other changes in this specification) at the +$\mathtt{0x02}$ (and the other changes in this specification) at the upgrade. Note that nodes will clear their mempools when the upgrade activates, -which will clear all plaintexts with lead byte :math:`\mathtt{0x01}` that were +which will clear all plaintexts with lead byte $\mathtt{0x01}$ that were sent conformantly and not mined before the upgrade. Historical note: in practice some note plaintexts with lead byte -:math:`\mathtt{0x01}` were non-conformantly sent even after the end of the +$\mathtt{0x01}$ were non-conformantly sent even after the end of the specified grace period. ZecWallet extended its implementation of the grace period by a further 161280 blocks (approximately 20 weeks) in order to allow for recovery of these funds [#zecwallet-grace-extension]_. @@ -315,9 +315,9 @@ assumption of the zk-SNARK. It is already assumed that the adversary cannot defeat the EC-DDH assumption of the Jubjub (or Pallas) elliptic curve, for it could perform a linkability attack trivially in that case. -In the naïve case where the protocol is modified so that :math:`\mathsf{esk}` +In the naïve case where the protocol is modified so that $\mathsf{esk}$ is supplied directly to the recipient (rather than derived through -:math:`\mathsf{rseed}\!`) this would lead to an instance of key-dependent +$\mathsf{rseed}$) this would lead to an instance of key-dependent encryption, which is difficult or perhaps impossible to prove secure using existing security notions. Our approach of using a key derivation, which ultimately queries an oracle, allows a proof for IND-CCA2 security to be diff --git a/zips/zip-0215.rst b/zips/zip-0215.rst index 25b282269..f90cdbfd1 100644 --- a/zips/zip-0215.rst +++ b/zips/zip-0215.rst @@ -56,24 +56,24 @@ signatures, as is the case for RedJubjub. Specification ============= -After activation of this ZIP, the :math:`\mathsf{JoinSplitSig}` validation rules +After activation of this ZIP, the $\mathsf{JoinSplitSig}$ validation rules in [#protocol-concreteed25519]_ are changed to the following: -- :math:`\underline{A}` and :math:`\underline{R}` MUST be encodings of points - :math:`A` and :math:`R` respectively on the complete twisted Edwards curve Ed25519; -- :math:`\underline{S}` MUST represent an integer :math:`S` less than :math:`\ell`; -- The group equation :math:`[8][S]B = [8]R + [8][k]A` MUST be satisfied, where - :math:`k` and :math:`B` are defined as in RFC 8032 sections §5.1.7 and §5.1 +- $\underline{A}$ and $\underline{R}$ MUST be encodings of points + $A$ and $R$ respectively on the complete twisted Edwards curve Ed25519; +- $\underline{S}$ MUST represent an integer $S$ less than $\ell$; +- The group equation $[8][S]B = [8]R + [8][k]A$ MUST be satisfied, where + $k$ and $B$ are defined as in RFC 8032 sections §5.1.7 and §5.1 respectively. [#RFC8032]_ -The language about :math:`\mathsf{ExcludedPointEncodings}` in §5.4.5 of the Zcash +The language about $\mathsf{ExcludedPointEncodings}$ in §5.4.5 of the Zcash specification [#protocol-concreteed25519]_ no longer applies. -It is *not* required that :math:`\underline{A}` and :math:`\underline{R}` +It is *not* required that $\underline{A}$ and $\underline{R}$ are canonical encodings; in other words, the integer encoding the -:math:`y`-coordinate of the points may be unreduced modulo :math:`2^{255}-19`. +$y$-coordinate of the points may be unreduced modulo $2^{255}-19$. -Note: the alternate validation equation :math:`[S]B = R + [k]A`, allowed +Note: the alternate validation equation $[S]B = R + [k]A$, allowed by RFC 8032, MUST NOT be used. diff --git a/zips/zip-0216.rst b/zips/zip-0216.rst index c2aa86548..55d9b17b3 100644 --- a/zips/zip-0216.rst +++ b/zips/zip-0216.rst @@ -39,7 +39,7 @@ modelled with just the abstract types. The intention of the Jubjub implementation (both in the `jubjub` crate [#jubjub-crate]_ and its prior implementations) was to ensure that only canonical point encodings would be accepted by the decoding logic. However, an oversight in the implementation allowed an -edge case to slip through: for each point on the curve where the :math:`u\!`-coordinate is +edge case to slip through: for each point on the curve where the $u$-coordinate is zero, there are two encodings that will be accepted: .. code-block:: rust @@ -51,13 +51,13 @@ zero, there are two encodings that will be accepted: This code accepts either sign bit, because ``u_negated == u``. -There are two points on the Jubjub curve with :math:`u\!`-coordinate zero: +There are two points on the Jubjub curve with $u$-coordinate zero: -- :math:`(0, 1)`, which is the identity; -- :math:`(0, -1)`, which is a point of order two. +- $(0, 1)$, which is the identity; +- $(0, -1)$, which is a point of order two. Each of these has a single non-canonical encoding in which the value of the sign bit is -:math:`1`. +$1$. This creates a consensus issue because (unlike other non-canonical point encodings that are rejected) either of the above encodings can be decoded, and then re-encoded to a @@ -79,39 +79,39 @@ required 4 specification revisions to get right, conclusively demonstrates the p Specification ============= -Let :math:`\mathsf{abst}_{\mathbb{J}}`, :math:`\mathsf{repr}_{\mathbb{J}}`, and -:math:`q_{\mathbb{J}}` be as defined in [#protocol-jubjub]_. +Let $\mathsf{abst}_{\mathbb{J}}$, $\mathsf{repr}_{\mathbb{J}}$, and +$q_{\mathbb{J}}$ be as defined in [#protocol-jubjub]_. Define a non-canonical compressed encoding of a Jubjub point to be a sequence of -:math:`256` bits, :math:`b`, such that :math:`\mathsf{abst}_{\mathbb{J}}(b) \neq \bot` -and :math:`\mathsf{repr_{\mathbb{J}}}\big(\mathsf{abst}_{\mathbb{J}}(b)\big) \neq b`. +$256$ bits, $b$, such that $\mathsf{abst}_{\mathbb{J}}(b) \neq \bot$ +and $\mathsf{repr_{\mathbb{J}}}\big(\mathsf{abst}_{\mathbb{J}}(b)\big) \neq b$. Non-normative note: There are two such bit sequences, -:math:`\mathsf{I2LEOSP}_{\ell_{\mathbb{J}}}(2^{255} + 1)` and -:math:`\mathsf{I2LEOSP}_{\ell_{\mathbb{J}}}(2^{255} + q_{\mathbb{J}} - 1)`. +$\mathsf{I2LEOSP}_{\ell_{\mathbb{J}}}(2^{255} + 1)$ and +$\mathsf{I2LEOSP}_{\ell_{\mathbb{J}}}(2^{255} + q_{\mathbb{J}} - 1)$. The Sapling protocol uses little-endian ordering when converting between bit and -byte sequences, so the first of these sequences corresponds to a :math:`\mathtt{0x01}` -byte, followed by :math:`30` zero bytes, and then a :math:`\mathtt{0x80}` byte. +byte sequences, so the first of these sequences corresponds to a $\mathtt{0x01}$ +byte, followed by $30$ zero bytes, and then a $\mathtt{0x80}$ byte. Once this ZIP activates, the following places within the Sapling consensus protocol where Jubjub points occur MUST reject non-canonical Jubjub point encodings. In Sapling Spend descriptions [#protocol-spenddesc]_: - - the :math:`\underline{R}` component (i.e. the first :math:`32` bytes) of the - :math:`\mathtt{spendAuthSig}` RedDSA signature. + - the $\underline{R}$ component (i.e. the first $32$ bytes) of the + $\mathtt{spendAuthSig}$ RedDSA signature. In transactions [#protocol-txnencoding]_: - - the :math:`\underline{R}` component (i.e. the first :math:`32` bytes) of the - :math:`\mathtt{bindingSigSapling}` RedDSA signature. + - the $\underline{R}$ component (i.e. the first $32$ bytes) of the + $\mathtt{bindingSigSapling}$ RedDSA signature. -In the plaintext obtained by decrypting the :math:`\mathsf{C^{out}}` field of a +In the plaintext obtained by decrypting the $\mathsf{C^{out}}$ field of a Sapling transmitted note ciphertext [#protocol-decryptovk]_: - - :math:`\mathsf{pk}\star_{\mathsf{d}}`. + - $\mathsf{pk}\star_{\mathsf{d}}$. -(This affects decryption of :math:`\mathsf{C^{out}}` in all cases, but is +(This affects decryption of $\mathsf{C^{out}}$ in all cases, but is consensus-critical only in the case of a shielded coinbase output. [#protocol-txnencoding]_) @@ -121,13 +121,13 @@ existing consensus rules. In Sapling Spend descriptions: - - :math:`\mathtt{cv}` - - :math:`\mathtt{rk}` + - $\mathtt{cv}$ + - $\mathtt{rk}$ In Sapling Output descriptions [#protocol-outputdesc]_: - - :math:`\mathtt{cv}` - - :math:`\mathtt{ephemeralKey}`. + - $\mathtt{cv}$ + - $\mathtt{ephemeralKey}$. These fields cannot by consensus contain small-order points. All of the points with non-canonical encodings are small-order. @@ -140,19 +140,19 @@ transaction IDs. In addition, Sapling addresses and full viewing keys MUST be considered invalid when imported if they contain non-canonical Jubjub point encodings, or encodings of points -that are not in the prime-order subgroup :math:`\mathbb{J}^{(r)}`. These requirements +that are not in the prime-order subgroup $\mathbb{J}^{(r)}$. These requirements \MAY be enforced in advance of NU5 activation. In Sapling addresses [#protocol-saplingpaymentaddrencoding]_: - - the encoding of :math:`\mathsf{pk_d}`. + - the encoding of $\mathsf{pk_d}$. In Sapling full viewing keys [#protocol-saplingfullviewingkeyencoding]_ and extended full viewing keys [#zip-0032-extfvk]_: - - the encoding of :math:`\mathsf{ak}`. + - the encoding of $\mathsf{ak}$. -(:math:`\mathsf{ak}` also MUST NOT encode the zero point :math:`\mathcal{O}_{\mathbb{J}}`.) +($\mathsf{ak}$ also MUST NOT encode the zero point $\mathcal{O}_{\mathbb{J}}$.) The above is intended to be a complete list of the places where compressed encodings of Jubjub points occur in the Zcash consensus protocol and in plaintext, address, or @@ -180,16 +180,16 @@ In Sapling, we are motivated instead to reject these non-canonical points: The necessary checks are very simple and do not require cryptographic operations, therefore the performance impact will be negligible. -The public inputs of Jubjub points to the Spend circuit (:math:`\mathsf{rk}` and -:math:`\mathsf{cv^{old}}`) and Output circuit (:math:`\mathsf{cv^{new}}` and -:math:`\mathsf{epk}`) are not affected because they are represented in affine +The public inputs of Jubjub points to the Spend circuit ($\!\mathsf{rk}$ and +$\mathsf{cv^{old}}$) and Output circuit ($\!\mathsf{cv^{new}}$ and +$\mathsf{epk}$) are not affected because they are represented in affine coordinates as elements of the correct field -(:math:`\mathbb{F}_{r_\mathbb{S}} = \mathbb{F}_{q_\mathbb{J}}`), +($\!\mathbb{F}_{r_\mathbb{S}} = \mathbb{F}_{q_\mathbb{J}}$), and so no issue of encoding canonicity arises. -Encodings of elliptic curve points on Curve25519, BN-254 :math:`\mathbb{G}_1`, -BN-254 :math:`\mathbb{G}_2`, BLS12-381 :math:`\mathbb{G}_1`, and -BLS12-381 :math:`\mathbb{G}_2` are not affected. +Encodings of elliptic curve points on Curve25519, BN-254 $\mathbb{G}_1$, +BN-254 $\mathbb{G}_2$, BLS12-381 $\mathbb{G}_1$, and +BLS12-381 $\mathbb{G}_2$ are not affected. Encodings of elliptic curve points on the Pallas and Vesta curves in the NU5 proposal [#protocol-pallasandvesta]_ are also not affected. diff --git a/zips/zip-0221.rst b/zips/zip-0221.rst index 74b42e15e..ab8d61a38 100644 --- a/zips/zip-0221.rst +++ b/zips/zip-0221.rst @@ -26,12 +26,12 @@ interpreted as described in ZIP 200. [#zip-0200]_ receive payments, but does not store or validate a copy of the block chain. *High probability* - An event occurs with high probability if it occurs with probability :math:`1-O(1/2^\lambda)`, - where :math:`\lambda` is a security parameter. + An event occurs with high probability if it occurs with probability $1-O(1/2^\lambda)$, + where $\lambda$ is a security parameter. *Negligible probability* - An event occurs with negligible probability if it occurs with probability :math:`O(1/2^\lambda)`, - where :math:`\lambda` is the security parameter. + An event occurs with negligible probability if it occurs with probability $O(1/2^\lambda)$, + where $\lambda$ is the security parameter. *Merkle mountain range (MMR)* A Merkle mountain range (MMR) is a binary hash tree that allows for efficient appends of @@ -53,9 +53,9 @@ Background An MMR is a Merkle tree which allows for efficient appends, proofs, and verifications. Informally, appending data to an MMR consists of creating a new leaf and then iteratively -merging neighboring subtrees with the same size. This takes at most :math:`\log(n)` operations +merging neighboring subtrees with the same size. This takes at most $\log(n)$ operations and only requires knowledge of the previous subtree roots, of which there are fewer than -:math:`\log(n)`. +$\log(n)$. (example adapted from [#mimblewimble]_) To illustrate this, consider a list of 11 leaves. We first construct the biggest perfect @@ -96,9 +96,9 @@ and represent this numbering in a flat list: | Altitude | 0 | 0 | 1 | 0 | 0 | 1 | 2 | 0 | 0 | 1 | 0 | 0 | 1 | 2 | 3 | 0 | 0 | 1 | 0 | +----------+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ -Let :math:`h` be the altitude of a given node. We can easily jump to the node's right -sibling (if it has one) by adding :math:`2^{h+1} - 1` to its position, and its left child -(if it has one) by subtracting :math:`2^h`. This allows us to efficiently find the subtree +Let $h$ be the altitude of a given node. We can easily jump to the node's right +sibling (if it has one) by adding $2^{h+1} - 1$ to its position, and its left child +(if it has one) by subtracting $2^h$. This allows us to efficiently find the subtree roots ("peaks") of the mountains. Once we have the positions of the mountain peaks, we "bag" them using the following @@ -144,14 +144,14 @@ MMR proofs are used in the FlyClient protocol [#FlyClient]_, to reduce the proof needed for light clients to verify: - the validity of a block chain received from a full node, and -- the inclusion of a block :math:`B` in that chain, and +- the inclusion of a block $B$ in that chain, and - certain metadata of any block or range of blocks in that chain. The protocol requires that an MMR that commits to the inclusion of all blocks since the -preceding network upgrade :math:`(B_x, \ldots, B_{n-1})` is formed for each block :math:`B_n`. -The root :math:`M_n` of the MMR MUST be included in the header of :math:`B_n`. +preceding network upgrade $(B_x, \ldots, B_{n-1})$ is formed for each block $B_n$. +The root $M_n$ of the MMR MUST be included in the header of $B_n$. -(:math:`x` is the activation height of the preceding network upgrade.) +($\!x$ is the activation height of the preceding network upgrade.) FlyClient reduces the number of block headers needed for light client verification of a valid chain, from linear (as in the current reference protocol) to logarithmic in @@ -169,14 +169,14 @@ devices. Specification ============= -For a block :math:`B_n` at height :math:`n > 0` in a given block chain, define the -"preceding network upgrade height" :math:`x` of :math:`B_n` to be the last network -upgrade activation height in the chain that is less than :math:`n`. (For this definition, -block height :math:`0` is considered to be the height of a network upgrade activation. +For a block $B_n$ at height $n > 0$ in a given block chain, define the +"preceding network upgrade height" $x$ of $B_n$ to be the last network +upgrade activation height in the chain that is less than $n$. (For this definition, +block height $0$ is considered to be the height of a network upgrade activation. The preceding network upgrade height of the genesis block is undefined.) -The leaves of the MMR at block :math:`B_n` are hash commitments to the header data -and metadata of each previous block :math:`B_x, \ldots, B_{n-1}`, where :math:`x` +The leaves of the MMR at block $B_n$ are hash commitments to the header data +and metadata of each previous block $B_x, \ldots, B_{n-1}$, where $x$ is defined as above. We extend the standard MMR to allow metadata to propagate upwards through the tree by either summing the metadata of both children, or inheriting the metadata of a specific child as necessary. This allows us to create efficient proofs @@ -202,8 +202,8 @@ Each MMR node is defined as follows: * This hash is encoded in internal byte order, and does NOT use the BLAKE2b-256 personalization string described above. * For clarity, in a given consensus branch, the ``hashSubtreeCommitment`` field - of leaf :math:`n-1` is *precisely equal* to the ``hashPrevBlock`` field in the - header of the block at height :math:`x+n`, where :math:`x` is the network + of leaf $n-1$ is *precisely equal* to the ``hashPrevBlock`` field in the + header of the block at height $x+n$, where $x$ is the network upgrade activation height of that consensus branch. Internal or root node @@ -285,16 +285,16 @@ Each MMR node is defined as follows: Leaf node The protocol-defined work of the block: - :math:`\mathsf{floor}(2^{256} / (\mathsf{ToTarget}(\mathsf{nBits}) + 1))`. [#protocol-workdef]_ + $\mathsf{floor}(2^{256} / (\mathsf{ToTarget}(\mathsf{nBits}) + 1))$. [#protocol-workdef]_ Internal or root node The sum of the ``nSubTreeTotalWork`` fields of both children. - Computations modulo :math:`2^{256}` are fine here; cumulative chain work is similarly - assumed elsewhere in the Zcash ecosystem to be at most :math:`2^{256}` (as inherited + Computations modulo $2^{256}$ are fine here; cumulative chain work is similarly + assumed elsewhere in the Zcash ecosystem to be at most $2^{256}$ (as inherited from Bitcoin). The computed work factors are, on average, equal to the computational efforts involved in the creation of the corresponding blocks, and an aggregate effort - of :math:`2^{256}` or more is infeasible in practice. + of $2^{256}$ or more is infeasible in practice. Serialized as ``uint256``. @@ -480,8 +480,8 @@ Tree nodes and hashing (pseudocode) Incremental push and pop (pseudocode) ------------------------------------- -With each new block :math:`B_n`, we append a new MMR leaf node corresponding to block -:math:`B_{n-1}`. The ``append`` operation is detailed below in pseudocode (adapted from +With each new block $B_n$, we append a new MMR leaf node corresponding to block +$B_{n-1}$. The ``append`` operation is detailed below in pseudocode (adapted from [#FlyClient]_): .. code-block:: python @@ -541,7 +541,7 @@ With each new block :math:`B_n`, we append a new MMR leaf node corresponding to return bag_peaks(merged[::-1]) In case of a block reorg, we have to delete the latest (i.e. rightmost) MMR leaf nodes, up -to the reorg length. This operation is :math:`O(\log(k))` where :math:`k` is the number of leaves +to the reorg length. This operation is $O(\log(k))$ where $k$ is the number of leaves in the right subtree of the MMR root. .. code-block:: python @@ -588,8 +588,8 @@ in [#zip-0244]_.) Prior to activation of the network upgrade that deploys this ZIP, this existing consensus rule on block headers (adjusted for the renamed field) is enforced: [#protocol-blockheader]_ - [Sapling onward] ``hashLightClientRoot`` MUST be :math:`\mathsf{LEBS2OSP}_{256}(\mathsf{rt})` - where :math:`\mathsf{rt}` is the root of the Sapling note commitment tree for the final + [Sapling onward] ``hashLightClientRoot`` MUST be $\mathsf{LEBS2OSP}_{256}(\mathsf{rt})$ + where $\mathsf{rt}$ is the root of the Sapling note commitment tree for the final Sapling tree state of this block. In the block that activates this ZIP, ``hashLightClientRoot`` MUST be set to all zero bytes. @@ -672,7 +672,7 @@ inclusion in a future upgrade. * This commitment serves the same purpose as ``hashFinalSaplingRoot`` in current Sapling semantics. - * However, because the MMR tree commits to blocks :math:`B_x \ldots B_{n-1}`, the latest + * However, because the MMR tree commits to blocks $B_x \ldots B_{n-1}$, the latest commitment will describe the final treestate of the previous block, rather than the current block. * Concretely: block 500 currently commits to the final treestate of block 500 in its @@ -744,7 +744,7 @@ implementation that would join these commitments, but it is clearly not appropri Zcash as it exists. The calculation of ``hashChainHistoryRoot`` is not well-defined for the genesis block, -since then :math:`n = 0` and there is no block :math:`B_{n-1}`. Also, in the case of +since then $n = 0$ and there is no block $B_{n-1}$. Also, in the case of chains that activate this ZIP after genesis (including Zcash Mainnet and Testnet), the ``hashChainHistoryRoot`` of the activation block would commit to the whole previous epoch if a special case were not made. It would be impractical to calculate this commitment all diff --git a/zips/zip-0224.rst b/zips/zip-0224.rst index b3b75fa32..450b8118a 100644 --- a/zips/zip-0224.rst +++ b/zips/zip-0224.rst @@ -92,7 +92,7 @@ embedded curve Jubjub: - Vesta is used as the "circuit curve"; its scalar field (being the base field of Pallas) is the "word" type over which the circuit is implemented (c/f BLS12-381). -We use the "simplified SWU" algorithm to define an infallible :math:`\mathsf{GroupHash}`, +We use the "simplified SWU" algorithm to define an infallible $\mathsf{GroupHash}$, instead of the fallible BLAKE2s-based mechanism used for Sapling. It is intended to follow (version 10 of) the IETF hash-to-curve Internet Draft [#ietf-hash-to-curve]_ (but the protocol specification takes precedence in the case of any discrepancy). @@ -102,7 +102,7 @@ of the cycle (Pallas being an embedded curve of Vesta); the full cycle is expect leveraged by future protocol updates. - Curve specifications: [#protocol-pallasandvesta]_ -- :math:`\mathsf{GroupHash}`: [#protocol-concretegrouphashpallasandvesta]_ +- $\mathsf{GroupHash}$: [#protocol-concretegrouphashpallasandvesta]_ - Supporting evidence: [#pasta-evidence]_ Proving system @@ -153,11 +153,11 @@ Keys and addresses Orchard keys and payment addresses are structurally similar to Sapling, with the following changes: -- The proof authorizing key is removed, and :math:`\mathsf{nk}` is now a field element. -- :math:`\mathsf{ivk}` is computed as a Sinsemilla commitment instead of a BLAKE2s output. - There is an additional :math:`\mathsf{rivk}` component of the full viewing key that acts +- The proof authorizing key is removed, and $\mathsf{nk}$ is now a field element. +- $\mathsf{ivk}$ is computed as a Sinsemilla commitment instead of a BLAKE2s output. + There is an additional $\mathsf{rivk}$ component of the full viewing key that acts as the randomizer for this commitment. -- :math:`\mathsf{ovk}` is derived from :math:`\mathsf{fvk}`, instead of being a component +- $\mathsf{ovk}$ is derived from $\mathsf{fvk}$, instead of being a component of the spending key. - All diversifiers now result in valid payment addresses. @@ -180,9 +180,9 @@ derivation mechanism (similar to Sprout). Notes ----- -Orchard notes have the structure :math:`(addr, v, \rho, \psi, \mathsf{rcm}).` :math:`\rho` +Orchard notes have the structure $(addr, v, \text{ρ}, \text{φ}, \mathsf{rcm}).$ $\text{ρ}$ is set to the nullifier of the spent note in the same action, which ensures it is unique. -:math:`\psi` and :math:`\mathsf{rcm}` are derived from a random seed (as with Sapling +$\text{φ}$ and $\mathsf{rcm}$ are derived from a random seed (as with Sapling after ZIP 212 [#zip-0212]_). - Orchard notes: [#protocol-notes]_ @@ -192,9 +192,9 @@ Nullifiers Nullifiers for Orchard notes are computed as: -:math:`\mathsf{nf} = [F_{\mathsf{nk}}(\rho) + \psi \pmod{p}] \mathcal{G} + \mathsf{cm}` +$\mathsf{nf} = [F_{\mathsf{nk}}(\text{ρ}) + \text{φ} \pmod{p}] \,\mathcal{G} + \mathsf{cm}$ -where :math:`F` is instantiated with Poseidon, and :math:`\mathcal{G}` is a fixed +where $F$ is instantiated with Poseidon, and $\mathcal{G}$ is a fixed independent base. - Poseidon: [#protocol-poseidonhash]_ @@ -234,14 +234,14 @@ Security and Privacy Considerations This ZIP defines a new shielded pool. As with Sapling, the Orchard protocol only supports spending Orchard notes, and moving ZEC into or out of the Orchard pool happens via the -:math:`\mathsf{valueBalanceOrchard}` transaction field. This has the following +$\mathsf{valueBalanceOrchard}$ transaction field. This has the following considerations: - The Orchard pool forms a separate anonymity set from the Sprout and Sapling pools. The new pool will start with zero notes (as Sapling did at its deployment), but transactions within Orchard will increase the size of the anonymity set more rapidly than Sapling, due to the arity-hiding nature of Orchard actions. -- The "transparent turnstile" created by the :math:`\mathsf{valueBalanceOrchard}` field, +- The "transparent turnstile" created by the $\mathsf{valueBalanceOrchard}$ field, combined with the consensus checks that each pool's balance cannot be negative, together enforce that any potential counterfeiting bugs in the Orchard protocol or implementation are contained within the Orchard pool, and similarly any potential counterfeiting bugs diff --git a/zips/zip-0225.rst b/zips/zip-0225.rst index a4bf7ce9e..c0b84b6c8 100644 --- a/zips/zip-0225.rst +++ b/zips/zip-0225.rst @@ -145,7 +145,7 @@ Transaction Format |``1`` |``flagsOrchard`` |``byte`` |An 8-bit value representing a set of flags. Ordered from LSB to MSB: | | | | | * ``enableSpendsOrchard`` | | | | | * ``enableOutputsOrchard`` | -| | | | * The remaining bits are set to ``0``. | +| | | | * The remaining bits are set to :math:`0\!`. | +-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+ |``8`` |``valueBalanceOrchard`` |``int64`` |The net value of Orchard spends minus outputs. | +-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+ @@ -153,7 +153,7 @@ Transaction Format | | | |height in the past. | +-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+ |``varies`` |``sizeProofsOrchard`` |``compactSize`` |Length in bytes of ``proofsOrchard``. Value is | -| | | |:math:`2720 + 2272 \cdot \mathtt{nActionsOrchard}`. | +| | | |:math:`2720 + 2272 \cdot \mathtt{nActionsOrchard}\!`. | +-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+ |``sizeProofsOrchard`` |``proofsOrchard`` |``byte[sizeProofsOrchard]`` |Encoding of aggregated zk-SNARK proofs for Orchard Actions. | +-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+ @@ -163,15 +163,15 @@ Transaction Format +-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+ * The fields ``valueBalanceSapling`` and ``bindingSigSapling`` are present if and only if - :math:`\mathtt{nSpendsSapling} + \mathtt{nOutputsSapling} > 0`. If ``valueBalanceSapling`` - is not present, then :math:`\mathsf{v^{balanceSapling}}`` is defined to be 0. + $\mathtt{nSpendsSapling} + \mathtt{nOutputsSapling} > 0$. If ``valueBalanceSapling`` + is not present, then $\mathsf{v^{balanceSapling}}$ is defined to be $0$. -* The field ``anchorSapling`` is present if and only if :math:`\mathtt{nSpendsSapling} > 0`. +* The field ``anchorSapling`` is present if and only if $\mathtt{nSpendsSapling} > 0$. * The fields ``flagsOrchard``, ``valueBalanceOrchard``, ``anchorOrchard``, ``sizeProofsOrchard``, ``proofsOrchard``, and ``bindingSigOrchard`` are present if and - only if :math:`\mathtt{nActionsOrchard} > 0`. If ``valueBalanceOrchard`` is not present, - then :math:`\mathsf{v^{balanceOrchard}}` is defined to be 0. + only if $\mathtt{nActionsOrchard} > 0$. If ``valueBalanceOrchard`` is not present, + then $\mathsf{v^{balanceOrchard}}$ is defined to be $0$. * The elements of ``vSpendProofsSapling`` and ``vSpendAuthSigsSapling`` have a 1:1 correspondence to the elements of ``vSpendsSapling`` and MUST be ordered such that the @@ -187,7 +187,7 @@ Transaction Format ``vActionsOrchard`` and MUST be ordered such that the proof or signature at a given index corresponds to the ``OrchardAction`` at the same index. -* For coinbase transactions, the ``enableSpendsOrchard`` bit MUST be set to ``0``. +* For coinbase transactions, the ``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`` @@ -216,21 +216,20 @@ and Consensus’ of the Zcash Protocol Specification [#protocol-spenddesc]_. Sapling Output Description (``OutputDescriptionV5``) ---------------------------------------------------- -+-----------------------------+--------------------------+--------------------------------------+------------------------------------------------------------+ -| Bytes | Name | Data Type | Description | -+=============================+==========================+======================================+============================================================+ -|``32`` |``cv`` |``byte[32]`` |A value commitment to the net value of the output note. | -+-----------------------------+--------------------------+--------------------------------------+------------------------------------------------------------+ -|``32`` |``cmu`` |``byte[32]`` |The u-coordinate of the note commitment for the output note.| -+-----------------------------+--------------------------+--------------------------------------+------------------------------------------------------------+ -|``32`` |``ephemeralKey`` |``byte[32]`` |An encoding of an ephemeral Jubjub public key. | -+-----------------------------+--------------------------+--------------------------------------+------------------------------------------------------------+ -|``580`` |``encCiphertext`` |``byte[580]`` |The encrypted contents of the note plaintext. | -+-----------------------------+--------------------------+--------------------------------------+------------------------------------------------------------+ -|``80`` |``outCiphertext`` |``byte[80]`` |The encrypted contents of the byte string created by | -| | | |concatenation of the transmission key with the ephemeral | -| | | |secret key. | -+-----------------------------+--------------------------+--------------------------------------+------------------------------------------------------------+ ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +| Bytes | Name | Data Type | Description | ++=============================+==========================+======================================+======================================================================+ +|``32`` |``cv`` |``byte[32]`` |A value commitment to the net value of the output note. | ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +|``32`` |``cmu`` |``byte[32]`` |The :math:`u\!`-coordinate of the note commitment for the output note.| ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +|``32`` |``ephemeralKey`` |``byte[32]`` |An encoding of an ephemeral Jubjub public key. | ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +|``580`` |``encCiphertext`` |``byte[580]`` |The encrypted contents of the note plaintext. | ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +|``80`` |``outCiphertext`` |``byte[80]`` |The encrypted contents of the byte string created by concatenation of | +| | | |the transmission key with the ephemeral secret key. | ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ The encodings of each of these elements are defined in §7.4 ‘Output Description Encoding and Consensus’ of the Zcash Protocol Specification [#protocol-outputdesc]_. @@ -238,27 +237,26 @@ and Consensus’ of the Zcash Protocol Specification [#protocol-outputdesc]_. Orchard Action Description (``OrchardAction``) ---------------------------------------------- -+-----------------------------+--------------------------+--------------------------------------+------------------------------------------------------------+ -| Bytes | Name | Data Type | Description | -+=============================+==========================+======================================+============================================================+ -|``32`` |``cv`` |``byte[32]`` |A value commitment to the net value of the input note minus | -| | | |the output note. | -+-----------------------------+--------------------------+--------------------------------------+------------------------------------------------------------+ -|``32`` |``nullifier`` |``byte[32]`` |The nullifier of the input note. | -+-----------------------------+--------------------------+--------------------------------------+------------------------------------------------------------+ -|``32`` |``rk`` |``byte[32]`` |The randomized validating key for the element of | -| | | |spendAuthSigsOrchard corresponding to this Action. | -+-----------------------------+--------------------------+--------------------------------------+------------------------------------------------------------+ -|``32`` |``cmx`` |``byte[32]`` |The x-coordinate of the note commitment for the output note.| -+-----------------------------+--------------------------+--------------------------------------+------------------------------------------------------------+ -|``32`` |``ephemeralKey`` |``byte[32]`` |An encoding of an ephemeral Pallas public key | -+-----------------------------+--------------------------+--------------------------------------+------------------------------------------------------------+ -|``580`` |``encCiphertext`` |``byte[580]`` |The encrypted contents of the note plaintext. | -+-----------------------------+--------------------------+--------------------------------------+------------------------------------------------------------+ -|``80`` |``outCiphertext`` |``byte[80]`` |The encrypted contents of the byte string created by | -| | | |concatenation of the transmission key with the ephemeral | -| | | |secret key. | -+-----------------------------+--------------------------+--------------------------------------+------------------------------------------------------------+ ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +| Bytes | Name | Data Type | Description | ++=============================+==========================+======================================+======================================================================+ +|``32`` |``cv`` |``byte[32]`` |A value commitment to the net value of the input note minus the | +| | | |output note. | ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +|``32`` |``nullifier`` |``byte[32]`` |The nullifier of the input note. | ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +|``32`` |``rk`` |``byte[32]`` |The randomized validating key for the element of | +| | | |spendAuthSigsOrchard corresponding to this Action. | ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +|``32`` |``cmx`` |``byte[32]`` |The :math:`x\!`-coordinate of the note commitment for the output note.| ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +|``32`` |``ephemeralKey`` |``byte[32]`` |An encoding of an ephemeral Pallas public key. | ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +|``580`` |``encCiphertext`` |``byte[580]`` |The encrypted contents of the note plaintext. | ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +|``80`` |``outCiphertext`` |``byte[80]`` |The encrypted contents of the byte string created by concatenation of | +| | | |the transmission key with the ephemeral secret key. | ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ The encodings of each of these elements are defined in §7.5 ‘Action Description Encoding and Consensus’ of the Zcash Protocol Specification [#protocol-actiondesc]_. @@ -292,23 +290,23 @@ ZIP 222 [#zip-0222]_ extension or by other means not yet determined. The original definitions for the transaction fields that have been removed are: -+-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+ -| **Sprout Transaction Fields** | -+-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+ -|``varies`` |``nJoinSplit`` |``compactSize`` |The number of JoinSplit descriptions in ``vJoinSplit``. | -+-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+ -|``1698 * nJoinSplit`` |``vJoinSplit`` |``JSDescriptionGroth16[nJoinSplit]`` |A sequence of JoinSplit descrptions using Groth16 proofs, | -| | | |encoded per §7.2 ‘JoinSplit Description Encoding and Consensus’. | -+-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+ -|``32`` |``joinSplitPubKey`` |``byte[32]`` |An encoding of a JoinSplitSig public validating key. | -+-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+ -|``64`` |``joinSplitSig`` |``byte[64]`` |A signature on a prefix of the transaction encoding, | -| | | |to be verfied using joinSplitPubKey as specified in §4.11 | -| | | |‘Non-malleability (Sprout)’. | -+-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+ ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +| **Sprout Transaction Fields** | ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +|``varies`` |``nJoinSplit`` |``compactSize`` |The number of JoinSplit descriptions in ``vJoinSplit``. | ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +|``1698 * nJoinSplit`` |``vJoinSplit`` |``JSDescriptionGroth16[nJoinSplit]`` |A sequence of JoinSplit descrptions using Groth16 proofs, | +| | | |encoded per §7.2 ‘JoinSplit Description Encoding and Consensus’. | ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +|``32`` |``joinSplitPubKey`` |``byte[32]`` |An encoding of a JoinSplitSig public validating key. | ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ +|``64`` |``joinSplitSig`` |``byte[64]`` |A signature on a prefix of the transaction encoding, | +| | | |to be verfied using joinSplitPubKey as specified in §4.11 | +| | | |‘Non-malleability (Sprout)’. | ++-----------------------------+--------------------------+--------------------------------------+----------------------------------------------------------------------+ * The ``joinSplitPubKey`` and ``joinSplitSig`` fields were specified to be - present if and only if :math:`\mathtt{nJoinSplit} > 0`. + present if and only if $\mathtt{nJoinSplit} > 0$. Reference implementation diff --git a/zips/zip-0226.rst b/zips/zip-0226.rst index 5eb080069..a31fa11a0 100644 --- a/zips/zip-0226.rst +++ b/zips/zip-0226.rst @@ -31,7 +31,7 @@ The terms "Asset", "Custom Asset" and "Wrapped Asset" in this document are to be We define the following additional terms: -- Split Input: an Action input used to ensure that the output note of that Action is of a validly issued :math:`\mathsf{AssetBase}` (see [#zip-0227-assetidentifier]_) when there is no corresponding real input note, in situations where the number of outputs are larger than the number of inputs. See formal definition in `Split Notes`_. +- Split Input: an Action input used to ensure that the output note of that Action is of a validly issued $\mathsf{AssetBase}$ (see [#zip-0227-assetidentifier]_) when there is no corresponding real input note, in situations where the number of outputs are larger than the number of inputs. See formal definition in `Split Notes`_. - Split Action: an Action that contains a Split Input. Abstract @@ -48,23 +48,23 @@ This ZIP builds on the issuance mechanism introduced in ZIP 227 [#zip-0227]_. Overview ======== -In order to be able to represent different Assets, we need to define a data field that uniquely represents the Asset in question, which we call the Asset Identifier :math:`\mathsf{AssetId}\!`. -This Asset Identifier maps to an Asset Base :math:`\mathsf{AssetBase}` that is stored in Orchard-based ZSA notes. +In order to be able to represent different Assets, we need to define a data field that uniquely represents the Asset in question, which we call the Asset Identifier $\mathsf{AssetId}$. +This Asset Identifier maps to an Asset Base $\mathsf{AssetBase}$ that is stored in Orchard-based ZSA notes. These terms are formally defined in ZIP 227 [#zip-0227]_. -The Asset Identifier (via means of the Asset Digest and Asset Base) will be used to enforce that the balance of an Action Description [#protocol-actions]_ [#protocol-actionencodingandconsensus]_ is preserved across Assets (see the Orchard Binding Signature [#protocol-orchardbalance]_), and by extension the balance of an Orchard transaction. That is, the sum of all the :math:`\mathsf{value^{net}}` from each Action Description, computed as :math:`\mathsf{value^{old}} - \mathsf{value^{new}}\!`, must be balanced **only with respect to the same Asset Identifier**. This is especially important since we will allow different Action Descriptions to transfer notes of different Asset Identifiers, where the overall balance is checked without revealing which (or how many distinct) Assets are being transferred. +The Asset Identifier (via means of the Asset Digest and Asset Base) will be used to enforce that the balance of an Action Description [#protocol-actions]_ [#protocol-actionencodingandconsensus]_ is preserved across Assets (see the Orchard Binding Signature [#protocol-orchardbalance]_), and by extension the balance of an Orchard transaction. That is, the sum of all the $\mathsf{value^{net}}$ from each Action Description, computed as $\mathsf{value^{old}} - \mathsf{value^{new}}$, must be balanced **only with respect to the same Asset Identifier**. This is especially important since we will allow different Action Descriptions to transfer notes of different Asset Identifiers, where the overall balance is checked without revealing which (or how many distinct) Assets are being transferred. -As was initially proposed by Jack Grigg and Daira-Emma Hopwood [#initial-zsa-issue]_ [#generalized-value-commitments]_, we propose to make this happen by changing the value base point, :math:`\mathcal{V}^{\mathsf{Orchard}}\!`, in the Homomorphic Pedersen Commitment that derives the value commitment, :math:`\mathsf{cv^{net}}\!`, of the *net value* in an Orchard Action. +As was initially proposed by Jack Grigg and Daira-Emma Hopwood [#initial-zsa-issue]_ [#generalized-value-commitments]_, we propose to make this happen by changing the value base point, $\mathcal{V}^{\mathsf{Orchard}}$, in the Homomorphic Pedersen Commitment that derives the value commitment, $\mathsf{cv^{net}}$, of the *net value* in an Orchard Action. Because in a single transaction all value commitments are balanced, there must be as many different value base points as there are Asset Identifiers for a given shielded protocol used in a transaction. We propose to make the Asset Base an auxiliary input to the proof for each Action statement [#protocol-actionstatement]_, represented already as a point on the Pallas curve. The circuit then should check that the same Asset Base is used in the old note commitment and the new note commitment [#protocol-concretesinsemillacommit]_, **and** as the base point in the value commitment [#protocol-concretehomomorphiccommit]_. This ensures (1) that the input and output notes are of the same Asset Base, and (2) that only Actions with the same Asset Base will balance out in the Orchard binding signature. -In order to ensure the security of the transfers, and as we will explain below, we are redefining input dummy notes [#protocol-orcharddummynotes]_ for Custom Assets, as we need to enforce that the :math:`\mathsf{AssetBase}` of the output note of that Split Action is the output of a valid :math:`\mathsf{ZSAValueBase}` computation defined in ZIP 227 [#zip-0227]_. +In order to ensure the security of the transfers, and as we will explain below, we are redefining input dummy notes [#protocol-orcharddummynotes]_ for Custom Assets, as we need to enforce that the $\mathsf{AssetBase}$ of the output note of that Split Action is the output of a valid $\mathsf{ZSAValueBase}$ computation defined in ZIP 227 [#zip-0227]_. -We include the ability to pause the ZSA functionality, via a :math:`\mathsf{enableZSA}` boolean flag. +We include the ability to pause the ZSA functionality, via a $\mathsf{enableZSA}$ boolean flag. When this flag is set to false, the proof will fail for any non-native Asset, making it impossible to perform transactions involving Custom Assets. -When this flag is set to true, the circuit will allow transactions involving Custom Assets subject to the values of the :math:`\mathsf{enableSpendsOrchard}` and :math:`\mathsf{enableOutputsOrchard}` flags, similar to the vanilla Orchard setting. +When this flag is set to true, the circuit will allow transactions involving Custom Assets subject to the values of the $\mathsf{enableSpendsOrchard}$ and $\mathsf{enableOutputsOrchard}$ flags, similar to the vanilla Orchard setting. -Finally, in this ZIP we also describe the *burn* mechanism, which is a direct extension of the transfer mechanism. The burn process uses a similar mechanism to what is used in Orchard to unshield ZEC, by using the :math:`\mathsf{valueBalance}` of the Asset in question. Burning Assets is useful for many purposes, including bridging of Wrapped Assets and removing supply of Assets. +Finally, in this ZIP we also describe the *burn* mechanism, which is a direct extension of the transfer mechanism. The burn process uses a similar mechanism to what is used in Orchard to unshield ZEC, by using the $\mathsf{valueBalance}$ of the Asset in question. Burning Assets is useful for many purposes, including bridging of Wrapped Assets and removing supply of Assets. Specification ============= @@ -74,9 +74,9 @@ Most of the protocol is kept the same as the Orchard protocol released with NU5, Asset Identifiers ----------------- -For every new Asset, there must be a new and unique Asset Identifier. Every Asset is defined by an *Asset description*, :math:`\mathsf{asset\_desc}\!`, which is a global byte string (scoped across all future versions of Zcash). From this Asset description and the issuance validating key of the issuer, the specific Asset Identifier, :math:`\mathsf{AssetId}\!`, the Asset Digest, and the Asset Base (:math:`\mathsf{AssetBase}\!`) are derived as defined in ZIP 227 [#zip-0227]_. +For every new Asset, there must be a new and unique Asset Identifier. Every Asset is defined by an *Asset description*, $\mathsf{asset\_desc}$, which is a global byte string (scoped across all future versions of Zcash). From this Asset description and the issuance validating key of the issuer, the specific Asset Identifier, $\mathsf{AssetId}$, the Asset Digest, and the Asset Base ($\!\mathsf{AssetBase}$) are derived as defined in ZIP 227 [#zip-0227]_. -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, :math:`\mathcal{V}^{\mathsf{Orchard}}\!`. +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}}$. Rationale for Asset Identifiers ``````````````````````````````` @@ -86,40 +86,44 @@ In future network and protocol upgrades, the same Asset description string can b Note Structure & Commitment --------------------------- -Let :math:`\mathsf{Note^{OrchardZSA}}` be the type of a ZSA note, i.e. -:math:`\mathsf{Note^{OrchardZSA}} := \mathsf{Note^{Orchard}} \times \mathbb{P}^*\!`. +Let $\mathsf{Note^{OrchardZSA}}$ be the type of a ZSA note, i.e. +$\mathsf{Note^{OrchardZSA}} := \mathsf{Note^{Orchard}} \times \mathbb{P}^*$. -An Orchard ZSA note differs from an Orchard note [#protocol-notes]_ by additionally including the Asset Base, :math:`\mathsf{AssetBase}\!`. So a ZSA note is a tuple :math:`(\mathsf{g_d}, \mathsf{pk_d}, \mathsf{v}, \text{ρ}, \text{ψ}, \mathsf{AssetBase})\!`, +An Orchard ZSA note differs from an Orchard note [#protocol-notes]_ by additionally including the Asset Base, $\mathsf{AssetBase}$. So a ZSA note is a tuple $(\mathsf{g_d}, \mathsf{pk_d}, \mathsf{v}, \text{ρ}, \text{ψ}, \mathsf{AssetBase})$, where -- :math:`\mathsf{AssetBase} : \mathbb{P}^*` is the unique element of the Pallas group [#protocol-pallasandvesta]_ that identifies each Asset in the Orchard protocol, defined as the Asset Base in ZIP 227 [#zip-0227]_, a valid group element that is not the identity and is not :math:`\bot\!`. The byte representation of the Asset Base is defined as :math:`\mathsf{asset\_base} : \mathbb{B}^{[\ell_{\mathbb{P}}]} := \mathsf{repr}_{\mathbb{P}}(\mathsf{AssetBase})\!`. +- $\mathsf{AssetBase} : \mathbb{P}^*$ is the unique element of the Pallas group [#protocol-pallasandvesta]_ that identifies each Asset in the Orchard protocol, defined as the Asset Base in ZIP 227 [#zip-0227]_, a valid group element that is not the identity and is not $\bot$. The byte representation of the Asset Base is defined as $\mathsf{asset\_base} : \mathbb{B}^{[\ell_{\mathbb{P}}]} := \mathsf{repr}_{\mathbb{P}}(\mathsf{AssetBase})$. Note that the above assumes a canonical encoding, which is true for the Pallas group, but may not hold for future shielded protocols. -We define the note commitment scheme :math:`\mathsf{NoteCommit^{OrchardZSA}_{rcm}}` as follows: +We define the note commitment scheme $\mathsf{NoteCommit^{OrchardZSA}_{rcm}}$ as follows: -.. math:: \mathsf{NoteCommit}^{\mathsf{OrchardZSA}} : \mathsf{NoteCommit}^{\mathsf{Orchard}}.\!\mathsf{Trapdoor} \times \mathbb{B}^{[\ell_{\mathbb{P}}]} \times \mathbb{B}^{[\ell_{\mathbb{P}}]} \times \{0 .. 2^{\ell_{\mathsf{value}}} - 1\} \times \mathbb{F}_{q_{\mathbb{P}}} \times \mathbb{F}_{q_{\mathbb{P}}} \times \mathbb{P}^* \to \mathsf{NoteCommit}^{\mathsf{Orchard}}.\!\mathsf{Output} +* $\mathsf{NoteCommit}^{\mathsf{OrchardZSA}} : \mathsf{NoteCommit^{Orchard}.Trapdoor}\hspace{-1em}$ + $\hspace{1em}\times\, \mathbb{B}^{[\ell_{\mathbb{P}}]}\hspace{-1em}$ + $\hspace{1em}\times\, \mathbb{B}^{[\ell_{\mathbb{P}}]}\hspace{-1em}$ + $\hspace{1em}\times\, \{0 .. 2^{\ell_{\mathsf{value}}} - 1\}\hspace{-1em}$ + $\hspace{1em}\times\, \mathbb{F}_{q_{\mathbb{P}}}\hspace{-1em}$ + $\hspace{1em}\times\, \mathbb{F}_{q_{\mathbb{P}}}\hspace{-1em}$ + $\hspace{1em}\times\, \mathbb{P}^* \to \mathsf{NoteCommit^{Orchard}.Output}$ -where :math:`\mathbb{P}, \ell_{\mathbb{P}}, q_{\mathbb{P}}` are as defined for the Pallas curve [#protocol-pallasandvesta]_, and where :math:`\mathsf{NoteCommit^{Orchard}}.\!\mathsf{Trapdoor}` and :math:`\mathsf{Orchard}.\!\mathsf{Output}` are as defined in the Zcash protocol specification [#protocol-abstractcommit]_. +where $\mathbb{P}, \ell_{\mathbb{P}}, q_{\mathbb{P}}$ are as defined for the Pallas curve [#protocol-pallasandvesta]_, and where $\mathsf{NoteCommit^{Orchard}.\{Trapdoor, Output\}}$ are as defined in the Zcash protocol specification [#protocol-abstractcommit]_. This note commitment scheme is instantiated using the Sinsemilla Commitment [#protocol-concretesinsemillacommit]_ as follows: -.. math:: \begin{align} - \mathsf{NoteCommit^{OrchardZSA}_{rcm}}(\mathsf{g_d}\star, \mathsf{pk_d}\star, \mathsf{v}, \text{ρ}, \text{ψ}, \mathsf{AssetBase}) - := \begin{cases} - \mathsf{NoteCommit^{Orchard}_{rcm}}(\mathsf{g_d}\star, \mathsf{pk_d}\star, \mathsf{v}, \text{ρ}, \text{ψ}), &\text{if } \mathsf{AssetBase} = \mathcal{V}^{\mathsf{Orchard}} \\ - \mathsf{cm_{ZSA}} &\text{otherwise} - \end{cases} - \end{align} +.. math:: + \mathsf{NoteCommit^{OrchardZSA}_{rcm}}(\mathsf{g_d}\star, \mathsf{pk_d}\star, \mathsf{v}, \text{ρ}, \text{ψ}, \mathsf{AssetBase}) := + \begin{cases} + \mathsf{NoteCommit^{Orchard}_{rcm}}(\mathsf{g_d}\star, \mathsf{pk_d}\star, \mathsf{v}, \text{ρ}, \text{ψ}), &\!\!\text{if } \mathsf{AssetBase} = \mathcal{V}^{\mathsf{Orchard}} \\ + \mathsf{cm_{ZSA}} &\!\!\text{otherwise} + \end{cases} where: -.. math:: \begin{align} - \mathsf{cm_{ZSA}} :=&\;\;\mathsf{SinsemillaHashToPoint}(\texttt{"z.cash:ZSA-NoteCommit-M"}, \\ - &\;\;\;\;\;\mathsf{g_{d}\star} \,||\, \mathsf{pk_{d}\star} \,||\, \mathsf{I2LEBSP_{64}(v)} \,||\, \mathsf{I2LEBSP}_{\ell^{\mathsf{Orchard}}_{\mathsf{base}}}(\text{ρ}) \,||\, \mathsf{I2LEBSP}_{\ell^{\mathsf{Orchard}}_{\mathsf{base}}}(\text{ψ}) \,||\, \mathsf{asset\_base}) \\ - &\;\;+\;\;[\mathsf{rcm}]\,\mathsf{GroupHash}^{\mathbb{P}}(\texttt{"z.cash:Orchard-NoteCommit-r"}, \texttt{""}) - \end{align} +* $\mathsf{cm_{ZSA}} := \mathsf{SinsemillaHashToPoint}(\texttt{“z.cash:ZSA-NoteCommit-M”},\hspace{-6em}$ + $\hspace{6em}\mathsf{g_{d}\star} \,||\, \mathsf{pk_{d}\star} \,||\, \mathsf{I2LEBSP_{64}(v)} \,||\, \mathsf{I2LEBSP}_{\ell^{\mathsf{Orchard}}_{\mathsf{base}}}(\text{ρ})\hspace{-6em}$ + $\hspace{6em}\,||\, \mathsf{I2LEBSP}_{\ell^{\mathsf{Orchard}}_{\mathsf{base}}}(\text{ψ}) \,||\, \mathsf{asset\_base})\hspace{-4em}$ + $\hspace{4em}\,+\; [\mathsf{rcm}]\,\mathsf{GroupHash}^{\mathbb{P}}(\texttt{“z.cash:Orchard-NoteCommit-r”}, \texttt{“”})$ -Note that :math:`\mathsf{repr}_{\mathbb{P}}` and :math:`\mathsf{GroupHash}^{\mathbb{P}}` are as defined for the Pallas curve [#protocol-pallasandvesta]_, :math:`\ell^{\mathsf{Orchard}}_{\mathsf{base}}` is as defined in §5.3 [#protocol-constants]_, and :math:`\mathsf{I2LEBSP}` is as defined in §5.1 [#protocol-endian]_ of the Zcash protocol specification. +Note that $\mathsf{repr}_{\mathbb{P}}$ and $\mathsf{GroupHash}^{\mathbb{P}}$ are as defined for the Pallas curve [#protocol-pallasandvesta]_, $\ell^{\mathsf{Orchard}}_{\mathsf{base}}$ is as defined in §5.3 [#protocol-constants]_, and $\mathsf{I2LEBSP}$ is as defined in §5.1 [#protocol-endian]_ of the Zcash protocol specification. The nullifier is generated in the same manner as in the Orchard protocol [#protocol-commitmentsandnullifiers]_. @@ -131,13 +135,13 @@ It consists of Rationale for Note Commitment ````````````````````````````` -In the ZSA protocol, the instance of the note commitment scheme, :math:`\mathsf{NoteCommit^{OrchardZSA}_{rcm}}\!`, differs from the Orchard note commitment :math:`\mathsf{NoteCommit^{Orchard}_{rcm}}` in that for Custom Assets, the Asset Base will be added as an input to the commitment computation. +In the ZSA protocol, the instance of the note commitment scheme, $\mathsf{NoteCommit^{OrchardZSA}_{rcm}}$, differs from the Orchard note commitment $\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 [#protocol-concretesinsemillacommit]_ 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 [#protocol-concretesinsemillahash]_. ZSA note commitments will therefore be added to the same Orchard Note Commitment Tree. In essence, we have: -.. math:: \mathsf{NoteCommit^{OrchardZSA}_{rcm}}(\mathsf{repr}_{\mathbb{P}}(\mathsf{g_d}), \mathsf{repr}_{\mathbb{P}}(\mathsf{pk_d}), \mathsf{v}, \text{ρ}, \text{ψ}, \mathsf{AssetBase}) \in \mathsf{NoteCommit^{Orchard}}.\!\mathsf{Output} +.. math:: \mathsf{NoteCommit^{OrchardZSA}_{rcm}}(\mathsf{repr}_{\mathbb{P}}(\mathsf{g_d}), \mathsf{repr}_{\mathbb{P}}(\mathsf{pk_d}), \mathsf{v}, \text{ρ}, \text{ψ}, \mathsf{AssetBase}) \in \mathsf{NoteCommit^{Orchard}.Output} 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. @@ -148,20 +152,20 @@ In the case of the Orchard-based ZSA protocol, the value of different Asset Iden .. math:: \mathsf{cv^{net}} := \mathsf{ValueCommit^{OrchardZSA}_{rcv}}(\mathsf{AssetBase_{AssetId}}, \mathsf{v^{net}_{AssetId}}) = [\mathsf{v^{net}_{AssetId}}]\,\mathsf{AssetBase_{AssetId}} + [\mathsf{rcv}]\,\mathcal{R}^{\mathsf{Orchard}} -where :math:`\mathsf{v^{net}_{AssetId}} = \mathsf{v^{old}_{AssetId}} - \mathsf{v^{new}_{AssetId}}` such that :math:`\mathsf{v^{old}_{AssetId}}` and :math:`\mathsf{v^{new}_{AssetId}}` are the values of the old and new notes of Asset Identifier :math:`\mathsf{AssetId}` respectively, +where $\mathsf{v^{net}_{AssetId}} = \mathsf{v^{old}_{AssetId}} - \mathsf{v^{new}_{AssetId}}$ such that .. _`asset base`: -:math:`\mathsf{AssetBase_{AssetId}}` is defined in ZIP 227 [#zip-0227]_, and +* $\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 [#zip-0227]_, and +* $\mathcal{R}^{\mathsf{Orchard}} := \mathsf{GroupHash^{\mathbb{P}}}(\texttt{“z.cash:Orchard-cv”}, \texttt{“r”})$, as in the Orchard protocol. -:math:`\mathcal{R}^{\mathsf{Orchard}} := \mathsf{GroupHash^{\mathbb{P}}}(\texttt{"z.cash:Orchard-cv"}, \texttt{"r"})\!`, as in the Orchard protocol. - -For ZEC, we define :math:`\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 [#zip-0224]_. As such :math:`\mathsf{ValueCommit^{Orchard}_{rcv}}(\mathsf{v})` as defined in [#zip-0224]_ is used as :math:`\mathsf{ValueCommit^{OrchardZSA}_{rcv}}(\mathcal{V}^{\mathsf{Orchard}}, \mathsf{v})` here. +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 [#zip-0224]_. As such $\mathsf{ValueCommit^{Orchard}_{rcv}}(\mathsf{v})$ as defined in [#zip-0224]_ is used as $\mathsf{ValueCommit^{OrchardZSA}_{rcv}}(\mathcal{V}^{\mathsf{Orchard}}, \mathsf{v})$ here. Rationale for Value Commitment `````````````````````````````` -The Orchard Protocol uses a Homomorphic Pedersen Commitment [#protocol-concretehomomorphiccommit]_ to perform the value commitment, with fixed base points :math:`\mathcal{V}^{\mathsf{Orchard}}` and :math:`\mathcal{R}^{\mathsf{Orchard}}` as the values represent the amount of ZEC being transferred. +The Orchard Protocol uses a Homomorphic Pedersen Commitment [#protocol-concretehomomorphiccommit]_ to perform the value commitment, with fixed base points $\mathcal{V}^{\mathsf{Orchard}}$ and $\mathcal{R}^{\mathsf{Orchard}}$ as the values represent the amount of ZEC being transferred. The use of different value base points for different Assets enables the final balance of the transaction to be securely computed, such that each Asset Identifier is balanced independently, which is required as different Assets are not meant to be mutually fungible. @@ -174,9 +178,9 @@ It is enforced at the consensus level, by using an extension of the value balanc Burning makes it globally provable that a given amount of a Custom Asset has been destroyed. Note that the OrchardZSA Protocol does not allow for the burning of ZEC (or TAZ). -In the `Orchard-ZSA Transaction Structure`_, there is now an :math:`\mathsf{assetBurn}` set. -For every Custom Asset (represented by its :math:`\mathsf{AssetBase}\!`) that is burnt in the transaction, the sender adds to :math:`\mathsf{assetBurn}` the tuple :math:`(\mathsf{AssetBase}, \mathsf{v})`, where :math:`\mathsf{v}` is the amount of the Custom Asset the sender wants to burn. -We denote by :math:`L` the cardinality of the :math:`\mathsf{assetBurn}` set in a transaction. +In the `Orchard-ZSA Transaction Structure`_, there is now an $\mathsf{assetBurn}$ set. +For every Custom Asset (represented by its $\mathsf{AssetBase}$) that is burnt in the transaction, the sender adds to $\mathsf{assetBurn}$ the tuple $(\mathsf{AssetBase}, \mathsf{v})$, where $\mathsf{v}$ is the amount of the Custom Asset the sender wants to burn. +We denote by $L$ the cardinality of the $\mathsf{assetBurn}$ set in a transaction. As described in `Value Balance Verification`_, this provides the information for the validator of the transaction to compute the value commitment with the corresponding Asset Base. This ensures that the values are all balanced out on a per-Asset basis in the transaction. @@ -184,12 +188,12 @@ This ensures that the values are all balanced out on a per-Asset basis in the tr Additional Consensus Rules `````````````````````````` -1. Check that for every :math:`(\mathsf{AssetBase}, \mathsf{v}) \in \mathsf{assetBurn}, \mathsf{AssetBase} \neq \mathcal{V}^{\mathsf{Orchard}}\!`. That is, ZEC or TAZ is not allowed to be burnt by this mechanism. -2. Check that for every :math:`(\mathsf{AssetBase}, \mathsf{v}) \in \mathsf{assetBurn}, \mathsf{v} \neq 0\!`. -3. Check that there is no duplication of Custom Assets in the :math:`\mathsf{assetBurn}` set. That is, every :math:`\mathsf{AssetBase}` has at most one entry in :math:`\mathsf{assetBurn}\!`. -4. Check that for every :math:`(\mathsf{AssetBase}, \mathsf{v}) \in \mathsf{assetBurn}\!`, :math:`\mathsf{v} \leq \mathsf{issued\_assets(AssetBase).balance}\!`, where the map :math:`\mathsf{issued\_assets}` is defined in ZIP 227 [#zip-0227-specification-global-issuance-state]_. That is, it is not possible to burn more of an Asset than is currently in circulation. +1. Check that for every $(\mathsf{AssetBase}, \mathsf{v}) \in \mathsf{assetBurn}, \mathsf{AssetBase} \neq \mathcal{V}^{\mathsf{Orchard}}$. That is, ZEC or TAZ is not allowed to be burnt by this mechanism. +2. Check that for every $(\mathsf{AssetBase}, \mathsf{v}) \in \mathsf{assetBurn}, \mathsf{v} \neq 0$. +3. Check that there is no duplication of Custom Assets in the $\mathsf{assetBurn}$ set. That is, every $\mathsf{AssetBase}$ has at most one entry in $\mathsf{assetBurn}$. +4. Check that for every $(\mathsf{AssetBase}, \mathsf{v}) \in \mathsf{assetBurn}$, $\mathsf{v} \leq \mathsf{issued\_assets(AssetBase).balance}$, where the map $\mathsf{issued\_assets}$ is defined in ZIP 227 [#zip-0227-specification-global-issuance-state]_. That is, it is not possible to burn more of an Asset than is currently in circulation. -If all these checks pass, then for every :math:`(\mathsf{AssetBase}, \mathsf{v}) \in \mathsf{assetBurn}\!`, reduce the value of :math:`\mathsf{issued\_assets(AssetBase).balance}` in the global state by :math:`\mathsf{v}\!`. +If all these checks pass, then for every $(\mathsf{AssetBase}, \mathsf{v}) \in \mathsf{assetBurn}$, reduce the value of $\mathsf{issued\_assets(AssetBase).balance}$ in the global state by $\mathsf{v}$. **Note:** Even if this mechanism allows having transparent ↔ shielded Asset transfers in theory, the transparent protocol will not be changed with this ZIP to adapt to a multiple Asset structure. This means that unless future consensus rules changes do allow it, unshielding will not be possible for Custom Assets. @@ -198,21 +202,21 @@ Value Balance Verification In order to verify the balance of the different Assets, the verifier MUST perform a similar process as for the Orchard protocol [#protocol-orchardbalance]_, with the addition of the burn information. -For a total of :math:`n` Actions in a transfer, the prover MUST still sign the SIGHASH transaction hash using the binding signature key -:math:`\mathsf{bsk} = \sum_{i=1}^{n} \mathsf{rcv}_i\!`. +For a total of $n$ Actions in a transfer, the prover MUST still sign the SIGHASH transaction hash using the binding signature key +$\mathsf{bsk} = \sum_{i=1}^{n} \mathsf{rcv}_i$. The verifier MUST compute the value balance verification equation: .. math:: \mathsf{bvk} = (\sum_{i=1}^{n} \mathsf{cv}^{\mathsf{net}}_i) - \mathsf{ValueCommit_0^{OrchardZSA}(\mathcal{V}^{\mathsf{Orchard}}, v^{balanceOrchard})} - \sum_{(\mathsf{AssetBase}, \mathsf{v}) \in \mathsf{assetBurn}} \mathsf{ValueCommit_0^{OrchardZSA}}(\mathsf{AssetBase}, \mathsf{v}) -After computing :math:`\mathsf{bvk}\!`, the verifier MUST use it to verify the binding signature on the SIGHASH transaction hash. +After computing $\mathsf{bvk}$, the verifier MUST use it to verify the binding signature on the SIGHASH transaction hash. Rationale for Value Balance Verification ```````````````````````````````````````` -We assume :math:`n` Actions in a transfer. Out of these :math:`n` Actions, we further distinguish (for the sake of clarity) between Actions related to ZEC and Actions related to Custom Assets. -We denote by :math:`S_{\mathsf{ZEC}} \subseteq \{1 .. n\}` the set of indices of Actions that are related to ZEC, and by :math:`S_{\mathsf{CA}} = \{1 .. n\} \setminus S_{\mathsf{ZEC}}` the set of indices of Actions that are related to Custom Assets. +We assume $n$ Actions in a transfer. Out of these $n$ Actions, we further distinguish (for the sake of clarity) between Actions related to ZEC and Actions related to Custom Assets. +We denote by $S_{\mathsf{ZEC}} \subseteq \{1 .. n\}$ the set of indices of Actions that are related to ZEC, and by $S_{\mathsf{CA}} = \{1 .. n\} \setminus S_{\mathsf{ZEC}}$ the set of indices of Actions that are related to Custom Assets. The right hand side of the value balance verification equation can be expanded to: @@ -221,13 +225,13 @@ The right hand side of the value balance verification equation can be expanded t This equation contains the balance check of the Orchard protocol [#protocol-orchardbalance]_. With ZSA, transfer Actions for Custom Assets must also be balanced across Asset Bases. All Custom Assets are contained within the shielded pool, and cannot be unshielded via a regular transfer. -Custom Assets can be burnt, the mechanism for which reveals the amount and identifier of the Asset being burnt, within the :math:`\mathsf{assetBurn}` set. -As such, for a correctly constructed transaction, we will get :math:`\sum_{j \in S_{\mathsf{CA}}} \mathsf{cv}^{\mathsf{net}}_j - \sum_{(\mathsf{AssetBase}, \mathsf{v}) \in \mathsf{assetBurn}} [\mathsf{v}]\,\mathsf{AssetBase} = \sum_{j \in S_{\mathsf{CA}}} [\mathsf{rcv}^{\mathsf{net}}_j]\,\mathcal{R}^{\mathsf{Orchard}}\!`. +Custom Assets can be burnt, the mechanism for which reveals the amount and identifier of the Asset being burnt, within the $\mathsf{assetBurn}$ set. +As such, for a correctly constructed transaction, we will get $\sum_{j \in S_{\mathsf{CA}}} \mathsf{cv}^{\mathsf{net}}_j - \sum_{(\mathsf{AssetBase}, \mathsf{v}) \in \mathsf{assetBurn}} [\mathsf{v}]\,\mathsf{AssetBase} = \sum_{j \in S_{\mathsf{CA}}} [\mathsf{rcv}^{\mathsf{net}}_j]\,\mathcal{R}^{\mathsf{Orchard}}$. -When the Asset is not being burnt, the net balance of the input and output values is zero, and there will be no addition to the :math:`\mathsf{assetBurn}` vector. -Therefore, the relationship between :math:`\mathsf{bvk}` and :math:`\mathsf{bsk}` will hold if and only if, per Custom Asset, the sum of the net values of the relevant Actions equals the corresponding :math:`\mathsf{v}_k` value (or equals :math:`0` if that Asset is not in the :math:`\mathsf{assetBurn}` set), and for ZEC, the sum of the net values of the relevant Actions equals the :math:`\mathsf{v^{balanceOrchard}}` value. +When the Asset is not being burnt, the net balance of the input and output values is zero, and there will be no addition to the $\mathsf{assetBurn}$ vector. +Therefore, the relationship between $\mathsf{bvk}$ and $\mathsf{bsk}$ will hold if and only if, per Custom Asset, the sum of the net values of the relevant Actions equals the corresponding $\mathsf{v}_k$ value (or equals $0$ if that Asset is not in the $\mathsf{assetBurn}$ set), and for ZEC, the sum of the net values of the relevant Actions equals the $\mathsf{v^{balanceOrchard}}$ value. -As in the Orchard protocol, the binding signature verification key, :math:`\mathsf{bvk}\!`, will only be valid (and hence verify the signature correctly), as long as the committed values sum to zero. In contrast, in this protocol, the committed values must sum to zero **per Asset Base**, as the Pedersen commitments add up homomorphically only with respect to the same value base point. +As in the Orchard protocol, the binding signature verification key, $\mathsf{bvk}$, will only be valid (and hence verify the signature correctly), as long as the committed values sum to zero. In contrast, in this protocol, the committed values must sum to zero **per Asset Base**, as the Pedersen commitments add up homomorphically only with respect to the same value base point. Split Notes @@ -235,7 +239,7 @@ Split Notes A Split Input is a copy of a previously issued input note (that is, a note that has previously been included in the Merkle tree), with the following changes: -- A :math:`\mathsf{split\_flag}` boolean is set to 1. +- A $\mathsf{split\_flag}$ boolean is set to 1. - The value of the note is replaced with the value 0 during the computation of the value commitment. Input notes are sometimes split in two (or more) output notes, as in most cases, not all the value in a single note is sent to a single output. @@ -252,7 +256,7 @@ For Split Notes, the nullifier is generated as follows: .. math:: \mathsf{nf_{old}} = \mathsf{Extract}_{\mathbb{P}} ([(\mathsf{PRF^{nfOrchard}_{nk}} (\text{ρ}^{\mathsf{old}}) + \text{ψ}^{\mathsf{nf}}) \bmod q_{\mathbb{P}}]\,\mathcal{K}^\mathsf{Orchard} + \mathsf{cm^{old}} + \mathcal{L}^\mathsf{Orchard}) -where :math:`\text{ψ}^{\mathsf{nf}}` is sampled uniformly at random on :math:`\mathbb{F}_{q_{\mathbb{P}}}\!`, :math:`\mathcal{K}^{\mathsf{Orchard}}` is the Orchard Nullifier Base as defined in [#protocol-commitmentsandnullifiers]_, and :math:`\mathcal{L}^{\mathsf{Orchard}} := \mathsf{GroupHash^{\mathbb{P}}}(\texttt{"z.cash:Orchard"}, \texttt{"L"})\!`. +where $\text{ψ}^{\mathsf{nf}}$ is sampled uniformly at random on $\mathbb{F}_{q_{\mathbb{P}}}$, $\mathcal{K}^{\mathsf{Orchard}}$ is the Orchard Nullifier Base as defined in [#protocol-commitmentsandnullifiers]_, and $\mathcal{L}^{\mathsf{Orchard}} := \mathsf{GroupHash^{\mathbb{P}}}(\texttt{“z.cash:Orchard”}, \texttt{“L”})$. Rationale for Split Notes ````````````````````````` @@ -261,7 +265,7 @@ In the Orchard protocol, since each Action represents an input and an output, th The Orchard technique requires modification for the ZSA protocol with multiple Asset Identifiers, as the output note of the split Actions *cannot* contain *just any* Asset Base. We must enforce it to be an actual output of a GroupHash computation (in fact, we want it to be of the same Asset Base as the original input note, but the binding signature takes care that the proper balancing is performed). Without this enforcement the prover could input a multiple (or linear combination) of an existing Asset Base, and thereby attack the network by overflowing the ZEC value balance and hence counterfeiting ZEC funds. -Therefore, for Custom Assets we enforce that *every* input note to an ZSA Action must be proven to exist in the set of note commitments in the note commitment tree. We then enforce this real note to be “unspendable” in the sense that its value will be zeroed in split Actions and the nullifier will be randomized, making the note not spendable in the specific Action. Then, the proof itself ensures that the output note is of the same Asset Base as the input note. In the circuit, the split note functionality will be activated by a boolean private input to the proof (aka the :math:`\mathsf{split\_flag}` boolean). +Therefore, for Custom Assets we enforce that *every* input note to an ZSA Action must be proven to exist in the set of note commitments in the note commitment tree. We then enforce this real note to be “unspendable” in the sense that its value will be zeroed in split Actions and the nullifier will be randomized, making the note not spendable in the specific Action. Then, the proof itself ensures that the output note is of the same Asset Base as the input note. In the circuit, the split note functionality will be activated by a boolean private input to the proof (aka the $\mathsf{split\_flag}$ boolean). This ensures that the value base points of all output notes of a transfer are actual outputs of a GroupHash, as they originate in the Issuance protocol which is publicly verified. Note that the Orchard dummy note functionality remains in use for ZEC notes, and the Split Input technique is used in order to support Custom Assets. @@ -277,28 +281,28 @@ All modifications in the Circuit are detailed in [#circuit-modifications]_. Asset Base Equality ``````````````````` -The following constraints must be added to ensure that the input and output note are of the same :math:`\mathsf{AssetBase}\!`: +The following constraints must be added to ensure that the input and output note are of the same $\mathsf{AssetBase}$: -- The Asset Base, :math:`\mathsf{AssetBase_{AssetId}}\!`, for the note is witnessed once, as an auxiliary input. -- In the Old note commitment integrity constraint in the Orchard Action statement [#protocol-actionstatement]_, :math:`\mathsf{NoteCommit^{Orchard}_{rcm^{old}}}(\mathsf{repr}_{\mathbb{P}}(\mathsf{g_d^{old}}), \mathsf{repr}_{\mathbb{P}}(\mathsf{pk_d^{old}}), \mathsf{v^{old}}, \text{ρ}^{\mathsf{old}}, \text{ψ}^{\mathsf{old}})` is replaced with :math:`\mathsf{NoteCommit^{OrchardZSA}_{rcm^{old}}}(\mathsf{repr}_{\mathbb{P}}(\mathsf{g_d^{old}}), \mathsf{repr}_{\mathbb{P}}(\mathsf{pk_d^{old}}), \mathsf{v^{old}}, \text{ρ}^{\mathsf{old}}, \text{ψ}^{\mathsf{old}}, \mathsf{AssetBase_{AssetId}})\!`. -- In the New note commitment integrity constraint in the Orchard Action statement [#protocol-actionstatement]_, :math:`\mathsf{NoteCommit^{Orchard}_{rcm^{new}}}(\mathsf{repr}_{\mathbb{P}}(\mathsf{g_d^{new}}), \mathsf{repr}_{\mathbb{P}}(\mathsf{pk_d^{new}}), \mathsf{v^{new}}, \text{ρ}^{\mathsf{new}}, \text{ψ}^{\mathsf{new}})` is replaced with :math:`\mathsf{NoteCommit^{OrchardZSA}_{rcm^{new}}}(\mathsf{repr}_{\mathbb{P}}(\mathsf{g_d^{new}}), \mathsf{repr}_{\mathbb{P}}(\mathsf{pk_d^{new}}), \mathsf{v^{new}}, \text{ρ}^{\mathsf{new}}, \text{ψ}^{\mathsf{new}}, \mathsf{AssetBase_{AssetId}})\!`. +- The Asset Base, $\mathsf{AssetBase_{AssetId}}$, for the note is witnessed once, as an auxiliary input. +- In the Old note commitment integrity constraint in the Orchard Action statement [#protocol-actionstatement]_, $\mathsf{NoteCommit^{Orchard}_{rcm^{old}}}(\mathsf{repr}_{\mathbb{P}}(\mathsf{g_d^{old}}), \mathsf{repr}_{\mathbb{P}}(\mathsf{pk_d^{old}}), \mathsf{v^{old}}, \text{ρ}^{\mathsf{old}}, \text{ψ}^{\mathsf{old}})$ is replaced with $\mathsf{NoteCommit^{OrchardZSA}_{rcm^{old}}}(\mathsf{repr}_{\mathbb{P}}(\mathsf{g_d^{old}}), \mathsf{repr}_{\mathbb{P}}(\mathsf{pk_d^{old}}), \mathsf{v^{old}}, \text{ρ}^{\mathsf{old}}, \text{ψ}^{\mathsf{old}}, \mathsf{AssetBase_{AssetId}})$. +- In the New note commitment integrity constraint in the Orchard Action statement [#protocol-actionstatement]_, $\mathsf{NoteCommit^{Orchard}_{rcm^{new}}}(\mathsf{repr}_{\mathbb{P}}(\mathsf{g_d^{new}}), \mathsf{repr}_{\mathbb{P}}(\mathsf{pk_d^{new}}), \mathsf{v^{new}}, \text{ρ}^{\mathsf{new}}, \text{ψ}^{\mathsf{new}})$ is replaced with $\mathsf{NoteCommit^{OrchardZSA}_{rcm^{new}}}(\mathsf{repr}_{\mathbb{P}}(\mathsf{g_d^{new}}), \mathsf{repr}_{\mathbb{P}}(\mathsf{pk_d^{new}}), \mathsf{v^{new}}, \text{ρ}^{\mathsf{new}}, \text{ψ}^{\mathsf{new}}, \mathsf{AssetBase_{AssetId}})$. -To make the evaluation of the note commitment easier, we add a boolean :math:`\mathsf{is\_native\_asset}` as an auxiliary witness. We also add some constraints to verify that this variable is activated (i.e. :math:`\mathsf{is\_native\_asset} = 1\!`) if the Asset Base is equal to :math:`\mathcal{V}^{\mathsf{Orchard}}` and this variable is not activated (i.e. :math:`\mathsf{is\_native\_asset} = 0\!`) if the Asset Base is not equal to :math:`\mathcal{V}^{\mathsf{Orchard}}\!`. +To make the evaluation of the note commitment easier, we add a boolean $\mathsf{is\_native\_asset}$ as an auxiliary witness. We also add some constraints to verify that this variable is activated (i.e. $\mathsf{is\_native\_asset} = 1$) if the Asset Base is equal to $\mathcal{V}^{\mathsf{Orchard}}$ and this variable is not activated (i.e. $\mathsf{is\_native\_asset} = 0$) if the Asset Base is not equal to $\mathcal{V}^{\mathsf{Orchard}}$. The :math:`\mathsf{enableZSA}` Flag -````````````````````````````````````` +``````````````````````````````````` -The following constraints must be added to disable transactions involving Custom Assets when the :math:`\mathsf{enableZSA}` flag is set to false: +The following constraints must be added to disable transactions involving Custom Assets when the $\mathsf{enableZSA}$ flag is set to false: -- if :math:`\mathsf{enableZSA}` is not activated (i.e. :math:`\mathsf{enableZSA} = 0\!`), then constrain :math:`\mathsf{is\_native\_asset} = 1\!`, since the :math:`\mathsf{AsssetBase}` must be equal to the native asset. +- if $\mathsf{enableZSA}$ is not activated (i.e. $\mathsf{enableZSA} = 0$), then constrain $\mathsf{is\_native\_asset} = 1$, since the $\mathsf{AsssetBase}$ must be equal to the native asset. Value Commitment Correctness ```````````````````````````` The following constraints must be added to ensure that the value commitment is computed using the witnessed Asset Base: -- The fixed-base multiplication constraint between the value and the value base point of the value commitment, :math:`\mathsf{cv}\!`, is replaced with a variable-base multiplication between the two. -- The witness to the value base point (as defined in the `asset base`_ equation) is the auxiliary input :math:`\mathsf{AssetBase_{AssetId}}\!`. +- The fixed-base multiplication constraint between the value and the value base point of the value commitment, $\mathsf{cv}$, is replaced with a variable-base multiplication between the two. +- The witness to the value base point (as defined in the `asset base`_ equation) is the auxiliary input $\mathsf{AssetBase_{AssetId}}$. Asset Identifier Consistency for Split Actions `````````````````````````````````````````````` @@ -306,13 +310,19 @@ Asset Identifier Consistency for Split Actions 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: - The Value Commitment Integrity should be changed: - - Replace the input note value by a generic value, :math:`\mathsf{v}'\!`, as :math:`\mathsf{cv^{net}} = \mathsf{ValueCommit_rcv^{OrchardZSA}}(\mathsf{AssetBase_{AssetId}}, \mathsf{v}' - \mathsf{v^{new}})` -- Add a boolean :math:`\mathsf{split\_flag}` variable as an auxiliary witness. This variable is to be activated :math:`\mathsf{split\_flag} = 1` if the Action in question has a Split Input and :math:`\mathsf{split\_flag} = 0` if the Action is actually spending an input note: - - If :math:`\mathsf{split\_flag} = 1` then constrain :math:`\mathsf{v}' = 0` otherwise constrain :math:`\mathsf{v}' = \mathsf{v^{old}}` from the auxiliary input. - - If :math:`\mathsf{split\_flag} = 1` then constrain :math:`\mathsf{is\_native\_asset} = 0` because split notes are only available for Custom Assets. + + - Replace the input note value by a generic value, $\mathsf{v}'$, as $\mathsf{cv^{net}} = \mathsf{ValueCommit_rcv^{OrchardZSA}}(\mathsf{AssetBase_{AssetId}}, \mathsf{v}' - \mathsf{v^{new}})$ + +- Add a boolean $\mathsf{split\_flag}$ variable as an auxiliary witness. This variable is to be activated $\mathsf{split\_flag} = 1$ if the Action in question has a Split Input and $\mathsf{split\_flag} = 0$ if the Action is actually spending an input note: + + - If $\mathsf{split\_flag} = 1$ then constrain $\mathsf{v}' = 0$ otherwise constrain $\mathsf{v}' = \mathsf{v^{old}}$ from the auxiliary input. + - If $\mathsf{split\_flag} = 1$ then constrain $\mathsf{is\_native\_asset} = 0$ because split notes are only available for Custom Assets. + - The Merkle Path Validity should check the existence of the note commitment as usual (and not like with dummy notes): - - Check for all notes except dummy notes that :math:`(\mathsf{path}, \mathsf{pos})` is a valid Merkle path of depth :math:`\mathsf{MerkleDepth^{Orchard}}\!`, from :math:`\mathsf{cm^{old}}` to the anchor :math:`\mathsf{rt^{Orchard}}\!`. - - The new constraint is :math:`\underbrace{(\mathsf{v^{old}} = 0 \land \mathsf{is\_native\_asset} = 1)}_\text{It is a dummy note} \lor \underbrace{(\mathsf{Valid\,Merkle\,Path})}_\text{The Merkle Path is valid}\!`. + + - Check for all notes except dummy notes that $(\mathsf{path}, \mathsf{pos})$ is a valid Merkle path of depth $\mathsf{MerkleDepth^{Orchard}}$, from $\mathsf{cm^{old}}$ to the anchor $\mathsf{rt^{Orchard}}$. + - The new constraint is $\underbrace{(\mathsf{v^{old}} = 0 \land \mathsf{is\_native\_asset} = 1)}_\text{It is a dummy note} \lor \underbrace{(\mathsf{Valid\,Merkle\,Path})}_\text{The Merkle Path is valid}$. + - The Nullifier Integrity will be changed to prevent the identification of notes as defined in the `Split Notes`_ section. Backwards Compatibility with ZEC Notes @@ -410,7 +420,7 @@ T.4d: orchard_zsa_burn_digest ''''''''''''''''''''''''''''' A BLAKE2b-256 hash of the data from the burn fields of the transaction. For each tuple in -the :math:`\mathsf{assetBurn}` set, the following elements are included in the hash:: +the $\mathsf{assetBurn}$ set, the following elements are included in the hash:: T.4d.i : assetBase (field encoding bytes) T.4d.ii: valueBurn (field encoding bytes) @@ -420,7 +430,7 @@ The personalization field of this hash is set to:: "ZTxIdOrcBurnHash" In case the transaction does not perform the burning of any Assets (i.e. the -:math:`\mathsf{assetBurn}` set is empty), the ''orchard_zsa_burn_digest'' is:: +$\mathsf{assetBurn}$ set is empty), the ''orchard_zsa_burn_digest'' is:: BLAKE2b-256("ZTxIdOrcBurnHash", []) @@ -466,7 +476,7 @@ Backward Compatibility In order to have backward compatibility with the ZEC notes, we have designed the circuit to support both ZEC and ZSA notes. As we specify above, there are three main reasons we can do this: -- Note commitments for ZEC notes will remain the same, while note commitments for Custom Assets will be computed taking into account the :math:`\mathsf{AssetBase}` value as well. +- Note commitments for ZEC notes will remain the same, while note commitments for Custom Assets will be computed taking into account the $\mathsf{AssetBase}$ value as well. - The existing Orchard shielded pool will continue to be used for the new ZSA notes post the upgrade. - The value commitment is abstracted to allow for the value base-point as a variable private input to the proof. - The ZEC-based Actions will still include dummy input notes, whereas the ZSA-based Actions will include split input notes and will not include dummy input notes. diff --git a/zips/zip-0227.rst b/zips/zip-0227.rst index 4a981f2c8..52ac96274 100644 --- a/zips/zip-0227.rst +++ b/zips/zip-0227.rst @@ -75,7 +75,7 @@ Requirements - Issuing or changing the attributes of a specific Asset should require cryptographic authorization. - The Asset identification should be unique (among all shielded pools) and different issuer public keys should not be able to generate the same Asset Identifier. - An issuer should be able to issue different Assets in the same transaction. In other words, in a single "issuance bundle", the issuer should be able publish many "issuance actions", potentially creating multiple Custom Assets. -- Every "issuance action" should contain a :math:`\mathsf{finalize}` boolean that defines whether the specific Custom Asset can have further tokens issued or not. +- Every "issuance action" should contain a $\mathsf{finalize}$ boolean that defines whether the specific Custom Asset can have further tokens issued or not. Specification: Issuance Keys and Issuance Authorization Signature Scheme @@ -83,9 +83,9 @@ Specification: Issuance Keys and Issuance Authorization Signature Scheme The Orchard-ZSA Protocol adds the following keys to the key components [#protocol-addressesandkeys]_ [#protocol-orchardkeycomponents]_: -1. The issuance authorizing key, denoted as :math:`\mathsf{isk}\!`, is the key used to authorize the issuance of Asset Identifiers by a given issuer, and is only used by that issuer. +1. The issuance authorizing key, denoted as $\mathsf{isk}$, is the key used to authorize the issuance of Asset Identifiers by a given issuer, and is only used by that issuer. -2. The issuance validating key, denoted as :math:`\mathsf{ik}\!`, is the key that is used to validate issuance transactions. This key is used to validate the issuance of Asset Identifiers by a given issuer, and is used by all blockchain users (specifically the owners of notes for that Asset, and consensus validators) to associate the Asset in question with the issuer. +2. The issuance validating key, denoted as $\mathsf{ik}$, is the key that is used to validate issuance transactions. This key is used to validate the issuance of Asset Identifiers by a given issuer, and is used by all blockchain users (specifically the owners of notes for that Asset, and consensus validators) to associate the Asset in question with the issuer. The relations between these keys are shown in the following diagram: @@ -100,20 +100,20 @@ The relations between these keys are shown in the following diagram: Issuance Authorization Signature Scheme --------------------------------------- -We instantiate the issuance authorization signature scheme :math:`\mathsf{IssueAuthSig}` as a BIP-340 Schnorr signature over the secp256k1 curve. The signing and validation algorithms, signature encoding, and public key encoding MUST follow BIP 340 [#bip-0340]_. +We instantiate the issuance authorization signature scheme $\mathsf{IssueAuthSig}$ as a BIP-340 Schnorr signature over the secp256k1 curve. The signing and validation algorithms, signature encoding, and public key encoding MUST follow BIP 340 [#bip-0340]_. -Batch verification MAY be used. Precomputation MAY be used if and only if it produces equivalent results; for example, for a given verification key :math:`pk` and :math:`\mathit{lift\_x}(\mathit{int}(pk))` MAY be precomputed. +Batch verification MAY be used. Precomputation MAY be used if and only if it produces equivalent results; for example, for a given verification key $pk$ and $\mathit{lift\_x}(\mathit{int}(pk))$ MAY be precomputed. We define the constants as per the secp256k1 standard parameters, as described in BIP 340. -The associated types of the :math:`\mathsf{IssueAuthSig}` signature scheme are as follows: +The associated types of the $\mathsf{IssueAuthSig}$ signature scheme are as follows: -* :math:`\mathsf{IssueAuthSig}.\!\mathsf{Message} = \mathbb{B}^{\mathbb{Y}^{[\mathbb{N}]}}` -* :math:`\mathsf{IssueAuthSig}.\!\mathsf{Signature} = \mathbb{B}^{\mathbb{Y}^{[64]}} \cup \{\bot\}` -* :math:`\mathsf{IssueAuthSig}.\!\mathsf{Public} = \mathbb{B}^{\mathbb{Y}^{[32]}} \cup \{\bot\}` -* :math:`\mathsf{IssueAuthSig}.\!\mathsf{Private} = \mathbb{B}^{\mathbb{Y}^{[32]}}` +* $\mathsf{IssueAuthSig.Message} = \mathbb{B}^{\mathbb{Y}^{[\mathbb{N}]}}$ +* $\mathsf{IssueAuthSig.Signature} = \mathbb{B}^{\mathbb{Y}^{[64]}} \cup \{\bot\}$ +* $\mathsf{IssueAuthSig.Public} = \mathbb{B}^{\mathbb{Y}^{[32]}} \cup \{\bot\}$ +* $\mathsf{IssueAuthSig.Private} = \mathbb{B}^{\mathbb{Y}^{[32]}}$ -where :math:`\mathbb{B}^{\mathbb{Y}^{[k]}}` denotes the set of sequences of :math:`k` bytes, and :math:`\mathbb{B}^{\mathbb{Y}^{[\mathbb{N}]}}` denotes the type of byte sequences of arbitrary length, as defined in the Zcash protocol specification [#protocol-notation]_. +where $\mathbb{B}^{\mathbb{Y}^{[k]}}$ denotes the set of sequences of $k$ bytes, and $\mathbb{B}^{\mathbb{Y}^{[\mathbb{N}]}}$ denotes the type of byte sequences of arbitrary length, as defined in the Zcash protocol specification [#protocol-notation]_. The issuance authorizing key generation algorithm and the issuance validating key derivation algorithm are defined in the `Issuance Key Derivation`_ section, while the corresponding signing and validation algorithms are defined in the `Issuance Authorization Signing and Validation`_ section. @@ -124,87 +124,87 @@ Issuance authorizing key generation for hierarchical deterministic wallets `````````````````````````````````````````````````````````````````````````` The issuance authorizing key is generated using the Hardened-only key derivation process defined in ZIP 32 [#zip-0032-hardened-only-key-derivation]_. -For the :math:`\mathsf{Issuance}` context, we define the following constants: +For the $\mathsf{Issuance}$ context, we define the following constants: -- :math:`\mathsf{Issuance.\!MKGDomain} := \texttt{"ZcashSA_Issue_V1"}` -- :math:`\mathsf{Issuance.\!CKDDomain} := \mathtt{0x81}\!` +- $\mathsf{Issuance.MKGDomain} := \texttt{“ZcashSA\_Issue\_V1”}$ +- $\mathsf{Issuance.CKDDomain} := \mathtt{0x81}$ -Let :math:`S` be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes. -We define the master extended issuance key :math:`m_{\mathsf{Issuance}} := \mathsf{MKGh}^{\mathsf{Issuance}}(S)\!`. +Let $S$ be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes. +We define the master extended issuance key $m_{\mathsf{Issuance}} := \mathsf{MKGh}^{\mathsf{Issuance}}(S)$. We use hardened-only child key derivation as defined in ZIP 32 [#zip-0032-hardened-only-child-key-derivation]_ for the issuance authorizing key. -:math:`\mathsf{CKDsk}((\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})$ : -- Return :math:`\mathsf{CKDh}^{\mathsf{Issuance}}((\mathsf{sk}_{par},\mathsf{c}_{par}), i)\!` +- Return $\mathsf{CKDh}^{\mathsf{Issuance}}((\mathsf{sk}_{par},\mathsf{c}_{par}), i)$ -We use the notation of ZIP 32 [#zip-0032-orchard-key-path]_ for shielded HD paths, and define the issuance authorizing key path as :math:`m_{\mathsf{Issuance}} / \mathit{purpose}' / \mathit{coin\_type}' / \mathit{account}'\!`. We fix the path levels as follows: +We use the notation of ZIP 32 [#zip-0032-orchard-key-path]_ for shielded HD paths, and define the issuance authorizing key path as $m_{\mathsf{Issuance}} / \mathit{purpose}' / \mathit{coin\_type}' / \mathit{account}'.$ We fix the path levels as follows: -- :math:`\mathit{purpose}`: a constant set to :math:`227` (i.e. :math:`\mathtt{0xe3}\!`). :math:`\mathit{purpose}'` is thus :math:`227'` (or :math:`\mathtt{0x800000e3}\!`) following the BIP 43 recommendation. -- :math:`\mathit{coin\_type}`: Defined as in ZIP 32 [#zip-0032-key-path-levels]_. -- :math:`\mathit{account}`: fixed to index :math:`0\!`. +- $\mathit{purpose}$: a constant set to $227$ (i.e. $\mathtt{0xe3}$). $\mathit{purpose}'$ is thus $227'$ (or $\mathtt{0x800000e3}$) following the BIP 43 recommendation. [#bip-0043]_ +- $\mathit{coin\_type}$: Defined as in ZIP 32 [#zip-0032-key-path-levels]_. +- $\mathit{account}$: fixed to index $0$. -From the generated :math:`(\mathsf{sk}, \mathsf{c})\!`, we set the issuance authorizing key to be :math:`\mathsf{isk} := \mathsf{sk}\!`. +From the generated $(\mathsf{sk}, \mathsf{c})$, we set the issuance authorizing key to be $\mathsf{isk} := \mathsf{sk}$. Derivation of issuance validating key ````````````````````````````````````` -Define :math:`\mathsf{IssueAuthSig}.\!\mathsf{DerivePublic}\; : \; (\mathsf{isk}\; : \; \mathsf{IssueAuthSig}.\!\mathsf{Private}) \to \mathsf{IssueAuthSig}.\!\mathsf{Public}` as: +Define $\mathsf{IssueAuthSig.DerivePublic} \;{\small ⦂}\; (\mathsf{isk} \;{\small ⦂}\; \mathsf{IssueAuthSig.Private}) \to \mathsf{IssueAuthSig.Public}$ as: -* :math:`\mathsf{ik} := \textit{PubKey}(\mathsf{isk})` -* Return :math:`\bot` if the :math:`\textit{PubKey}` algorithm invocation fails, otherwise return :math:`\mathsf{ik}\!`. +* $\mathsf{ik} := \textit{PubKey}(\mathsf{isk})$ +* Return $\bot$ if the $\textit{PubKey}$ algorithm invocation fails, otherwise return $\mathsf{ik}$. -where the :math:`\textit{PubKey}` algorithm is defined in BIP 340 [#bip-0340]_. -Note that the byte representation of :math:`\mathsf{ik}` is in big-endian order as defined in BIP 340. +where the $\textit{PubKey}$ algorithm is defined in BIP 340 [#bip-0340]_. +Note that the byte representation of $\mathsf{ik}$ is in big-endian order as defined in BIP 340. -It is possible for the :math:`\textit{PubKey}` algorithm to fail with very low probability, which means that :math:`\mathsf{IssueAuthSig}.\!\mathsf{DerivePublic}` could return :math:`\bot` with very low probability. -If this happens, discard the keys and repeat with a different :math:`\mathsf{isk}\!`. +It is possible for the $\textit{PubKey}$ algorithm to fail with very low probability, which means that $\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 [#zip-0032]_. 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. Issuance Authorization Signing and Validation --------------------------------------------- -Define :math:`\mathsf{IssueAuthSig}.\!\mathsf{Sign}\; : \; (\mathsf{isk}\; : \; \mathsf{IssueAuthSig}.\!\mathsf{Private}) \times (M\; : \; \mathsf{IssueAuthSig}.\!\mathsf{Message}) \to \mathsf{IssueAuthSig}.\!\mathsf{Signature}` as: +Define $\mathsf{IssueAuthSig.Sign} \;{\small ⦂}\; (\mathsf{isk} \;{\small ⦂}\; \mathsf{IssueAuthSig.Private}) \times (M \;{\small ⦂}\; \mathsf{IssueAuthSig.Message}) \to \mathsf{IssueAuthSig.Signature}$ as: -* Let the auxiliary data :math:`a = [\mathtt{0x00}]^{32}\!`. -* Let :math:`\text{σ} = \mathsf{Sign}(\mathsf{isk}, M)\!`. -* Return :math:`\bot` if the :math:`\mathsf{Sign}` algorithm fails in the previous step, otherwise return :math:`\text{σ}\!`. +* Let the auxiliary data $a = [\mathtt{0x00}]^{32}$. +* Let $\text{σ} = \mathsf{Sign}(\mathsf{isk}, M)$. +* Return $\bot$ if the $\mathsf{Sign}$ algorithm fails in the previous step, otherwise return $\text{σ}$. -where the :math:`\mathsf{Sign}` algorithm is defined in BIP 340 and :math:`a` denotes the auxiliary data used in BIP 340 [#bip-0340]_. -Note that :math:`\mathsf{IssueAuthSig}.\!\mathsf{Sign}` could return :math:`\bot` with very low probability. +where the $\mathsf{Sign}$ algorithm is defined in BIP 340 and $a$ denotes the auxiliary data used in BIP 340 [#bip-0340]_. +Note that $\mathsf{IssueAuthSig.Sign}$ could return $\bot$ with very low probability. -Define :math:`\mathsf{IssueAuthSig}.\!\mathsf{Validate}\; : \; (\mathsf{ik}\; : \; \mathsf{IssueAuthSig}.\!\mathsf{Public}) \times (M\; : \; \mathsf{IssueAuthSig}.\!\mathsf{Message}) \times (\text{σ}\; : \; \mathsf{IssueAuthSig}.\!\mathsf{Signature}) \to \mathbb{B}` as: +Define $\mathsf{IssueAuthSig.Validate} \;{\small ⦂}\; (\mathsf{ik} \;{\small ⦂}\; \mathsf{IssueAuthSig.Public}) \times (M \;{\small ⦂}\; \mathsf{IssueAuthSig.Message}) \times (\text{σ} \;{\small ⦂}\; \mathsf{IssueAuthSig.Signature}) \to \mathbb{B}$ as: -* Return :math:`0` if :math:`\text{σ} = \bot\!`. -* Return :math:`1` if :math:`\mathsf{Verify}(\mathsf{ik}, M, \text{σ})` succeeds, otherwise :math:`0\!`. +* Return $0$ if $\text{σ} = \bot$. +* Return $1$ if $\mathsf{Verify}(\mathsf{ik}, M, \text{σ})$ succeeds, otherwise $0$. -where the :math:`\mathsf{Verify}` algorithm is defined in BIP 340 [#bip-0340]_. +where the $\mathsf{Verify}$ algorithm is defined in BIP 340 [#bip-0340]_. Specification: Asset Identifier =============================== -For every new Asset, there must be a new and unique Asset Identifier, denoted :math:`\mathsf{AssetId}\!`. We define this to be a globally unique pair :math:`\mathsf{AssetId} := (\mathsf{ik}, \mathsf{asset\_desc})\!`, where :math:`\mathsf{ik}` is the issuance key and :math:`\mathsf{asset\_desc}` is a byte string. +For every new Asset, there must be a new and unique Asset Identifier, denoted $\mathsf{AssetId}$. We define this to be a globally unique pair $\mathsf{AssetId} := (\mathsf{ik}, \mathsf{asset\_desc})$, where $\mathsf{ik}$ is the issuance key and $\mathsf{asset\_desc}$ is a byte string. -A given Asset Identifier is used across all Zcash protocols that support ZSAs -- that is, the Orchard-ZSA protocol and potentially future Zcash shielded protocols. For this Asset Identifier, we derive an Asset Digest, :math:`\mathsf{AssetDigest}\!`, which is simply is a :math:`\textsf{BLAKE2b-512}` hash of the Asset Identifier. +A given Asset Identifier is used across all Zcash protocols that support ZSAs -- that is, the Orchard-ZSA protocol and potentially future Zcash shielded protocols. For this Asset Identifier, we derive an Asset Digest, $\mathsf{AssetDigest}$, which is simply is a $\textsf{BLAKE2b-512}$ hash of the Asset Identifier. From the Asset Digest, we derive a specific Asset Base within each shielded protocol using the applicable hash-to-curve algorithm. This Asset Base is included in shielded notes. Let -- :math:`\mathsf{asset\_desc}` be the asset description, which includes any information pertaining to the issuance, and is a byte sequence of up to 512 bytes which SHOULD be a well-formed UTF-8 code unit sequence according to Unicode 15.0.0 or later. -- :math:`\mathsf{ik}` be the issuance validating key of the issuer, a public key used to verify the signature on the issuance transaction's SIGHASH. +- $\mathsf{asset\_desc}$ be the asset description, which includes any information pertaining to the issuance, and is a byte sequence of up to 512 bytes which SHOULD be a well-formed UTF-8 code unit sequence according to Unicode 15.0.0 or later. +- $\mathsf{ik}$ be the issuance validating key of the issuer, a public key used to verify the signature on the issuance transaction's SIGHASH. -Define :math:`\mathsf{AssetDigest_{AssetId}} := \textsf{BLAKE2b-512}(\texttt{"ZSA-Asset-Digest"},\; \mathsf{EncodeAssetId}(\mathsf{AssetId}))\!`, +Define $\mathsf{AssetDigest_{AssetId}} := \textsf{BLAKE2b-512}(\texttt{“ZSA-Asset-Digest”},\; \mathsf{EncodeAssetId}(\mathsf{AssetId}))$, where -- :math:`\mathsf{EncodeAssetId}(\mathsf{AssetId}) = \mathsf{EncodeAssetId}((\mathsf{ik}, \mathsf{asset\_desc})) := \mathtt{0x00} || \mathsf{ik} || \mathsf{asset\_desc}\!\!`. -- Note that the initial :math:`\mathtt{0x00}` byte is a version byte. +- $\mathsf{EncodeAssetId}(\mathsf{AssetId}) = \mathsf{EncodeAssetId}((\mathsf{ik}, \mathsf{asset\_desc})) := \mathtt{0x00} || \mathsf{ik} || \mathsf{asset\_desc}\!$. +- Note that the initial $\mathtt{0x00}$ byte is a version byte. -Define :math:`\mathsf{AssetBase_{AssetId}} := \mathsf{ZSAValueBase}(\mathsf{AssetDigest_{AssetId}})` +Define $\mathsf{AssetBase_{AssetId}} := \mathsf{ZSAValueBase}(\mathsf{AssetDigest_{AssetId}})$ -In the case of the Orchard-ZSA protocol, we define :math:`\mathsf{ZSAValueBase}(\mathsf{AssetDigest_{AssetId}}) := \mathsf{GroupHash}^\mathbb{P}(\texttt{"z.cash:OrchardZSA"}, \mathsf{AssetDigest_{AssetId}})` -where :math:`\mathsf{GroupHash}^\mathbb{P}` is defined as in [#protocol-concretegrouphashpallasandvesta]_. +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}})$ +where $\mathsf{GroupHash}^\mathbb{P}$ is defined as in [#protocol-concretegrouphashpallasandvesta]_. The relations between the Asset Identifier, Asset Digest, and Asset Base are shown in the following diagram: @@ -216,9 +216,9 @@ The relations between the Asset Identifier, Asset Digest, and Asset Base are sho Diagram relating the Asset Identifier, Asset Digest, and Asset Base in the ZSA Protocol -**Note:** To keep notations light and concise, we may omit :math:`\mathsf{AssetId}` (resp. :math:`\mathsf{Protocol}\!`) in the subscript (resp. superscript) when the Asset Identifier (resp. Protocol) is clear from the context. +**Note:** To keep notations light and concise, we may omit $\mathsf{AssetId}$ (resp. $\mathsf{Protocol}$) in the subscript (resp. superscript) when the Asset Identifier (resp. Protocol) is clear from the context. -Wallets MUST NOT display just the :math:`\mathsf{asset\_desc}` string to their users as the name of the Asset. Some possible alternatives include: +Wallets MUST NOT display just the $\mathsf{asset\_desc}$ string to their users as the name of the Asset. Some possible alternatives include: - Wallets could allow clients to provide an additional configuration file that stores a one-to-one mapping of names to Asset Identifiers via a petname system. This allows clients to rename the Assets in a way they find useful. Default versions of this file with well-known Assets listed can be made available online as a starting point for clients. - The Asset Digest could be used as a more compact bytestring to uniquely determine an Asset, and wallets could support clients scanning QR codes to load Asset information into their wallets. @@ -228,13 +228,13 @@ Specification: Global Issuance State Issuance requires the following additions to the global state defined at block boundaries: -A map, :math:`\mathsf{issued\_assets}\!`, from the Asset Base, :math:`\mathsf{AssetBase}`, to a tuple :math:`(\mathsf{balance}, \mathsf{final})\!`, for every Asset that has been issued up until the block boundary. For each Asset: +A map, $\mathsf{issued\_assets}$, from the Asset Base, $\mathsf{AssetBase}$, to a tuple $(\mathsf{balance}, \mathsf{final})$, for every Asset that has been issued up until the block boundary. For each Asset: -- The amount of the Asset in circulation, computed as the amount of the Asset that has been issued less the amount of the Asset that has been burnt, is stored in :math:`\mathsf{balance}\!`. -- The boolean :math:`\mathsf{final}` stores the finalization status of the Asset (i.e.: whether the :math:`\mathsf{finalize}` flag has been set to :math:`1` in some issuance transaction for the Asset preceding the block boundary). The value of :math:`\mathsf{final}` for any Asset cannot be changed from :math:`1` to :math:`0`. +- The amount of the Asset in circulation, computed as the amount of the Asset that has been issued less the amount of the Asset that has been burnt, is stored in $\mathsf{balance}$. +- The boolean $\mathsf{final}$ stores the finalization status of the Asset (i.e.: whether the $\mathsf{finalize}$ flag has been set to $1$ in some issuance transaction for the Asset preceding the block boundary). The value of $\mathsf{final}$ for any Asset cannot be changed from $1$ to $0$. -We use the notation :math:`\mathsf{issued\_assets}(\mathsf{AssetBase}).\!\mathsf{balance}` and :math:`\mathsf{issued\_assets}(\mathsf{AssetBase}).\!\mathsf{final}` to access, respectively, the balance and finalization status of the Asset stored in the global state. +We use the notation $\mathsf{issued\_assets}(\mathsf{AssetBase}).\!\mathsf{balance}$ and $\mathsf{issued\_assets}(\mathsf{AssetBase}).\!\mathsf{final}$ to access, respectively, the balance and finalization status of the Asset stored in the global state. Rationale for Global Issuance State ----------------------------------- @@ -245,7 +245,7 @@ Therefore, we require that all nodes maintain a record of the current amount in 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 :math:`\mathsf{issued\_assets}` map allows nodes to store whether or not a given Asset has been finalized. +The $\mathsf{issued\_assets}$ map allows nodes to store whether or not a given Asset has been finalized. Specification: Issuance Action, Issuance Bundle and Issuance Protocol ===================================================================== @@ -255,12 +255,12 @@ Issuance Action Description An issuance action, ``IssueAction``, is the instance of issuing a specific Custom Asset, and contains the following fields: -- ``assetDescSize``: the size of the Asset description, a number between :math:`0` and :math:`512\!`, stored in two bytes. +- ``assetDescSize``: the size of the Asset description, a number between $0$ and $512$, stored in two bytes. - ``asset_desc``: the Asset description, a byte string of up to 512 bytes as defined in the `Specification: Asset Identifier`_ section. - ``vNotes``: an array of ``Note`` containing the unencrypted output notes of the recipients of the Asset. -- ``flagsIssuance``: a byte that stores the :math:`\mathsf{finalize}` boolean that defines whether the issuance of that specific Custom Asset is finalized or not. +- ``flagsIssuance``: a byte that stores the $\mathsf{finalize}$ boolean that defines whether the issuance of that specific Custom Asset is finalized or not. -An asset's :math:`\mathsf{AssetDigest}` is added to the :math:`\mathsf{previously\_finalized}` set after a block that contains any issuance transaction for that asset with :math:`\mathsf{finalize} = 1\!`. It then cannot be removed from this set. For Assets with :math:`\mathsf{AssetDigest} \in \mathsf{previously\_finalized}\!`, no further tokens can be issued, so as seen below, the validators will reject the transaction. For Assets with :math:`\mathsf{AssetDigest} \not\in \mathsf{previously\_finalized}\!`, new issuance actions can be issued in future transactions. These must use the same Asset description, :math:`\mathsf{asset\_desc}\!`, and can either maintain :math:`\mathsf{finalize} = 0` or change it to :math:`\mathsf{finalize} = 1\!`, denoting that this Custom Asset cannot be issued after the containing block. +An asset's $\mathsf{AssetDigest}$ is added to the $\mathsf{previously\_finalized}$ set after a block that contains any issuance transaction for that asset with $\mathsf{finalize} = 1$. It then cannot be removed from this set. For Assets with $\mathsf{AssetDigest} \in \mathsf{previously\_finalized}$, no further tokens can be issued, so as seen below, the validators will reject the transaction. For Assets with $\mathsf{AssetDigest} \not\in \mathsf{previously\_finalized}$, new issuance actions can be issued in future transactions. These must use the same Asset description, $\mathsf{asset\_desc}$, and can either maintain $\mathsf{finalize} = 0$ or change it to $\mathsf{finalize} = 1$, denoting that this Custom Asset cannot be issued after the containing block. +-----------------------------+--------------------------+-------------------------------------------+---------------------------------------------------------------------+ @@ -292,9 +292,9 @@ An issuance bundle, ``IssueBundle``, is the aggregate of all the issuance-relate Specifically, contains all the issuance actions and the issuer signature on the transaction SIGHASH that validates the issuance itself. It contains the following fields: -- :math:`\mathsf{ik}`: the issuance validating key, that allows the validators to verify that the :math:`\mathsf{AssetId}` is properly associated with the issuer. +- $\mathsf{ik}$: the issuance validating key, that allows the validators to verify that the $\mathsf{AssetId}$ is properly associated with the issuer. - ``vIssueActions``: an array of issuance actions, of type ``IssueAction``. -- :math:`\mathsf{issueAuthSig}`: the signature of the transaction SIGHASH, signed by the issuance authorizing key, :math:`\mathsf{isk}\!`, that validates the issuance. +- $\mathsf{issueAuthSig}$: the signature of the transaction SIGHASH, signed by the issuance authorizing key, $\mathsf{isk}$, that validates the issuance. 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 [#protocol-txnencoding]_. @@ -318,21 +318,21 @@ The issuer program performs the following operations: For all actions ``IssueAction``: -- encode :math:`\mathsf{asset\_desc}` as a UTF-8 byte string of size up to 512. -- compute :math:`\mathsf{AssetDigest}` from the issuance validating key :math:`\mathsf{ik}` and :math:`\mathsf{asset\_desc}` as decribed in the `Specification: Asset Identifier`_ section. -- compute :math:`\mathsf{AssetBase}` from :math:`\mathsf{AssetDigest}` as decribed in the `Specification: Asset Identifier`_ section. -- set the :math:`\mathsf{finalize}` boolean as desired (if more issuance actions are to be created for this :math:`\mathsf{AssetBase}\!`, set :math:`\mathsf{finalize} = 0\!`, otherwise set :math:`\mathsf{finalize} = 1\!`). -- for each recipient :math:`i`: +- encode $\mathsf{asset\_desc}$ as a UTF-8 byte string of size up to 512. +- compute $\mathsf{AssetDigest}$ from the issuance validating key $\mathsf{ik}$ and $\mathsf{asset\_desc}$ as decribed in the `Specification: Asset Identifier`_ section. +- compute $\mathsf{AssetBase}$ from $\mathsf{AssetDigest}$ as decribed in the `Specification: Asset Identifier`_ section. +- set the $\mathsf{finalize}$ boolean as desired (if more issuance actions are to be created for this $\mathsf{AssetBase}$, set $\mathsf{finalize} = 0$, otherwise set $\mathsf{finalize} = 1$). +- for each recipient $i$: - - generate a ZSA output note that includes the Asset Base. For an Orchard-ZSA note this is :math:`\mathsf{note}_i = (\mathsf{d}_i, \mathsf{pk}_{\mathsf{d}_i}, \mathsf{v}_i, \text{ρ}_i, \mathsf{rseed}_i, \mathsf{AssetBase}, \mathsf{rcm}_i)\!`. + - generate a ZSA output note that includes the Asset Base. For an Orchard-ZSA note this is $\mathsf{note}_i = (\mathsf{d}_i, \mathsf{pk}_{\mathsf{d}_i}, \mathsf{v}_i, \text{ρ}_i, \mathsf{rseed}_i, \mathsf{AssetBase}, \mathsf{rcm}_i)$. - encode the ``IssueAction`` into the vector ``vIssueActions`` of the bundle. For the ``IssueBundle``: - encode the ``vIssueActions`` vector. -- encode the :math:`\mathsf{ik}` as 32 byte-string. -- sign the SIGHASH transaction hash with the issuance authorizing key, :math:`\mathsf{isk}\!`, using the :math:`\mathsf{IssueAuthSig}` signature scheme. The signature is then added to the issuance bundle. +- encode the $\mathsf{ik}$ as 32 byte-string. +- sign the SIGHASH transaction hash with the issuance authorizing key, $\mathsf{isk}$, using the $\mathsf{IssueAuthSig}$ signature scheme. The signature is then added to the issuance bundle. **Note:** that the commitment is not included in the ``IssuanceAction`` itself. As explained below, it is computed later by the validators and added to the note commitment tree. @@ -343,26 +343,26 @@ Specification: Consensus Rule Changes For the ``IssueBundle``: -- Validate the issuance authorization signature, :math:`\mathsf{issueAuthSig}\!`, on the SIGHASH transaction hash, :math:`\mathsf{SigHash}\!`, by invoking :math:`\mathsf{IssueAuthSig}.\!\mathsf{Validate}(\mathsf{ik}, \mathsf{SigHash}, \mathsf{issueAuthSig})\!`. +- Validate the issuance authorization signature, $\mathsf{issueAuthSig}$, on the SIGHASH transaction hash, $\mathsf{SigHash}$, by invoking $\mathsf{IssueAuthSig.Validate}(\mathsf{ik}, \mathsf{SigHash}, \mathsf{issueAuthSig})$. For each ``IssueAction`` in ``IssueBundle``: -- check that :math:`0 < \mathtt{assetDescSize} \leq 512\!`. -- check that :math:`\mathsf{asset\_desc}` is a string of length :math:`\mathtt{assetDescSize}` bytes. +- check that $0 < \mathtt{assetDescSize} \leq 512$. +- check that $\mathsf{asset\_desc}$ is a string of length $\mathtt{assetDescSize}$ bytes. -- retrieve :math:`\mathsf{AssetBase}` from the first note in the sequence and check that :math:`\mathsf{AssetBase}` is derived from the issuance validating key :math:`\mathsf{ik}` and :math:`\mathsf{asset\_desc}` as described in the `Specification: Asset Identifier`_ section. -- check that :math:`\mathsf{issued\_assets(AssetBase).final} \neq 1` in the global state. -- check that every note in the ``IssueAction`` contains the same :math:`\mathsf{AssetBase}` and is properly constructed as :math:`\mathsf{note} = (\mathsf{g_d}, \mathsf{pk_d}, \mathsf{v}, \text{ρ}, \mathsf{rseed}, \mathsf{AssetBase})\!`. +- retrieve $\mathsf{AssetBase}$ from the first note in the sequence and check that $\mathsf{AssetBase}$ is derived from the issuance validating key $\mathsf{ik}$ and $\mathsf{asset\_desc}$ as described in the `Specification: Asset Identifier`_ section. +- check that $\mathsf{issued\_assets(AssetBase).final} \neq 1$ in the global state. +- check that every note in the ``IssueAction`` contains the same $\mathsf{AssetBase}$ and is properly constructed as $\mathsf{note} = (\mathsf{g_d}, \mathsf{pk_d}, \mathsf{v}, \text{ρ}, \mathsf{rseed}, \mathsf{AssetBase})$. If all of the above checks pass, do the following: - For each note, - - compute the note commitment as :math:`\mathsf{cm} = \mathsf{NoteCommit^{OrchardZSA}_{rcm}}(\mathsf{repr}_{\mathbb{P}}(\mathsf{g_d}), \mathsf{repr}_{\mathbb{P}}(\mathsf{pk_d}), \mathsf{v}, \text{ρ}, \text{ψ}, \mathsf{AssetBase})` as defined in the Note Structure and Commitment section of ZIP 226 [#zip-0226-notestructure]_. - - Add :math:`\mathsf{cm}` to the Merkle tree of note commitments. - - Increase the value of :math:`\mathsf{issued\_assets(AssetBase).balance}` by the value of the note, :math:`\mathsf{v}`. + - compute the note commitment as $\mathsf{cm} = \mathsf{NoteCommit^{OrchardZSA}_{rcm}}(\mathsf{repr}_{\mathbb{P}}(\mathsf{g_d}), \mathsf{repr}_{\mathbb{P}}(\mathsf{pk_d}), \mathsf{v}, \text{ρ}, \text{ψ}, \mathsf{AssetBase})$ as defined in the Note Structure and Commitment section of ZIP 226 [#zip-0226-notestructure]_. + - Add $\mathsf{cm}$ to the Merkle tree of note commitments. + - Increase the value of $\mathsf{issued\_assets(AssetBase).balance}$ by the value of the note, $\mathsf{v}$. -- If :math:`\mathsf{finalize} = 1\!`, set :math:`\mathsf{issued\_assets(AssetBase).final}` to :math:`1` in the global state. +- If $\mathsf{finalize} = 1$, set $\mathsf{issued\_assets(AssetBase).final}$ to $1$ in the global state. - (Replay Protection) If issue bundle is present, the fees MUST be greater than zero. @@ -374,14 +374,14 @@ The following is a list of rationale for different decisions made in the proposa - The issuance key structure is independent of the original key tree, but derived in an analogous manner (via ZIP 32). This is in order to keep the issuance details and the Asset Identifiers consistent across multiple shielded pools. - The design decision is not to have a chosen name to describe the Custom Asset, but to delegate it to an off-chain mapping, as this would imply a land-grab “war”. -- The :math:`\mathsf{asset\_desc}` is a general byte string in order to allow for a wide range of information type to be included that may be associated with the Assets. Some are: +- The $\mathsf{asset\_desc}$ is a general byte string in order to allow for a wide range of information type to be included that may be associated with the Assets. Some are: - links for storage such as for NFTs. - metadata for Assets, encoded in any format. - bridging information for Wrapped Assets (chain of origin, issuer name, etc) - information to be committed by the issuer, though not enforceable by the protocol. -- We limit the size of the :math:`\mathsf{asset\_desc}` string to 512 bytes as it is a reasonable size to store metadata about the Asset, for example in JSON format. +- We limit the size of the $\mathsf{asset\_desc}$ string to 512 bytes as it is a reasonable size to store metadata about the Asset, for example in JSON format. - We require non-zero fees in the presence of an issue bundle, in order to preclude the possibility of a transaction containing only an issue bundle. If a transaction includes only an issue bundle, the SIGHASH transaction hash would be computed solely based on the issue bundle. A duplicate bundle would have the same SIGHASH transaction hash, potentially allowing for a replay attack. Concrete Applications @@ -389,19 +389,19 @@ Concrete Applications **Asset Features** -- By using the :math:`\mathsf{finalize}` boolean and the burning mechanism defined in [#zip-0226]_, issuers can control the supply production of any Asset associated to their issuer keys. For example, +- By using the $\mathsf{finalize}$ boolean and the burning mechanism defined in [#zip-0226]_, issuers can control the supply production of any Asset associated to their issuer keys. For example, - - by setting :math:`\mathsf{finalize} = 1` from the first issuance action for that Asset Identifier, the issuer is in essence creating a one-time issuance transaction. This is useful when the max supply is capped from the beginning and the distribution is known in advance. All tokens are issued at once and distributed as needed. + - by setting $\mathsf{finalize} = 1$ from the first issuance action for that Asset Identifier, the issuer is in essence creating a one-time issuance transaction. This is useful when the max supply is capped from the beginning and the distribution is known in advance. All tokens are issued at once and distributed as needed. - Issuers can also stop the existing supply production of any Asset associated to their issuer keys. This could be done by - - issuing a last set of tokens of that specific :math:`\mathsf{AssetId}\!`, for which :math:`\mathsf{finalize} = 1\!`, or by - - issuing a transaction with a single note in the issuance action pertaining to that :math:`\mathsf{AssetId}\!`, where the note will contain a :math:`\mathsf{value} = 0\!`. This can be used for application-specific purposes (NFT collections) or for security purposes to revoke the Asset issuance (see Security and Privacy Considerations). - - Note in the above cases, that the setting of the :math:`\mathsf{finalize}` flag will take effect at the block boundary, that is, after all the transactions in the block. + - issuing a last set of tokens of that specific $\mathsf{AssetId}$, for which $\mathsf{finalize} = 1$, or by + - issuing a transaction with a single note in the issuance action pertaining to that $\mathsf{AssetId}$, where the note will contain a $\mathsf{value} = 0$. This can be used for application-specific purposes (NFT collections) or for security purposes to revoke the Asset issuance (see Security and Privacy Considerations). + - Note in the above cases, that the setting of the $\mathsf{finalize}$ flag will take effect at the block boundary, that is, after all the transactions in the block. - The issuance and burn mechanisms can be used in conjunction to determine the supply of Assets on the Zcash ecosystem. This allows for the bridging of Assets defined on other chains. -- Furthermore, NFT issuance is enabled by issuing in a single bundle several issuance actions, where each :math:`\mathsf{AssetId}` corresponds to :math:`\mathsf{value} = 1` at the fundamental unit level. Issuers and users should make sure that :math:`\mathsf{finalize} = 1` for each of the actions in this scenario. +- Furthermore, NFT issuance is enabled by issuing in a single bundle several issuance actions, where each $\mathsf{AssetId}$ corresponds to $\mathsf{value} = 1$ at the fundamental unit level. Issuers and users should make sure that $\mathsf{finalize} = 1$ for each of the actions in this scenario. @@ -496,7 +496,7 @@ T.5a.iii: flagsIssuance ''''''''''''''''''''''' An 8-bit value representing a set of flags. Ordered from LSB to MSB: -- :math:`\mathsf{finalize}` +- $\mathsf{finalize}$ - The remaining bits are set to `0\!`. @@ -587,7 +587,7 @@ Issuance Key Compromise The design of this protocol does not currently allow for rotation of the issuance validating key that would allow for replacing the key of a specific Asset. In case of compromise, the following actions are recommended: -- If an issuance validating key is compromised, the :math:`\mathsf{finalize}` boolean for all the Assets issued with that key should be set to :math:`1` and the issuer should change to a new issuance authorizing key, and issue new Assets, each with a new :math:`\mathsf{AssetId}\!`. +- If an issuance validating key is compromised, the $\mathsf{finalize}$ boolean for all the Assets issued with that key should be set to $1$ and the issuer should change to a new issuance authorizing key, and issue new Assets, each with a new $\mathsf{AssetId}$. Bridging Assets --------------- @@ -600,7 +600,7 @@ Other Considerations Implementing Zcash Nodes ------------------------ -Although not enforced in the global state, it is RECOMMENDED that Zcash full validators keep track of the total supply of Assets as a mutable mapping :math:`\mathsf{issuanceSupplyInfoMap}` from :math:`\mathsf{AssetId}` to :math:`(\mathsf{totalSupply}, \mathsf{finalize})` in order to properly keep track of the total supply for different Asset Identifiers. This is useful for wallets and other applications that need to keep track of the total supply of Assets. +Although not enforced in the global state, it is RECOMMENDED that Zcash full validators keep track of the total supply of Assets as a mutable mapping $\mathsf{issuanceSupplyInfoMap}$ from $\mathsf{AssetId}$ to $(\mathsf{totalSupply}, \mathsf{finalize})$ in order to properly keep track of the total supply for different Asset Identifiers. This is useful for wallets and other applications that need to keep track of the total supply of Assets. Fee Structures -------------- @@ -644,6 +644,7 @@ References .. [#zip-0244-sigdigest] `ZIP 244: Transaction Identifier Non-Malleability: Signature Digest `_ .. [#zip-0244-authcommitment] `ZIP 244: Transaction Identifier Non-Malleability: Authorizing Data Commitment `_ .. [#zip-0317b] `ZIP 317: Proportional Transfer Fee Mechanism `_ +.. [#bip-0043] `BIP 43: Purpose Field for Deterministic Wallets `_ .. [#bip-0340] `BIP 340: Schnorr Signatures for secp256k1 `_ .. [#protocol-notation] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 2: Notation `_ .. [#protocol-addressesandkeys] `Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 3.1: Payment Addresses and Keys `_ diff --git a/zips/zip-0230.rst b/zips/zip-0230.rst index eef1b6d00..05a236f8b 100644 --- a/zips/zip-0230.rst +++ b/zips/zip-0230.rst @@ -217,10 +217,10 @@ Transaction Format * The fields ``valueBalanceSapling`` and ``bindingSigSapling`` are present if and only if - :math:`\mathtt{nSpendsSapling} + \mathtt{nOutputsSapling} > 0\!`. If ``valueBalanceSapling`` - is not present, then :math:`\mathsf{v^{balanceSapling}}`` is defined to be :math:`0\!`. + $\mathtt{nSpendsSapling} + \mathtt{nOutputsSapling} > 0$. If ``valueBalanceSapling`` + is not present, then $\mathsf{v^{balanceSapling}}$ is defined to be $0$. -* The field ``anchorSapling`` is present if and only if :math:`\mathtt{nSpendsSapling} > 0\!`. +* The field ``anchorSapling`` is present if and only if $\mathtt{nSpendsSapling} > 0$. * The elements of ``vSpendProofsSapling`` and ``vSpendAuthSigsSapling`` have a 1:1 correspondence to the elements of ``vSpendsSapling`` and MUST be ordered such that the @@ -233,17 +233,17 @@ Transaction Format * The fields ``flagsOrchard``, ``valueBalanceOrchard``, ``anchorOrchard``, ``sizeProofsOrchardZSA``, ``proofsOrchardZSA``, and ``bindingSigOrchard`` are present if and - only if :math:`\mathtt{nActionsOrchard} > 0\!`. If ``valueBalanceOrchard`` is not present, - then :math:`\mathsf{v^{balanceOrchard}}` is defined to be :math:`0\!`. + only if $\mathtt{nActionsOrchard} > 0$. If ``valueBalanceOrchard`` is not present, + then $\mathsf{v^{balanceOrchard}}$ is defined to be $0$. * The proofs aggregated in ``proofsOrchardZSA``, 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 ``OrchardZsaAction`` at the same index. -* The fields ``ik`` and ``issueAuthSig`` are present if and only if :math:`\mathtt{nIssueActions} > 0\!`. +* The fields ``ik`` and ``issueAuthSig`` are present if and only if $\mathtt{nIssueActions} > 0$. -* For coinbase transactions, the ``enableSpendsOrchard`` and ``enableZSAs`` bits MUST be set to :math:`0\!`. +* For coinbase transactions, the ``enableSpendsOrchard`` and ``enableZSAs`` bits 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 ``SpendDescriptionV6``, ``OutputDescriptionV6`` @@ -400,39 +400,38 @@ In addition to the parameters defined in the Fee calculation section of ZIP 317 ===================================== ========================================================================== Parameter Value ===================================== ========================================================================== -:math:`issuance\_fee` :math:`100 \cdot marginal\_fee` per issuance action (as defined below) +:math:`\mathsf{issuance\_fee}` :math:`100 \cdot marginal\_fee` per issuance action (as defined below) ===================================== ========================================================================== -Wallets implementing this specification SHOULD use a conventional fee, viz. :math:`zsa\_conventional\_fee`, that is +Wallets implementing this specification SHOULD use a conventional fee, viz. $\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: -================================ ====== ==================================================================================================================== -Input Units Description -================================ ====== ==================================================================================================================== -:math:`nOrchardActions` number the number of OrchardZSA transfer actions (including ZEC actions) -:math:`nTotalOutputsZsaIssuance` number the total number of OrchardZSA issuance outputs (added across issuance actions) -:math:`nCreateActions` number the number of OrchardZSA issuance actions that issue a Custom Asset that is not present in the Global Issuance State -================================ ====== ==================================================================================================================== +========================================= ====== ==================================================================================================================== +Input Units Description +========================================= ====== ==================================================================================================================== +:math:`\mathsf{nOrchardActions}` number the number of OrchardZSA transfer actions (including ZEC actions) +:math:`\mathsf{nTotalOutputsZsaIssuance}` number the total number of OrchardZSA issuance outputs (added across issuance actions) +:math:`\mathsf{nCreateActions}` number the number of OrchardZSA issuance actions that issue a Custom Asset that is not present in the Global Issuance State +========================================= ====== ==================================================================================================================== The other inputs to this formula are taken from transaction fields defined in the Zcash protocol specification [#protocol-txnencoding]_ and the global state. They are defined in the Fee calculation section of ZIP 317 [#zip-0317-fee-calc]_. -Note that :math:`nOrchardActions`, that is used in the computation of :math:`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. +Note that $\mathsf{nOrchardActions}$, that is used in the computation of $\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 :math:`zsa\_logical\_actions` (with the updated computation of :math:`logical\_actions` as described above) is: +The formula for the computation of the $\mathsf{zsa\_logical\_actions}$ (with the updated computation of +$\mathsf{logical\_actions}$ as described above) is: .. math:: - zsa\_logical\_actions = logical\_actions \;+ nTotalOutputsZsaIssuance + \mathsf{zsa\_logical\_actions} = \mathsf{logical\_actions} \;+ \mathsf{nTotalOutputsZsaIssuance} -The formula for the computation of the :math:`zsa\_conventional\_fee` is: +The formula for the computation of the $\mathsf{zsa\_conventional\_fee}$ is: .. math:: - \begin{array}{rcl} - zsa\_conventional\_fee &=& marginal\_fee \cdot \mathsf{max}(grace\_actions, zsa\_logical\_actions) \;+ \\ - & & issuance\_fee \cdot nCreateActions - \end{array} - - - + \begin{array}{rcl} + \mathsf{zsa\_conventional\_fee} &=& \mathsf{marginal\_fee} \cdot \mathsf{max}(\mathsf{grace\_actions}, \mathsf{zsa\_logical\_actions}) \;+ \\ + & & \mathsf{issuance\_fee} \cdot \mathsf{nCreateActions} + \end{array} It is not a consensus requirement that fees follow this formula; however, wallets SHOULD create transactions that pay this fee, in order to reduce diff --git a/zips/zip-0231.md b/zips/zip-0231.md index 3d1c96231..dc41d80a0 100644 --- a/zips/zip-0231.md +++ b/zips/zip-0231.md @@ -136,7 +136,7 @@ be used to encrypt more than one memo within a single transaction. If an output no memo data, it is assigned the memo key consisting of 32 $\mathtt{0xFF}$ bytes. In note plaintexts of v6-onward transactions, the 512-byte memo field is replaced -by $\mathsf{K^{memo}}\!$. +by $\mathsf{K^{memo}}$. The transaction builder generates a 32-byte salt value $\mathsf{salt}$ from a CSPRNG. A new salt MUST be generated for each memo bundle. @@ -159,7 +159,7 @@ as follows: $\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}]\!$. +where $\mathsf{nonce} = \mathsf{I2BEOSP}_{88}(\mathsf{counter}) \,||\, [\mathsf{final\_chunk}]$. This is a variant of the STREAM construction [^stream]. @@ -270,23 +270,23 @@ In § 3.2.1 ‘Note Plaintexts and Memo Fields’: * Change - > Each Sapling or Orchard note plaintext (denoted $\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 Sapling or Orchard note plaintext (denoted $\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 + to - > The form of a Sapling or Orchard note plaintext depends on 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 $\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 $\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]}})$ + > The form of a Sapling or Orchard note plaintext depends on 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 $\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 $\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’ [^protocol-noteptencoding]: @@ -295,21 +295,21 @@ In § 5.5 ‘Encodings of Note Plaintexts and Memo Fields’ [^protocol-notepten * Add a new paragraph at the end of the section: - > The encoding of a v6-onward Sapling or Orchard note plaintext consists of: - > - > | | | | | | - > |---------------------------|---------------------|---------------------|--------------------------|-----------------------------| - > | 8-bit $\mathsf{leadByte}$ | 88-bit $\mathsf{d}$ | 64-bit $\mathsf{v}$ | 256-bit $\mathsf{rseed}$ | 32-byte $\mathsf{K^{memo}}$ | - > - > * A byte 0x03, indicating this version of the encoding of a v6-onward - > Sapling or Orchard note plaintext. - > * 11 bytes specifying $\mathsf{d}$. - > * 8 bytes specifying $\mathsf{v}$. - > * 32 bytes specifying $\mathsf{rseed}$. - > * 32 bytes specifying $\mathsf{K^{memo}}$. - > - > A value consisting of 32 $\mathtt{0xFF}$ bytes for $\mathsf{K^{memo}}$ is used - > to indicate that there is no memo for this note plaintext. + > The encoding of a v6-onward Sapling or Orchard note plaintext consists of: + > + > | | | | | | + > |---------------------------|---------------------|---------------------|--------------------------|-----------------------------| + > | 8-bit $\mathsf{leadByte}$ | 88-bit $\mathsf{d}$ | 64-bit $\mathsf{v}$ | 256-bit $\mathsf{rseed}$ | 32-byte $\mathsf{K^{memo}}$ | + > + > * A byte 0x03, indicating this version of the encoding of a v6-onward + > Sapling or Orchard note plaintext. + > * 11 bytes specifying $\mathsf{d}$. + > * 8 bytes specifying $\mathsf{v}$. + > * 32 bytes specifying $\mathsf{rseed}$. + > * 32 bytes specifying $\mathsf{K^{memo}}$. + > + > A value consisting of 32 $\mathtt{0xFF}$ bytes for $\mathsf{K^{memo}}$ is used + > to indicate that there is no memo for this note plaintext. In § 4.7.2 ‘Sending Notes (Sapling)’ [^protocol-saplingsend] and § 4.7.3 ‘Sending Notes (Orchard)’ [^protocol-orchardsend]: @@ -319,38 +319,38 @@ In § 4.7.2 ‘Sending Notes (Sapling)’ [^protocol-saplingsend] and * Change - > Let $\mathbf{np} = (\mathsf{leadByte}, \mathsf{d}, \mathsf{v}, \mathsf{rseed}, \mathsf{memo})\!$. + > Let $\mathbf{np} = (\mathsf{leadByte}, \mathsf{d}, \mathsf{v}, \mathsf{rseed}, \mathsf{memo})$. - to + to - > 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. + > 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. + replacing "Sapling" with Orchard in the case of § 4.7.3. In § 4.20.1 ‘Encryption (Sapling and Orchard)’ [^protocol-saplingandorchardinband]: * Change - > 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’. + > 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 + to - > 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’. + > 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: - > * $\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. + > * $\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. In § 4.20.2 ‘Decryption using an Incoming Viewing Key (Sapling and Orchard)’ [^protocol-decryptivk] and § 4.20.3 ‘Decryption using a Full Viewing Key (Sapling and Orchard)’ [^protocol-decryptovk]: -* Replace $\mathsf{memo} ⦂ \mathbb{B^{Y[512]}}$ with $\mathsf{memoOrKey}$. +* Replace $\mathsf{memo} \;⦂\; \mathbb{B^{Y[512]}}$ with $\mathsf{memoOrKey}$. * Specify that the type of $\mathsf{memoOrKey}$ is $\mathbb{B^{Y[512]}}$ when decrypting a pre-v6 note ciphertext, or $\mathbb{B^{Y[32]}}$ when decrypting a v6-onward note ciphertext. In the latter case, it is used as $\mathsf{K^{memo}}$ @@ -394,10 +394,8 @@ With 10 KiB limit on amount of memo data as the constant in this table, the maximum number of unique memos you can create, and the cost in bytes of that memo data plus auth when using a 32-byte memo key, is: -| | 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%) | @@ -415,10 +413,8 @@ in between). If we used a 16-byte memo key instead of 32 bytes, the transaction size overhead becomes: -| | 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%) | diff --git a/zips/zip-0234.md b/zips/zip-0234.md index 56bc883f7..bcc331b30 100644 --- a/zips/zip-0234.md +++ b/zips/zip-0234.md @@ -54,7 +54,7 @@ calculated by $\mathsf{IssuedSupply}(\mathsf{height})$ defined in "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 -$\mathsf{MAX\_MONEY} - \mathsf{IssuedSupply}(\mathsf{height})\!$. +$\mathsf{MAX\_MONEY} - \mathsf{IssuedSupply}(\mathsf{height})$. # Abstract @@ -122,9 +122,9 @@ that satisfies the following requirements: ## Parameters -$\mathtt{BLOCK\_SUBSIDY\_FRACTION} = 4126 / 10\_000\_000\_000 = 0.0000004126$ +$\mathsf{BLOCK\_SUBSIDY\_FRACTION} = 4126 / 10\_000\_000\_000 = 0.0000004126$ -`DEPLOYMENT_BLOCK_HEIGHT` = `TBD` +$\mathsf{DEPLOYMENT\_BLOCK\_HEIGHT} = \mathsf{TBD}$ The block height will be chosen by the following criteria: @@ -146,10 +146,10 @@ whether or not burns are accounted for (since future burns cannot be 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 -$\mathtt{BLOCK\_SUBSIDY\_FRACTION}$. For example, if a total of 100,000 ZEC +$\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\text{ ZEC} \cdot \mathtt{BLOCK\_SUBSIDY\_FRACTION}\!$, +$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 @@ -157,15 +157,15 @@ 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. -$\mathsf{MoneyReserveAfter}(\mathsf{height}) \;\,=$ The value of the Money Reserve +$\mathsf{MoneyReserveAfter}(\mathsf{height}) =$ The value of the Money Reserve after the specified block height. ## Issuance Calculation -At the `DEPLOYMENT_BLOCK_HEIGHT`, nodes should switch from the current issuance +At the $\mathsf{DEPLOYMENT\_BLOCK\_HEIGHT}$, nodes should switch from the current issuance calculation, to the following: -$\mathsf{BlockSubsidy}(\mathsf{height}) = \mathsf{ceiling}(\mathtt{BLOCK\_SUBSIDY\_FRACTION} \cdot \mathsf{MoneyReserveAfter}(\mathsf{height} - 1))$ +$\mathsf{BlockSubsidy}(\mathsf{height}) = \mathsf{ceiling}(\mathsf{BLOCK\_SUBSIDY\_FRACTION} \cdot \mathsf{MoneyReserveAfter}(\mathsf{height} - 1))$ ## Applicability @@ -179,11 +179,11 @@ All of these changes apply identically to Mainnet and Testnet. ## BLOCK_SUBSIDY_FRACTION -Let $\mathsf{IntendedMoneyReserveFractionRemainingAfterFourYears} = 0.5\!$. +Let $\mathsf{IntendedMoneyReserveFractionRemainingAfterFourYears} = 0.5$. The value $4126 / 10\_000\_000\_000$ satisfies the approximation within $\pm 0.002\%$: -$(1 - \mathtt{BLOCK\_SUBSIDY\_FRACTION})^\mathsf{PostBlossomHalvingInterval} \approx \mathsf{IntendedMoneyReserveFractionRemainingAfterFourYears}$ +$(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**. @@ -191,7 +191,7 @@ have been issued as block subsidies, thus satisfying **Requirement 4**. The largest possible value in the Money Reserve is $\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\!$. +$\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. diff --git a/zips/zip-0235.md b/zips/zip-0235.md index 20de9bd7e..acfbdff73 100644 --- a/zips/zip-0235.md +++ b/zips/zip-0235.md @@ -99,7 +99,7 @@ to the long-term sustainability of the network as described below: For a given block, the coinbase transaction MUST have a $\mathsf{burn\_amount}$, as defined in [^zip-0233], that is greater than or equal to -$\mathsf{floor}(\mathsf{transactionFees} \cdot 6 / 10)\!$. +$\mathsf{floor}(\mathsf{transactionFees} \cdot 6 / 10)$. The version of a coinbase transaction MUST be v6 or later [^zip-0230]. @@ -174,6 +174,8 @@ ZIP 233 ("NSM: Burning" [^zip-0233]), and ZIP 234 ("NSM: Issuance Smoothing" [^protocol]: [Zcash Protocol Specification, Version 2024.5.1 [NU6] or later](protocol/protocol.pdf) +[^protocol-notation]: [Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 2: Notation](protocol/protocol.pdf#notation) + [^protocol-networks]: [Zcash Protocol Specification, Version 2024.5.1 [NU6]. Section 3.12: Mainnet and Testnet](protocol/protocol.pdf#networks) [^zip-0200]: [ZIP 200: Network Upgrade Mechanism](zip-0200.rst) diff --git a/zips/zip-0244.rst b/zips/zip-0244.rst index 8972feda7..19f5e10c3 100644 --- a/zips/zip-0244.rst +++ b/zips/zip-0244.rst @@ -762,9 +762,9 @@ 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 -:math:`\mathsf{ceil(log_2(tx\_count))}`, padded with leaves having the "null" -hash value ``[0u8; 32]``. Note that :math:`\mathsf{log_2(tx\_count)}` is -well-defined because :math:`\mathsf{tx\_count} > 0`, due to the coinbase +$\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$, due to the coinbase transaction in each block. Non-leaf hashes in this tree are BLAKE2b-256 hashes personalized by the string ``"ZcashAuthDatHash"``. diff --git a/zips/zip-0304.rst b/zips/zip-0304.rst index 995eefc7b..de65e29a6 100644 --- a/zips/zip-0304.rst +++ b/zips/zip-0304.rst @@ -67,29 +67,29 @@ Conventions The following constants and functions used in this ZIP are defined in the Zcash protocol specification: [#protocol]_ -- :math:`\mathsf{MerkleDepth}^\mathsf{Sapling}` and - :math:`\mathsf{Uncommitted}^\mathsf{Sapling}` [#protocol-constants]_ -- :math:`\mathsf{MerkleCRH}^\mathsf{Sapling}` [#protocol-saplingmerklecrh]_ -- :math:`\mathsf{DiversifyHash}(\mathsf{d})` [#protocol-concretediversifyhash]_ -- :math:`\mathsf{MixingPedersenHash}(\mathsf{cm}, position)` [#protocol-concretemixinghash]_ -- :math:`\mathsf{PRF}^\mathsf{nfSapling}_\mathsf{nk}(ρ)` [#protocol-concreteprfs]_ -- :math:`\mathsf{SpendAuthSig.RandomizePrivate}(α, \mathsf{sk})`, - :math:`\mathsf{SpendAuthSig.RandomizePublic}(α, \mathsf{vk})`, - :math:`\mathsf{SpendAuthSig.Sign}(\mathsf{sk}, m)`, and - :math:`\mathsf{SpendAuthSig.Verify}(\mathsf{vk}, m, σ)` [#protocol-concretespendauthsig]_ -- :math:`\mathsf{NoteCommit}^\mathsf{Sapling}_\mathsf{rcm}(\mathsf{g_d}, \mathsf{pk_d}, value)` [#protocol-concretewindowedcommit]_ -- :math:`\mathsf{ValueCommit}_\mathsf{rcv}(value)` [#protocol-concretehomomorphiccommit]_ +- $\mathsf{MerkleDepth}^\mathsf{Sapling}$ and + $\mathsf{Uncommitted}^\mathsf{Sapling}$ [#protocol-constants]_ +- $\mathsf{MerkleCRH}^\mathsf{Sapling}$ [#protocol-saplingmerklecrh]_ +- $\mathsf{DiversifyHash}(\mathsf{d})$ [#protocol-concretediversifyhash]_ +- $\mathsf{MixingPedersenHash}(\mathsf{cm}, position)$ [#protocol-concretemixinghash]_ +- $\mathsf{PRF}^\mathsf{nfSapling}_\mathsf{nk}(ρ)$ [#protocol-concreteprfs]_ +- $\mathsf{SpendAuthSig.RandomizePrivate}(α, \mathsf{sk})$, + $\mathsf{SpendAuthSig.RandomizePublic}(α, \mathsf{vk})$, + $\mathsf{SpendAuthSig.Sign}(\mathsf{sk}, m)$, and + $\mathsf{SpendAuthSig.Verify}(\mathsf{vk}, m, σ)$ [#protocol-concretespendauthsig]_ +- $\mathsf{NoteCommit}^\mathsf{Sapling}_\mathsf{rcm}(\mathsf{g_d}, \mathsf{pk_d}, value)$ [#protocol-concretewindowedcommit]_ +- $\mathsf{ValueCommit}_\mathsf{rcv}(value)$ [#protocol-concretehomomorphiccommit]_ We also reproduce some notation and functions here for convenience: -- :math:`a\,||\,b` means the concatenation of sequences :math:`a` then :math:`b`. +- $a\,||\,b$ means the concatenation of sequences $a$ then $b$. -- :math:`\mathsf{repr}_\mathbb{J}(P)` is the representation of the Jubjub elliptic curve - point :math:`P` as a bit sequence, defined in [#protocol-jubjub]_. +- $\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 +- $\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`. + string $p$, and input $x$. Requirements @@ -120,7 +120,7 @@ Specification A Sapling address signature is created by taking the process for creating a Sapling Spend description, and running it with fixed inputs: -- A fake Sapling note with a value of :math:`1` zatoshi and :math:`\mathsf{rcm} = 0`. +- A fake Sapling note with a value of $1$ zatoshi and $\mathsf{rcm} = 0$. - A Sapling commitment tree that is empty except for the commitment for the fake note. Signature algorithm @@ -128,86 +128,86 @@ Signature algorithm The inputs to the signature algorithm are: -- The payment address :math:`(\mathsf{d}, \mathsf{pk_d})`, -- Its corresponding expanded spending key :math:`(\mathsf{ask}, \mathsf{nsk}, \mathsf{ovk})`, +- The payment address $(\mathsf{d}, \mathsf{pk_d})$, +- Its corresponding expanded spending key $(\mathsf{ask}, \mathsf{nsk}, \mathsf{ovk})$, - The SLIP-44 [#slip-0044]_ coin type, and -- The message :math:`msg` to be signed. +- The message $msg$ to be signed. The signature is created as follows: -- Derive the full viewing key :math:`(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk})` from the expanded spending key. +- Derive the full viewing key $(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk})$ from the expanded spending key. -- Let :math:`\mathsf{g_d} = \mathsf{DiversifyHash}(\mathsf{d})`. +- Let $\mathsf{g_d} = \mathsf{DiversifyHash}(\mathsf{d})$. -- Let :math:`\mathsf{cm} = \mathsf{NoteCommit}^\mathsf{Sapling}_0(\mathsf{repr}_\mathbb{J}(\mathsf{g_d}), \mathsf{repr}_\mathbb{J}(\mathsf{pk_d}), 1)`. +- Let $\mathsf{cm} = \mathsf{NoteCommit}^\mathsf{Sapling}_0(\mathsf{repr}_\mathbb{J}(\mathsf{g_d}), \mathsf{repr}_\mathbb{J}(\mathsf{pk_d}), 1)$. -- Let :math:`\mathsf{rt}` be the root of a Merkle tree with depth - :math:`\mathsf{MerkleDepth}^\mathsf{Sapling}` and hashing function - :math:`\mathsf{MerkleCRH}^\mathsf{Sapling}`, containing :math:`\mathsf{cm}` at position 0, and - :math:`\mathsf{Uncommitted}^\mathsf{Sapling}` at all other positions. +- Let $\mathsf{rt}$ be the root of a Merkle tree with depth + $\mathsf{MerkleDepth}^\mathsf{Sapling}$ and hashing function + $\mathsf{MerkleCRH}^\mathsf{Sapling}$, containing $\mathsf{cm}$ at position 0, and + $\mathsf{Uncommitted}^\mathsf{Sapling}$ at all other positions. -- Let :math:`path` be the Merkle path from position 0 to :math:`\mathsf{rt}`. [#protocol-merklepath]_ +- Let $path$ be the Merkle path from position 0 to $\mathsf{rt}$. [#protocol-merklepath]_ -- Let :math:`\mathsf{cv} = \mathsf{ValueCommit}_0(1)`. +- Let $\mathsf{cv} = \mathsf{ValueCommit}_0(1)$. - This is a constant and may be pre-computed. -- Let :math:`\mathsf{nf} = \mathsf{PRF}^\mathsf{nfSapling}_{\mathsf{repr}_\mathbb{J}(\mathsf{nk})}(\mathsf{repr}_\mathbb{J}(\mathsf{MixingPedersenHash}(\mathsf{cm}, 0)))`. +- Let $\mathsf{nf} = \mathsf{PRF}^\mathsf{nfSapling}_{\mathsf{repr}_\mathbb{J}(\mathsf{nk})}(\mathsf{repr}_\mathbb{J}(\mathsf{MixingPedersenHash}(\mathsf{cm}, 0)))$. -- Select a random :math:`α`. +- Select a random $α$. -- Let :math:`\mathsf{rk} = \mathsf{SpendAuthSig.RandomizePublic}(α, \mathsf{ak})`. +- Let $\mathsf{rk} = \mathsf{SpendAuthSig.RandomizePublic}(α, \mathsf{ak})$. -- Let :math:`zkproof` be the byte sequence representation of a Sapling spend proof with primary input - :math:`(\mathsf{rt}, \mathsf{cv}, \mathsf{nf}, \mathsf{rk})` - and auxiliary input :math:`(path, 0, \mathsf{g_d}, \mathsf{pk_d}, 1, 0, \mathsf{cm}, 0, α, \mathsf{ak}, \mathsf{nsk})`. +- Let $zkproof$ be the byte sequence representation of a Sapling spend proof with primary input + $(\mathsf{rt}, \mathsf{cv}, \mathsf{nf}, \mathsf{rk})$ + and auxiliary input $(path, 0, \mathsf{g_d}, \mathsf{pk_d}, 1, 0, \mathsf{cm}, 0, α, \mathsf{ak}, \mathsf{nsk})$. [#protocol-spendstatement]_ -- Let :math:`\mathsf{rsk} = \mathsf{SpendAuthSig.RandomizePrivate}(α, \mathsf{ask})`. +- Let $\mathsf{rsk} = \mathsf{SpendAuthSig.RandomizePrivate}(α, \mathsf{ask})$. -- Let :math:`coinType` be the 4-byte little-endian encoding of the coin type in its index +- Let $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). -- Let :math:`digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZIP304Signed"}\,||\,coinType, zkproof\,||\,msg)`. +- Let $digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{“ZIP304Signed”}\,||\,coinType, zkproof\,||\,msg)$. -- Let :math:`spendAuthSig = \mathsf{SpendAuthSig.Sign}(\mathsf{rsk}, digest)`. +- Let $spendAuthSig = \mathsf{SpendAuthSig.Sign}(\mathsf{rsk}, digest)$. -- Return :math:`(\mathsf{nf}, \mathsf{rk}, zkproof, spendAuthSig)`. +- Return $(\mathsf{nf}, \mathsf{rk}, zkproof, spendAuthSig)$. Verification algorithm ---------------------- The inputs to the verification algorithm are: -- The payment address :math:`(\mathsf{d}, \mathsf{pk_d})`, +- The payment address $(\mathsf{d}, \mathsf{pk_d})$, - The SLIP-44 [#slip-0044]_ coin type, -- The message :math:`msg` that is claimed to be signed, and -- The ZIP 304 signature :math:`(\mathsf{nf}, \mathsf{rk}, zkproof, spendAuthSig)`. +- The message $msg$ that is claimed to be signed, and +- The ZIP 304 signature $(\mathsf{nf}, \mathsf{rk}, zkproof, spendAuthSig)$. The signature MUST be verified as follows: -- Let :math:`coinType` be the 4-byte little-endian encoding of the coin type in its index +- Let $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). -- Let :math:`digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZIP304Signed"}\,||\,coinType, zkproof\,||\,msg)`. +- Let $digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{“ZIP304Signed”}\,||\,coinType, zkproof\,||\,msg)$. -- If :math:`\mathsf{SpendAuthSig.Verify}(\mathsf{rk}, digest, spendAuthSig) = 0`, return false. +- If $\mathsf{SpendAuthSig.Verify}(\mathsf{rk}, digest, spendAuthSig) = 0$, return false. -- Let :math:`\mathsf{cm} = \mathsf{NoteCommit}^\mathsf{Sapling}_0(\mathsf{repr}_\mathbb{J}(\mathsf{DiversifyHash}(\mathsf{d})), \mathsf{repr}_\mathbb{J}(\mathsf{pk_d}), 1)`. +- Let $\mathsf{cm} = \mathsf{NoteCommit}^\mathsf{Sapling}_0(\mathsf{repr}_\mathbb{J}(\mathsf{DiversifyHash}(\mathsf{d})), \mathsf{repr}_\mathbb{J}(\mathsf{pk_d}), 1)$. -- Let :math:`\mathsf{rt}` be the root of a Merkle tree with depth - :math:`\mathsf{MerkleDepth}^\mathsf{Sapling}` and hashing function - :math:`\mathsf{MerkleCRH}^\mathsf{Sapling}`, containing :math:`\mathsf{cm}` at position 0, and - :math:`\mathsf{Uncommitted}^\mathsf{Sapling}` at all other positions. +- Let $\mathsf{rt}$ be the root of a Merkle tree with depth + $\mathsf{MerkleDepth}^\mathsf{Sapling}$ and hashing function + $\mathsf{MerkleCRH}^\mathsf{Sapling}$, containing $\mathsf{cm}$ at position 0, and + $\mathsf{Uncommitted}^\mathsf{Sapling}$ at all other positions. -- Let :math:`path` be the Merkle path from position 0 to :math:`\mathsf{rt}`. [#protocol-merklepath]_ +- Let $path$ be the Merkle path from position 0 to $\mathsf{rt}$. [#protocol-merklepath]_ -- Let :math:`\mathsf{cv} = \mathsf{ValueCommit}_0(1)`. +- Let $\mathsf{cv} = \mathsf{ValueCommit}_0(1)$. - This is a constant and may be pre-computed. -- Decode and verify :math:`zkproof` as a Sapling spend proof with primary input - :math:`(\mathsf{rt}, \mathsf{cv}, \mathsf{nf}, \mathsf{rk})`. [#protocol-spendstatement]_ If verification fails, return false. +- Decode and verify $zkproof$ as a Sapling spend proof with primary input + $(\mathsf{rt}, \mathsf{cv}, \mathsf{nf}, \mathsf{rk})$. [#protocol-spendstatement]_ If verification fails, return false. - Return true. @@ -215,13 +215,13 @@ Signature encoding ------------------ The raw form of a ZIP 304 signature is -:math:`\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 :math:`\texttt{"zip304:"}` followed by the result of Base64-encoding [#RFC4648]_ +the string $\texttt{“zip304:”}$ followed by the result of Base64-encoding [#RFC4648]_ the raw form of the signature. Rationale @@ -232,13 +232,13 @@ and its parameters. It is possible to construct a signature scheme with a smalle signature, but this would require a new circuit and another parameter-generation ceremony (if Groth16 were used). -We use a note value of :math:`1` zatoshi instead of zero to ensure that the payment address is -fully bound to :math:`zkproof`. Notes with zero value have certain constraints disabled +We use a note value of $1$ zatoshi instead of zero to ensure that the payment address is +fully bound to $zkproof$. Notes with zero value have certain constraints disabled inside the circuit. -We set :math:`\mathsf{rcm}` and :math:`\mathsf{rcv}` to zero because we do not need the hiding properties of +We set $\mathsf{rcm}$ and $\mathsf{rcv}$ to zero because we do not need the hiding properties of the note commitment or value commitment schemes (as we are using a fixed-value fake note), -and can thus omit both :math:`\mathsf{rcm}` and :math:`\mathsf{rcv}` from the signature. +and can thus omit both $\mathsf{rcm}$ and $\mathsf{rcv}$ from the signature. Security and Privacy Considerations @@ -251,18 +251,18 @@ the payment address, as the first 32 bytes of each signature will be identical. A signature is bound to a specific diversified address of the spending key. Signatures for different diversified addresses of the same spending key are unlinkable, as long as -:math:`α` is never re-used across signatures. +$α$ is never re-used across signatures. Most of the data within a ZIP 304 signature is inherently non-malleable: -- :math:`\mathsf{nf}` is a binary public input to :math:`zkproof`. -- :math:`\mathsf{rk}` is internally bound to :math:`spendAuthSig` by the design of RedJubjub. +- $\mathsf{nf}$ is a binary public input to $zkproof$. +- $\mathsf{rk}$ is internally bound to $spendAuthSig$ by the design of RedJubjub. - RedJubjub signatures are themselves non-malleable. -The one component that is inherently malleable is :math:`zkproof`. The zero-knowledge +The one component that is inherently malleable is $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 :math:`zkproof` to :math:`spendAuthSig`, by including :math:`zkproof` in the +encoding of $zkproof$ to $spendAuthSig$, by including $zkproof$ in the message digest. diff --git a/zips/zip-0307.rst b/zips/zip-0307.rst index 720443c80..5e536a428 100644 --- a/zips/zip-0307.rst +++ b/zips/zip-0307.rst @@ -253,39 +253,39 @@ server here without loss of generality. Local processing ---------------- -Given a ``CompactBlock`` at block height :math:`\mathsf{height}` received in height-sequential +Given a ``CompactBlock`` at block height $\mathsf{height}$ received in height-sequential order from a proxy server, a light client can process it in four ways: Scanning for relevant transactions `````````````````````````````````` For every ``CompactOutput`` in the ``CompactBlock``, the light client can trial-decrypt it against a set of Sapling incoming viewing keys. The procedure for trial-decrypting a -``CompactOutput`` :math:`(\mathtt{cmu}, \mathtt{ephemeralKey}, \mathsf{ciphertext})` with an incoming -viewing key :math:`\mathsf{ivk}` is a slight deviation from the standard decryption process +``CompactOutput`` $(\mathtt{cmu}, \mathtt{ephemeralKey}, \mathsf{ciphertext})$ with an incoming +viewing key $\mathsf{ivk}$ is a slight deviation from the standard decryption process [#protocol-saplingdecryptivk]_ (all constants and algorithms are as defined there): -- let :math:`\mathsf{epk} = \mathsf{abst}_{\mathbb{J}}(\mathtt{ephemeralKey})` -- if :math:`\mathsf{epk} = \bot`, return :math:`\bot` -- let :math:`\mathsf{sharedSecret} = \mathsf{KA^{Sapling}.Agree}(\mathsf{ivk}, \mathsf{epk})` -- let :math:`K^{\mathsf{enc}} = \mathsf{KDF^{Sapling}}(\mathsf{sharedSecret}, \mathtt{ephemeralKey})` -- let :math:`P^{\mathsf{enc}} = \mathsf{ChaCha20.Decrypt}_{K^{\mathsf{enc}}}(\mathsf{ciphertext})` -- extract :math:`\mathbf{np} = (\mathsf{leadByte}, \mathsf{d}, \mathsf{v}, \mathsf{rseed})` from :math:`P^{\mathsf{enc}}` -- [Pre-Canopy] if :math:`\mathsf{leadByte} \neq 0x01`, return :math:`\bot` -- [Pre-Canopy] let :math:`\mathsf{\underline{rcm}} = \mathsf{rseed}` -- [Canopy onward] if :math:`\mathsf{height} < \mathsf{CanopyActivationHeight} + \mathsf{ZIP212GracePeriod}` and :math:`\mathsf{leadByte} \not\in \{ \mathtt{0x01}, \mathtt{0x02} \}`, return :math:`\bot` -- [Canopy onward] if :math:`\mathsf{height} < \mathsf{CanopyActivationHeight} + \mathsf{ZIP212GracePeriod}` and :math:`\mathsf{leadByte} \neq \mathtt{0x02}`, return :math:`\bot` -- [Canopy onward] let :math:`\mathsf{\underline{rcm}} = \begin{cases}\mathsf{rseed}, &\text{if } \mathsf{leadByte} = \mathtt{0x01} \\ \mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([5])), &\text{otherwise}\end{cases}` -- let :math:`\mathsf{rcm} = \mathsf{LEOS2IP}_{256}(\mathsf{\underline{rcm}})` and :math:`\mathsf{g_d} = \mathsf{DiversifyHash}(\mathsf{d})` -- if :math:`\mathsf{rcm} \geq r_{\mathbb{J}}` or :math:`\mathsf{g_d} = \bot`, return :math:`\bot` -- [Canopy onward] if :math:`\mathsf{leadByte} \neq \mathtt{0x01}`: - - * :math:`\mathsf{esk} = \mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([4]))` - * if :math:`\mathsf{repr}_{\mathbb{J}}(\mathsf{KA^{Sapling}.DerivePublic}(\mathsf{esk}, \mathsf{g_d})) \neq \mathtt{ephemeralKey}`, return :math:`\bot` - -- let :math:`\mathsf{pk_d} = \mathsf{KA^{Sapling}.DerivePublic}(\mathsf{ivk}, \mathsf{g_d})` -- let :math:`\mathsf{cm}_u' = \mathsf{Extract}_{\mathbb{J}^{(r)}}(\mathsf{NoteCommit^{Sapling}_{rcm}}(\mathsf{repr}_{\mathbb{J}}(\mathsf{g_d}), \mathsf{repr}_{\mathbb{J}}(\mathsf{pk_d}), \mathsf{v}))`. -- if :math:`\mathsf{LEBS2OSP}_{256}(\mathsf{cm}_u') \neq \mathtt{cmu}`, return :math:`\bot` -- return :math:`\mathbf{np}`. +- let $\mathsf{epk} = \mathsf{abst}_{\mathbb{J}}(\mathtt{ephemeralKey})$ +- if $\mathsf{epk} = \bot$, return $\bot$ +- let $\mathsf{sharedSecret} = \mathsf{KA^{Sapling}.Agree}(\mathsf{ivk}, \mathsf{epk})$ +- let $K^{\mathsf{enc}} = \mathsf{KDF^{Sapling}}(\mathsf{sharedSecret}, \mathtt{ephemeralKey})$ +- let $P^{\mathsf{enc}} = \mathsf{ChaCha20.Decrypt}_{K^{\mathsf{enc}}}(\mathsf{ciphertext})$ +- extract $\mathbf{np} = (\mathsf{leadByte}, \mathsf{d}, \mathsf{v}, \mathsf{rseed})$ from $P^{\mathsf{enc}}$ +- [Pre-Canopy] if $\mathsf{leadByte} \neq 0x01$, return $\bot$ +- [Pre-Canopy] let $\mathsf{\underline{rcm}} = \mathsf{rseed}$ +- [Canopy onward] if $\mathsf{height} < \mathsf{CanopyActivationHeight} + \mathsf{ZIP212GracePeriod}$ and $\mathsf{leadByte} \not\in \{ \mathtt{0x01}, \mathtt{0x02} \}$, return $\bot$ +- [Canopy onward] if $\mathsf{height} < \mathsf{CanopyActivationHeight} + \mathsf{ZIP212GracePeriod}$ and $\mathsf{leadByte} \neq \mathtt{0x02}$, return $\bot$ +- [Canopy onward] let $\mathsf{\underline{rcm}} = \begin{cases}\mathsf{rseed}, &\text{if } \mathsf{leadByte} = \mathtt{0x01} \\ \mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([5])), &\text{otherwise}\end{cases}$ +- let $\mathsf{rcm} = \mathsf{LEOS2IP}_{256}(\mathsf{\underline{rcm}})$ and $\mathsf{g_d} = \mathsf{DiversifyHash}(\mathsf{d})$ +- if $\mathsf{rcm} \geq r_{\mathbb{J}}$ or $\mathsf{g_d} = \bot$, return $\bot$ +- [Canopy onward] if $\mathsf{leadByte} \neq \mathtt{0x01}$: + + * $\mathsf{esk} = \mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([4]))$ + * if $\mathsf{repr}_{\mathbb{J}}(\mathsf{KA^{Sapling}.DerivePublic}(\mathsf{esk}, \mathsf{g_d})) \neq \mathtt{ephemeralKey}$, return $\bot$ + +- let $\mathsf{pk_d} = \mathsf{KA^{Sapling}.DerivePublic}(\mathsf{ivk}, \mathsf{g_d})$ +- let $\mathsf{cm}_u' = \mathsf{Extract}_{\mathbb{J}^{(r)}}(\mathsf{NoteCommit^{Sapling}_{rcm}}(\mathsf{repr}_{\mathbb{J}}(\mathsf{g_d}), \mathsf{repr}_{\mathbb{J}}(\mathsf{pk_d}), \mathsf{v}))$. +- if $\mathsf{LEBS2OSP}_{256}(\mathsf{cm}_u') \neq \mathtt{cmu}$, return $\bot$ +- return $\mathbf{np}$. Creating and updating note witnesses ```````````````````````````````````` diff --git a/zips/zip-0311.rst b/zips/zip-0311.rst index b55b94bac..c83d91af1 100644 --- a/zips/zip-0311.rst +++ b/zips/zip-0311.rst @@ -145,27 +145,27 @@ Conventions The following functions used in this ZIP are defined in the Zcash protocol specification: [#protocol]_ -- :math:`\mathsf{DiversifyHash}(\mathsf{d})` [#protocol-concretediversifyhash]_ +- $\mathsf{DiversifyHash}(\mathsf{d})$ [#protocol-concretediversifyhash]_ -- :math:`\mathsf{SpendAuthSig.RandomizePrivate}(α, \mathsf{sk})`, - :math:`\mathsf{SpendAuthSig.Sign}(\mathsf{sk}, m)`, and - :math:`\mathsf{SpendAuthSig.Verify}(\mathsf{vk}, m, σ)` [#protocol-concretespendauthsig]_ +- $\mathsf{SpendAuthSig.RandomizePrivate}(α, \mathsf{sk})$, + $\mathsf{SpendAuthSig.Sign}(\mathsf{sk}, m)$, and + $\mathsf{SpendAuthSig.Verify}(\mathsf{vk}, m, σ)$ [#protocol-concretespendauthsig]_ We reproduce some notation and functions from [#protocol]_ here for convenience: -- :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{BLAKE2b}\text{-}\mathsf{256}(p, x)` refers to unkeyed BLAKE2b-256 in +- $\mathsf{BLAKE2b}\text{-}\mathsf{256}(p, x)$ refers to unkeyed BLAKE2b-256 in sequential mode, with an output digest length of 32 bytes, 16-byte personalization - string :math:`p`, and input :math:`x`. + string $p$, and input $x$. We also define the following notation here: -- :math:`[a..b]` means the sequence of values inclusive of :math:`a` and exclusive of - :math:`b`. +- $[a..b]$ means the sequence of values inclusive of $a$ and exclusive of + $b$. -- :math:`\mathsf{length}(a)` means the length of the sequence :math:`a`. +- $\mathsf{length}(a)$ means the length of the sequence $a$. Specification @@ -181,11 +181,11 @@ A payment disclosure has the following fields: - `msg`: A message field, which could contain a challenge value from the party to whom the payment disclosure is directed. -- :math:`\mathsf{transparentInputs}`: A sequence of the transparent inputs for which we are - proving spend authority :math:`[0..\mathsf{length}(\mathsf{tx.vin})]` +- $\mathsf{transparentInputs}$: A sequence of the transparent inputs for which we are + proving spend authority $[0..\mathsf{length}(\mathsf{tx.vin})]$ - - :math:`\mathsf{index}`: An index into :math:`\mathsf{tx.vin}`. - - :math:`\mathsf{sig}`: A BIP 322 signature. [#bip-0322]_ + - $\mathsf{index}$: An index into $\mathsf{tx.vin}$. + - $\mathsf{sig}$: A BIP 322 signature. [#bip-0322]_ - TODO: `zcashd` currently only supports the legacy format defined in BIP 322. We may want to backport full BIP 322 support before having transparent input support in @@ -194,27 +194,27 @@ A payment disclosure has the following fields: process. We will likely need to migrate it over to an equivalent ZIP that specifies these for Zcash (which has a different set of script validation consensus rules). -- :math:`\mathsf{saplingSpends}`: A sequence of the Sapling Spends for which we are proving - spend authority :math:`[0..\mathsf{length}(\mathsf{tx.shieldedSpends})]` +- $\mathsf{saplingSpends}$: A sequence of the Sapling Spends for which we are proving + spend authority $[0..\mathsf{length}(\mathsf{tx.shieldedSpends})]$ - - :math:`\mathsf{index}`: An index into :math:`\mathsf{tx.shieldedSpends}`. - - :math:`\mathsf{cv}`: A value commitment to the spent note. - - :math:`\mathsf{rk}`: A randomized public key linked to the spent note. - - :math:`\mathsf{zkproof_{spend}}`: A Sapling spend proof. + - $\mathsf{index}$: An index into $\mathsf{tx.shieldedSpends}$. + - $\mathsf{cv}$: A value commitment to the spent note. + - $\mathsf{rk}$: A randomized public key linked to the spent note. + - $\mathsf{zkproof_{spend}}$: A Sapling spend proof. - [Optional] A payment address proof `addr_proof`: - - Any :math:`(\mathsf{d, pk_d})` such that - :math:`\mathsf{pk_d} = [\mathsf{ivk}] \mathsf{DiversifyHash}(\mathsf{d})` - - :math:`\mathsf{nullifier_{addr}}`: A nullifier for a ZIP 304 fake note. [#zip-0304]_ - - :math:`\mathsf{zkproof_{addr}}`: A Sapling spend proof. + - Any $(\mathsf{d, pk_d})$ such that + $\mathsf{pk_d} = [\mathsf{ivk}] \mathsf{DiversifyHash}(\mathsf{d})$ + - $\mathsf{nullifier_{addr}}$: A nullifier for a ZIP 304 fake note. [#zip-0304]_ + - $\mathsf{zkproof_{addr}}$: A Sapling spend proof. - - :math:`\mathsf{spendAuthSig}` + - $\mathsf{spendAuthSig}$ -- :math:`\mathsf{saplingOutputs}`: A sequence of the Sapling Outputs that we are disclosing - :math:`[0..\mathsf{length}(\mathsf{tx.shieldedOutputs})]` +- $\mathsf{saplingOutputs}$: A sequence of the Sapling Outputs that we are disclosing + $[0..\mathsf{length}(\mathsf{tx.shieldedOutputs})]$ - - :math:`\mathsf{index}`: An index into :math:`\mathsf{tx.shieldedOutputs}`. - - :math:`\mathsf{ock}`: The outgoing cipher key that allows this output to be recovered. + - $\mathsf{index}$: An index into $\mathsf{tx.shieldedOutputs}$. + - $\mathsf{ock}$: The outgoing cipher key that allows this output to be recovered. [#protocol-saplingencrypt]_ TODO: Add support for Orchard. @@ -230,17 +230,17 @@ The inputs to a payment disclosure are: - The transaction. - The SLIP-44 [#slip-0044]_ coin type. -- The message :math:`msg` to be included (which may be empty). -- A sequence of :math:`(\mathsf{outputIndex}, \mathsf{ock})` tuples (which may be empty). +- The message $msg$ to be included (which may be empty). +- A sequence of $(\mathsf{outputIndex}, \mathsf{ock})$ tuples (which may be empty). - A sequence of Sapling spend tuples (which may be empty) containing: - A Sapling spend index. - - Its corresponding expanded spending key :math:`(\mathsf{ask}, \mathsf{nsk}, \mathsf{ovk})`. - - [Optional] An associated payment address :math:`(\mathsf{d}, \mathsf{pk_d})`. + - Its corresponding expanded spending key $(\mathsf{ask}, \mathsf{nsk}, \mathsf{ovk})$. + - [Optional] An associated payment address $(\mathsf{d}, \mathsf{pk_d})$. - A sequence of transparent input tuples (which may be empty) containing: - - :math:`\mathsf{index}`: An index into :math:`\mathsf{tx.vin}`. + - $\mathsf{index}$: An index into $\mathsf{tx.vin}$. - The inputs to a BIP 322 signature (excluding `message_data`). The caller MUST provide at least one input tuple of any type (either a Sapling spend tuple @@ -251,14 +251,14 @@ The payment disclosure is created as follows: - For each Sapling spend index: - Create a Sapling spend proof for the note that was spent in - :math:`\mathsf{tx.shieldedSpends[index]}`, using the same anchor, to obtain - :math:`(\mathsf{cv}, \mathsf{rk}, \mathsf{zkproof_{spend}})` as well as the random - :math:`\alpha` that was generated internally. + $\mathsf{tx.shieldedSpends[index]}$, using the same anchor, to obtain + $(\mathsf{cv}, \mathsf{rk}, \mathsf{zkproof_{spend}})$ as well as the random + $\alpha$ that was generated internally. - [Optional] If an associated payment address was provided for this spend index, create - a ZIP 304 signature proof for that payment address, [#zip-0304]_ using :math:`\alpha` - and :math:`\mathsf{rk}` from the previous step. We obtain - :math:`(\mathsf{nullifier_{addr}}, \mathsf{zkproof_{addr}})` from this step. + a ZIP 304 signature proof for that payment address, [#zip-0304]_ using $\alpha$ + and $\mathsf{rk}$ from the previous step. We obtain + $(\mathsf{nullifier_{addr}}, \mathsf{zkproof_{addr}})$ from this step. - For each transparent input index: @@ -266,18 +266,18 @@ The payment disclosure is created as follows: - Construct an unsigned payment disclosure from the disclosed Sapling outputs, and the above data for the Sapling spends and transparent inputs. Define the encoding of this as - :math:`unsignedPaymentDisclosure`. + $unsignedPaymentDisclosure$. - For each Sapling spend index: - - Let :math:`\mathsf{rsk} = \mathsf{SpendAuthSig.RandomizePrivate}(\alpha, \mathsf{ask})`. + - Let $\mathsf{rsk} = \mathsf{SpendAuthSig.RandomizePrivate}(\alpha, \mathsf{ask})$. - - Let :math:`coinType` be the 4-byte little-endian encoding of the SLIP 44 coin type in its + - Let $coinType$ be the 4-byte little-endian encoding of the SLIP 44 coin type in its index form, not its hardened form (i.e. 133 for mainnet Zcash). - - Let :math:`digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZIP311Signed"}\,||\,coinType, unsignedPaymentDisclosure)`. + - Let $digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{“ZIP311Signed”}\,||\,coinType, unsignedPaymentDisclosure)$. - - Let :math:`spendAuthSig = \mathsf{SpendAuthSig.Sign}(\mathsf{rsk}, digest)`. + - Let $spendAuthSig = \mathsf{SpendAuthSig.Sign}(\mathsf{rsk}, digest)$. - For each transparent input index: @@ -289,76 +289,76 @@ The payment disclosure is created as follows: Verifying a payment disclosure ------------------------------ -Given a payment disclosure :math:`\mathsf{pd}`, a transaction :math:`\mathsf{tx}`, and the -`height` of the block in which :math:`\mathsf{tx}` was mined (which we assume was verified +Given a payment disclosure $\mathsf{pd}$, a transaction $\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: - Perform the following structural correctness checks, returning false if any check fails: - - :math:`\mathsf{pd.txid} = \mathsf{tx.txid}()` + - $\mathsf{pd.txid} = \mathsf{tx.txid}()$ - Sequence length correctness: - - :math:`\mathsf{length}(\mathsf{pd.saplingOutputs}) \leq \mathsf{length}(\mathsf{tx.shieldedOutputs})` - - :math:`\mathsf{length}(\mathsf{pd.saplingSpends}) \leq \mathsf{length}(\mathsf{tx.shieldedSpends})` - - :math:`\mathsf{length}(\mathsf{pd.transparentInputs}) \leq \mathsf{length}(\mathsf{tx.vin})` + - $\mathsf{length}(\mathsf{pd.saplingOutputs}) \leq \mathsf{length}(\mathsf{tx.shieldedOutputs})$ + - $\mathsf{length}(\mathsf{pd.saplingSpends}) \leq \mathsf{length}(\mathsf{tx.shieldedSpends})$ + - $\mathsf{length}(\mathsf{pd.transparentInputs}) \leq \mathsf{length}(\mathsf{tx.vin})$ - Index uniqueness: - - For every :math:`\mathsf{output}` in :math:`\mathsf{pd.saplingOutputs}`, - :math:`\mathsf{output.index}` only occurs once. - - For every :math:`\mathsf{spend}` in :math:`\mathsf{pd.saplingSpends}`, - :math:`\mathsf{spend.index}` only occurs once. - - For every :math:`\mathsf{input}` in :math:`\mathsf{pd.transparentInputs}`, - :math:`\mathsf{input.index}` only occurs once. + - For every $\mathsf{output}$ in $\mathsf{pd.saplingOutputs}$, + $\mathsf{output.index}$ only occurs once. + - For every $\mathsf{spend}$ in $\mathsf{pd.saplingSpends}$, + $\mathsf{spend.index}$ only occurs once. + - For every $\mathsf{input}$ in $\mathsf{pd.transparentInputs}$, + $\mathsf{input.index}$ only occurs once. - Index correctness: - - For every :math:`\mathsf{output}` in :math:`\mathsf{pd.saplingOutputs}`, - :math:`\mathsf{output.index} < \mathsf{length}(\mathsf{tx.shieldedOutputs})` - - For every :math:`\mathsf{spend}` in :math:`\mathsf{pd.saplingSpends}`, - :math:`\mathsf{spend.index} < \mathsf{length}(\mathsf{tx.shieldedSpends})` - - For every :math:`\mathsf{input}` in :math:`\mathsf{pd.transparentInputs}`, - :math:`\mathsf{input.index} < \mathsf{length}(\mathsf{tx.vin})` + - For every $\mathsf{output}$ in $\mathsf{pd.saplingOutputs}$, + $\mathsf{output.index} < \mathsf{length}(\mathsf{tx.shieldedOutputs})$ + - For every $\mathsf{spend}$ in $\mathsf{pd.saplingSpends}$, + $\mathsf{spend.index} < \mathsf{length}(\mathsf{tx.shieldedSpends})$ + - For every $\mathsf{input}$ in $\mathsf{pd.transparentInputs}$, + $\mathsf{input.index} < \mathsf{length}(\mathsf{tx.vin})$ - - :math:`\mathsf{length}(\mathsf{pd.saplingSpends}) + \mathsf{length}(\mathsf{pd.transparentInputs}) > 0` + - $\mathsf{length}(\mathsf{pd.saplingSpends}) + \mathsf{length}(\mathsf{pd.transparentInputs}) > 0$ -- Let :math:`unsignedPaymentDisclosure` be the encoding of the payment disclosure without +- Let $unsignedPaymentDisclosure$ be the encoding of the payment disclosure without signatures. -- Let :math:`coinType` be the 4-byte little-endian encoding of the coin type in its index +- Let $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). -- Let :math:`digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZIP311Signed"}\,||\,coinType, unsignedPaymentDisclosure)`. +- Let $digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{“ZIP311Signed”}\,||\,coinType, unsignedPaymentDisclosure)$. -- For every :math:`\mathsf{spend}` in :math:`\mathsf{pd.saplingSpends}`: +- For every $\mathsf{spend}$ in $\mathsf{pd.saplingSpends}$: - - If :math:`\mathsf{SpendAuthSig.Verify}(\mathsf{spend.rk}, digest, \mathsf{spend.spendAuthSig}) = 0`, return false. + - If $\mathsf{SpendAuthSig.Verify}(\mathsf{spend.rk}, digest, \mathsf{spend.spendAuthSig}) = 0$, return false. - - [Optional] If a payment address proof :math:`\mathsf{addrProof}` is present in - :math:`\mathsf{spend}`, verify :math:`(\mathsf{addrProof.nullifier_{addr}}, \mathsf{spend.rk}, \mathsf{addrProof.zkproof_{addr}})` as a ZIP 304 proof - for :math:`(\mathsf{addrProof.d}, \mathsf{addrProof.pk_d})` [#zip-0304]_. If verification fails, return + - [Optional] If a payment address proof $\mathsf{addrProof}$ is present in + $\mathsf{spend}$, verify $(\mathsf{addrProof.nullifier_{addr}}, \mathsf{spend.rk}, \mathsf{addrProof.zkproof_{addr}})$ as a ZIP 304 proof + for $(\mathsf{addrProof.d}, \mathsf{addrProof.pk_d})$ [#zip-0304]_. If verification fails, return false. - - Decode and verify :math:`\mathsf{zkproof_{spend}}` as a Sapling spend proof + - Decode and verify $\mathsf{zkproof_{spend}}$ as a Sapling spend proof [#protocol-spendstatement]_ with primary input: - - :math:`\mathsf{tx.shieldedSpends[spend.index].rt}` - - :math:`\mathsf{spend.cv}` - - :math:`\mathsf{tx.shieldedSpends[spend.index].nf}` - - :math:`\mathsf{spend.rk}` + - $\mathsf{tx.shieldedSpends[spend.index].rt}$ + - $\mathsf{spend.cv}$ + - $\mathsf{tx.shieldedSpends[spend.index].nf}$ + - $\mathsf{spend.rk}$ If verification fails, return false. -- For every :math:`\mathsf{input}` in :math:`\mathsf{pd.transparentInputs}`: +- For every $\mathsf{input}$ in $\mathsf{pd.transparentInputs}$: - TODO: BIP 322 verification. -- For every :math:`\mathsf{output}` in :math:`\mathsf{pd.saplingOutputs}`: +- For every $\mathsf{output}$ in $\mathsf{pd.saplingOutputs}$: - - Recover the Sapling note in :math:`\mathsf{tx.shieldedOutputs}[\mathsf{output.index}]` + - Recover the Sapling note in $\mathsf{tx.shieldedOutputs}[\mathsf{output.index}]$ via the process specified in [#protocol-saplingdecryptovk]_ with inputs - :math:`(height, \mathsf{output.ock})`. If recovery returns :math:`\bot`, return false. + $(height, \mathsf{output.ock})$. If recovery returns $\bot$, return false. - Return true. @@ -377,10 +377,10 @@ should convey the various kinds of validity information: Rationale ========= -If a sender elects, at transaction creation time, to use an :math:`\mathsf{ovk}` of -:math:`\bot` for a specific Sapling output, then they are unable to subsequently create a +If a sender elects, at transaction creation time, to use an $\mathsf{ovk}$ of +$\bot$ for a specific Sapling output, then they are unable to subsequently create a payment disclosure that discloses that output. This maintains the semantics of -:math:`\mathsf{ovk}`, in that the sender explicitly chose to lose the capability to +$\mathsf{ovk}$, in that the sender explicitly chose to lose the capability to recover that output. Payment disclosures that prove Sapling spend authority are not required to reveal a diff --git a/zips/zip-0312.rst b/zips/zip-0312.rst index 0033cba50..05c4619f5 100644 --- a/zips/zip-0312.rst +++ b/zips/zip-0312.rst @@ -87,7 +87,7 @@ shielded transaction: as an auxiliary (secret) input, among others. When employing re-randomizable FROST as specified in this ZIP, the goal is to -split the spend authorization private key :math:`\mathsf{ask}` among multiple +split the spend authorization private key $\mathsf{ask}$ among multiple possible signers. This means that the proof generation will still be performed by a single participant, likely the one that created the transaction in the first place. Note that this user already controls the privacy of the transaction since @@ -130,8 +130,8 @@ The types Scalar, Element, and G are defined in [#frost-primeordergroup]_, 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 :math:`[k] P` with the group -implied by :math:`P`. +multiplication, where the protocol spec would use $[k] P$ with the group +implied by $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 @@ -143,12 +143,12 @@ Key Generation While key generation is out of scope for this ZIP and the FROST spec [#FROST]_, it needs to be consistent with FROST, see [#frost-tdkg]_ for guidance. The spend -authorization private key :math:`\mathsf{ask}` [#protocol-spendauthsig]_ is the +authorization private key $\mathsf{ask}$ [#protocol-spendauthsig]_ is the particular key that must be used in the context of this ZIP. Note that the -:math:`\mathsf{ask}` is usually derived from the spending key -:math:`\mathsf{sk}`, though that is not required. Not doing so allows using +$\mathsf{ask}$ is usually derived from the spending key +$\mathsf{sk}$, though that is not required. Not doing so allows using distributed key generation, since the key it generates is unpredictable. Note -however that not deriving :math:`\mathsf{ask}` from :math:`\mathsf{sk}` prevents +however that not deriving $\mathsf{ask}$ from $\mathsf{sk}$ prevents using seed phrases to recover the original secret (which may be something desirable in the context of FROST). @@ -263,16 +263,16 @@ This ciphersuite uses Jubjub for the Group and BLAKE2b-512 for the Hash function meant to produce signatures indistinguishable from RedJubjub Sapling Spend Authorization Signatures as specified in [#protocol-concretespendauthsig]_. -- Group: Jubjub [#protocol-jubjub]_ with base point :math:`\mathcal{G}^{\mathsf{Sapling}}` +- Group: Jubjub [#protocol-jubjub]_ with base point $\mathcal{G}^{\mathsf{Sapling}}$ as defined in [#protocol-concretespendauthsig]_. - - Order: :math:`r_\mathbb{J}` as defined in [#protocol-jubjub]_. + - Order: $r_\mathbb{J}$ as defined in [#protocol-jubjub]_. - Identity: as defined in [#protocol-jubjub]_. - RandomScalar(): Implemented by returning a uniformly random Scalar in the range \[0, ``G.Order()`` - 1\]. Refer to {{frost-randomscalar}} for implementation guidance. - - SerializeElement(P): Implemented as :math:`\mathsf{repr}_\mathbb{J}(P)` as defined in [#protocol-jubjub]_ - - DeserializeElement(P): Implemented as :math:`\mathsf{abst}_\mathbb{J}(P)` as defined in [#protocol-jubjub]_, - returning an error if :math:`\bot` is returned. Additionally, this function + - SerializeElement(P): Implemented as $\mathsf{repr}_\mathbb{J}(P)$ as defined in [#protocol-jubjub]_ + - DeserializeElement(P): Implemented as $\mathsf{abst}_\mathbb{J}(P)$ as defined in [#protocol-jubjub]_, + returning an error if $\bot$ is returned. Additionally, this function validates that the resulting element is not the group identity element, returning an error if the check fails. - SerializeScalar: Implemented by outputting the little-endian 32-byte encoding @@ -290,8 +290,8 @@ Authorization Signatures as specified in [#protocol-concretespendauthsig]_. - H2(m): Implemented by computing BLAKE2b-512("Zcash_RedJubjubH", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo ``G.Order()``. - (This is equivalent to :math:`\mathsf{H}^\circledast(m)`, as defined by - the :math:`\mathsf{RedJubjub}` scheme instantiated in [#protocol-concretereddsa]_.) + (This is equivalent to $\mathsf{H}^\circledast(m)$, as defined by + the $\mathsf{RedJubjub}$ scheme instantiated in [#protocol-concretereddsa]_.) - H3(m): Implemented by computing BLAKE2b-512("FROST_RedJubjubN", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo ``G.Order()``. @@ -312,16 +312,16 @@ This ciphersuite uses Pallas for the Group and BLAKE2b-512 for the Hash function meant to produce signatures indistinguishable from RedPallas Orchard Spend Authorization Signatures as specified in [#protocol-concretespendauthsig]_. -- Group: Pallas [#protocol-pallasandvesta]_ with base point :math:`\mathcal{G}^{\mathsf{Orchard}}` +- Group: Pallas [#protocol-pallasandvesta]_ with base point $\mathcal{G}^{\mathsf{Orchard}}$ as defined in [#protocol-concretespendauthsig]_. - - Order: :math:`r_\mathbb{P}` as defined in [#protocol-pallasandvesta]_. + - Order: $r_\mathbb{P}$ as defined in [#protocol-pallasandvesta]_. - Identity: as defined in [#protocol-pallasandvesta]_. - RandomScalar(): Implemented by returning a uniformly random Scalar in the range \[0, ``G.Order()`` - 1\]. Refer to {{frost-randomscalar}} for implementation guidance. - - SerializeElement(P): Implemented as :math:`\mathsf{repr}_\mathbb{P}(P)` as defined in [#protocol-pallasandvesta]_. - - DeserializeElement(P): Implemented as :math:`\mathsf{abst}_\mathbb{P}(P)` as defined in [#protocol-pallasandvesta]_, - failing if :math:`\bot` is returned. Additionally, this function validates that the resulting + - SerializeElement(P): Implemented as $\mathsf{repr}_\mathbb{P}(P)$ as defined in [#protocol-pallasandvesta]_. + - DeserializeElement(P): Implemented as $\mathsf{abst}_\mathbb{P}(P)$ as defined in [#protocol-pallasandvesta]_, + failing if $\bot$ is returned. Additionally, this function validates that the resulting element is not the group identity element, returning an error if the check fails. - SerializeScalar: Implemented by outputting the little-endian 32-byte encoding of the Scalar value. @@ -338,8 +338,8 @@ Authorization Signatures as specified in [#protocol-concretespendauthsig]_. - H2(m): Implemented by computing BLAKE2b-512("Zcash_RedPallasH", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo ``G.Order()``. - (This is equivalent to :math:`\mathsf{H}^\circledast(m)`, as defined by - the :math:`\mathsf{RedPallas}` scheme instantiated in [#protocol-concretereddsa]_.) + (This is equivalent to $\mathsf{H}^\circledast(m)$, as defined by + the $\mathsf{RedPallas}$ scheme instantiated in [#protocol-concretereddsa]_.) - H3(m): Implemented by computing BLAKE2b-512("FROST_RedPallasN", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo ``G.Order()``. @@ -361,22 +361,22 @@ since there is no widespread standard for Schnorr signatures, it must be ensured that the signatures generated by the FROST variant specified in this ZIP can be verified successfully by a Zcash implementation following its specification. In practice this entails making sure that the generated signature can be verified -by the :math:`\mathsf{RedDSA.Validate}` function specified in +by the $\mathsf{RedDSA.Validate}$ function specified in [#protocol-concretereddsa]_: - The FROST signature, when split into R and S in the first step of - :math:`\mathsf{RedDSA.Validate}`, must yield the values expected by the + $\mathsf{RedDSA.Validate}$, must yield the values expected by the function. This is ensured by defining SerializeElement and SerializeScalar in each ciphersuite to yield those values. - The challenge c used during FROST signing must be equal to the challenge c - computed during :math:`\mathsf{RedDSA.Validate}`. This requires defining the - ciphersuite H2 function as the :math:`\mathsf{H}^\circledast(m)` Zcash + computed during $\mathsf{RedDSA.Validate}$. This requires defining the + ciphersuite H2 function as the $\mathsf{H}^\circledast(m)$ Zcash function in the ciphersuites, and making sure its input will be the same. Fortunately FROST and Zcash use the same input order (R, public key, message) so we just need to make sure that SerializeElement (used to compute the encoded public key before passing to the hash function) matches what - :math:`\mathsf{RedDSA.Validate}` expects; which is possible since both `R` and + $\mathsf{RedDSA.Validate}$ expects; which is possible since both `R` and `vk` (the public key) are encoded in the same way as in Zcash. - Note that ``r`` (and thus ``R``) will not be generated as specified in RedDSA.Sign. @@ -385,7 +385,7 @@ by the :math:`\mathsf{RedDSA.Validate}` function specified in uniformly at random, which is true for FROST. - The above will ensure that the verification equation in - :math:`\mathsf{RedDSA.Validate}` will pass, since FROST ensures the exact same + $\mathsf{RedDSA.Validate}$ will pass, since FROST ensures the exact same equation will be valid as described in [#frost-primeorderverify]_. The second step is adding the re-randomization functionality so that each FROST @@ -403,8 +403,8 @@ signing generates a re-randomized signature: 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 - :math:`\mathsf{RedDSA.RandomizedPrivate}`, which refers to the randomizer as - :math:`\alpha`) and ``sum(lambda_i * c * (sk_i + randomizer))``. The latter + $\mathsf{RedDSA.RandomizedPrivate}$, which refers to the randomizer as + $\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`` @@ -414,10 +414,10 @@ signing generates a re-randomized signature: [#protocol-concretereddsa]_ to ensure that re-randomized keys are uniformly distributed and signatures are unlinkable. This is also true; observe that ``randomizer_generate`` generates randomizer uniformly at random as required - by :math:`\mathsf{RedDSA.GenRandom}`; and signature generation is compatible - with :math:`\mathsf{RedDSA.RandomizedPrivate}`, - :math:`\mathsf{RedDSA.RandomizedPublic}`, :math:`\mathsf{RedDSA.Sign}` and - :math:`\mathsf{RedDSA.Validate}` as explained in the previous item. + by $\mathsf{RedDSA.GenRandom}$; and signature generation is compatible + with $\mathsf{RedDSA.RandomizedPrivate}$, + $\mathsf{RedDSA.RandomizedPublic}$, $\mathsf{RedDSA.Sign}$ and + $\mathsf{RedDSA.Validate}$ as explained in the previous item. The security of Re-Randomized FROST with respect to the security assumptions of regular FROST is shown in [#frost-rerandomized]_. diff --git a/zips/zip-0316.rst b/zips/zip-0316.rst index 0ea140de0..973735b2c 100644 --- a/zips/zip-0316.rst +++ b/zips/zip-0316.rst @@ -364,14 +364,14 @@ for distinct types. That is, the set may optionally contain one Receiver of each of the Receiver Types in the following fixed Priority List: -* Typecode :math:`\mathtt{0x03}` — an Orchard raw address as defined +* Typecode $\mathtt{0x03}$ — an Orchard raw address as defined in [#protocol-orchardpaymentaddrencoding]_; -* Typecode :math:`\mathtt{0x02}` — a Sapling raw address as defined +* Typecode $\mathtt{0x02}$ — a Sapling raw address as defined in [#protocol-saplingpaymentaddrencoding]_; -* Typecode :math:`\mathtt{0x01}` — a Transparent P2SH address, *or* - Typecode :math:`\mathtt{0x00}` — a Transparent P2PKH address. +* Typecode $\mathtt{0x01}$ — a Transparent P2SH address, *or* + Typecode $\mathtt{0x00}$ — a Transparent P2PKH address. If, and only if, the user of a Producer or Consumer wallet explicitly opts into an experiment as described in `Experimental Usage`_, the @@ -392,33 +392,33 @@ Orchard Receiver and possibly other Receivers, it MUST send to the Orchard Receiver. The raw encoding of a Unified Address is a concatenation of -:math:`(\mathtt{typecode}, \mathtt{length}, \mathtt{addr})` encodings +$(\mathtt{typecode}, \mathtt{length}, \mathtt{addr})$ encodings of the constituent Receivers, in ascending order of Typecode: -* :math:`\mathtt{typecode} : \mathtt{compactSize}` — the Typecode from the +* $\mathtt{typecode} : \mathtt{compactSize}$ — the Typecode from the above Priority List; -* :math:`\mathtt{length} : \mathtt{compactSize}` — the length in bytes of - :math:`\mathtt{addr};` +* $\mathtt{length} : \mathtt{compactSize}$ — the length in bytes of + $\mathtt{addr};$ -* :math:`\mathtt{addr} : \mathtt{byte[length]}` — the Receiver Encoding. +* $\mathtt{addr} : \mathtt{byte[length]}$ — the Receiver Encoding. -The values of the :math:`\mathtt{typecode}` and :math:`\mathtt{length}` -fields MUST be less than or equal to :math:`\mathtt{0x2000000}.` +The values of the $\mathtt{typecode}$ and $\mathtt{length}$ +fields MUST be less than or equal to $\mathtt{0x2000000}.$ (The limitation on the total length of encodings described below imposes -a smaller limit for :math:`\mathtt{length}` in practice.) +a smaller limit for $\mathtt{length}$ in practice.) A Receiver Encoding is the raw encoding of a Shielded Payment Address, -or the :math:`160\!`-bit script hash of a P2SH address [#P2SH]_, or the -:math:`160\!`-bit validating key hash of a P2PKH address [#P2PKH]_. +or the $160$-bit script hash of a P2SH address [#P2SH]_, or the +$160$-bit validating key hash of a P2PKH address [#P2PKH]_. Let ``padding`` be the Human-Readable Part of the Unified Address in US-ASCII, padded to 16 bytes with zero bytes. We append ``padding`` to -the concatenated encodings, and then apply the :math:`\mathsf{F4Jumble}` +the concatenated encodings, and then apply the $\mathsf{F4Jumble}$ algorithm as described in `Jumbling`_. (In order for the limitation on -the :math:`\mathsf{F4Jumble}` input size to be met, the total length of -encodings MUST be at most :math:`\ell^\mathsf{MAX}_M - 16` bytes, where -:math:`\ell^\mathsf{MAX}_M` is defined in `Jumbling`_.) +the $\mathsf{F4Jumble}$ input size to be met, the total length of +encodings MUST be at most $\ell^\mathsf{MAX}_M - 16$ bytes, where +$\ell^\mathsf{MAX}_M$ is defined in `Jumbling`_.) The output is then encoded with Bech32m [#bip-0350]_, ignoring any length restrictions. This is chosen over Bech32 in order to better handle variable-length inputs. @@ -427,7 +427,7 @@ To decode a Unified Address Encoding, a Consumer MUST use the following procedure: * Decode using Bech32m, rejecting any address with an incorrect checksum. -* Apply :math:`\mathsf{F4Jumble}^{-1}` (this can also reject if the input +* Apply $\mathsf{F4Jumble}^{-1}$ (this can also reject if the input is not in the correct range of lengths). * Let ``padding`` be the Human-Readable Part, padded to 16 bytes as for encoding. If the result ends in ``padding``, remove these 16 bytes; @@ -461,40 +461,40 @@ future, and these will not necessarily use the same Typecode as the corresponding Unified Address. The following FVK or IVK Encodings are used in place of the -:math:`\mathtt{addr}` field: +$\mathtt{addr}$ field: -* An Orchard FVK or IVK Encoding, with Typecode :math:`\mathtt{0x03},` is +* An Orchard FVK or IVK Encoding, with Typecode $\mathtt{0x03},$ is the raw encoding of the Orchard Full Viewing Key or Orchard Incoming Viewing Key respectively. -* A Sapling FVK Encoding, with Typecode :math:`\mathtt{0x02},` is the - encoding of :math:`(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk})` - given by :math:`\mathsf{EncodeExtFVKParts}(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk})`, - where :math:`\mathsf{EncodeExtFVKParts}` is defined in [#zip-0032-sapling-helper-functions]_. +* A Sapling FVK Encoding, with Typecode $\mathtt{0x02},$ is the + encoding of $(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk})$ + given by $\mathsf{EncodeExtFVKParts}(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk})$, + where $\mathsf{EncodeExtFVKParts}$ is defined in [#zip-0032-sapling-helper-functions]_. This SHOULD be derived from the Extended Full Viewing Key at the Account level of the ZIP 32 hierarchy. -* A Sapling IVK Encoding, also with Typecode :math:`\mathtt{0x02},` - is an encoding of :math:`(\mathsf{dk}, \mathsf{ivk})` given by - :math:`\mathsf{dk}\,||\,\mathsf{I2LEOSP}_{256}(\mathsf{ivk}).` +* A Sapling IVK Encoding, also with Typecode $\mathtt{0x02},$ + is an encoding of $(\mathsf{dk}, \mathsf{ivk})$ given by + $\mathsf{dk}\,||\,\mathsf{I2LEOSP}_{256}(\mathsf{ivk}).$ * There is no defined way to represent a Viewing Key for a Transparent P2SH Address in a UFVK or UIVK (because P2SH Addresses cannot be - diversified in an unlinkable way). The Typecode :math:`\mathtt{0x01}` + diversified in an unlinkable way). The Typecode $\mathtt{0x01}$ MUST NOT be included in a UFVK or UIVK by Producers, and MUST be treated as unrecognised by Consumers. * For Transparent P2PKH Addresses that are derived according to BIP 32 [#bip-0032]_ and BIP 44 [#bip-0044]_, the FVK and IVK Encodings have - Typecode :math:`\mathtt{0x00}.` Both of these are encodings of the - chain code and public key :math:`(\mathsf{c}, \mathsf{pk})` given by - :math:`\mathsf{c}\,||\,\mathsf{ser_P}(\mathsf{pk})`. (This is the + Typecode $\mathtt{0x00}.$ Both of these are encodings of the + chain code and public key $(\mathsf{c}, \mathsf{pk})$ given by + $\mathsf{c}\,||\,\mathsf{ser_P}(\mathsf{pk})$. (This is the same as the last 65 bytes of the extended public key format defined in section “Serialization format” of BIP 32 [#bip-0032-serialization-format]_.) However, the FVK uses the key at the Account level, i.e. at path - :math:`m / 44' / coin\_type' / account'`, while the IVK uses the + $m / 44' / coin\_type' / account'$, while the IVK uses the external (non-change) child key at the Change level, i.e. at path - :math:`m / 44' / coin\_type' / account' / 0`. + $m / 44' / coin\_type' / account' / 0$. The Human-Readable Part is as specified for a Unified Viewing Key in `Revisions`_. @@ -525,13 +525,13 @@ Requirements for both Unified Addresses and Unified Viewing Keys ---------------------------------------------------------------- * A `Revision 0`_ Unified Address or Unified Viewing Key MUST contain - at least one shielded Item (Typecodes :math:`\mathtt{0x02}` and - :math:`\mathtt{0x03}`). This requirement is dropped for `Revision 1`_ + at least one shielded Item (Typecodes $\mathtt{0x02}$ and + $\mathtt{0x03}$). This requirement is dropped for `Revision 1`_ UA/UVKs; however, a `Revision 1`_ UA/UVK MUST contain at least one non-Metadata Item. -* The :math:`\mathtt{typecode}` and :math:`\mathtt{length}` fields are - encoded as :math:`\mathtt{compactSize}.` [#Bitcoin-CompactSize]_ +* The $\mathtt{typecode}$ and $\mathtt{length}$ fields are + encoded as $\mathtt{compactSize}.$ [#Bitcoin-CompactSize]_ (Although existing Receiver Encodings and Viewing Key Encodings are all less than 256 bytes and so could use a one-byte length field, encodings for experimental types may be longer.) @@ -643,8 +643,8 @@ be introduced either by a modification to this ZIP or by a new ZIP, in accordance with the ZIP Process [#zip-0000]_. For experimentation prior to proposing a ZIP, experimental types MAY -be added using the reserved Typecodes :math:`\mathtt{0xFFFA}` to -:math:`\mathtt{0xFFFF}` inclusive. This provides for six simultaneous +be added using the reserved Typecodes $\mathtt{0xFFFA}$ to +$\mathtt{0xFFFF}$ inclusive. This provides for six simultaneous experiments, which can be referred to as experiments A to F. This should be sufficient because experiments are expected to be reasonably short-term, and should otherwise be either standardized in a ZIP (and @@ -659,7 +659,7 @@ to give access only to view incoming payments (as opposed to change). Metadata Items -------------- -Typecodes :math:`\mathtt{0xC0}` to :math:`\mathtt{0xFC}` inclusive +Typecodes $\mathtt{0xC0}$ to $\mathtt{0xFC}$ inclusive are reserved to indicate Metadata Items other than Receivers or Viewing Keys. These Items MAY affect the overall interpretation of the UA/UVK (for example, by specifying an expiration date). @@ -667,7 +667,7 @@ the UA/UVK (for example, by specifying an expiration date). .. _`MUST-understand Typecodes`: As of `Revision 1`_ of this ZIP, the subset of Metadata Typecodes in -the range :math:`\mathtt{0xE0}` to :math:`\mathtt{0xFC}` inclusive are +the range $\mathtt{0xE0}$ to $\mathtt{0xFC}$ inclusive are designated as "MUST-understand": if a Consumer is unable to recognise the meaning of a Metadata Item with a Typecode in this range, then it MUST regard the entire UA/UVK as unsupported and not process it further. @@ -708,21 +708,21 @@ such implementations. Address Expiration Metadata --------------------------- -As of `Revision 1`_, Typecodes :math:`\mathtt{0xE0}` and :math:`\mathtt{0xE1}` +As of `Revision 1`_, Typecodes $\mathtt{0xE0}$ and $\mathtt{0xE1}$ are reserved for optional address expiry metadata. A producer MAY choose to generate Unified Addresses containing either or both of the following Metadata Item Types, or none. -The value of a :math:`\mathtt{0xE0}` item MUST be an unsigned 32-bit integer in +The value of a $\mathtt{0xE0}$ item MUST be an unsigned 32-bit integer in little-endian order specifying the Address Expiry Height, a block height of the Zcash chain associated with the UA/UVK. A Unified Address containing metadata -Typecode :math:`\mathtt{0xE0}` MUST be considered expired when the height of +Typecode $\mathtt{0xE0}$ MUST be considered expired when the height of the Zcash chain is greater than this value. -The value of a :math:`\mathtt{0xE1}` item MUST be an unsigned 64-bit integer in +The value of a $\mathtt{0xE1}$ item MUST be an unsigned 64-bit integer in little-endian order specifying a Unix Epoch Time, hereafter referred to as the Address Expiry Time. A Unified Address containing Metadata Typecode -:math:`\mathtt{0xE1}` MUST be considered expired when the current time is +$\mathtt{0xE1}$ MUST be considered expired when the current time is after the Address Expiry Time. A Sender that supports `Revision 1`_ of this specification MUST set @@ -732,7 +732,7 @@ sent to a Unified Address that defines an Address Expiry Height. If the Address Expiry Height, then the transaction MUST NOT be sent. If only an Address Expiry Time is specified, then the Sender SHOULD choose a value for ``nExpiryHeight`` such that the transaction will expire no more than 24 hours -after the current time. If both :math:`\mathtt{0xE0}` and :math:`\mathtt{0xE1}` +after the current time. If both $\mathtt{0xE0}$ and $\mathtt{0xE1}$ Metadata Items are present, then both restrictions apply. If a Sender sends to multiple Unified Addresses in the same transaction, then @@ -751,19 +751,19 @@ that although changes to metadata will result in a visually distinct address, such updated addresses will be directly linkable to the original addresses because they share the same Receivers. -When deriving a UIVK from a UFVK containing Typecodes :math:`\mathtt{0xE0}` -and/or :math:`\mathtt{0xE1}`, these Metadata Items MUST be retained unmodified +When deriving a UIVK from a UFVK containing Typecodes $\mathtt{0xE0}$ +and/or $\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 :math:`\mathtt{0xE0}`, the derived Unified Address MUST contain -a Metadata Item having Typecode :math:`\mathtt{0xE0}` such that the Address +having Typecode $\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 :math:`\mathtt{0xE1}`, the derived Unified Address MUST contain -a Metadata Item having Typecode :math:`\mathtt{0xE1}` such that the Address +having Typecode $\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. @@ -816,17 +816,17 @@ We desire the following properties for viewing authority of both shielded and transparent key trees: - A holder of an FVK can derive external and internal IVKs, and - external and internal :math:`\mathsf{ovk}` components. + external and internal $\mathsf{ovk}$ components. - A holder of the external IVK cannot derive the internal IVK, or - any of the :math:`\mathsf{ovk}` components. + any of the $\mathsf{ovk}$ components. -- A holder of the external :math:`\mathsf{ovk}` component cannot derive - the internal :math:`\mathsf{ovk}` component, or any of the IVKs. +- A holder of the external $\mathsf{ovk}$ component cannot derive + the internal $\mathsf{ovk}$ component, or any of the IVKs. For shielded keys, these properties are achieved by the one-wayness of -:math:`\mathsf{PRF^{expand}}` and of :math:`\mathsf{CRH^{ivk}}` or -:math:`\mathsf{Commit^{ivk}}` (for Sapling and Orchard respectively). +$\mathsf{PRF^{expand}}$ and of $\mathsf{CRH^{ivk}}$ or +$\mathsf{Commit^{ivk}}$ (for Sapling and Orchard respectively). Derivation of an internal shielded FVK from an external shielded FVK is specified in the "Sapling internal key derivation" [#zip-0032-sapling-internal-key-derivation]_ and @@ -834,15 +834,15 @@ is specified in the sections of ZIP 32. To satisfy the above properties for transparent (P2PKH) keys, we derive -the external and internal :math:`\mathsf{ovk}` components from the -transparent FVK :math:`(\mathsf{c}, \mathsf{pk})` (described in +the external and internal $\mathsf{ovk}$ components from the +transparent FVK $(\mathsf{c}, \mathsf{pk})$ (described in `Encoding of Unified Full/Incoming Viewing Keys`_) as follows: -- Let :math:`I_\mathsf{ovk} = \mathsf{PRF^{expand}}_{\mathsf{LEOS2BSP}_{256}(\mathsf{c})}\big([\mathtt{0xd0}] \,||\, \mathsf{ser_P}(\mathsf{pk})\big)` - where :math:`\mathsf{ser_P}(pk)` is :math:`33` bytes, as specified in [#bip-0032-serialization-format]_. -- Let :math:`\mathsf{ovk_{external}}` be the first :math:`32` bytes of - :math:`I_\mathsf{ovk}` and let :math:`\mathsf{ovk_{internal}}` be the - remaining :math:`32` bytes of :math:`I_\mathsf{ovk}`. +- Let $I_\mathsf{ovk} = \mathsf{PRF^{expand}}_{\mathsf{LEOS2BSP}_{256}(\mathsf{c})}\big([\mathtt{0xd0}] \,||\, \mathsf{ser_P}(\mathsf{pk})\big)$ + where $\mathsf{ser_P}(pk)$ is $33$ bytes, as specified in [#bip-0032-serialization-format]_. +- Let $\mathsf{ovk_{external}}$ be the first $32$ bytes of + $I_\mathsf{ovk}$ and let $\mathsf{ovk_{internal}}$ be the + remaining $32$ bytes of $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 @@ -877,7 +877,7 @@ The following derivations are applied to each component FVK: specified in [#protocol-orchardkeycomponents]_. * For a Transparent P2PKH FVK, the corresponding Transparent P2PKH IVK - is obtained by deriving the child key with non-hardened index :math:`0` + is obtained by deriving the child key with non-hardened index $0$ as described in [#bip-0032-public-to-public]_. In each case, the Typecode remains the same as in the FVK. @@ -911,13 +911,13 @@ UIVK. That is, defined in ZIP 32 section “Sapling diversifier derivation” [#zip-0032-sapling-diversifier-derivation]_. -* A Transparent diversifier index MUST be in the range :math:`0` to - :math:`2^{31} - 1` inclusive. +* A Transparent diversifier index MUST be in the range $0$ to + $2^{31} - 1$ inclusive. * There are no additional constraints on an Orchard diversifier index. Note: A diversifier index of 0 may not generate a valid Sapling -diversifier (with probability :math:`1/2`). Some wallets (either prior +diversifier (with probability $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, @@ -945,7 +945,7 @@ diversifier index: assumed to correspond to the extended public key for the external (non-change) element of the path. That is, if the UIVK was constructed correctly then the BIP 44 path of the Transparent P2PKH Receiver will be - :math:`m / 44' / \mathit{coin\_type\kern0.05em'} / \mathit{account\kern0.1em'} / 0 / \mathit{diversifier\_index}.` + $m / 44' / \mathit{coin\_type\kern0.05em'} / \mathit{account\kern0.1em'} / 0 / \mathit{diversifier\_index}.$ In each case, the Typecode remains the same as in the IVK. @@ -997,7 +997,7 @@ most preferred Receiver Type (as given in `Encoding of Unified Addresses`_) of any funds sent in the transaction. If the sending Account has been determined, then the Sender -SHOULD use the external or internal :math:`\mathsf{ovk}` +SHOULD use the external or internal $\mathsf{ovk}$ (according to the type of transfer), as specified by the preferred sending protocol, of the full viewing key for that Account (i.e. at the ZIP 32 Account level). @@ -1006,7 +1006,7 @@ If the sending Account is undetermined, then the Sender SHOULD choose one of the addresses, restricted to addresses for the preferred sending protocol, from which funds are being sent (for example, the first one for that protocol), and then use -the external or internal :math:`\mathsf{ovk}` (according to the +the external or internal $\mathsf{ovk}$ (according to the type of transfer) of the full viewing key for that address. @@ -1015,15 +1015,15 @@ Jumbling Security goal (**near second preimage resistance**): -* An adversary is given :math:`q` Unified Addresses/Viewing Keys, generated +* An adversary is given $q$ Unified Addresses/Viewing Keys, generated honestly. * The attack goal is to produce a “partially colliding” valid Unified Address/Viewing Key that: a) has a string encoding matching that of *one of* the input Addresses/Viewing Keys on some subset of characters (for concreteness, - consider the first :math:`n` and last :math:`m` characters, up to some - bound on :math:`n+m`); + consider the first $n$ and last $m$ characters, up to some + bound on $n+m$); b) is controlled by the adversary (for concreteness, the adversary knows *at least one* of the private keys of the constituent Addresses). @@ -1042,20 +1042,20 @@ Discussion There is a generic brute force attack against near second preimage resistance. The adversary generates UAs / UVKs at random with known keys, until one has an -encoding that partially collides with one of the :math:`q` targets. It may be +encoding that partially collides with one of the $q$ targets. It may be possible to improve on this attack by making use of properties of checksums, etc. The generic attack puts an upper bound on the achievable security: if it takes -work :math:`w` to produce and verify a UA/UVK, and the size of the character -set is :math:`c,` then the generic attack costs :math:`\sim \frac{w \cdot +work $w$ to produce and verify a UA/UVK, and the size of the character +set is $c,$ then the generic attack costs :math:`\sim \frac{w \cdot c^{n+m}}{q}.` There is also a generic brute force attack against nonmalleability. The adversary modifies the target UA/UVK slightly and computes the corresponding decoding, then repeats until the decoding is valid and also useful to the adversary (e.g. it would lead to the Sender using a Transparent Address). -With :math:`w` defined as above, the cost is :math:`w/p` where :math:`p` is +With $w$ defined as above, the cost is $w/p$ where $p$ is the probability that a random decoding is of the required form. Solution @@ -1064,41 +1064,41 @@ Solution We use an unkeyed 4-round Feistel construction to approximate a random permutation. (As explained below, 3 rounds would not be sufficient.) -Let :math:`H_i` be a hash personalized by :math:`i,` with maximum output -length :math:`\ell_H` bytes. Let :math:`G_i` be a XOF (a hash function with -extendable output length) based on :math:`H,` personalized by :math:`i.` +Let $H_i$ be a hash personalized by $i,$ with maximum output +length $\ell_H$ bytes. Let $G_i$ be a XOF (a hash function with +extendable output length) based on $H,$ personalized by $i.$ -Define :math:`\ell^\mathsf{MAX}_M = (2^{16} + 1) \cdot \ell_H.` +Define $\ell^\mathsf{MAX}_M = (2^{16} + 1) \cdot \ell_H.$ For the instantiation using BLAKE2b defined below, -:math:`\ell^\mathsf{MAX}_M = 4194368.` +$\ell^\mathsf{MAX}_M = 4194368.$ -Given input :math:`M` of length :math:`\ell_M` bytes such that -:math:`38 \leq \ell_M \leq \ell^\mathsf{MAX}_M,` define -:math:`\mathsf{F4Jumble}(M)` by: +Given input $M$ of length $\ell_M$ bytes such that +$38 \leq \ell_M \leq \ell^\mathsf{MAX}_M,$ define +$\mathsf{F4Jumble}(M)$ by: -* let :math:`\ell_L = \mathsf{min}(\ell_H, \mathsf{floor}(\ell_M/2))` -* let :math:`\ell_R = \ell_M - \ell_L` -* split :math:`M` into :math:`a` of length :math:`\ell_L` bytes and :math:`b` of length :math:`\ell_R` bytes -* let :math:`x = b \oplus G_0(a)` -* let :math:`y = a \oplus H_0(x)` -* let :math:`d = x \oplus G_1(y)` -* let :math:`c = y \oplus H_1(d)` -* return :math:`c \,||\, d.` +* let $\ell_L = \mathsf{min}(\ell_H, \mathsf{floor}(\ell_M/2))$ +* let $\ell_R = \ell_M - \ell_L$ +* split $M$ into $a$ of length $\ell_L$ bytes and $b$ of length $\ell_R$ bytes +* let $x = b \oplus G_0(a)$ +* let $y = a \oplus H_0(x)$ +* let $d = x \oplus G_1(y)$ +* let $c = y \oplus H_1(d)$ +* return $c \,||\, d.$ -The inverse function :math:`\mathsf{F4Jumble}^{-1}` is obtained in the usual -way for a Feistel construction, by observing that :math:`r = p \oplus q` implies :math:`p = r \oplus q.` +The inverse function $\mathsf{F4Jumble}^{-1}$ is obtained in the usual +way for a Feistel construction, by observing that $r = p \oplus q$ implies $p = r \oplus q.$ The first argument to BLAKE2b below is the personalization. -We instantiate :math:`H_i(u)` by -:math:`\mathsf{BLAKE2b‐}(8\ell_L)(\texttt{“UA_F4Jumble_H”} \,||\,` -:math:`[i, 0, 0], u),` with :math:`\ell_H = 64.` +We instantiate $H_i(u)$ by +$\mathsf{BLAKE2b‐}(8\ell_L)(\texttt{“UA\_F4Jumble\_H”} \,||\,$ +$[i, 0, 0], u),$ with $\ell_H = 64.$ -We instantiate :math:`G_i(u)` as the first :math:`\ell_R` bytes of the +We instantiate $G_i(u)$ as the first $\ell_R$ bytes of the concatenation of -:math:`[\mathsf{BLAKE2b‐}512(\texttt{“UA_F4Jumble_G”} \,||\, [i] \,||\,` -:math:`\mathsf{I2LEOSP}_{16}(j), u) \text{ for } j \text{ from}` -:math:`0 \text{ up to } \mathsf{ceiling}(\ell_R/\ell_H)-1].` +$[\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].$ .. figure:: ../rendered/assets/images/zip-0316-f4.png :width: 372px @@ -1107,8 +1107,8 @@ concatenation of Diagram of 4-round unkeyed Feistel construction -(In practice the lengths :math:`\ell_L` and :math:`\ell_R` will be roughly -the same until :math:`\ell_M` is larger than :math:`128` bytes.) +(In practice the lengths $\ell_L$ and $\ell_R$ will be roughly +the same until $\ell_M$ is larger than $128$ bytes.) Usage for Unified Addresses, UFVKs, and UIVKs ''''''''''''''''''''''''''''''''''''''''''''' @@ -1116,12 +1116,12 @@ Usage for Unified Addresses, UFVKs, and UIVKs In order to prevent the generic attack against nonmalleability, there needs to be some redundancy in the encoding. Therefore, the Producer of a Unified Address, UFVK, or UIVK appends the HRP, padded to 16 bytes with -zero bytes, to the raw encoding, then applies :math:`\mathsf{F4Jumble}` +zero bytes, to the raw encoding, then applies $\mathsf{F4Jumble}$ before encoding the result with Bech32m. The Consumer rejects any Bech32m-decoded byte sequence that is less than -38 bytes or greater than :math:`\ell^\mathsf{MAX}_M` bytes; otherwise it -applies :math:`\mathsf{F4Jumble}^{-1}.` It rejects any result that does +38 bytes or greater than $\ell^\mathsf{MAX}_M$ bytes; otherwise it +applies $\mathsf{F4Jumble}^{-1}.$ It rejects any result that does not end in the expected 16-byte padding, before stripping these 16 bytes and parsing the result. @@ -1133,7 +1133,7 @@ Rationale for length restrictions
      Click to show/hide -A minimum input length to :math:`\mathsf{F4Jumble}^{-1}` of 38 bytes +A minimum input length to $\mathsf{F4Jumble}^{-1}$ of 38 bytes allows for the minimum size of a UA/UVK Item encoding to be 22 bytes including the typecode and length, taking into account 16 bytes of padding. This allows for a UA containing only a Transparent P2PKH Receiver: @@ -1144,15 +1144,15 @@ This allows for a UA containing only a Transparent P2PKH Receiver: * 1-byte encoding of length * 20-byte transparent address hash -:math:`\ell^\mathsf{MAX}_M` bytes is the largest input/output size -supported by :math:`\mathsf{F4Jumble}.` +$\ell^\mathsf{MAX}_M$ bytes is the largest input/output size +supported by $\mathsf{F4Jumble}.$ Allowing only a Transparent P2PKH Receiver is consistent with dropping the requirement to have at least one shielded Item in Revision 1 UA/UVKs (`see rationale <#rationale-for-dropping-the-at-least-one-shielded-item-restriction>`_). Note that Revision 0 of this ZIP specified a minimum input length to -:math:`\mathsf{F4Jumble}^{-1}` of 48 bytes. Since there were no sets +$\mathsf{F4Jumble}^{-1}$ of 48 bytes. Since there were no sets of UA/UVK Item Encodings valid in Revision 0 to which a byte sequence (after removal of the 16-byte padding) of length between 22 and 31 bytes inclusive could be parsed, the difference between the 38 and 48-byte @@ -1178,31 +1178,31 @@ A 3-round unkeyed Feistel, as shown, is not sufficient: Diagram of 3-round unkeyed Feistel construction Suppose that an adversary has a target input/output pair -:math:`(a \,||\, b, c \,||\, d),` and that the input to :math:`H_0` is -:math:`x.` By fixing :math:`x,` we can obtain another pair -:math:`((a \oplus t) \,||\, b', (c \oplus t) \,||\, d')` such that -:math:`a \oplus t` is close to :math:`a` and :math:`c \oplus t` is close -to :math:`c.` -(:math:`b'` and :math:`d'` will not be close to :math:`b` and :math:`d,` +$(a \,||\, b, c \,||\, d),$ and that the input to $H_0$ is +$x.$ By fixing $x,$ we can obtain another pair +$((a \oplus t) \,||\, b', (c \oplus t) \,||\, d')$ such that +$a \oplus t$ is close to $a$ and $c \oplus t$ is close +to $c.$ +($\!b'$ and $d'$ will not be close to $b$ and $d,$ but that isn't necessarily required for a valid attack.) -A 4-round Feistel thwarts this and similar attacks. Defining :math:`x` and -:math:`y` as the intermediate values in the first diagram above: +A 4-round Feistel thwarts this and similar attacks. Defining $x$ and +$y$ as the intermediate values in the first diagram above: -* if :math:`(x', y')` are fixed to the same values as :math:`(x, y),` then - :math:`(a', b', c', d') = (a, b, c, d);` +* if $(x', y')$ are fixed to the same values as $(x, y),$ then + $(a', b', c', d') = (a, b, c, d);$ -* if :math:`x' = x` but :math:`y' \neq y,` then the adversary is able to - introduce a controlled :math:`\oplus\!`-difference - :math:`a \oplus a' = y \oplus y',` but the other three pieces - :math:`(b, c, d)` are all randomized, which is sufficient; +* if $x' = x$ but $y' \neq y,$ then the adversary is able to + introduce a controlled $\oplus$-difference + $a \oplus a' = y \oplus y',$ but the other three pieces + $(b, c, d)$ are all randomized, which is sufficient; -* if :math:`y' = y` but :math:`x' \neq x,` then the adversary is able to - introduce a controlled :math:`\oplus\!`-difference - :math:`d \oplus d' = x \oplus x',` but the other three pieces - :math:`(a, b, c)` are all randomized, which is sufficient; +* if $y' = y$ but $x' \neq x,$ then the adversary is able to + introduce a controlled $\oplus$-difference + $d \oplus d' = x \oplus x',$ but the other three pieces + $(a, b, c)$ are all randomized, which is sufficient; -* if :math:`x' \neq x` and :math:`y' \neq y,` all four pieces are +* if $x' \neq x$ and $y' \neq y,$ all four pieces are randomized. Note that the size of each piece is at least 19 bytes. @@ -1220,36 +1220,36 @@ attacks, or attacks that confuse addresses with viewing keys. Efficiency '''''''''' -The cost is dominated by 4 BLAKE2b compressions for :math:`\ell_M \leq 128` +The cost is dominated by 4 BLAKE2b compressions for $\ell_M \leq 128$ bytes. A UA containing a Transparent Address, a Sapling Address, and an -Orchard Address, would have :math:`\ell_M = 128` bytes. The restriction +Orchard Address, would have $\ell_M = 128$ bytes. The restriction to a single Address with a given Typecode (and at most one Transparent Address) means that this is also the maximum length of a Unified Address containing only defined Receiver Types as of NU5 activation. For longer UAs (when other Receiver Types are added) or UVKs, the cost -increases to 6 BLAKE2b compressions for :math:`128 < \ell_M \leq 192,` and -10 BLAKE2b compressions for :math:`192 < \ell_M \leq 256,` for example. The +increases to 6 BLAKE2b compressions for $128 < \ell_M \leq 192,$ and +10 BLAKE2b compressions for $192 < \ell_M \leq 256,$ for example. The maximum cost for which the algorithm is defined would be 196608 BLAKE2b -compressions at :math:`\ell_M = \ell^\mathsf{MAX}_M` bytes. +compressions at $\ell_M = \ell^\mathsf{MAX}_M$ bytes. -A naĂŻve implementation of the :math:`\mathsf{F4Jumble}^{-1}` function would -require roughly :math:`\ell_M` bytes plus the size of a BLAKE2b hash state. -However, it is possible to reduce this by streaming the :math:`d` part of +A naĂŻve implementation of the $\mathsf{F4Jumble}^{-1}$ function would +require roughly $\ell_M$ bytes plus the size of a BLAKE2b hash state. +However, it is possible to reduce this by streaming the $d$ part of the jumbled encoding three times from a less memory-constrained device. It -is essential that the streamed value of :math:`d` is the same on each pass, +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 :math:`d`, the implementation is able to compute :math:`y;` after -the second pass it is able to compute :math:`a;` and the third allows it to -compute and incrementally parse :math:`b.` The maximum memory usage during +pass of $d$, the implementation is able to compute $y;$ after +the second pass it is able to compute $a;$ and the third allows it to +compute and incrementally parse $b.$ The maximum memory usage during this process would be 128 bytes plus two BLAKE2b hash states. -Since this streaming implementation of :math:`\mathsf{F4Jumble}^{-1}` is +Since this streaming implementation of $\mathsf{F4Jumble}^{-1}$ is quite complicated, we do not require all Consumers to support streaming. If a Consumer implementation cannot support UAs / UVKs up to the maximum length, -it MUST nevertheless support UAs / UVKs with :math:`\ell_M` of at least -:math:`256` bytes. Note that this effectively defines two conformance levels +it MUST nevertheless support UAs / UVKs with $\ell_M$ of at least +$256$ bytes. Note that this effectively defines two conformance levels to this specification. A full implementation will support UAs / UVKs up to the maximum length. diff --git a/zips/zip-0317.rst b/zips/zip-0317.rst index b57b8a9a1..d60facef5 100644 --- a/zips/zip-0317.rst +++ b/zips/zip-0317.rst @@ -90,10 +90,10 @@ Notation
      -Let :math:`\mathsf{min}(a, b)` be the lesser of :math:`a` and :math:`b\!`. |br| -Let :math:`\mathsf{max}(a, b)` be the greater of :math:`a` and :math:`b\!`. |br| -Let :math:`\mathsf{floor}(x)` be the largest integer :math:`\leq x\!`. |br| -Let :math:`\mathsf{ceiling}(x)` be the smallest integer :math:`\geq x\!`. +Let $\mathsf{min}(a, b)$ be the lesser of $a$ and $b$. |br| +Let $\mathsf{max}(a, b)$ be the greater of $a$ and $b$. |br| +Let $\mathsf{floor}(x)$ be the largest integer $\leq x$. |br| +Let $\mathsf{ceiling}(x)$ be the smallest integer $\geq x$. Fee calculation --------------- @@ -161,7 +161,7 @@ impact on the network, without discriminating between different protocols (Orchard, Sapling, or transparent). The impact on the network depends on the numbers of inputs and outputs. -A previous proposal used :math:`inputs + outputs` instead of logical actions. +A previous proposal used $inputs + outputs$ instead of logical actions. This would have disadvantaged Orchard transactions, as a result of an Orchard Action combining an input and an output. The effect of this combining is that Orchard requires padding of either inputs or outputs @@ -193,7 +193,7 @@ Grace Actions transaction builder. * Without a grace window, an input with value below the marginal fee would never be worth including in the resulting transaction. - With a grace window, an input with value below :math:`marginal\_fee` + With a grace window, an input with value below $marginal\_fee$ *is* worth including, if a second input is available that covers both the primary output amount and the conventional transaction fee. @@ -205,18 +205,18 @@ transaction that permits both an output to a recipient, and a change output. However, as stated above, `zcashd` and the mobile SDK transaction builder will pad the number of inputs to at least 2. -Let :math:`min\_actions` be the minimum number of logical actions +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, :math:`min\_actions = 2`. +produce change. Due to the aforementioned padding, $min\_actions = 2$. -Having a grace window size greater than :math:`min\_actions` would +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 :math:`B`, then possible choices of :math:`marginal\_fee` are -bounded above by :math:`B / \max(min\_actions, grace\_actions)`. -Therefore, the optimal choice of :math:`grace\_actions` to maximize +is $B$, then possible choices of $marginal\_fee$ are +bounded above by $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 -:math:`B`, is :math:`grace\_actions = min\_actions = 2`. This also +$B$, is $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. @@ -227,16 +227,16 @@ Transparent Contribution 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 :math:`\mathsf{max}(transparent\_inputs, transparent\_outputs)`. +simply as $\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 :math:`p2pkh\_standard\_input\_size` and -:math:`p2pkh\_standard\_output\_size` are based on the maximum encoded +The chosen values for $p2pkh\_standard\_input\_size$ and +$p2pkh\_standard\_output\_size$ are based on the maximum encoded length for P2PKH inputs and outputs, as follows: -* :math:`p2pkh\_standard\_input\_size` +* $p2pkh\_standard\_input\_size$ * outpoint: 36 bytes * script: 110 bytes @@ -245,7 +245,7 @@ length for P2PKH inputs and outputs, as follows: * sequence: 4 bytes -* :math:`p2pkh\_standard\_output\_size` +* $p2pkh\_standard\_output\_size$ * value: 8 bytes * script: 26 bytes @@ -278,7 +278,7 @@ normally relay transactions are expected to do so for transactions that pay at least the conventional fee as specified in this ZIP, unless there are other reasons not to do so for robustness or denial-of-service mitigation. -If a transaction has more than :math:`block\_unpaid\_action\_limit` "unpaid actions" +If a transaction has more than $block\_unpaid\_action\_limit$ "unpaid actions" as defined by the `Recommended algorithm for block template construction`_, it will never be mined by that algorithm. Nodes MAY drop these transactions, or transactions with more unpaid actions than a configurable limit (see the @@ -288,7 +288,7 @@ Mempool size limiting --------------------- zcashd and zebrad limit the size of the mempool as described in [#zip-0401]_. -This specifies a :math:`low\_fee\_penalty` that is added to the "eviction weight" +This specifies a $low\_fee\_penalty$ that is added to the "eviction weight" if the transaction pays a fee less than the conventional transaction fee. This threshold is modified to use the new conventional fee formula. @@ -302,47 +302,47 @@ following section is planned to be implemented by `zcashd` and `zebrad`. Recommended algorithm for block template construction ''''''''''''''''''''''''''''''''''''''''''''''''''''' -Define constants :math:`weight\_ratio\_cap = 4` and -:math:`block\_unpaid\_action\_limit = 50\!`. +Define constants $weight\_ratio\_cap = 4$ and +$block\_unpaid\_action\_limit = 50$. -Let :math:`conventional\_fee(tx)` be the conventional fee for transaction -:math:`tx` calculated according to the section `Fee calculation`_. +Let $conventional\_fee(tx)$ be the conventional fee for transaction +$tx$ calculated according to the section `Fee calculation`_. -Let :math:`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 $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 :math:`block\_unpaid\_actions(block) = \sum_{tx \,\in\, block}\, unpaid\_actions(tx)`. +Let $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: -1. Set the block template :math:`T` to include a placeholder for the +1. Set the block template $T$ to include a placeholder for the coinbase transaction (see Note below). -2. For each transaction :math:`tx` in the mempool, calculate - :math:`tx.\!weight\_ratio = \mathsf{min}\!\left(\frac{\mathsf{max}(1,\, tx.fee)}{conventional\_fee(tx)},\, weight\_ratio\_cap\right)\!` +2. For each transaction $tx$ in the mempool, calculate + $tx.\!weight\_ratio = \mathsf{min}\!\left(\frac{\mathsf{max}(1,\, tx.fee)}{conventional\_fee(tx)},\, weight\_ratio\_cap\right)$ and add the transaction to the set of candidate transactions. 3. Repeat while there is any candidate transaction that pays at least the conventional fee: a. Pick one of those transactions at random with probability in direct - proportion to its :math:`weight\_ratio\!`, and remove it from the set of - candidate transactions. Let :math:`B` be the block template :math:`T` + proportion to its $weight\_ratio$, and remove it from the set of + candidate transactions. Let $B$ be the block template $T$ with this transaction included. - b. If :math:`B` would be within the block size limit and block sigop - limit [#sigop-limit]_, set :math:`T := B\!`. + b. If $B$ would be within the block size limit and block sigop + limit [#sigop-limit]_, set $T := B$. 4. Repeat while there is any candidate transaction: a. Pick one of those transactions at random with probability in direct - proportion to its :math:`weight\_ratio\!`, and remove it from the set of - candidate transactions. Let :math:`B` be the block template :math:`T` + proportion to its $weight\_ratio$, and remove it from the set of + candidate transactions. Let $B$ be the block template $T$ with this transaction included. - b. If :math:`B` would be within the block size limit and block sigop - limit [#sigop-limit]_ and :math:`block\_unpaid\_actions(B) \leq block\_unpaid\_action\_limit\!`, - set :math:`T := B\!`. + b. If $B$ would be within the block size limit and block sigop + limit [#sigop-limit]_ and $block\_unpaid\_actions(B) \leq block\_unpaid\_action\_limit$, + set $T := B$. -5. Return :math:`T\!`. +5. Return $T$. Note: In step 1, the final coinbase transaction cannot be included at this stage because it depends on the fees paid by other transactions. In practice, @@ -360,40 +360,40 @@ this block template algorithm more quickly while still giving transactions created by such wallets a reasonable chance of being mined, we allow a limited number of "unpaid" logical actions in each block. Roughly speaking, if a transaction falls short of paying the conventional transaction fee by -:math:`k` times the marginal fee, we count that as :math:`k` unpaid logical +$k$ times the marginal fee, we count that as $k$ unpaid logical actions. Regardless of how full the mempool is (according to the ZIP 401 [#zip-0401]_ cost limiting), and regardless of what strategy a denial-of-service adversary may use, the number of unpaid logical actions in each block is always limited -to at most :math:`block\_unpaid\_action\_limit\!`. +to at most $block\_unpaid\_action\_limit$. The weighting in step 2 does not create a situation where the adversary gains a significant advantage over other users by paying more than the conventional fee, for two reasons: 1. The weight ratio cap limits the relative probability of picking a given - transaction to be at most :math:`weight\_ratio\_cap` times greater than a + transaction to be at most $weight\_ratio\_cap$ times greater than a transaction that pays exactly the conventional fee. -2. Compare the case where the adversary pays :math:`c` times the conventional +2. Compare the case where the adversary pays $c$ times the conventional fee for one transaction, to that where they pay the conventional fee for - :math:`c` transactions. In the former case they are more likely to get *each* + $c$ transactions. In the former case they are more likely to get *each* transaction into the block relative to competing transactions from other users, *but* those transactions take up less block space, all else (e.g. choice of input or output types) being equal. This is not what the attacker wants; they get a transaction into the block only at the expense of leaving more block space for the other users' transactions. -The rationale for choosing :math:`weight\_ratio\_cap = 4` is as a compromise +The rationale for choosing $weight\_ratio\_cap = 4$ is as a compromise between not allowing any prioritization of transactions relative to those that pay the conventional fee, and allowing arbitrary prioritization based on ability to pay. -Calculating :math:`tx.\!weight\_ratio` in terms of :math:`\mathsf{max}(1,\, tx.\!fee)` -rather than just :math:`tx.\!fee` avoids needing to define "with probability in direct -proportion to its :math:`weight\_ratio\!`" for the case where all remaining candidate -transactions would have :math:`weight\_ratio = 0\!`. +Calculating $tx.\!weight\_ratio$ in terms of $\mathsf{max}(1,\, tx.\!fee)$ +rather than just $tx.\!fee$ avoids needing to define "with probability in direct +proportion to its $weight\_ratio$" for the case where all remaining candidate +transactions would have $weight\_ratio = 0$. Incentive compatibility for miners '''''''''''''''''''''''''''''''''' @@ -440,7 +440,7 @@ Deployment ========== Wallets SHOULD deploy these changes immediately. Nodes SHOULD deploy the -change to the :math:`low\_fee\_penalty` threshold described in +change to the $low\_fee\_penalty$ threshold described in `Mempool size limiting`_ immediately. Nodes supporting block template construction SHOULD deploy the new @@ -474,7 +474,7 @@ in: * https://github.com/zcash/zcash/pull/6527 (fee computation) * https://github.com/zcash/zcash/pull/6564 (block template construction) -The value used for :math:`block\_unpaid\_action\_limit` by `zcashd` +The value used for $block\_unpaid\_action\_limit$ by `zcashd` can be overridden using the ``-blockunpaidactionlimit`` configuration parameter. @@ -511,7 +511,7 @@ block template construction`_ in: * https://github.com/ZcashFoundation/zebra/pull/5776 (algorithm update) `zebra` v1.0.0-rc.2 had implemented an earlier version of this algorithm. -The value used for :math:`block\_unpaid\_action\_limit` in `zebra` is not +The value used for $block\_unpaid\_action\_limit$ in `zebra` is not configurable. `zebra` v1.0.0-rc.2 implemented the change to `Mempool size limiting`_ in: @@ -539,16 +539,16 @@ below are roughly half of what they would be under the current formula. Possible alternatives for the parameters: -* :math:`marginal\_fee = 250` in @nuttycom's proposal. -* :math:`marginal\_fee = 1000` adapted from @madars' proposal [#madars-1]_. -* :math:`marginal\_fee = 2500` in @daira's proposal. -* :math:`marginal\_fee = 1000` for Shielded, Shielding and De-shielding - transactions, and :math:`marginal\_fee = 10000` for Transparent transactions +* $marginal\_fee = 250$ in @nuttycom's proposal. +* $marginal\_fee = 1000$ adapted from @madars' proposal [#madars-1]_. +* $marginal\_fee = 2500$ in @daira's proposal. +* $marginal\_fee = 1000$ for Shielded, Shielding and De-shielding + transactions, and $marginal\_fee = 10000$ for Transparent transactions adapted from @nighthawk24's proposal. (In @madars' and @nighthawk24's original proposals, there was an additional -:math:`base\_fee` parameter that caused the relationship between fee and number -of inputs/outputs to be non-proportional above the :math:`grace\_actions` +$base\_fee$ parameter that caused the relationship between fee and number +of inputs/outputs to be non-proportional above the $grace\_actions$ threshold. This is no longer expressible with the formula specified above.) diff --git a/zips/zip-0320.rst b/zips/zip-0320.rst index 19d4e4968..141f24cbf 100644 --- a/zips/zip-0320.rst +++ b/zips/zip-0320.rst @@ -128,14 +128,14 @@ following steps: 1. Decode the address to a byte sequence using the Base58Check decoding algorithm [#Base58Check]_. 2. If the length of the resulting byte sequence is not 22 bytes or if its two-byte - address prefix is not :math:`[\mathtt{0x1C}, \mathtt{0xB8}]`, return an error. + address prefix is not $[\mathtt{0x1C}, \mathtt{0xB8}]$, return an error. Otherwise, let the **validating key hash** be the remaining 20 bytes of the sequence after removing the two-byte address prefix. 3. Reencode the 20-byte **validating key hash** using the Bech32m encoding defined in [#bip-0350]_ with the human-readable prefix (HRP) ``"tex"``. For Testnet addresses, the required lead bytes of a P2PKH address in step 2 are -:math:`[\mathtt{0x1D}, \mathtt{0x25}]`, and the ``"textest"`` HRP is used when +$[\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.: diff --git a/zips/zip-0324.rst b/zips/zip-0324.rst index 93f861e56..babc95416 100644 --- a/zips/zip-0324.rst +++ b/zips/zip-0324.rst @@ -386,7 +386,7 @@ In the above description, we explicitly list the notes involved in the payment ( Instead, we can have the nodes be implicitly identified by the spending key (or similar) included in the URI. This can make URI shorter, thus less scary and less likely to run into length limits (consider SMS). The following alternatives are feasible: -:math:`\hspace{0.9em}`\0. Explicitly list the note commitments within the URI. +$\hspace{0.9em}$\0. Explicitly list the note commitments within the URI. 1. Include only the spending key(s) in the URI, and have the recipient scan the blockchain using the existing mechanism (trial decryption of the encrypted memo field). This is very slow, and risks denial-of-service attacks. Would be faster in the nominal case if the scanning is done backwards (newest block first), or if told by the sender when the transactions were mined; but scanning the whole chain for nonexistent transactions (perhaps induced by a DoS) would still take very long. diff --git a/zips/zip-0401.rst b/zips/zip-0401.rst index e319996a8..c47f18f8e 100644 --- a/zips/zip-0401.rst +++ b/zips/zip-0401.rst @@ -165,7 +165,7 @@ 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 :math:`10000 + 40000 = 50000 = 10000 \times 5`). +eviction (because $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 diff --git a/zips/zip-2001.rst b/zips/zip-2001.rst index 410f6475f..487eac25c 100644 --- a/zips/zip-2001.rst +++ b/zips/zip-2001.rst @@ -56,7 +56,7 @@ Requirements ============ The Zcash protocol will maintain a new Deferred chain pool value balance -:math:`\mathsf{ChainValuePoolBalance^{Deferred}}` for the deferred funding pool, +$\mathsf{ChainValuePoolBalance^{Deferred}}$ for the deferred funding pool, in much the same fashion as it maintains chain pool value balances for the transparent, Sprout, Sapling, and Orchard pools. @@ -84,33 +84,33 @@ In the section **Funding streams** [#zip-0207-funding-streams]_, instead of: it will be modified to read: - Each element of :math:`\mathsf{fs.Recipients}` MUST represent either a transparent + Each element of $\mathsf{fs.Recipients}$ MUST represent either a transparent P2SH address as specified in [#protocol-transparentaddrencoding]_, or a Sapling shielded payment address as specified in [#protocol-saplingpaymentaddrencoding]_, - or the identifier :math:`\mathsf{DEFERRED}\_\mathsf{POOL}\!`. + or the identifier $\mathsf{DEFERRED\_POOL}$. After the section **Funding streams**, a new section is added with the heading "Deferred Development Fund Chain Value Pool Balance" and the following contents: 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. In the section **Consensus rules** [#zip-0207-consensus-rules]_, instead of: @@ -120,26 +120,26 @@ In the section **Consensus rules** [#zip-0207-consensus-rules]_, instead of: it will be modified to read: - - 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 + $\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})$. 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 [#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. In the section **Deployment** [#zip-0207-deployment]_, the following sentence is @@ -153,21 +153,21 @@ Changes to the Zcash Protocol Specification In section **4.17 Chain Value Pool Balances** [#protocol-chainvaluepoolbalances]_ (which is new in version 2024.5.1 of the protocol specification), include the following: - Define :math:`\mathsf{totalDeferredOutput}` as in [#protocol-subsidies]_. + Define $\mathsf{totalDeferredOutput}$ as in [#protocol-subsidies]_. Then, consistent with [#zip-0207]_, the deferred development fund chain value pool - balance for a block chain up to and including height :math:`\mathsf{height}` is given by - :math:`\mathsf{ChainValuePoolBalance^{Deferred}}(\mathsf{height}) := \sum_{\mathsf{h} = 0}^{\mathsf{height}} \mathsf{totalDeferredOutput}(\mathsf{h})\!`. + 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})$. Non-normative notes: - * :math:`\mathsf{totalDeferredOutput}(\mathsf{h})` is necessarily zero for heights - :math:`\mathsf{h}` prior to NU6 activation. + * $\mathsf{totalDeferredOutput}(\mathsf{h})$ is necessarily zero for heights + $\mathsf{h}$ prior to NU6 activation. * Currently there is no way to withdraw from the deferred development fund chain value pool, so there is no possibility of it going negative. Therefore, no consensus rule to prevent that eventuality is needed at this time. - The *total issued supply* of a block chain at block height :math:`\mathsf{height}` + The *total issued supply* of a block chain at block height $\mathsf{height}$ is given by the function: .. math:: @@ -183,24 +183,24 @@ In section **4.17 Chain Value Pool Balances** [#protocol-chainvaluepoolbalances] In section **7.1.2 Transaction Consensus Rules** [#protocol-txnconsensus]_, instead of: The total value in zatoshi of transparent outputs from a coinbase transaction, - minus :math:`\mathsf{v^{balanceSapling}}\!`, minus :math:`\mathsf{v^{balanceOrchard}}\!`, + minus $\mathsf{v^{balanceSapling}}$, minus $\mathsf{v^{balanceOrchard}}$, MUST NOT be greater than the value in zatoshi of the block subsidy plus the transaction fees paid by transactions in this block. it will be modified to read: - For the block at block height :math:`\mathsf{height}`: + For the block at block height $\mathsf{height}$: - define the "total output value" of its coinbase transaction to be the total value - in zatoshi of its transparent outputs, minus :math:`\mathsf{v^{balanceSapling}}\!`, - minus :math:`\mathsf{v^{balanceOrchard}}\!`, plus :math:`\mathsf{totalDeferredOutput}(\mathsf{height})\!`; + in zatoshi of its transparent outputs, minus $\mathsf{v^{balanceSapling}}$, + minus $\mathsf{v^{balanceOrchard}}$, plus $\mathsf{totalDeferredOutput}(\mathsf{height})$; - define the "total input value" of its coinbase transaction to be the value in zatoshi of the block subsidy, plus the transaction fees paid by transactions in the block. The total output value of a coinbase transaction MUST NOT be greater than its total input value. -where :math:`\mathsf{totalDeferredOutput}(\mathsf{height})` is defined consistently +where $\mathsf{totalDeferredOutput}(\mathsf{height})$ is defined consistently with ZIP 207. Note: this ZIP and ZIP 236 both make changes to the above rule. Their combined effect diff --git a/zips/zip-2002.rst b/zips/zip-2002.rst index 49d392e26..3ef1b33b0 100644 --- a/zips/zip-2002.rst +++ b/zips/zip-2002.rst @@ -99,7 +99,7 @@ ZIP 236 [#zip-0236]_), add the following consensus rule and note: In § 7.1 ‘Transaction Encoding and Consensus’ [#protocol-txnconsensus]_, add: - [NU7 onward] ``fee`` MUST be in the range :math:`\{ 0 .. \mathsf{MAX\_MONEY} \}`. + [NU7 onward] ``fee`` MUST be in the range $\{ 0 .. \mathsf{MAX\_MONEY} \}$. Modifications relative to ZIP 244 [#zip-0244]_ diff --git a/zips/zip-2004.rst b/zips/zip-2004.rst index 2d974cf7b..7f09e1482 100644 --- a/zips/zip-2004.rst +++ b/zips/zip-2004.rst @@ -80,41 +80,41 @@ Specification Changes to the Zcash Protocol Specification ------------------------------------------- -In § 5.4.3 'Symmetric Encryption', rename :math:`Sym` to :math:`NoteSym` and +In § 5.4.3 'Symmetric Encryption', rename $Sym$ to $NoteSym$ and add the following text: - Let :math:`\mathsf{NullSym.}\mathbf{K} := \mathbb{B}^{[256]}`, - :math:`\mathsf{NullSym.}\mathbf{P} := \mathbb{B^Y}^{\mathbb{N}}`, and - :math:`\mathsf{NullSym.}\mathbf{C} := \mathbb{B^Y}^{\mathbb{N}}\!`. + Let $\mathsf{NullSym.}\mathbf{K} := \mathbb{B}^{[256]}$, + $\mathsf{NullSym.}\mathbf{P} := \mathbb{B^Y}^{\mathbb{N}}$, and + $\mathsf{NullSym.}\mathbf{C} := \mathbb{B^Y}^{\mathbb{N}}$. - Let :math:`\mathsf{NullSym.Encrypt_K}(\mathsf{P}) := \mathsf{P} \,||\, [0x00]^{16}\!`. + Let $\mathsf{NullSym.Encrypt_K}(\mathsf{P}) := \mathsf{P} \,||\, [0x00]^{16}$. - Define :math:`\mathsf{NullSym.Decrypt_K}(\mathsf{C})` as follows: + Define $\mathsf{NullSym.Decrypt_K}(\mathsf{C})$ as follows: - * If the last 16 bytes of :math:`\mathsf{C}` are not :math:`[0x00]^{16}\!`, - return :math:`\bot\!`. Otherwise discard those 16 bytes and return the - remaining prefix of :math:`\mathsf{C}\!`. + * If the last 16 bytes of $\mathsf{C}$ are not $[0x00]^{16}$, + return $\bot$. Otherwise discard those 16 bytes and return the + remaining prefix of $\mathsf{C}$. - Note: These definitions intentionally ignore the key; :math:`\mathsf{NullSym}` + Note: These definitions intentionally ignore the key; $\mathsf{NullSym}$ is not a secure authenticated encryption scheme. It MUST be used only for notes in shielded coinbase outputs, which are intended to be visible as cleartext. In § 4.20 'In-band secret distribution (Sapling and Orchard)', change: - let :math:`\mathsf{Sym}` be the encryption scheme instantiated in + let $\mathsf{Sym}$ be the encryption scheme instantiated in § 5.4.3 'Symmetric Encryption'. to - let :math:`\mathsf{NoteSym}` and :math:`\mathsf{NullSym}` be as + let $\mathsf{NoteSym}$ and $\mathsf{NullSym}$ be as instantiated in § 5.4.3 'Symmetric Encryption'. - [Pre-NU7] let :math:`\mathsf{Sym}` be :math:`\mathsf{NoteSym}\!`. + [Pre-NU7] let $\mathsf{Sym}$ be $\mathsf{NoteSym}$. [NU7 onward] if the note to be decrypted is in an output of a version 6 - or later coinbase transaction, let :math:`\mathsf{Sym}` be - :math:`\mathsf{NullSym}\!`, otherwise let it be :math:`\mathsf{NoteSym}\!`. + or later coinbase transaction, let $\mathsf{Sym}$ be + $\mathsf{NullSym}$, otherwise let it be $\mathsf{NoteSym}$. These changes apply identically to Mainnet and Testnet. diff --git a/zips/zip-guide-markdown.md b/zips/zip-guide-markdown.md index 4cc0091cb..bdf82facc 100644 --- a/zips/zip-guide-markdown.md +++ b/zips/zip-guide-markdown.md @@ -142,10 +142,13 @@ ZIPs are different from RFCs in the following ways: ## Using mathematical notation -Embedded LaTeX $x + y$ 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 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 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