zips/drafts/str4d-overwinter-sighash/draft1.rst

330 lines
14 KiB
ReStructuredText
Raw Normal View History

2018-01-08 05:14:15 -08:00
::
ZIP: 143
Title: Transaction Signature Verification for Overwinter
Author: Jack Grigg <jack@z.cash>
Daira Hopwood <daira@z.cash>
Credits: Johnson Lau <jl2012@xbt.hk>
Pieter Wuille <pieter.wuille@gmail.com>
2018-02-09 07:48:27 -08:00
Bitcoin-ABC
2018-02-26 14:47:20 -08:00
Category: Consensus
2018-01-08 05:14:15 -08:00
Created: 2017-12-27
License: MIT
Terminology
===========
The key words "MUST" and "MUST NOT" in this document are to be interpreted as described in RFC 2119.
Abstract
========
This proposal defines a new transaction digest algorithm for signature verification from the Overwinter
network upgrade, in order to minimize redundant data hashing in verification, and to cover the input value by
the signature.
Motivation
==========
There are 4 ECDSA signature verification codes in the original Zcash script system: ``CHECKSIG``,
``CHECKSIGVERIFY``, ``CHECKMULTISIG``, ``CHECKMULTISIGVERIFY`` ("sigops"). According to the sighash type
(``ALL``, ``NONE``, or ``SINGLE``, possibly modified by ``ANYONECANPAY``), a transaction digest is generated
with a double SHA256 of a serialized subset of the transaction, and the signature is verified against this
digest with a given public key. The detailed procedure is described in a Bitcoin Wiki article. [#wiki-checksig]_
The transaction digest is additionally used for the JoinSplit signature (solely with sighash type ``ALL``).
[#zcash-protocol]_
2018-01-08 05:14:15 -08:00
Unfortunately, there are at least 2 weaknesses in the original SignatureHash transaction digest algorithm:
* For the verification of each signature, the amount of data hashing is proportional to the size of the
transaction. Therefore, data hashing grows in O(n\ :sup:`2`) as the number of sigops in a transaction
increases. While a 1 MB block would normally take 2 seconds to verify with an average computer in 2015, a
1MB transaction with 5569 sigops may take 25 seconds to verify. This could be fixed by optimizing the digest
algorithm by introducing some reusable “midstate”, so the time complexity becomes O(n). [#quadratic]_
* The algorithm does not involve the value being spent by the input. This is usually not a problem for online
network nodes as they could request for the specified transaction to acquire the output value. For an
offline transaction signing device ("cold wallet"), however, the lack of knowledge of input amount makes it
impossible to calculate the exact amount being spent and the transaction fee. To cope with this problem a
cold wallet must also acquire the full transaction being spent, which could be a big obstacle in the
implementation of a lightweight, air-gapped wallet. By including the input value of part of the transaction
digest, a cold wallet may safely sign a transaction by learning the value from an untrusted source. In the
case that a wrong value is provided and signed, the signature would be invalid and no funds would be lost.
[#offline-wallets]_
Deploying the aforementioned fixes in the original script system is not a simple task.
Specification
=============
A new transaction digest algorithm is defined::
2018-02-09 08:16:48 -08:00
2018-02-09 07:57:06 -08:00
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)
2018-02-09 06:19:57 -08:00
7. nLockTime of the transaction (4-byte little endian)
8. nExpiryHeight of the transaction (4-byte little endian)
9. sighash type of the signature (4-byte little endian)
10. If we are serializing an input (ie. this is not a JoinSplit signature hash):
2018-01-08 05:14:15 -08:00
a. outpoint (32-byte hash + 4-byte little endian)
b. scriptCode of the input (serialized as scripts inside CTxOuts) [TODO]
c. value of the output spent by this input (8-byte little endian)
d. nSequence of the input (4-byte little endian)
2018-02-09 07:48:27 -08:00
The new algorithm is based on the Bitcoin transaction digest algorithm defined in BIP 143, [#BIP0143]_ with
replay protection inspired by BUIP-HF v1.2. [#BUIP-HF]_
The new algorithm MUST be used for signatures created over the Overwinter transaction format.
[#ZIP-overwinter-tx-format]_ Combined with the new consensus rule that v1 and v2 transaction formats will be
invalid from the Overwinter upgrade, [#ZIP-overwinter-tx-format]_ this effectively means that all transactions
signatures from the Overwinter activation height will use the new algorithm. [#ZIP0000]_
2018-01-08 05:14:15 -08:00
The BLAKE2b-256 personalization field [#BLAKE2-personalization]_ is set to::
2018-01-08 05:14:15 -08:00
"ZcashSigHash" || CONSENSUS_BRANCH_ID
2018-02-09 08:20:40 -08:00
``CONSENSUS_BRANCH_ID`` is the little-endian encoding of ``BRANCH_ID`` for the epoch of the block containing
the transaction. [#ZIP-activation-mechanism]_ 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.
2018-01-11 03:30:50 -08:00
Semantics of the original sighash types remain unchanged, except the following:
2018-01-08 05:14:15 -08:00
2018-01-11 03:30:50 -08:00
#. The serialization format is changed;
2018-01-08 05:14:15 -08:00
#. All sighash types commit to the amount being spent by the signed input;
#. ``SINGLE`` does not commit to the input index. When ``ANYONECANPAY`` is not set, the semantics are
unchanged since ``hashPrevouts`` and ``outpoint`` together implictly commit to the input index. When
``SINGLE`` is used with ``ANYONECANPAY``, omission of the index commitment allows permutation of the
input-output pairs, as long as each pair is located at an equivalent index.
Field definitions
-----------------
2018-02-09 08:35:54 -08:00
The items 7, 9, 10a, 10d have the same meaning as the original algorithm from Bitcoin. [#wiki-checksig]_
1: ``header``
`````````````
Deserialized into two transaction properties: ``fOverwintered`` and ``nVersion``. For transactions that use
this transaction digest algorithm, ``fOverwintered`` is always set. [#ZIP-overwinter-tx-format]_
2: ``nVersionGroupId``
``````````````````````
Provides domain separation of ``nVersion``. It is only defined if ``fOverwintered`` is set, which means that
it is always defined for transactions that use this algorithm. [#ZIP-overwinter-tx-format]_
2018-01-08 05:14:15 -08:00
3: ``hashPrevouts``
2018-01-08 05:14:15 -08:00
```````````````````
2018-02-09 07:57:06 -08:00
* If the ``ANYONECANPAY`` flag is not set, ``hashPrevouts`` is the BLAKE2b-256 hash of the serialization of
all input outpoints;
2018-01-08 05:14:15 -08:00
2018-02-16 14:02:57 -08:00
* The BLAKE2b-256 personalization field is set to ``ZcashPrevoutHash``.
2018-01-08 05:14:15 -08:00
* Otherwise, ``hashPrevouts`` is a ``uint256`` of ``0x0000......0000``.
4: ``hashSequence``
2018-01-08 05:14:15 -08:00
```````````````````
2018-02-09 07:57:06 -08:00
* If none of the ``ANYONECANPAY``, ``SINGLE``, ``NONE`` sighash type is set, ``hashSequence`` is the
BLAKE2b-256 hash of the serialization of ``nSequence`` of all inputs;
2018-01-08 05:14:15 -08:00
2018-02-16 14:02:57 -08:00
* The BLAKE2b-256 personalization field is set to ``ZcashSequencHash``.
2018-01-08 05:14:15 -08:00
* Otherwise, ``hashSequence`` is a ``uint256`` of ``0x0000......0000``.
5: ``hashOutputs``
2018-01-08 05:14:15 -08:00
``````````````````
2018-02-09 07:57:06 -08:00
* If the sighash type is neither ``SINGLE`` nor ``NONE``, ``hashOutputs`` is the BLAKE2b-256 hash of the
2018-01-08 05:14:15 -08:00
serialization of all output amount (8-byte little endian) with ``scriptPubKey`` (serialized as scripts
inside CTxOuts);
* If sighash type is ``SINGLE`` and the input index is smaller than the number of outputs, ``hashOutputs`` is
2018-02-09 07:57:06 -08:00
the BLAKE2b-256 hash of the output (serialized as above) with the same index as the input;
2018-01-08 05:14:15 -08:00
2018-02-16 14:02:57 -08:00
* The BLAKE2b-256 personalization field is set to ``ZcashOutputsHash`` in both cases above.
2018-01-08 05:14:15 -08:00
* Otherwise, ``hashOutputs`` is a ``uint256`` of ``0x0000......0000``. [#01-change]_
6: ``hashJoinSplits``
2018-01-08 05:14:15 -08:00
`````````````````````
2018-02-09 07:57:06 -08:00
* If ``vjoinsplits`` is non-empty, ``hashJoinSplits`` is the BLAKE2b-256 hash of the serialization of all
2018-01-11 03:30:50 -08:00
JoinSplits (in their canonical transaction serialization format) concatenated with the joinSplitPubKey;
2018-01-08 05:14:15 -08:00
2018-02-16 14:02:57 -08:00
* 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 and v2 transactions.
2018-01-08 05:14:15 -08:00
* Otherwise, ``hashJoinSplits`` is a ``uint256`` of ``0x0000......0000``.
8: ``nExpiryHeight``
````````````````````
The block height after which the transaction becomes unilaterally invalid, and can never be mined.
[#ZIP-tx-expiry]_
10b: ``scriptCode``
2018-02-09 08:35:54 -08:00
```````````````````
The script being currently executed: ``redeemScript`` for P2SH, or ``scriptPubKey`` in the general case. This
is the same script as serialized in the Sprout transaction digest algorithm.
2018-01-08 05:14:15 -08:00
10c: value
2018-01-08 05:14:15 -08:00
`````````
An 8-byte value of the amount of ZEC spent in this input.
Notes
-----
The ``hashPrevouts``, ``hashSequence``, ``hashOutputs``, and ``hashJoinSplits`` calculated in an earlier
verification may 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
2018-02-16 14:02:57 -08:00
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'};
2018-02-09 07:57:06 -08:00
2018-01-08 05:14:15 -08:00
uint256 hashPrevouts;
uint256 hashSequence;
uint256 hashOutputs;
uint256 hashJoinSplits;
if (!(nHashType & SIGHASH_ANYONECANPAY)) {
2018-02-16 14:02:57 -08:00
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_PREVOUTS_HASH_PERSONALIZATION);
2018-01-08 05:14:15 -08:00
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) {
2018-02-16 14:02:57 -08:00
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_SEQUENCE_HASH_PERSONALIZATION);
2018-01-08 05:14:15 -08:00
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) {
2018-02-16 14:02:57 -08:00
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_OUTPUTS_HASH_PERSONALIZATION);
2018-01-08 05:14:15 -08:00
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()) {
2018-02-16 14:02:57 -08:00
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_OUTPUTS_HASH_PERSONALIZATION);
2018-01-08 05:14:15 -08:00
ss << txTo.vout[nIn];
hashOutputs = ss.GetHash();
}
if (!txTo.vjoinsplit.empty()) {
2018-02-16 14:02:57 -08:00
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_JOINSPLITS_HASH_PERSONALIZATION);
2018-01-08 05:14:15 -08:00
for (unsigned int n = 0; n < txTo.vjoinsplit.size(); n++) {
ss << txTo.vjoinsplit[n];
}
ss << txTo.joinSplitPubKey;
hashJoinSplits = ss.GetHash();
}
uint32_t leConsensusBranchId = htole32(consensusBranchId);
2018-01-08 05:14:15 -08:00
unsigned char personalization[16] = {};
memcpy(personalization, "ZcashSigHash", 12);
memcpy(personalization+12, &leConsensusBranchId, 4);
2018-01-08 05:14:15 -08:00
2018-02-09 07:57:06 -08:00
CBLAKE2bWriter ss(SER_GETHASH, 0, personalization);
// fOverwintered and nVersion
ss << txTo.GetHeader();
// Version group ID
ss << txTo.nVersionGroupId;
2018-01-08 05:14:15 -08:00
// Input prevouts/nSequence (none/all, depending on flags)
ss << hashPrevouts;
ss << hashSequence;
// Outputs (none/one/all, depending on flags)
ss << hashOutputs;
// JoinSplits
ss << hashJoinSplits;
// Locktime
ss << txTo.nLockTime;
// Expiry height
ss << txTo.nExpiryHeight;
2018-01-08 05:14:15 -08:00
// 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
2018-02-09 08:05:07 -08:00
// may already be contained in hashSequence.
2018-01-08 05:14:15 -08:00
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 Overwinter network upgrade.
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
========================
2018-02-09 08:23:23 -08:00
https://github.com/zcash/zcash/pull/2903
2018-01-08 05:14:15 -08:00
References
==========
.. [#wiki-checksig] https://en.bitcoin.it/wiki/OP_CHECKSIG
.. [#zcash-protocol] `Zcash Protocol Specification, Section 4.6 <https://github.com/zcash/zips/blob/master/protocol/protocol.pdf>`_
2018-01-08 05:14:15 -08:00
.. [#quadratic]
* `CVE-2013-2292 <https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-2292>`_
* `New Bitcoin vulnerability: A transaction that takes at least 3 minutes to verify <https://bitcointalk.org/?topic=140078>`_
* `The Megatransaction: Why Does It Take 25 Seconds? <http://rusty.ozlabs.org/?p=522>`_
.. [#offline-wallets] `SIGHASH_WITHINPUTVALUE: Super-lightweight HW wallets and offline data <https://bitcointalk.org/index.php?topic=181734.0>`_
2018-02-09 07:48:27 -08:00
.. [#BIP0143] `Transaction Signature Verification for Version 0 Witness Program <https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki>`_
.. [#BUIP-HF] `BUIP-HF Digest for replay protected signature verification across hard forks, version 1.2 <https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/doc/abc/replay-protected-sighash.md>`_
2018-01-08 05:14:15 -08:00
.. [#ZIP0000] ZIP???: Overwinter Network Upgrade
.. [#ZIP-activation-mechanism] ZIP???: Network Upgrade Activation Mechanism
.. [#ZIP-overwinter-tx-format] ZIP???: Overwinter Transaction Format
.. [#BLAKE2-personalization] `"BLAKE2: simpler, smaller, fast as MD5", Section 2.8 <https://blake2.net/blake2.pdf>`_
2018-01-08 05:14:15 -08:00
.. [#01-change] In the original algorithm, a ``uint256`` of ``0x0000......0001`` is committed if the input
index for a ``SINGLE`` signature is greater than or equal to the number of outputs. In this ZIP a
``0x0000......0000`` is commited, without changing the semantics.
.. [#ZIP-tx-expiry] ZIP???: Transaction expiry