ZIP 243: Transaction Signature Verification for Sapling

This commit is contained in:
str4d 2018-04-11 14:36:12 -06:00
parent f5784f516e
commit 301ad7cea9
No known key found for this signature in database
GPG Key ID: 665DBCD284F7DAFF
1 changed files with 291 additions and 0 deletions

291
zip-0243.rst Normal file
View File

@ -0,0 +1,291 @@
::
ZIP: 243
Title: Transaction Signature Verification for Sapling
Author: Jack Grigg <jack@z.cash>
Daira Hopwood <daira@z.cash>
Category: Consensus
Created: 2018-04-10
License: MIT
Terminology
===========
The key words "MUST" and "MUST NOT" in this document are to be interpreted as described in RFC 2119.
The terms "branch" and "network upgrade" in this document are to be interpreted as described in ZIP 200. [#zip-0200]_
The term "Overwinter" in this document is to be interpreted as described in ZIP 201. [#zip-0201]_
The term "Sapling" in this document is to be interpreted as described in ZIP XXX. [#zip-0XXX]_
Abstract
========
This proposal defines a new transaction digest algorithm for signature verification from the Sapling network
upgrade, to account for the presence of Sapling shielded inputs and outputs in transactions.
Motivation
==========
The Sapling network upgrade introduced new shielded inputs and outputs. We want these to be covered by the
transaction digest algorithm used for signatures, in order to ensure they are correctly bound.
Specification
=============
A new transaction digest algorithm is defined::
BLAKE2b-256 hash of the serialization of:
1. header of the transaction (4-byte little endian)
2. nVersionGroupId of the transaction (4-byte little endian)
3. hashPrevouts (32-byte hash)
4. hashSequence (32-byte hash)
5. hashOutputs (32-byte hash)
6. hashJoinSplits (32-byte hash)
7. hashShieldedSpends (32-byte hash)
8. hashShieldedOutputs (32-byte hash)
9. nLockTime of the transaction (4-byte little endian)
10. nExpiryHeight of the transaction (4-byte little endian)
11. valueBalance of the transaction (8-byte little endian)
12. sighash type of the signature (4-byte little endian)
13. If we are serializing an input (i.e. this is not a JoinSplit signature hash):
a. outpoint (32-byte hash + 4-byte little endian)
b. scriptCode of the input (serialized as scripts inside CTxOuts)
c. value of the output spent by this input (8-byte little endian)
d. nSequence of the input (4-byte little endian)
The new algorithm is based on the transaction digest algorithm defined in ZIP 143 [#zip-0143]_.
The new algorithm MUST be used for signatures created over the Sapling transaction format [#zip-0XXX]_.
Combined with the new consensus rule that v3 transaction formats will be invalid from the Sapling upgrade
[#zip-0XXX]_, this effectively means that all transaction signatures from the Sapling activation height will
use the new algorithm [#zip-0XXX]_.
The BLAKE2b-256 personalization field [#BLAKE2-personalization]_ is set to::
"ZcashSigHash" || CONSENSUS_BRANCH_ID
``CONSENSUS_BRANCH_ID`` is the little-endian encoding of ``BRANCH_ID`` for the epoch of the block containing
the transaction. [#zip-0200]_ Domain separation of the signature hash across parallel branches provides replay
protection: transactions targeted for one branch will have invalid signatures on other branches.
Transaction creators MUST specify the epoch they want their transaction to be mined in. Across a network
upgrade, this means that if a transaction is not mined before the activation height, it will never be mined.
Semantics of the original sighash types are as in ZIP 143 [#zip-0143]_.
Field definitions
-----------------
The items 1, 2, 3, 4, 5, 9, 10, 12, and 13 have the same meaning as in ZIP 143 [#zip-0143]_.
6: ``hashJoinSplits``
`````````````````````
* If ``vjoinsplits`` is non-empty, ``hashJoinSplits`` is the BLAKE2b-256 hash of the serialization of all
JoinSplits (in their canonical v4 transaction serialization format) concatenated with the
``joinSplitPubKey``;
* The BLAKE2b-256 personalization field is set to ``ZcashJSplitsHash``.
* Note that while signatures are ommitted, the JoinSplit proofs are included in the signature hash, as with
v1, v2, and v3 transactions.
* Otherwise, ``hashJoinSplits`` is a ``uint256`` of ``0x0000......0000``.
7: ``hashShieldedSpends``
`````````````````````````
* If ``vShieldedSpend`` is non-empty, ``hashShieldedSpends`` is the BLAKE2b-256 hash of the serialization of
all Spend Descriptions (in their canonical transaction serialization format minus ``spendAuthSig``);
* The BLAKE2b-256 personalization field is set to ``ZcashSSpendsHash``.
* Note that the Spend proofs are included in the signature hash, as with JoinSplit proofs in v1, v2, and v3
transactions.
* Otherwise, ``hashShieldedSpends`` is a ``uint256`` of ``0x0000......0000``.
8: ``hashShieldedOutputs``
``````````````````````````
* If ``vShieldedOutput`` is non-empty, ``hashShieldedOutputs`` is the BLAKE2b-256 hash of the serialization of
all Output Descriptions (in their canonical transaction serialization format);
* The BLAKE2b-256 personalization field is set to ``ZcashSOutputHash``.
* Note that the Output proofs are included in the signature hash, as with JoinSplit proofs in v1, v2, and v3
transactions.
* Otherwise, ``hashShieldedOutputs`` is a ``uint256`` of ``0x0000......0000``.
11: ``valueBalance``
````````````````````
An 8-byte signed two's-complement little-endian value of the net amount, in zatoshi, exiting the Sapling value
pool. For clarity, a negative value corresponds to an amount *entering* the Sapling value pool.
Notes
-----
The ``hashPrevouts``, ``hashSequence``, ``hashOutputs``, ``hashJoinSplits``, ``hashShieldedSpends``, and
``hashShieldedOutputs`` calculated in an earlier verification can be reused in other inputs of the same
transaction, so that the time complexity of the whole hashing process reduces from O(n\ :sup:`2`) to O(n).
Refer to the reference implementation, reproduced below, for the precise algorithm:
.. code:: cpp
const unsigned char ZCASH_PREVOUTS_HASH_PERSONALIZATION[16] =
{'Z','c','a','s','h','P','r','e','v','o','u','t','H','a','s','h'};
const unsigned char ZCASH_SEQUENCE_HASH_PERSONALIZATION[16] =
{'Z','c','a','s','h','S','e','q','u','e','n','c','H','a','s','h'};
const unsigned char ZCASH_OUTPUTS_HASH_PERSONALIZATION[16] =
{'Z','c','a','s','h','O','u','t','p','u','t','s','H','a','s','h'};
const unsigned char ZCASH_JOINSPLITS_HASH_PERSONALIZATION[16] =
{'Z','c','a','s','h','J','S','p','l','i','t','s','H','a','s','h'};
const unsigned char ZCASH_SHIELDED_SPENDS_HASH_PERSONALIZATION[16] =
{'Z','c','a','s','h','S','S','p','e','n','d','s','H','a','s','h'};
const unsigned char ZCASH_SHIELDED_OUTPUTS_HASH_PERSONALIZATION[16] =
{'Z','c','a','s','h','S','O','u','t','p','u','t','H','a','s','h'};
// The default values are zeroes
uint256 hashPrevouts;
uint256 hashSequence;
uint256 hashOutputs;
uint256 hashJoinSplits;
uint256 hashShieldedSpends;
uint256 hashShieldedOutputs;
if (!(nHashType & SIGHASH_ANYONECANPAY)) {
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_PREVOUTS_HASH_PERSONALIZATION);
for (unsigned int n = 0; n < txTo.vin.size(); n++) {
ss << txTo.vin[n].prevout;
}
hashPrevouts = ss.GetHash();
}
if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_SEQUENCE_HASH_PERSONALIZATION);
for (unsigned int n = 0; n < txTo.vin.size(); n++) {
ss << txTo.vin[n].nSequence;
}
hashSequence = ss.GetHash();
}
if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_OUTPUTS_HASH_PERSONALIZATION);
for (unsigned int n = 0; n < txTo.vout.size(); n++) {
ss << txTo.vout[n];
}
hashOutputs = ss.GetHash();
} else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) {
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_OUTPUTS_HASH_PERSONALIZATION);
ss << txTo.vout[nIn];
hashOutputs = ss.GetHash();
}
if (!txTo.vjoinsplit.empty()) {
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_JOINSPLITS_HASH_PERSONALIZATION);
for (unsigned int n = 0; n < txTo.vjoinsplit.size(); n++) {
ss << txTo.vjoinsplit[n];
}
ss << txTo.joinSplitPubKey;
hashJoinSplits = ss.GetHash();
}
if (!txTo.vShieldedSpends.empty()) {
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_SHIELDED_SPENDS_HASH_PERSONALIZATION);
for (unsigned int n = 0; n < txTo.vShieldedSpends.size(); n++) {
ss << txTo.vShieldedSpends[n];
}
hashShieldedSpends = ss.GetHash();
}
if (!txTo.vShieldedOutputs.empty()) {
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_SHIELDED_OUTPUTS_HASH_PERSONALIZATION);
for (unsigned int n = 0; n < txTo.vShieldedOutputs.size(); n++) {
ss << txTo.vShieldedOutputs[n];
}
hashShieldedOutputs = ss.GetHash();
}
uint32_t leConsensusBranchId = htole32(consensusBranchId);
unsigned char personalization[16] = {};
memcpy(personalization, "ZcashSigHash", 12);
memcpy(personalization+12, &leConsensusBranchId, 4);
CBLAKE2bWriter ss(SER_GETHASH, 0, personalization);
// fOverwintered and nVersion
ss << txTo.GetHeader();
// Version group ID
ss << txTo.nVersionGroupId;
// Input prevouts/nSequence (none/all, depending on flags)
ss << hashPrevouts;
ss << hashSequence;
// Outputs (none/one/all, depending on flags)
ss << hashOutputs;
// JoinSplits
ss << hashJoinSplits;
// Spend Descriptions
ss << hashShieldedSpends;
// Output Descriptions
ss << hashShieldedOutputs;
// Locktime
ss << txTo.nLockTime;
// Expiry height
ss << txTo.nExpiryHeight;
// Sapling value balance
ss << txTo.valueBalance;
// Sighash type
ss << nHashType;
if (nIn != NOT_AN_INPUT) {
// The input being signed (replacing the scriptSig with scriptCode + amount)
// The prevout may already be contained in hashPrevout, and the nSequence
// may already be contained in hashSequence.
ss << txTo.vin[nIn].prevout;
ss << static_cast<const CScriptBase&>(scriptCode);
ss << amount;
ss << txTo.vin[nIn].nSequence;
}
return ss.GetHash();
Example
=======
TBC
Deployment
==========
This proposal is deployed with the Sapling network upgrade. [#zip-0XXX]_
Backward compatibility
======================
This proposal is backwards-compatible with old UTXOs. It is **not** backwards-compatible with older software.
All transactions will be required to use this transaction digest algorithm for signatures, and so transactions
created by older software will be rejected by the network.
Reference Implementation
========================
https://github.com/zcash/zcash/pull/XXXX
References
==========
.. [#BLAKE2-personalization] `"BLAKE2: simpler, smaller, fast as MD5", Section 2.8 <https://blake2.net/blake2.pdf>`_
.. [#zip-0200] `ZIP 200: Network Upgrade Mechanism <https://github.com/zcash/zips/blob/master/zip-0200.rst>`_
.. [#zip-0201] `ZIP 201: Network Peer Management for Overwinter <https://github.com/zcash/zips/blob/master/zip-0201.rst>`_