Skip to content

Commit

Permalink
ZIP 244: Fix ill-defined commitments for shielded coinbase
Browse files Browse the repository at this point in the history
In zcash#577 we altered ZIP 244 to have shielded signatures commit
to the same data as transparent inputs, in transactions that contain
transparent components. However, the edge case of shielded coinbase was
not correctly handled; they contain both a consensus-required "dummy"
transparent input, and binding signatures which would be required to
commit to a `CTxOut` that does not exist.

We resolve this by partially reverting one of the zcash#577 changes,
by having S.2 for coinbase transactions be identical to T.2. This reverts
binding signatures in coinbase transactions to effectively signing the
transaction ID.

At the same time, we also revert the same change for transactions with no
transparent inputs but some transparent outputs; these also now revert to
using the transaction ID for all shielded signatures (like fully-shielded
transactions). The hardware wallet edge case does not apply here, as all
input values are shielded and therefore directly committed to.
  • Loading branch information
str4d committed Jan 24, 2022
1 parent 43c8cae commit 4075c18
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 17 deletions.
8 changes: 4 additions & 4 deletions zip-0244.html
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,8 @@
<p>Identical to that specified for the transaction identifier.</p>
</section>
<section id="s-2-transparent-sig-digest"><h6><span class="section-heading">S.2: transparent_sig_digest</span><span class="section-anchor"> <a rel="bookmark" href="#s-2-transparent-sig-digest"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h6>
<p>In the case that transparent inputs or outputs are present, the value of <code>transparent_sig_digest</code> depends upon the value of a <code>hash_type</code> flag.</p>
<p>If we are producing a hash for either a coinbase transaction, or a non-coinbase transaction that has no transparent inputs, the value of <code>transparent_sig_digest</code> is identical to the value specified in section <a href="#t-2-transparent-digest">T.2</a>.</p>
<p>If we are producing a hash for a non-coinbase transaction that has transparent inputs, the value of <code>transparent_sig_digest</code> depends upon the value of a <code>hash_type</code> flag, as follows.</p>
<p>The construction of each component below depends upon the values of the <code>hash_type</code> flag bits. Each component will be described separately.</p>
<p>This digest is a BLAKE2b-256 hash of the following values</p>
<pre>S.2a: hash_type (1 byte)
Expand All @@ -266,8 +267,6 @@
S.2g: txin_sig_digest (32-byte hash)</pre>
<p>The personalization field of this hash is set to:</p>
<pre>"ZTxIdTranspaHash"</pre>
<p>In the case that the transaction has no transparent inputs or outputs, <code>transparent_sig_digest</code> is</p>
<pre>BLAKE2b-256("ZTxIdTranspaHash", [])</pre>
<section id="s-2a-hash-type"><h7><span class="section-heading">S.2a: hash_type</span><span class="section-anchor"> <a rel="bookmark" href="#s-2a-hash-type"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h7>
<p>This is an 8-bit unsigned value. The <code>SIGHASH</code> encodings from the legacy script system are reused: one of <code>SIGHASH_ALL</code> (0x01), <code>SIGHASH_NONE</code> (0x02), and <code>SIGHASH_SINGLE</code> (0x03), with or without the <code>SIGHASH_ANYONECANPAY</code> flag (0x80). The following restrictions apply, which cause validation failure if violated:</p>
<ul>
Expand Down Expand Up @@ -428,7 +427,8 @@
</ul>
</li>
</ul>
<p>Signatures over Sapling Spends or Orchard Actions commit to the same data as for transparent inputs, in order to ensure that they commit to all transparent input values. Without this commitment, there is a similar difficulty in the case where a hardware wallet is only signing shielded inputs, in a transaction that also contains transparent inputs from a malicious other party (where that party lies about their coins' values).</p>
<p>Signatures over Sapling Spends or Orchard Actions, in transactions containing transparent inputs, commit to the same data that the transparent inputs do, including all of the transparent input values. Without this commitment, there would be a similar difficulty for a hardware wallet in the case where it is only signing shielded inputs, when the transaction also contains transparent inputs from a malicious other party, because that party could lie about their coins' values.</p>
<p>By contrast, binding signatures for shielded coinbase transactions continue to be over the transaction ID, as for non-coinbase transactions without transparent inputs. This is necessary because coinbase transactions have a single "dummy" transparent input element that has no corresponding previous output to commit to. It is also sufficient because the data in that transparent input either is already bound elsewhere (namely the block height, placed in <code>expiry_height</code> from NU5 activation), or does not need to be bound to the shielded outputs (e.g. miner-identifying information).</p>
</section>
<section id="reference-implementation"><h2><span class="section-heading">Reference implementation</span><span class="section-anchor"> <a rel="bookmark" href="#reference-implementation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<ul>
Expand Down
36 changes: 23 additions & 13 deletions zip-0244.rst
Original file line number Diff line number Diff line change
Expand Up @@ -490,8 +490,13 @@ Identical to that specified for the transaction identifier.

S.2: transparent_sig_digest
```````````````````````````
In the case that transparent inputs or outputs are present, the value of
``transparent_sig_digest`` depends upon the value of a ``hash_type`` flag.
If we are producing a hash for either a coinbase transaction, or a non-coinbase
transaction that has no transparent inputs, the value of ``transparent_sig_digest``
is identical to the value specified in section `T.2 <#t-2-transparent-digest>`_.

If we are producing a hash for a non-coinbase transaction that has transparent
inputs, the value of ``transparent_sig_digest`` depends upon the value of a
``hash_type`` flag, as follows.

The construction of each component below depends upon the values of the
``hash_type`` flag bits. Each component will be described separately.
Expand All @@ -510,11 +515,6 @@ The personalization field of this hash is set to::

"ZTxIdTranspaHash"

In the case that the transaction has no transparent inputs or outputs,
``transparent_sig_digest`` is ::

BLAKE2b-256("ZTxIdTranspaHash", [])

S.2a: hash_type
'''''''''''''''
This is an 8-bit unsigned value. The ``SIGHASH`` encodings from the legacy
Expand Down Expand Up @@ -854,12 +854,22 @@ align with BIP 341 [#bip-0341]_:
same effect under consensus (spends the same inputs and produces the same
outputs).

Signatures over Sapling Spends or Orchard Actions commit to the same data as for
transparent inputs, in order to ensure that they commit to all transparent input
values. Without this commitment, there is a similar difficulty in the case where
a hardware wallet is only signing shielded inputs, in a transaction that also
contains transparent inputs from a malicious other party (where that party lies
about their coins' values).
Signatures over Sapling Spends or Orchard Actions, in transactions containing
transparent inputs, commit to the same data that the transparent inputs do,
including all of the transparent input values. Without this commitment, there
would be a similar difficulty for a hardware wallet in the case where it is
only signing shielded inputs, when the transaction also contains transparent
inputs from a malicious other party, because that party could lie about their
coins' values.

By contrast, binding signatures for shielded coinbase transactions continue to
be over the transaction ID, as for non-coinbase transactions without transparent
inputs. This is necessary because coinbase transactions have a single "dummy"
transparent input element that has no corresponding previous output to commit
to. It is also sufficient because the data in that transparent input either is
already bound elsewhere (namely the block height, placed in ``expiry_height``
from NU5 activation), or does not need to be bound to the shielded outputs
(e.g. miner-identifying information).

========================
Reference implementation
Expand Down

0 comments on commit 4075c18

Please sign in to comment.