ZIP: 210 Title: Sapling Anchor Deduplication within Transactions Owners: Jack Grigg <[email protected]> Status: Draft Category: Consensus Created: 2019-03-27 License: MIT
The key words "MUST" and "MAY" in this document are to be interpreted as described in RFC 2119. [1]
The term "network upgrade" in this document is to be interpreted as described in ZIP 200 [2].
The term "Sapling" in this document is to be interpreted as described in ZIP 205 [3].
This proposal defines a modification to the transaction format whereby a single Sapling anchor is used for all Sapling spends. This change removes a potential implementation fingerprint, and reduces the size of Sapling transactions within the block chain.
The Sapling network upgrade [3] introduced new shielded inputs (spends) and outputs. Each spend proves the existence of the note being spent by including the anchor of a Merkle tree that contains the note's commitment, and proving in zero knowledge the existence of a path from the commitment to the anchor (a witness). Valid anchors correspond to the state of the Sapling commitment tree after each block in the chain.
The choice of anchor leaks information about the note being spent, namely that the note was created no later than the anchor's block height. This is an unavoidable outcome of the Zcash design, and the least information it is possible to leak about a note being spent. However, the Sapling v4 transaction format [4] includes a separate anchor for each Sapling spend, and thus it is possible to leak additional information by using different anchors for different notes. The anchor selection choices could also be used as a fingerprint to identify transactions created by particular wallet implementations, reducing the privacy set.
Modifying the transaction format to have a single Sapling anchor field, instead of one field per Sapling spend, removes the ability (within the new transaction format version) to create transactions with this fingerprint. It also reduces the size of the transaction, costing 32 bytes per transaction instead of 32 bytes per spend.
A new transaction format is defined, identical to the Sapling v4 transaction format except for two changes:
- The
anchor
field inSpendDescription
is removed. - A new field
saplingAnchor
is placed betweenvShieldedOutput
andvJoinSplit
, if and only ifvShieldedSpend
is not empty.
Consensus rules that previously applied to individual anchor
entries MUST be applied
to saplingAnchor
.
TODO: If this is the only ZIP updating the transaction format in a NU, specify the full transaction format here. Otherwise, reference the new transaction format when specified.
Implementations that support older transaction formats MAY copy saplingAnchor
into
each spend's in-memory representation during parsing to reduce code duplication, and MUST
ensure that these per-spend in-memory anchors are all identical prior to serialization.
Placing the saplingAnchor
field after vShieldedOutput
means that it can be
conditionally included (saving space when there are no Sapling spends), while ensuring
that the transaction can still be parsed unambiguously.
Requiring all Sapling spends to use the same anchor removes a possible performance optimisation in certain classes of (particularly light) wallets, where witnesses for older notes are only updated periodically instead of every block. This optimisation is exactly the kind of behaviour that can be used as a fingerprint in the v4 transaction format, and that we are choosing to prevent with this proposal.
This proposal eliminates a possible avenue for distinguishing transactions based on the client implementation that created them.
TBD
[1] | Key words for use in RFCs to Indicate Requirement Levels |
[2] | ZIP 200: Network Upgrade Activation Mechanism |
[3] | (1, 2) ZIP 205: Deployment of the Sapling Network Upgrade |
[4] | Section 7.1: Encoding of Transactions. Zcash Protocol Specification, Version 2019.0-beta-37 [Overwinter+Sapling] |