1

BIP370 specifies a bit flag (bit 2) in PSBT_GLOBAL_TX_MODIFIABLE field, that "indicates whether the transaction has a SIGHASH_SINGLE signature who's input and output pairing must be preserved" and "If the Has SIGHASH_SINGLE flag is True, then the Constructor must iterate through the inputs and find the inputs which have signatures that use SIGHASH_SINGLE. The same number of inputs and outputs must be added before those inputs and their corresponding outputs"

BIP370 does not specify how to handle this flag in other situations, when the inconsistency of the flag with other fields can indicate some problem and it may be best to somehow react to this problem rather than ignore it.

For example, the code that parses PSBTv2 may find that 'Has SIGHASH_SINGLE flag' is false in PSBT_GLOBAL_TX_MODIFIABLE, but later, when processing the input fields, finds out that one of psbt inputs has SIGHASH_SINGLE.

How the code should react to this ? This is obvious inconsistency, if this situation is ignored, and the 'Has SIGHASH_SINGLE flag' is considered false despite the presence of SIGHASH_SIGNGLE in the inputs, the signatures can be invalidated when moving inputs or outputs.

Likewise, if the flag is true, but there are no inputs having SIGHASH_SINGLE sighash types, should this be taken as an indication of inconsistent PSBT ?

Can we say "this flag is always equal to any(input.has_sighash_single() for input in psbt.inputs)" (1) ?

PSBT_IN_SIGHASH_TYPE is not required to be present, and if it is absent, signer "may use any sighash type they wish". But let's imagine that BIP text would state that PSBT_IN_SIGHASH_TYPE must always be present if SIGHASH_SINGLE is to be used. Will (1) be true in this case ? Would we even need this flag then ?

Should say that 'Has SIGHASH_SINGLE' flag is to be ignored if there are finalized inputs because any adding of inputs must have been done before finalization ?

How would it be possible to check the finalized inputs for the use of SIGHASH_SINGLE signatures in case of finalized inputs when custom scripts are used with unknown format for the witness data ?

BIP174 says that on finalization, finalized scriptSig and scriptWitness should remain, and "All other data except the UTXO and unknown fields in the input key-value map should be cleared from the PSBT"*. If PSBT_IN_SIGHASH_TYPE is cleared, there's no way to know in general if the witness has signatures with SIGHASH_SINGLE, unless the code can somehow understand the format of the witness.

* By the way, this wording should include not only unknown fields, but proprietary fields, too should be preserved. Should I make PR to add this ?

2
  • By the way, the 'Constructor' section in BIP370 talks about looking for 'inputs that have signatures', and at the same time talks about checking timelocks and SIGHASH_SINGLE on the inputs. This seems to be a reference to BIP371 that defines special fields for signatures. But this is a forward reference that cannot be understood without reading BIP371 first, and such checks cannot be done on finalized inputs (because all those fields would be already removed on finalization) Dec 16, 2021 at 18:19
  • I forgot that there's PSBT_IN_PARTIAL_SIG that has signatures that Constructor can look at. Dec 17, 2021 at 20:02

1 Answer 1

2

Figuring out how to handle SIGHASH_SINGLE inputs in PSBTv2 was one of the major problems when designing it. Unfortunately, when this was brought up on the mailing list, there was little to no response, and so the result was that I had to try to come up with a solution myself, which may be slightly deficient.

For example, the code that parses PSBTv2 may find that 'Has SIGHASH_SINGLE flag' is false in PSBT_GLOBAL_TX_MODIFIABLE, but later, when processing the input fields, finds out that one of psbt inputs has SIGHASH_SINGLE.

The expectation is that such an inconsistency would not occur because it is in the Sginer's best interest to make sure that the Has SIGHASH_SINGLE flag is set when they add a SIGHASH_SINGLE signature. There is no need for anyone to be checking that no other signatures are SIGHASH_SINGLE, and so the expected action is that the inconsistency is ignored. This could result in an invalid transaction, but that is an allowed outcome.

Likewise, if the flag is true, but there are no inputs having SIGHASH_SINGLE sighash types, should this be taken as an indication of inconsistent PSBT ?

Yes, but setting when there are no SIGHASH_SINGLE signatures does not necessarily cause harm other than making adding additional inputs slower.

Can we say "this flag is always equal to any(input.has_sighash_single() for input in psbt.inputs)" (1) ?

That is the intention.

PSBT_IN_SIGHASH_TYPE is not required to be present, and if it is absent, signer "may use any sighash type they wish". But let's imagine that BIP text would state that PSBT_IN_SIGHASH_TYPE must always be present if SIGHASH_SINGLE is to be used. Will (1) be true in this case ? Would we even need this flag then ?

There is no real need for the flag other than as an optimization. It exists in order to allow Constructors to skip having to inspect every input, but if the flag did not exist, it could simply have been that Constructors must check every input for SIGHASH_SINGLE signatures. So if PSBT_IN_SIGHASH_TYPE were provided for every input, Has SIGHASH_SINGLE would still be a used.

Should say that 'Has SIGHASH_SINGLE' flag is to be ignored if there are finalized inputs because any adding of inputs must have been done before finalization ?

No, it is possible that an input is finalized while additional inputs are being added. The use of SIGHASH_SINGLE & SIGHASH_ANYONECANPAY allows for this.

How would it be possible to check the finalized inputs for the use of SIGHASH_SINGLE signatures in case of finalized inputs when custom scripts are used with unknown format for the witness data ?

A script interpreter would be needed. The process would be to execute the finalized scriptSigs and scriptWitnesses with a signature verifier that can report whether it had to verify any SIGHASH_SINGLE inputs. Part of the reason that Has SIGHASH_SINGLE was added was because I thought it was unreasonable that Constructors had to have a script interpreter just to make sure that they weren't breaking any SIGHASH_SINGLE things.

* By the way, this wording should include not only unknown fields, but proprietary fields, too should be preserved. Should I make PR to add this ?

Proprietary fields are generally lumped together with unknown fields because they are unknown to implementations that do not implement those specific proprietary fields. But yes, the text could be clarified.

2
  • So if the Constructor that adds inputs does not have a script interpreter, and 'Has SIGHASH_SINGLE' is true, it should treat any finalized input that it cannot analyze, as having a SIGHASH_SINGLE signature. Dec 17, 2021 at 19:32
  • @DmitryPetukhov Yes, that would be a reasonable thing to do (assuming it is not SIGHASH_ALL, but if it were, then the tx should not be modifiable).
    – Andrew Chow
    Dec 17, 2021 at 20:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.