Skip to content

fix(wallet): add support for bip-431 rule 2 - #478

Merged
ValuedMammal merged 2 commits into
bitcoindevkit:masterfrom
oleonardolima:test/unconfirmed-truc-txs
Jul 23, 2026
Merged

fix(wallet): add support for bip-431 rule 2#478
ValuedMammal merged 2 commits into
bitcoindevkit:masterfrom
oleonardolima:test/unconfirmed-truc-txs

Conversation

@oleonardolima

@oleonardolima oleonardolima commented May 4, 2026

Copy link
Copy Markdown
Collaborator

partially addresses #477
supersedes #442

Description

Adds support for BIP-431 (TRUC) rule 2 in filter_utxos. When building a transaction, unconfirmed UTXOs are filtered based on version compatibility with the transaction being constructed:

  • If building a TRUC (v3) transaction, only unconfirmed outputs from TRUC transactions are eligible as optional UTXOs.
  • If building a non-TRUC transaction, only unconfirmed outputs from non-TRUC transactions are eligible as optional UTXOs.
  • Confirmed outputs may be spent by either TRUC or non-TRUC transactions regardless of the source transaction's version.

The filter is implemented inline in filter_utxos, which now takes a version parameter passed down from the transaction builder. The version compatibility check uses an equality comparison on the == Version(3) predicate, ensuring the unconfirmed output's transaction version matches the version class (TRUC or non-TRUC) of the transaction being built.

Note that manually selected UTXOs bypass this filter — callers are responsible for ensuring any manually selected unconfirmed UTXO is compatible with the transaction version being built.

Changelog notice

### Fixed

- fix(wallet): filter unconfirmed UTXOs by BIP-431 (TRUC) rule-2

Checklists

All Submissions:

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature

Bugfixes:

  • This pull request breaks the existing API
  • I've added tests to reproduce the issue which are now passing
  • I'm linking the issue being fixed by this PR

@oleonardolima oleonardolima added this to the Wallet 3.1.0 milestone May 4, 2026
@oleonardolima
oleonardolima requested a review from ValuedMammal May 4, 2026 20:30
@oleonardolima oleonardolima self-assigned this May 4, 2026
@oleonardolima oleonardolima added the bug Something isn't working label May 4, 2026
@oleonardolima

Copy link
Copy Markdown
Collaborator Author

cc @yan-pi as he already reviewed the other PR and has a reproducible test using bdk-cli too.

@oleonardolima

Copy link
Copy Markdown
Collaborator Author

I noticed in CI I need to fix some bdk_testenv/electrs/esplora related issues. However, the fix in bc05f88 is ready for review/discussion.

@codecov

codecov Bot commented May 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.22%. Comparing base (75e0d30) to head (7982b6e).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #478      +/-   ##
==========================================
+ Coverage   81.15%   81.22%   +0.06%     
==========================================
  Files          24       24              
  Lines        5552     5565      +13     
  Branches      247      248       +1     
==========================================
+ Hits         4506     4520      +14     
+ Misses        970      969       -1     
  Partials       76       76              
Flag Coverage Δ
rust 81.22% <100.00%> (+0.06%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@yan-pi yan-pi left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

tACK 1d32117.

IMO The is_truc helper is more functional and reads cleaner than the XNOR in #442, and definitely is a good foundation for the rest of #477.

Tested it locally by checking out test/unconfirmed-truc-txs and rebuilding the rust-repro binaries from https://github.com/yan-pi/bdk-pr442-repro against the PR via [dependencies] bdk_wallet = { path = "../../bdk_wallet" }:

The inverse direction of Rule 2: the non-v3 unconfirmed UTXO was filtered correclty.

One concern not flagged inline: the integration test is great, but maybe the unit-level coverage from #442 is also worth keeping?

Plus two minor nits and typos.

Comment thread src/wallet/mod.rs Outdated
Comment thread src/wallet/mod.rs Outdated
Comment thread src/wallet/mod.rs Outdated
@luisschwab
luisschwab self-requested a review June 1, 2026 23:39
@oleonardolima
oleonardolima force-pushed the test/unconfirmed-truc-txs branch 3 times, most recently from b8d9ae1 to 85143c2 Compare June 5, 2026 00:44

@lorenzolfm lorenzolfm left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ACK 85143c2

@ValuedMammal
ValuedMammal marked this pull request as draft June 10, 2026 15:31
@oleonardolima
oleonardolima force-pushed the test/unconfirmed-truc-txs branch 2 times, most recently from 47bba04 to d6fca63 Compare June 15, 2026 19:08
@oleonardolima
oleonardolima force-pushed the test/unconfirmed-truc-txs branch from d6fca63 to 6145afc Compare June 15, 2026 19:23
@oleonardolima oleonardolima moved this from In Progress to Needs Review in BDK Wallet Jun 15, 2026
@oleonardolima
oleonardolima marked this pull request as ready for review June 15, 2026 19:25

@lorenzolfm lorenzolfm left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ACK 6145afc

@oleonardolima
oleonardolima removed the request for review from yan-pi June 17, 2026 01:42
Comment thread src/wallet/mod.rs Outdated
Comment thread src/wallet/mod.rs Outdated

@ValuedMammal ValuedMammal 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.

#442 added docs explaining the manual selection caveat #442 (comment), but that seems to be missing from this branch.

oleonardolima and others added 2 commits July 14, 2026 15:10
- add new step in `filter_utxos` to validate BIP-431 rule 2, which
  validates the proper usage of unconfirmed TRUC/non-TRUC ancestor in a
  TRUC/non-TRUC tx.
- update docs explaining the manual selection caveat when building
  non-TRUC/TRUC txs.
- introduce `test_create_and_spend_from_tx` to exercise BIP-431 rule-2
  filtering in-memory, not relying on `bdk_testenv`/`bdk_electrum`.

NOTE: I asked Claude to remove the `bdk_testenv` dependency, keeping
the test behavior in-memory.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@oleonardolima
oleonardolima force-pushed the test/unconfirmed-truc-txs branch from 6145afc to 7982b6e Compare July 14, 2026 18:10
@oleonardolima

Copy link
Copy Markdown
Collaborator Author

#442 added docs explaining the manual selection caveat #442 (comment), but that seems to be missing from this branch.

@ValuedMammal Thanks! I updated the code following some of the suggestions, let me know if there's anything else to address.

@ValuedMammal ValuedMammal 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 7982b6e; ran the tests locally

@nymius nymius 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.

ACK 7982b6e

This solution is inline with the current approach for UTXO filtering, so I agree with it, however, the number of constraints we impose on the local utxo seems to be always growing.
I usually come back to the idea that this filtering should be done in a detachable pipeline, with customizable filters rather than manually adding new ones each time we need.
In that case I would prefer to create a wrapper around txouts injecting all the information we need to filter them later, or providing an oracle that can be called with custom made closure to apply these filters.
Has anyone have any ideas about this?

Comment thread tests/wallet.rs
Comment on lines +3438 to +3443
assert!(
tx_c.input
.iter()
.all(|txin| txin.previous_output.txid.ne(&txid_b)),
"SHOULD NOT try to spend an unconfirmed non-TRUC output in a TRUC tx!"
);

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.

Why not checking we are funding the TRUC tx with another TRUC tx?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, that would also work.

@ValuedMammal
ValuedMammal merged commit b71129e into bitcoindevkit:master Jul 23, 2026
18 checks passed
@github-project-automation github-project-automation Bot moved this from Needs Review to Done in BDK Wallet Jul 23, 2026
@oleonardolima

Copy link
Copy Markdown
Collaborator Author

ACK 7982b6e

This solution is inline with the current approach for UTXO filtering, so I agree with it, however, the number of constraints we impose on the local utxo seems to be always growing. I usually come back to the idea that this filtering should be done in a detachable pipeline, with customizable filters rather than manually adding new ones each time we need. In that case I would prefer to create a wrapper around txouts injecting all the information we need to filter them later, or providing an oracle that can be called with custom made closure to apply these filters. Has anyone have any ideas about this?

In the new create_psbt and PsbtParams flow, you could have a custom filter instead of this always-growing one, doesn't that solve this issue ? Let me know if I'm missing your point here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants