Add antiprobing check to reject payjoin inputs already offered in a prior session - #863
Add antiprobing check to reject payjoin inputs already offered in a prior session#863Sandipmandal25 wants to merge 1 commit into
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughPayjoin sender construction now persistently tracks offered transaction outpoints, rejects reused inputs before proceeding, records accepted inputs before session persistence, and tests behavior across persister instances. ChangesPayjoin anti-probing
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant build_sender
participant PayjoinSessionPersister
participant redb
build_sender->>PayjoinSessionPersister: check_no_inputs_seen_before(signed_psbt inputs)
PayjoinSessionPersister->>redb: read inputs_offered
build_sender->>PayjoinSessionPersister: record_offered_inputs(inputs)
PayjoinSessionPersister->>redb: persist outpoints and timestamps
build_sender->>PayjoinSessionPersister: save sender session
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryAdds persistent PayJoin input tracking and rejects previously offered outpoints before constructing a new sender session.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains. Important Files Changed
Reviews (3): Last reviewed commit: "Add anti-probing check to reject payjoin..." | Re-trigger Greptile |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
rust/src/manager/wallet_manager/payjoin.rs (1)
173-180: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse the repository’s error-context helpers.
Replace these
map_err(|e| eyre::eyre!(...))closures withcove_util::ResultExt::map_err_stror.map_err_prefixso redb error context is added consistently.As per coding guidelines: “Use
cove_util::ResultExt::map_err_strand.map_err_prefixinstead of equivalentmap_errclosures that construct error variants from strings.”Also applies to: 184-186, 207-213, 218-223
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@rust/src/manager/wallet_manager/payjoin.rs` around lines 173 - 180, Replace the string-building map_err closures in the payjoin database operations, including begin_read and the ranges around open_table and lines 207-213 and 218-223, with cove_util::ResultExt::map_err_str or map_err_prefix. Preserve the existing error context and special TableDoesNotExist handling while using the repository’s ResultExt helpers consistently.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@rust/src/manager/wallet_manager/payjoin.rs`:
- Around line 418-422: Move persister.record_offered_inputs(&input_outpoints)
out of the pre-construction path in the payjoin flow. Ensure
build_recommended(...) completes successfully before recording inputs, then
perform the check-and-record immediately before the session’s .save(persister)
call so construction failures leave inputs reusable while save failures still
burn them.
- Around line 371-374: Make the anti-probing check and offered-input insertion
atomic in the flow around build_sender and check_no_inputs_seen_before: perform
lookup and insertion for INPUTS_OFFERED_TABLE within a single redb write
transaction, ensuring concurrent calls cannot both pass before recording. Update
the affected persistence API as needed and add a regression test that runs
concurrent build_sender calls with the same input outpoint and verifies only one
succeeds.
---
Nitpick comments:
In `@rust/src/manager/wallet_manager/payjoin.rs`:
- Around line 173-180: Replace the string-building map_err closures in the
payjoin database operations, including begin_read and the ranges around
open_table and lines 207-213 and 218-223, with cove_util::ResultExt::map_err_str
or map_err_prefix. Preserve the existing error context and special
TableDoesNotExist handling while using the repository’s ResultExt helpers
consistently.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 0c47ad86-7a4e-4376-aecf-5f56b913096e
📒 Files selected for processing (1)
rust/src/manager/wallet_manager/payjoin.rs
6d65f90 to
5677334
Compare
5677334 to
18373b3
Compare
|
@Sandipmandal25 will the database get filled up? is there a clean up mechanism? is there any legit reason for the UTXOs to be offered more than once? should there be a user override? |
| persister: &PayjoinSessionPersister, | ||
| ) -> Result<V2Sender<WithReplyKey>> { | ||
| // TODO: anti-probing (inputs_seen), verify our inputs have not appeared in a prior session | ||
| // TODO: surface payjoin downgrade to the user when the fallback tx is broadcast instead of the proposal |
There was a problem hiding this comment.
this todo is about surfacing payjoin downgrade to the user when the fallback tx broadcasts instead of the proposal. its a cross layer change not related to anti probing i will do this in follow up was waiting for this pr to merge.
table grows some bytes per input per payjoin attempt, storage is not a concern. no cleanup by design once a receiver has seen ourinputs they can probe again on retry so removing entries reopens the attack. legit reuse is a valid concern though if a payjoin times out the user would want to retry with the same UTXOs. i can add a user override or scope the block to sessions that actually reached the directory. which do you prefer? |
89d8169 to
18373b3
Compare
Summary
redbtable.Why
Without this check, a malicious receiver could probe which UTXOs belong to the sender by initiating multiple PayJoin sessions and observing which inputs reappear.
Offered inputs are never removed, even after fallback or cancellation, because the receiver has already seen them.
Checklist
resolves #779
Summary by CodeRabbit
Security
Bug Fixes