• # 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.