zcash / zips

Zcash Improvement Proposals
https://zips.z.cash
MIT License
274 stars 156 forks source link

ZIP-143/244: Clarify how prevouts from coinbase transactions are hashed in the sighash computation #535

Open conradoplg opened 3 years ago

conradoplg commented 3 years ago

In ZIP-143 and ZIP-244 it's not clear how the prevouts of coinbase transactions should be handled. This may have contributed to a bug in Zebra.

The expected behaviour is implicit, since Bitcoin uses a "fake" outpoint for coinbase transactions and this outpoint is what must be hashed.

It would be helpful to mention this explicitly in those ZIPs.

str4d commented 3 days ago

AFAICT the prevouts for coinbase transactions are explicitly specified.

Protocol Spec 3.11 Coinbase Transactions:

A transaction that has a single transparent input with a null prevout field, is called a coinbase transaction.

S.2: transparent_sig_digest:

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:

In the case that transparent inputs or outputs are present, the transparent digest consists of a BLAKE2b-256 hash of the following values

T.2a: prevouts_digest (32-byte hash)
T.2b: sequence_digest (32-byte hash)
T.2c: outputs_digest  (32-byte hash)

T.2a: prevouts_digest:

A BLAKE2b-256 hash of the field encoding of all outpoint field values of transparent inputs to the transaction.

ZIP 244 Terminology:

The term "field encoding" refers to the binary serialized form of a Zcash transaction field, as specified in section 7.1 of the Zcash protocol specification.

7.1 Transaction Encoding and Consensus:

Transparent inputs, encoded as in Bitcoin.

The Bitcoin coinbase format you referenced above:

Bytes Name Data Type Description
32 hash (null) char[32] A 32-byte null, as a coinbase has no previous outpoint.
4 index (UINT32_MAX) uint32_t 0xffffffff, as a coinbase has no previous outpoint.

Thus, the required field encoding of the output field values for the transparent input of a coinbase transaction, is the field encoding of a null prevout. And indeed that is what we use.

I will note that "3.11 Coinbase Transactions" was added to the protocol spec in March 2022, after the Zebra bug occurred and this issue was filed. However, ZIP 244 is clear that the encoding is the one used in the transaction, and AFAIK Zebra did not have a bug in how it parsed and serialized coinbase transactions (and thus must have been correctly handling null prevouts).

I also note an issue with that March 2022 change: the protocol spec uses "null prevout" and "non-null prevout", but does not specify "prevout" AFAICT.