Skip to content

Commit

Permalink
BIP78: Allow mixed inputs
Browse files Browse the repository at this point in the history
Disallowing mixed inputs was based on incorrect assumption that no
wallet supports mixed inputs and thus mixed inputs imply PayJoin.
However there are at least three wallets supporting mixed inputs.
(Confirmed: Bitcoin Core, LND, Coinomi) Thus it makes sense to enable
mixed inputs to avoid a payjoin-specific fingerptint. To avoid
compatibility issues a grace period is suggested.

Co-authored-by: Martin Habovstiak <[email protected]>
  • Loading branch information
DanGould and Kixunil committed May 31, 2024
1 parent 24a15a6 commit d5fc59b
Showing 1 changed file with 8 additions and 8 deletions.
16 changes: 8 additions & 8 deletions bip-0078.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ The original PSBT MUST:
The original PSBT MAY:
* Have outputs unrelated to the payment for batching purpose.
The original PSBT SHOULD NOT:
* Include mixed input types until September 2024. Mixed inputs were previously completely disallowed so this gives some grace period for recivers to update.
The payjoin proposal MUST:
* Use all the inputs from the original PSBT.
* Use all the outputs which do not belongs to the receiver from the original PSBT.
Expand All @@ -115,6 +118,9 @@ The payjoin proposal MUST:
The payjoin proposal MAY:
* Add, remove or modify the outputs belonging to the receiver.
The payjoin proposal SHOULD NOT:
* Include mixed input types until May 2024. Mixed inputs were previously completely disallowed so this gives some grace period for senders to update.
The payjoin proposal MUST NOT:
* Shuffle the order of inputs or outputs, the additional outputs or additional inputs must be inserted at a random index.
* Decrease the absolute fee of the original transaction.
Expand Down Expand Up @@ -242,7 +248,6 @@ The receiver needs to do some check on the original PSBT before proceeding:

* Non-interactive receivers (like a payment processor) need to check that the original PSBT is broadcastable. <code>*</code>
* If the sender included inputs in the original PSBT owned by the receiver, the receiver must either return error <code>original-psbt-rejected</code> or make sure they do not sign those inputs in the payjoin proposal.
* If the sender's inputs are all from the same scriptPubKey type, the receiver must match the same type. If the receiver can't match the type, they must return error <code>unavailable</code>.
* Make sure that the inputs included in the original transaction have never been seen before.
** This prevent [[#probing-attack|probing attacks]].
** This prevent reentrant payjoin, where a sender attempts to use payjoin transaction as a new original transaction for a new payjoin.
Expand All @@ -268,7 +273,6 @@ The sender should check the payjoin proposal before signing it to prevent a mali
*** Verify the PSBT input is finalized
*** Verify that <code>non_witness_utxo</code> or <code>witness_utxo</code> are filled in.
** Verify that the payjoin proposal did not introduced mixed input's sequence.
** Verify that the payjoin proposal did not introduced mixed input's type.
** Verify that all of sender's inputs from the original PSBT are in the proposal.
* For each outputs in the proposal:
** Verify that no keypaths is in the PSBT output
Expand Down Expand Up @@ -429,7 +433,6 @@ public async Task<PSBT> RequestPayjoin(
var endpoint = bip21.ExtractPayjointEndpoint();
if (signedPSBT.IsAllFinalized())
throw new InvalidOperationException("The original PSBT should not be finalized.");
ScriptPubKeyType inputScriptType = wallet.ScriptPubKeyType();
PSBTOutput feePSBTOutput = null;

bool allowOutputSubstitution = !optionalParameters.DisableOutputSubstitution;
Expand Down Expand Up @@ -520,9 +523,6 @@ public async Task<PSBT> RequestPayjoin(
if (proposedPSBTInput.NonWitnessUtxo == null && proposedPSBTInput.WitnessUtxo == null)
throw new PayjoinSenderException("The receiver did not specify non_witness_utxo or witness_utxo for one of their inputs");
sequences.Add(proposedTxIn.Sequence);
// Verify that the payjoin proposal did not introduced mixed inputs' type.
if (inputScriptType != proposedPSBTInput.GetInputScriptPubKeyType())
throw new PayjoinSenderException("Mixed input type detected in the proposal");
}
}
Expand Down Expand Up @@ -565,8 +565,8 @@ public async Task<PSBT> RequestPayjoin(
throw new PayjoinSenderException("The actual contribution is not only paying fee");
// Make sure the actual contribution is only paying for fee incurred by additional inputs
int additionalInputsCount = proposalGlobalTx.Inputs.Count - originalGlobalTx.Inputs.Count;
if (actualContribution > originalFeeRate * GetVirtualSize(inputScriptType) * additionalInputsCount)
throw new PayjoinSenderException("The actual contribution is not only paying for additional inputs");
if (additionalInputsCount <= 0)
throw new PayjoinSenderException("Our additional contribution is not paying for additional inputs");
}
else if (allowOutputSubstitution && output.OriginalTxOut.ScriptPubKey == paymentScriptPubKey)
{
Expand Down

0 comments on commit d5fc59b

Please sign in to comment.