Skip to content

Receiver<Monitor> integration tests for different script patterns and sender behaviors#1211

Merged
spacebear21 merged 3 commits intopayjoin:masterfrom
mehmetefeumit:receiver-monitor-tests
Dec 9, 2025
Merged

Receiver<Monitor> integration tests for different script patterns and sender behaviors#1211
spacebear21 merged 3 commits intopayjoin:masterfrom
mehmetefeumit:receiver-monitor-tests

Conversation

@mehmetefeumit
Copy link
Contributor

@mehmetefeumit mehmetefeumit commented Dec 2, 2025

Pull Request Checklist

Please confirm the following before requesting review:

Closes #1137.

Overview

This PR adds:

  1. Documentation for Receiver<Monitor> and the check_payment function.
  2. Integration tests for the following cases:
    • v2 P2WPKH and Taproot addresses. It checks if the correct confirmation function is used for each case, and that the final receiver persister state is what is expected.
    • v2 sender fallback test. It checks whether the receiver can detect when the sender broadcasts the fallback transaction and that the final receiver persister state is what is expected.

Note that this PR does not implement tests for other wallet types or double-spend attack due to #1214. When the non-segwit monitoring is finalized, there should be more integration test scenarios to cover them.

@coveralls
Copy link
Collaborator

coveralls commented Dec 2, 2025

Pull Request Test Coverage Report for Build 19999836616

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.03%) to 83.489%

Totals Coverage Status
Change from base Build 19938128275: 0.03%
Covered Lines: 9001
Relevant Lines: 10781

💛 - Coveralls

@arminsabouri arminsabouri self-requested a review December 2, 2025 19:00
Copy link
Collaborator

@arminsabouri arminsabouri left a comment

Choose a reason for hiding this comment

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

I appreciate you keeping these commits clean! Did a first pass, approach looks good. Hand a handful of pointers for reducing the code changes in this PR and a few nits.

|_| {
panic!("We should never check outpoints since the payjoin tx has been broadcasted")
|outpoint| {
match address_type {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we need a match on address type?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is an additional validation for the order of operations in the check_payment function. Since it should return Success if the TXID is found, this closure should never be run. This validates that that is the case.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I understand now, thanks. We could use a comment to explain this. Same thing for getting the tx via txid. e.g "non-segwit inputs will have a different txid after sender signs"

|_| {
panic!("We should never check outpoints since the payjoin tx has been broadcasted")
|outpoint| {
match address_type {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I understand now, thanks. We could use a comment to explain this. Same thing for getting the tx via txid. e.g "non-segwit inputs will have a different txid after sender signs"

// broadcasting the fallback transaction (both of which the receiver is aware of)
// instead they broadcast another transaction which spends the senders outputs in a
// transaction the receiver has not seen before.
let double_spend_tx = extract_pj_tx(&sender, double_spend_psbt)?;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unrelated to this PR but extract_pj_tx should probably be renamed to sign_and_finalize_psbt

// transaction the receiver has not seen before, but using the outpoint which the
// sender included in the original proposal.
let mut double_spend_tx = psbt.clone().unsigned_tx;
double_spend_tx.output[0].value -= Amount::from_sat(1);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I am not sure this is actually emulating a double spend. This is the fallback tx with the output value slightly adjusted -- kinda emulating a RBF on a fallback tx. I was expecting a tx spending the same inputs to entirely different outputs. However, I still think there is some merit behind this test. If the sender does RBF the fallback, the receiver can still pick it up. In that case we may want to rename this test to something like: "RBF'd fallback" or "Output adjusted fallback".

Copy link
Contributor Author

@mehmetefeumit mehmetefeumit Dec 5, 2025

Choose a reason for hiding this comment

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

In the current Monitor implementation, if the sender does RBF on a non-segwit fallback transaction, the receiver will pick it up as a double-spend (which I thought what double-spend in the context of a Payjoin session was while writing the PR 😅)

With that in mind, I do not think the source code is ready for this test at the moment. Or we can put a big TODO next to it to and keep it active so that it tests the eventual fix or re-design under #1214.

Copy link
Collaborator

@arminsabouri arminsabouri left a comment

Choose a reason for hiding this comment

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

cACK c14b2c1
Great work reducing the boilerplate and code de-duplication.

panic!("psbt should exist");
};

let broadcasted_transaction = match sender_final_action {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit:

Suggested change
let broadcasted_transaction = match sender_final_action {
let tx_to_broadcast = match sender_final_action {

Copy link
Collaborator

@spacebear21 spacebear21 left a comment

Choose a reason for hiding this comment

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

ACK c14b2c1, nice work on the SenderFinalAction refactor!

@spacebear21 spacebear21 merged commit 84b9e7c into payjoin:master Dec 9, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Integration tests on the various receiver monitoring outcomes

4 participants