BIP352: PSBT support

I don’t think a silent payment signer cares if anyone else has used ACP. Rather, I think each silent payments aware signer needs to verify the proofs, generate the PSBT_OUT_SCRIPT for each silent payments output from the provided shares and check that it matches what the other signers have committed to. Consider the following scenarios for two silent payment aware signers, A and B:

  • NONE | ACP

    • A adds input, proof, share to the transaction and signs with NONE | ACP
    • B adds input, proof, share, generates the PSBT_OUT_SCRIPT and signs with ALL
  • SINGLE | ACP

    • Signers exchange shares and A generates the correct script from A and B shares, signs with SINGLE | ACP where SINGLE commits to the output of the generated script
    • B verifies the output is correct and signs with ALL
    • Alternatively, B determines A did not generate the correct script and refuses to sign
    • A signs with SINGLE | ACP where SINGLE commits to a non-silent payments output (e.g. a change output for A)
    • B adds their inputs, generates the scripts and signs with ALL
  • ALL | ACP

    • Signers exchange shares, A generates the scripts and signs with ALL | ACP
    • B verifies the generated scripts are correct and signs with ALL
    • Alternatively, B determines the generated scripts are not correct and refuses to sign

In all of these scenarios, B can determine whether or not A has committed to the correct output scripts and sign the transaction with ALL. Alternatively, B could add inputs to the transaction which burn the money, which means A is trusting B to finish the transaction honestly. Hence, I think it’s sufficient to say a silent payments signer must:

  1. Never use ACP without fully trusting the other signers
  2. Independently generate the PSBT_OUT_SCRIPT and verify the match what the other signers have committed to before signing

I don’t have a strong opinion here. If we have n inputs covered by the same proof, this would be n\cdot 36 + (33 + 64) bytes vs n\cdot (33 + 64) bytes. So better in some cases, worse in others?

Here A has signed their input, which can then be broadcast by itself or with another input attached by an outside observer to meet the correct amount, and the output will go to an invalid destination. Regardless of whether B signs with ALL or not, the outside observer can strip B and add their own input or not. Therefore it is insecure for A to sign at all with ACP. Am I missing something?

Even with trusting the other signers, an outside observer can strip out your ACP inputs and add their own to them right?

Nope, we completely agree on this point! What I was trying to illustrate was B does not need to care whether or not A signed with ACP: in all cases, a 3rd party observer would need to strip B's inputs from the transaction before adding their own. More specifically, if A insecurely signs with ACP, B can still safely sign the transaction with ALL. Either the transaction will go through, or B's inputs will be removed from the transaction. A should never sign with ACP because doing so puts A's funds at risk of being stolen or burned.

1 Like

I think I see the confusion. What I meant was the silent payment aware signers must check for any ACP on any inputs they will sign for and fail if there are any silent payment outputs. If all signers are following the BIP spec, then there should not be any inputs signed with ACP anyways. Actually, the signer should probably fail if there is any sighash flag other than ALL if there are any silent payment outputs.

One other possibility that could simplify things. If a signer is able to sign for all inputs, they could add a global share and proof covering all inputs with the key data being the scan key. If a signer is unable to sign for all inputs, then they add a per input share and proof covering only that input as described by @achow101 above. This keeps the key data clean and optimizes for the common scenario of a single signer wallet using a hardware signing device.

Gotcha! I had read this as “fail if ACP was used on outputs that are not your own.”

I think “If a sighash type is provided, the signer must check that the sighash is acceptable. If unacceptable, they must fail” is sufficient, perhaps with a footnote that explains what unacceptable is for a silent payments transaction?

In the case of multiple signers where each signer has multiple inputs, this would require the signer to compute the ECDH shares individually (vs summing up the private keys and then doing the ECDH step. If we imagine something like a coinjoin, this could recreate the problem of “I have 10 inputs, so now I need to do ~30 ECC mults.” Another alternative would be:

  • Global proof is the signer owns all inputs
  • Proof per group of inputs (proof is duplicated on each input)

In the case where each signer owns their own input, this would be the same as @achow101 's proposal. This does add more data to the PSBT in the form of duplicate proofs in the case of multiple signers signing for multiple inputs, but that seems better to me than requiring the signers to do more CPU intensive work. That being said, I’m not sure which is better. If a signer has low compute power, doing 30 ECC mults can be annoying. On the flipside, if the signer has low memory and we want to require a signer to verify proofs on each input before signing, the inline proofs for each input seems better.

One thing about duplicating a group proof on each input is that it doesn’t protect against a constructor removing an input. It protects against reordering, but if a constructor decides to swap an input with a more desirable one, then the proof is invalidated and won’t be detectable. It will just fail when verifying. This would require setting Inputs Modifiable to false if any shares and proofs were added before signing, which I don’t think we want.

1 Like

Got some feedback on the PSBT draft I wrote that we should move the DLEQ stuff out into its own BIP.

I wrote up a draft based on @RubenSomsen’s gist here DLEQ.mediawiki · GitHub.

Not sure if anyone has started working on this yet. Any thoughts appreciated.

1 Like

Have you considered also implementing the Anti-exfil protocol in secp256k1 library given that we are gonna require DLEQ proofs anyways in v3 of PSBT? It would make sense given that some of the top hardware wallets don’t come with any particular software wallet and will only implement things inherent in core, in the secp library and in a well tested and accepted psbt spec. The new darkskippy.com attack only re-iterates the need for things like this and I can’t help but think this new spec is an excellent opportunity to kill two birds with one stone?