[Sapling] Disunify Mint and Pour #2170
Labels
A-circuit
Area: zk-SNARK circuits
A-consensus
Area: Consensus rules
A-crypto
Area: Cryptography
C-future-proofing
Category: Changes that minimise the effects of shocks and stresses of future events.
I-performance
Problems and improvements with respect to performance
I-privacy
Problems and improvements related to privacy.
I-SECURITY
Problems and improvements related to security.
M-requires-nu
A network upgrade is required to implement this.
note selection and shielded tx construction
NU1-sapling
Network upgrade: Sapling-specific tasks
protocol spec
special to Daira
Threat Model
Z-NU2-Blossom wishlist
One of the protocol differences between Zerocash and Zcash is that the former has separate Mint and Pour operations, while the latter unifies these into JoinSplit operations. A JoinSplit is like a Zerocash Pour, except that it takes a transparent input and therefore subsumes the functionality of a Zerocash Mint. However, it has the performance characteristics of a Pour even in the case where there are only transparent inputs.
This was a performance vs simplicity+privacy trade-off that we took in favour of simplicity+privacy. I think it was a perfectly reasonable decision at the time; it did simplify the code, the protocol design, and the user-visible concepts significantly. In particular it simplified the solution to the Faerie Gold attack (see sections 7.3 and 7.4 of the protocol specification). It also improves privacy slightly by reducing the distinguishability of some operations. (This is quite subtle because JoinSplits that take a transparent input are still distinguishable; the improvement is that those JoinSplits can be operating on shielded notes at the same time.)
However, given the expense of generating zk-SNARK proofs (currently ~42 seconds and ~3.1GB on our benchmark server), we should consider whether to disunify these operations in order to allow faster creation of shielded notes from transparent inputs. While there is plenty of scope for reducing proving time and/or memory (#647, #2064, #750, #1966, #2005, #43, #40, #2171, #2173, #2230, #2233, #2234, #2235), those options can't compete on performance with eliminating the proof entirely for some cases.
An obvious difficulty is how to support compatibility with existing notes. When we fixed the InternalH bug (see section 7.5 of the protocol spec), we changed the note commitment from the two-level structure used in Zerocash, to a one-level structure (#704, #738). The purpose of the two-level structure was to allow Mint operations to reveal the opening of the outer commitment (v, k, s), which is necessary to prove that the Mint is creating a coin of the right value v. It is highly desirable, when changing the circuit, to maintain a single note anonymity set, so that new transactions can spend old notes without loss of privacy. On the other hand, we may want to change the commitment in any case in order to allow for User-Issued Tokens (#830) or other extensions (#344, #608, #716, #718, #782, #794, #829). Also see #790 about note commitment extensibility.
I believe it should be relatively straightforward to support a new commitment structure in parallel with the old one. Minted notes would always use the new structure, as would output notes from JoinSplits. The input side of the JoinSplit circuit would accept either the old or new structure; it can potentially do so without any performance cost (i.e. still with only two SHA256Compress evaluations per input), if the new format is arranged carefully.
For the protocol integration, I suggest adding a vector of Mint operations to a transaction, in the same way as we currently have a vector of JoinSplits. All of the Mints would take effect (adding to the note commitment tree) before any of the JoinSplits. This is sufficient because the Mints do not require any of the notes output by the JoinSplits. We can continue to have a vpubold input to a JoinSplit; it is low-cost to support, and simplifies maintaining backward compatibility.
To fix the Faerie Gold attack for Mints, we can specify that ρ is derived from r and hSig via a collision-resistant PRF; this allows the recipient of a coin to check that ρ is not repeated without needing to keep track of all seen ρ values. The reason we didn't do it that way originally is that only the note recipient can do this check; generation of notes with repeated ρ is not prevented by public verification, as it is for notes that are JoinSplit outputs. However, I believe this doesn't actually cause any security problem.
[Aside: before we decided to unify the operations, we had renamed "Mint" to "Protect". However given our current terminology, I'd suggest calling this operation "Shield".]
The text was updated successfully, but these errors were encountered: