Skip to content

chain 0.23.x: Fix ChainPosition ordering#2146

Merged
evanlinjin merged 2 commits intobitcoindevkit:release/chain-0.23.xfrom
evanlinjin:fix/chain-0.23.x-better-chain-position-ord
Mar 12, 2026
Merged

chain 0.23.x: Fix ChainPosition ordering#2146
evanlinjin merged 2 commits intobitcoindevkit:release/chain-0.23.xfrom
evanlinjin:fix/chain-0.23.x-better-chain-position-ord

Conversation

@evanlinjin
Copy link
Member

@evanlinjin evanlinjin commented Mar 11, 2026

Description

Back-ported from #2074
Depends on #2148

This PR fixes incorrect ordering of ChainPosition that affected how wallet transactions are displayed. Previously, unconfirmed transactions that were never seen in the mempool would incorrectly appear before transactions with mempool timestamps due to the derived Ord implementation treating None as less than Some(_).

Problem

The derived Ord implementation for ChainPosition::Unconfirmed caused incorrect transaction ordering:

  • Unconfirmed { first_seen: None, last_seen: None } (never in mempool)
  • Would appear before Unconfirmed { first_seen: Some(10), last_seen: Some(10) } (seen in mempool)

This resulted in a confusing wallet display where transactions never broadcast would appear before pending mempool transactions.

Solution

Implemented manual Ord and PartialOrd traits for ChainPosition with the correct ordering:

  1. Confirmed transactions (earliest first by block height)
  2. Unconfirmed transactions seen in mempool (ordered by first_seen)
  3. Unconfirmed transactions never seen (these come last)

Additional ordering rules:

  • At the same confirmation height, transitive confirmations come before direct confirmations (as they may actually be confirmed earlier)
  • Tie-breaking uses transaction IDs for deterministic ordering

Changelog notice

### Fixed
- Fixed `ChainPosition` ordering so unconfirmed transactions never seen in mempool appear last instead of first

### Changed
- `ChainPosition`, `CanonicalTx`, and `FullTxOut` now require `A: Ord` for their `Ord` implementations
- Simplified `FullTxOut` ordering to only use essential fields (chain_position, outpoint, spent_by)

Checklists

All Submissions:

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

@evanlinjin evanlinjin self-assigned this Mar 11, 2026
@evanlinjin evanlinjin added this to the Chain 0.23.3 milestone Mar 11, 2026
@evanlinjin evanlinjin changed the title 0.23.x: Fix ChainPosition ordering bdk_chain v0.23.x: Fix ChainPosition ordering Mar 11, 2026
@evanlinjin evanlinjin changed the title bdk_chain v0.23.x: Fix ChainPosition ordering chain 0.23.x: Fix ChainPosition ordering Mar 11, 2026
@evanlinjin evanlinjin force-pushed the fix/chain-0.23.x-better-chain-position-ord branch from 7b45aa9 to 8e386a3 Compare March 11, 2026 13:26
@evanlinjin evanlinjin marked this pull request as ready for review March 11, 2026 13:26
@evanlinjin evanlinjin requested a review from luisschwab March 11, 2026 13:49
@evanlinjin evanlinjin moved this to Needs Review in BDK Chain Mar 11, 2026
@evanlinjin evanlinjin added the backport A bug fix or security patch to be ported to a previous release label Mar 11, 2026
@oleonardolima oleonardolima force-pushed the fix/chain-0.23.x-better-chain-position-ord branch from 8e386a3 to c3e960f Compare March 11, 2026 17:06
Copy link
Member

@luisschwab luisschwab left a comment

Choose a reason for hiding this comment

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

ACK c3e960f

Copy link
Member

@notmandatory notmandatory left a comment

Choose a reason for hiding this comment

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

ACK c3e960f

I ran it through the LLM 🤖 reviewer also and its only comments were about missing edge case tests with invalid ChainPosition data. But preventing invalid data should already be covered in other tests.

…play

Previously, unconfirmed transactions never seen in mempool would appear
before those with mempool timestamps due to derived Ord implementation.

Changes:
- Manual Ord impl: confirmed < unconfirmed < never-in-mempool
- At same height: transitive confirmations < direct (potentially earlier)
- Simplify FullTxOut ordering to only essential fields
- Add comprehensive tests and documentation
- Update CanonicalTx and FullTxOut to use manual Ord with A: Ord bound
@evanlinjin evanlinjin force-pushed the fix/chain-0.23.x-better-chain-position-ord branch from c3e960f to aff800d Compare March 12, 2026 06:39
@evanlinjin evanlinjin merged commit 3ef748f into bitcoindevkit:release/chain-0.23.x Mar 12, 2026
19 checks passed
@github-project-automation github-project-automation bot moved this from Needs Review to Done in BDK Chain Mar 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport A bug fix or security patch to be ported to a previous release

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants