Skip to content

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

Merged
spacebear21 merged 3 commits into
payjoin: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 into
payjoin:masterfrom
mehmetefeumit:receiver-monitor-tests

Conversation

@mehmetefeumit

@mehmetefeumit mehmetefeumit commented Dec 2, 2025

Copy link
Copy Markdown
Contributor
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

coveralls commented Dec 2, 2025

Copy link
Copy Markdown
Collaborator

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

@arminsabouri arminsabouri left a comment

Copy link
Copy Markdown
Contributor

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.

Comment thread payjoin/src/core/receive/v2/mod.rs Outdated
Comment thread payjoin/src/core/receive/v2/mod.rs Outdated
Comment thread payjoin/tests/integration.rs Outdated
Comment thread payjoin/tests/integration.rs Outdated
Comment thread payjoin/tests/integration.rs Outdated
|_| {
panic!("We should never check outpoints since the payjoin tx has been broadcasted")
|outpoint| {
match address_type {

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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
Copy Markdown
Contributor

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"

Comment thread payjoin/tests/integration.rs Outdated
Comment thread payjoin/tests/integration.rs Outdated
Comment thread payjoin/tests/integration.rs Outdated
Comment thread payjoin/tests/integration.rs Outdated
Comment thread payjoin/tests/integration.rs Outdated
Comment thread payjoin/tests/integration.rs Outdated
Comment thread payjoin/tests/integration.rs Outdated
Comment thread payjoin/tests/integration.rs
Comment thread payjoin/tests/integration.rs Outdated
|_| {
panic!("We should never check outpoints since the payjoin tx has been broadcasted")
|outpoint| {
match address_type {

Copy link
Copy Markdown
Contributor

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"

Comment thread payjoin/tests/integration.rs Outdated
// 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
Copy Markdown
Contributor

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

Comment thread payjoin/tests/integration.rs Outdated
// 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
Copy Markdown
Contributor

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".

@mehmetefeumit mehmetefeumit Dec 5, 2025

Copy link
Copy Markdown
Contributor Author

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.

@arminsabouri arminsabouri left a comment

Copy link
Copy Markdown
Contributor

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
Copy Markdown
Contributor

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 {

@spacebear21 spacebear21 left a comment

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.

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