mirror of https://github.com/zcash/zips.git
ZIP 243: Transaction Signature Verification for Sapling
This commit is contained in:
parent
f5784f516e
commit
301ad7cea9
|
@ -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>`_
|
Loading…
Reference in New Issue