diff --git a/zip-0307.html b/zip-0307.html index d42b51a63..e4002da8e 100644 --- a/zip-0307.html +++ b/zip-0307.html @@ -56,7 +56,7 @@
  • Detect a spend of your shielded Sapling notes
  • Update your witnesses to generate new Sapling spend proofs.
  • -

    A compact block and its component compact transactions are encoded on the wire using the following Protocol Buffers [#protocolbuffers] format:

    +

    A compact block and its component compact transactions are encoded on the wire using the following Protocol Buffers 9 format:

    message BlockID {
          uint64 blockHeight = 1;
          bytes blockHash = 2;
    @@ -96,7 +96,7 @@
                                 8-bit 0x01
                                 88-bit d
                                 64-bit v
    -                            256-bit rcm
    +                            256-bit rseed
                                 memo (512 bytes) + tag (16 bytes)
                             
                         
    @@ -107,7 +107,7 @@
                     

    Since the note commitment is sent outside the ciphertext and is authenticated by the binding signature over the entire transaction, it serves as an adequate check on the validity of the decrypted plaintext (assuming you trust the entity assembling transactions). We therefore recalculate the note commitment from the decrypted plaintext. If the recalculated commitment matches the one in the output, we accept the note as valid and spendable.

    Spend Compression

    -

    Recall that a full Sapling Spend description is 384 bytes long [#protocol-spendencoding]:

    +

    Recall that a full Sapling Spend description is 384 bytes long 6:

    @@ -193,13 +193,15 @@

    Client operation

    Light clients obtain compact blocks from one or more proxy servers, which they then process locally to update their view of the block chain. We consider only a single proxy server here without loss of generality.

    Local processing

    -

    Given a CompactBlock received in height-sequential order from a proxy server, a light client can process it in four ways:

    +

    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 \((\mathtt{cmu}, \mathsf{epk}, \mathsf{ciphertext})\) with an incoming viewing key \(\mathsf{ivk}\) - is a slight deviation from the standard decryption process 4:

    + is a slight deviation from the standard decryption process 4 (all constants and algorithms are as defined there):

    • let \(\mathsf{sharedSecret} = \mathsf{KA^{Sapling}.Agree}(\mathsf{ivk}, \mathsf{epk})\) @@ -211,12 +213,37 @@ \(P^{\mathsf{enc}} = \mathsf{ChaCha20.Decrypt}_{K^{\mathsf{enc}}}(\mathsf{ciphertext})\)
    • extract - \(\mathbf{np} = (\mathsf{d}, \mathsf{v}, \mathsf{rcm})\) + \(\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{rcm})\) + \(\mathsf{rcm} = \mathsf{LEOS2IP}_{256}(\mathsf{\underline{rcm}})\) and \(\mathsf{g_d} = \mathsf{DiversifyHash}(\mathsf{d})\)
    • @@ -237,14 +264,28 @@ \(\mathsf{LEBS2OSP}_{256}(\mathsf{cm}_u') \neq \mathtt{cmu}\) , return \(\bot\) - , else return + +
    • [Canopy onward] if + \(\mathsf{leadByte} \neq \mathtt{0x01}\) + : +
        +
      • + \(\mathsf{esk} = \mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([4]))\) +
      • +
      • if + \(\mathsf{KA^{Sapling}.DerivePublic}(\mathsf{esk}, \mathsf{g_d}) \neq \mathsf{epk}\) + , return + \(\bot\) +
      • +
      +
    • +
    • return \(\mathbf{np}\) .
    -

    TODO: update this for ZIP 212 8.

    Creating and updating note witnesses

    -

    As CompactBlocks are received in height order, and the transactions within them have their order preserved, the cmu values in each CompactOutput can be sequentially appended to an incremental Merkle tree of depth 32 in order to maintain a local copy of the Sapling note commitment tree. 2 This can then be used to create incremental witnesses for each unspent note the light client is tracking. 10 An incremental witness updated to height X corresponds to a Merkle path from the note to the Sapling commitment tree anchor for block X. 3

    +

    As CompactBlocks are received in height order, and the transactions within them have their order preserved, the cmu values in each CompactOutput can be sequentially appended to an incremental Merkle tree of depth 32 in order to maintain a local copy of the Sapling note commitment tree. 2 This can then be used to create incremental witnesses for each unspent note the light client is tracking. 10 An incremental witness updated to height X corresponds to a Merkle path from the note to the Sapling commitment tree anchor for block X. 3

    Let tree be the Sapling note commitment tree at height X-1, and note_witnesses be the incremental witnesses for unspent notes detected up to height X-1. When the CompactBlock at height X is received:

    • For each CompactTx in CompactBlock: @@ -270,7 +311,7 @@

    Block header validation

    This section describes a proposed enhancement that has been only partially implemented: currently only prevHash is checked.

    -

    If the CompactBlock for height X contains a block header, the light client can validate it in a similar way to SPV clients 11 by performing the following checks:

    +

    If the CompactBlock for height X contains a block header, the light client can validate it in a similar way to SPV clients 11 by performing the following checks:

    • version >= MIN_BLOCK_VERSION
    • prevHash == prevBlock.id.blockHash where prevBlock is the previous CompactBlock received (at height X-1).
    • @@ -478,7 +519,7 @@
    - +
    1Key words for use in RFCs to Indicate Requirement LevelsRFC 2119: Key words for use in RFCs to Indicate Requirement Levels
    @@ -486,7 +527,7 @@ 2 - Section 3.7: Note Commitment Trees. Zcash Protocol Specification, Version 2020.1.6 + Section 3.7: Note Commitment Trees. Zcash Protocol Specification, Version 2020.1.14 or later @@ -494,7 +535,7 @@ 3 - Section 4.8: Merkle Path Validity. Zcash Protocol Specification, Version 2020.1.6 + Section 4.8: Merkle Path Validity. Zcash Protocol Specification, Version 2020.1.14 or later @@ -502,7 +543,7 @@ 4 - Section 4.17.2: Decryption using an Incoming Viewing Key (Sapling). Zcash Protocol Specification, Version 2020.1.6 + Section 4.17.2: Decryption using an Incoming Viewing Key (Sapling). Zcash Protocol Specification, Version 2020.1.14 or later @@ -510,7 +551,7 @@ 5 - Section 5.5: Encodings of Note Plaintexts and Memo Fields. Zcash Protocol Specification, Version 2020.1.6 + Section 5.5: Encodings of Note Plaintexts and Memo Fields. Zcash Protocol Specification, Version 2020.1.14 or later @@ -518,7 +559,7 @@ 6 - Section 7.3: Encoding of Spend Descriptions. Zcash Protocol Specification, Version 2020.1.6 + Section 7.3: Encoding of Spend Descriptions. Zcash Protocol Specification, Version 2020.1.14 or later @@ -526,7 +567,7 @@ 7 - Section 7.4: Encoding of Output Descriptions. Zcash Protocol Specification, Version 2020.1.6 + Section 7.4: Encoding of Output Descriptions. Zcash Protocol Specification, Version 2020.1.14 or later @@ -542,7 +583,7 @@ 9 - Protocol Buffers. + Protocol Buffers documentation @@ -550,7 +591,7 @@ 10 - TODO + zcash_primitives Rust crate — merkle_tree.rs @@ -558,7 +599,7 @@ 11 - TODO + Bitcoin Wiki: Scalability — Simplified payment verification diff --git a/zip-0307.rst b/zip-0307.rst index e96dffbe8..f6c17ba15 100644 --- a/zip-0307.rst +++ b/zip-0307.rst @@ -92,7 +92,7 @@ A **compact block** is a packaging of ONLY the data from a block needed to: 3. Update your witnesses to generate new Sapling spend proofs. A compact block and its component compact transactions are encoded on the wire using the -following Protocol Buffers [#protocolbuffers] format: +following Protocol Buffers [#protocolbuffers]_ format: .. code:: proto @@ -139,9 +139,9 @@ Output Compression In the normal Zcash protocol, the output ciphertext consists of the AEAD encrypted form of a *note plaintext* [#protocol-notept]_: -+------------+----------+----------+-------------+-----------------------------------+ -| 8-bit 0x01 | 88-bit d | 64-bit v | 256-bit rcm | memo (512 bytes) + tag (16 bytes) | -+------------+----------+----------+-------------+-----------------------------------+ ++------------+----------+----------+---------------+-----------------------------------+ +| 8-bit 0x01 | 88-bit d | 64-bit v | 256-bit rseed | memo (512 bytes) + tag (16 bytes) | ++------------+----------+----------+---------------+-----------------------------------+ A recipient detects their transactions by trial-decrypting this ciphertext. On a full node that has the entire block chain, the primary cost is computational. For light clients @@ -171,7 +171,7 @@ and spendable. Spend Compression ----------------- -Recall that a full Sapling Spend description is 384 bytes long [#protocol-spendencoding]: +Recall that a full Sapling Spend description is 384 bytes long [#protocol-spendencoding]_: +-------+--------------+-----------+ | Bytes | Name | Type | @@ -252,8 +252,8 @@ server here without loss of generality. Local processing ---------------- -Given a ``CompactBlock`` received in height-sequential order from a proxy server, a light -client can process it in four ways: +Given a ``CompactBlock`` at block height :math:`\mathsf{height}` received in height-sequential +order from a proxy server, a light client can process it in four ways: Scanning for relevant transactions `````````````````````````````````` @@ -261,19 +261,28 @@ For every ``CompactOutput`` in the ``CompactBlock``, the light client can trial- against a set of Sapling incoming viewing keys. The procedure for trial-decrypting a ``CompactOutput`` :math:`(\mathtt{cmu}, \mathsf{epk}, \mathsf{ciphertext})` with an incoming viewing key :math:`\mathsf{ivk}` is a slight deviation from the standard decryption process -[#protocol-saplingdecryptivk]_: +[#protocol-saplingdecryptivk]_ (all constants and algorithms are as defined there): - let :math:`\mathsf{sharedSecret} = \mathsf{KA^{Sapling}.Agree}(\mathsf{ivk}, \mathsf{epk})` - let :math:`K^{\mathsf{enc}} = \mathsf{KDF^{Sapling}}(\mathsf{sharedSecret}, \mathsf{epk})` - let :math:`P^{\mathsf{enc}} = \mathsf{ChaCha20.Decrypt}_{K^{\mathsf{enc}}}(\mathsf{ciphertext})` -- extract :math:`\mathbf{np} = (\mathsf{d}, \mathsf{v}, \mathsf{rcm})` from :math:`P^{\mathsf{enc}}` -- let :math:`\mathsf{rcm} = \mathsf{LEOS2IP}_{256}(\mathsf{rcm})` and :math:`\mathsf{g_d} = \mathsf{DiversifyHash}(\mathsf{d})` +- 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` - 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`, else return :math:`\mathbf{np}`. +- if :math:`\mathsf{LEBS2OSP}_{256}(\mathsf{cm}_u') \neq \mathtt{cmu}`, return :math:`\bot` +- [Canopy onward] if :math:`\mathsf{leadByte} \neq \mathtt{0x01}`: -TODO: update this for ZIP 212 [#zip-0212]_. + * :math:`\mathsf{esk} = \mathsf{ToScalar}(\mathsf{PRF^{expand}_{rseed}}([4]))` + * if :math:`\mathsf{KA^{Sapling}.DerivePublic}(\mathsf{esk}, \mathsf{g_d}) \neq \mathsf{epk}`, return :math:`\bot` + +- return :math:`\mathbf{np}`. Creating and updating note witnesses ```````````````````````````````````` @@ -596,14 +605,14 @@ Electric Coin Company. References ========== -.. [#RFC2119] `Key words for use in RFCs to Indicate Requirement Levels `_ -.. [#protocol-merkletree] `Section 3.7: Note Commitment Trees. Zcash Protocol Specification, Version 2020.1.6 `_ -.. [#protocol-merklepath] `Section 4.8: Merkle Path Validity. Zcash Protocol Specification, Version 2020.1.6 `_ -.. [#protocol-saplingdecryptivk] `Section 4.17.2: Decryption using an Incoming Viewing Key (Sapling). Zcash Protocol Specification, Version 2020.1.6 `_ -.. [#protocol-notept] `Section 5.5: Encodings of Note Plaintexts and Memo Fields. Zcash Protocol Specification, Version 2020.1.6 `_ -.. [#protocol-spendencoding] `Section 7.3: Encoding of Spend Descriptions. Zcash Protocol Specification, Version 2020.1.6 `_ -.. [#protocol-outputencoding] `Section 7.4: Encoding of Output Descriptions. Zcash Protocol Specification, Version 2020.1.6 `_ +.. [#RFC2119] `RFC 2119: Key words for use in RFCs to Indicate Requirement Levels `_ +.. [#protocol-merkletree] `Section 3.7: Note Commitment Trees. Zcash Protocol Specification, Version 2020.1.14 or later `_ +.. [#protocol-merklepath] `Section 4.8: Merkle Path Validity. Zcash Protocol Specification, Version 2020.1.14 or later `_ +.. [#protocol-saplingdecryptivk] `Section 4.17.2: Decryption using an Incoming Viewing Key (Sapling). Zcash Protocol Specification, Version 2020.1.14 or later `_ +.. [#protocol-notept] `Section 5.5: Encodings of Note Plaintexts and Memo Fields. Zcash Protocol Specification, Version 2020.1.14 or later `_ +.. [#protocol-spendencoding] `Section 7.3: Encoding of Spend Descriptions. Zcash Protocol Specification, Version 2020.1.14 or later `_ +.. [#protocol-outputencoding] `Section 7.4: Encoding of Output Descriptions. Zcash Protocol Specification, Version 2020.1.14 or later `_ .. [#zip-0212] `ZIP 212: Allow Recipient to Derive Sapling Ephemeral Secret from Note Plaintext `_ -.. [#protocolbuffers] `Protocol Buffers. `_ -.. [#incremental-witness] `TODO` -.. [#spv-clients] `TODO` +.. [#protocolbuffers] `Protocol Buffers documentation `_ +.. [#incremental-witness] `zcash_primitives Rust crate — merkle_tree.rs `_ +.. [#spv-clients] `Bitcoin Wiki: Scalability — Simplified payment verification `_