Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions bip-0078.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,12 @@ public async Task<PSBT> RequestPayjoin(
if (optionalParameters.AdditionalFeeOutputIndex != null && optionalParameters.MaxAdditionalFeeContribution != null)
feePSBTOutput = signedPSBT.Outputs[optionalParameters.AdditionalFeeOutputIndex];
Script paymentScriptPubKey = bip21.Address == null ? null : bip21.Address.ScriptPubKey;

FeeRate originalFeeRate;
if (!signedPSBT.TryGetEstimatedFeeRate(out originalFeeRate))
throw new PayjoinSenderException("signedPSBT should have utxo information");
decimal originalFee = signedPSBT.GetFee();

PSBT originalPSBT = CreateOriginalPSBT(signedPSBT);
Transaction originalGlobalTx = signedPSBT.GetGlobalTransaction();
TxOut feeOutput = feePSBTOutput == null ? null : originalGlobalTx.Outputs[feePSBTOutput.Index];
Expand Down Expand Up @@ -466,29 +471,27 @@ public async Task<PSBT> RequestPayjoin(
throw new PayjoinSenderException("The receiver added keypaths to an input");
if (proposedPSBTInput.PartialSigs.Count != 0)
throw new PayjoinSenderException("The receiver added partial signatures to an input");
PSBTInput proposedTxIn = proposalGlobalTx.Inputs.FindIndexedInput(proposedPSBTInput.PrevOut).TxIn;
TxIn proposedTxIn = proposalGlobalTx.Inputs.FindIndexedInput(proposedPSBTInput.PrevOut).TxIn;
bool isOurInput = originalInputs.Count > 0 && originalInputs.Peek().OriginalTxIn.PrevOut == proposedPSBTInput.PrevOut;
// If it is one of our input
if (isOurInput)
{
OutPoint inputPrevout = ourPrevouts.Dequeue();
TxIn originalTxin = originalGlobalTx.Inputs.FromOutpoint(inputPrevout);
PSBTInput originalPSBTInput = originalPSBT.Inputs.FromOutpoint(inputPrevout);
var input = originalInputs.Dequeue();
// Verify that sequence is unchanged.
if (input.OriginalTxIn.Sequence != proposedTxIn.Sequence)
throw new PayjoinSenderException("The proposedTxIn modified the sequence of one of our inputs")
throw new PayjoinSenderException("The proposedTxIn modified the sequence of one of our inputs");
// Verify the PSBT input is not finalized
if (proposedPSBTInput.IsFinalized())
throw new PayjoinSenderException("The receiver finalized one of our inputs");

sequences.Add(proposedTxIn.Sequence);

// Fill up the info from the original PSBT input so we can sign and get fees.
proposedPSBTInput.NonWitnessUtxo = input.SignedPSBTInput.NonWitnessUtxo;
proposedPSBTInput.WitnessUtxo = input.SignedPSBTInput.WitnessUtxo;
// We fill up information we had on the signed PSBT, so we can sign it.
foreach (var hdKey in input.SignedPSBTInput.HDKeyPaths)
proposedPSBTInput.HDKeyPaths.Add(hdKey.Key, hdKey.Value);
proposedPSBTInput.RedeemScript = signedPSBTInput.RedeemScript;
proposedPSBTInput.HDKeyPaths.Add(hdKey.Key, hdKey.Value);
proposedPSBTInput.RedeemScript = input.SignedPSBTInput.RedeemScript;
}
else
Expand All @@ -511,7 +514,9 @@ public async Task<PSBT> RequestPayjoin(
if (sequences.Count != 1)
throw new PayjoinSenderException("Mixed sequence detected in the proposal");

decimal newFee = proposal.GetFee();
decimal newFee;
if (!proposal.TryGetFee(out newFee))
throw new PayjoinSenderException("The payjoin receiver did not included UTXO information to calculate fee correctly");
decimal additionalFee = newFee - originalFee;
if (additionalFee < 0)
throw new PayjoinSenderException("The receiver decreased absolute fee");
Expand Down Expand Up @@ -543,10 +548,10 @@ public async Task<PSBT> RequestPayjoin(
// Make sure the actual contribution is only paying for fee incurred by additional inputs
// This assumes an additional input can be up to 110 bytes.
int additionalInputsCount = proposalGlobalTx.Inputs.Count - originalGlobalTx.Inputs.Count;
if (actualContribution > originalFeeRate * 110 * additionalInputsCount)
if (actualContribution > originalFeeRate.GetFee(110) * additionalInputsCount)
throw new PayjoinSenderException("The actual contribution is not only paying for additional inputs");
}
else if (allowOutputSubstitution && output.OriginalTxOut.ScriptPubKey == paymentScriptPubKey)
else if (allowOutputSubstitution && originalOutput.OriginalTxOut.ScriptPubKey == paymentScriptPubKey)
{
// That's the payment output, the receiver may have changed it.
}
Expand All @@ -556,9 +561,9 @@ public async Task<PSBT> RequestPayjoin(
throw new PayjoinSenderException("The receiver decreased the value of one of the outputs");
}
// We fill up information we had on the signed PSBT, so we can sign it.
foreach (var hdKey in output.SignedPSBTOutput.HDKeyPaths)
foreach (var hdKey in originalOutput.SignedPSBTOutput.HDKeyPaths)
proposedPSBTOutput.HDKeyPaths.Add(hdKey.Key, hdKey.Value);
proposedPSBTOutput.RedeemScript = output.SignedPSBTOutput.RedeemScript;
proposedPSBTOutput.RedeemScript = originalOutput.SignedPSBTOutput.RedeemScript;
}
}
// Verify that all of sender's outputs from the original PSBT are in the proposal.
Expand Down