Skip to content
Merged
Show file tree
Hide file tree
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
32 changes: 21 additions & 11 deletions payjoin/src/core/receive/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,23 @@ impl PsbtContext {
sender_input_indexes
}

/// Returns payjoin proposal PSBT to be signed
///
/// Removes all sender signatures which are received with the original PSBT
/// as these signatures are now invalid
fn psbt_to_sign(&self) -> Psbt {
Comment thread
arminsabouri marked this conversation as resolved.
let mut psbt = self.payjoin_psbt.clone();
// Remove now-invalid sender signatures before applying the receiver signatures
for i in self.sender_input_indexes() {
tracing::trace!("Clearing sender input {i}");
psbt.inputs[i].final_script_sig = None;
psbt.inputs[i].final_script_witness = None;
psbt.inputs[i].tap_key_sig = None;
}

psbt
}

/// Finalizes the Payjoin proposal into a PSBT which the sender will find acceptable before
/// they sign the transaction and broadcast it to the network.
///
Expand All @@ -322,23 +339,16 @@ impl PsbtContext {
self,
wallet_process_psbt: impl Fn(&Psbt) -> Result<Psbt, ImplementationError>,
) -> Result<Psbt, ImplementationError> {
let mut psbt = self.payjoin_psbt.clone();
// Remove now-invalid sender signatures before applying the receiver signatures
for i in self.sender_input_indexes() {
tracing::trace!("Clearing sender input {i}");
psbt.inputs[i].final_script_sig = None;
psbt.inputs[i].final_script_witness = None;
psbt.inputs[i].tap_key_sig = None;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Odd that we remove keyspend sigs and not script or any other partial sig. Which should not be present either way (only final_script_sig or final_script_witness)

}
let finalized_psbt = wallet_process_psbt(&psbt)?;
let psbt = self.psbt_to_sign();
let signed_psbt = wallet_process_psbt(&psbt)?;
let expected_ntxid = self.payjoin_psbt.unsigned_tx.compute_ntxid();
let actual_ntxid = finalized_psbt.unsigned_tx.compute_ntxid();
let actual_ntxid = signed_psbt.unsigned_tx.compute_ntxid();
if expected_ntxid != actual_ntxid {
return Err(ImplementationError::from(
format!("Ntxid mismatch: expected {expected_ntxid}, got {actual_ntxid}").as_str(),
));
}
let payjoin_proposal = self.prepare_psbt(finalized_psbt);
let payjoin_proposal = self.prepare_psbt(signed_psbt);
Ok(payjoin_proposal)
}
}
Expand Down
2 changes: 1 addition & 1 deletion payjoin/src/core/receive/v1/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ impl ProvisionalProposal {
/// In some applications the entity that progresses the typestate
/// is different from the entity that has access to the private keys,
/// so the PSBT to sign must be accessible to such implementers.
pub fn psbt_to_sign(&self) -> Psbt { self.psbt_context.payjoin_psbt.clone() }
pub fn psbt_to_sign(&self) -> Psbt { self.psbt_context.psbt_to_sign() }
}

/// A finalized Payjoin proposal, complete with fees and receiver signatures, that the sender
Expand Down
2 changes: 1 addition & 1 deletion payjoin/src/core/receive/v2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,7 @@ impl Receiver<ProvisionalProposal> {
/// In some applications the entity that progresses the typestate
/// is different from the entity that has access to the private keys,
/// so the PSBT to sign must be accessible to such implementers.
pub fn psbt_to_sign(&self) -> Psbt { self.state.psbt_context.payjoin_psbt.clone() }
pub fn psbt_to_sign(&self) -> Psbt { self.state.psbt_context.psbt_to_sign() }

pub(crate) fn apply_payjoin_proposal(self, payjoin_psbt: Psbt) -> ReceiveSession {
let psbt_context = PsbtContext {
Expand Down
Loading