]> Untitled Git - bdk/commit
Merge bitcoindevkit/bdk#2146: `chain 0.23.x`: Fix `ChainPosition` ordering
authormerge-script <hello@evanlinjin.me>
Thu, 12 Mar 2026 06:49:06 +0000 (06:49 +0000)
committermerge-script <hello@evanlinjin.me>
Thu, 12 Mar 2026 06:49:06 +0000 (06:49 +0000)
commit3ef748f5193c15043fc677ae3613ef8ee8ed865b
tree63b53b5f5ee80b2b108eaa65f546503498cf72cb
parentecfe271ca85445ddeb4912668c112ef16b15a525
parentaff800d86c760f643bffb9731e46d7f22198a0f2
Merge bitcoindevkit/bdk#2146: `chain 0.23.x`: Fix `ChainPosition` ordering

aff800d86c760f643bffb9731e46d7f22198a0f2 fix(chain): correct unconfirmed `ChainPosition` `last_seen` tiebreaker (志宇)
9d2dedcd53a7ccde454c84f2c40327ef18603b51 fix(chain): correct ChainPosition ordering for wallet transaction display (志宇)

Pull request description:

  ## 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

  ```md
  ### 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:

  * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)

  ### Bugfixes:

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

Top commit has no ACKs.

Tree-SHA512: eccdf30a47c7e8ef40312f1dd4bf72ce42a3e26a1dd1e6d1f7dc4776350c99029408474439730256414bd0f173e755977a3e3deb81617a930e40ca7962bd490b