Subject: [bitcoin-dev] Extension to BIP Format for Multiple Required SigHash Flags

From: Jeremy <[email-masked]>
Date: Sun, 10 Jan 2021 11:39:15 -0800

- *# The Issue:*
- Currently the PSBT BIP has a slight "conceptual gap" where it is possible
to both:
-
- 1) Have a PSBT which obtains multiple signatures per-input with any set
of SIGHASH Flags
- 2) Have a PSBT which obtains multiple signatures per-input with a fixed
SigHash type applying to all signatures.
-
- But not possible to:
3) Have a PSBT which obtains multiple signatures per-input with a fixed
sighash type applying to a specific key's signature
4) Gracefully handle a PSBT with multiple uses of the same key, but
different code-separators.

To solve this we should introduce a new key type compatible with the
existing PSBT Spec (no V2 Requirement).

(I'm not convinced that 4 needs to be fully supported, but I believe that
it makes sense to lay the groundwork for it to be supported as the handling
of different requests for sighash flags and multiple uses of the same key
with different codeseps should happen from the same field.)

Excerpted relevant BIP text:
```

* Type: Partial Signature <tt>PSBT_IN_PARTIAL_SIG = 0x02</tt>
** Key: The public key which corresponds to this signature.
*** <tt>{0x02}|{public key}</tt>
** Value: The signature as would be pushed to the stack from a
scriptSig or witness.
*** <tt>{signature}</tt>

* Type: Sighash Type <tt>PSBT_IN_SIGHASH_TYPE = 0x03</tt>
** Key: None. The key must only contain the 1 byte type.
*** <tt>{0x03}</tt>
** Value: The 32-bit unsigned integer specifying the sighash type to
be used for this input. Signatures for this input must use the sighash
type, finalizers must fail to finalize inputs which have signatures
that do not match the specified sighash type. Signers who cannot
produce signatures with the sighash type must not provide a signature.
*** <tt>{sighash type}</tt>

```

*# Motivation*:
As An example where it may be relevant to cleanly support this, consider
the script:

`2 <Key 1 Checks Approved Output Addresses> <Key 2 Checks Input Allowed to
Spend> 2 CHECKMULTI`

Under such a script, we might have 2 HSMs operating each key. Key 2 is used
first which verifies internal business logic only about the permissibility
of spending an output, but does not sign off on any other logic. Key 1 is
used last which checks that transaction sends only to the currently allowed
addresses and is signed by Key 1. In such an example (discussion of this
particular application is off topic, this is a contrived example to
demonstrate the technical issue), it is not possible to express that Key 1
will sign with SIGHASH_ALL | ANYONECANPAY and Key 2 will sign with
SIGHASH_NONE | ANYONECANPAY. It would be impossible to finalize a PSBT with
SigHash type set, because the sighashes conflict. And while it is possible
to not have any Sighash type set and successfully finalize, this fails to
capture the relevant information around which sighash types are supposed to
be used.

(why the example is contrived: one could argue that you should just have
such business logic *always* use SIGHASH_ALL for such business logic
servers, but there are technical reasons (e.g., adding a change input or
output dynamically with SIGHASH_SINGLES) that you might have to do post-hoc)

*# A Solution*
To address this I propose to add a new key type
PSBT_IN_SIGHASH_PER_KEY_TYPE (e.g., 0x0e) which is followed by a public
key, a 8-bit bool (must be 0 or 1) if the next field will be a sighash
flag, optionally a 32-bit unsigned integer representing the sighash type,
and a compact size integer representing the codeseparator position + 1 (so
that 0 may represent no codeseparator) in the scriptpubkey. If a
codeseparator is set, the redeem script (+ witness script if witness) must
be present.

Finalizers should verify that each requested signature is available.

PSBT_IN_SIGHASH_PER_KEY_TYPE is fully compatible with existing PSBT as long
as PSBT_IN_SIGHASH_TYPE is not set (or, trivially, if it is set and all
PSBT_IN_SIGHASH_PER_KEY_TYPE's match it).

Finalizers could deduce which codeseparator was used if multiple
PSBT_IN_PARTIAL_SIGS are delivered by process of elimination, thus a new
PSBT_IN_PARTIAL_SIG type to specify codeseparator is not required. However,
in the case of multiple signatures, PSBT_IN_PARTIAL_SIG would lead to a
duplicated key-pair specification error so we should also introduce the
type PSBT_IN_PARTIAL_SIG_EXTRA which has a key of a public key followed by
a compact size integer code separator (n.b. no +1 value to exclude the
default!), and a signature as a value. Finalizers shall check that the
PSBT_IN_PARTIAL_SIG_EXTRA values match the corresponding
PSBT_IN_SIGHASH_PER_KEY_TYPE requests. Compatibility: PSBT_IN_PARTIAL_SIG
does not overlap with PSBT_IN_PARTIAL_SIG_EXTRA as '_EXTRA must specify a
codeseparator. Thus, as long as no repeated key/codeseparators are used,
the new PSBT remains fully backwards compatible.

--
@JeremyRubin <https://twitter.com/JeremyRubin>