Skip to content

Comments

fix(qt): stable sort for equal items in Coin Control dialog#7156

Merged
PastaPastaPasta merged 1 commit intodashpay:developfrom
UdjinM6:feat/coin-control-stable-sort
Feb 23, 2026
Merged

fix(qt): stable sort for equal items in Coin Control dialog#7156
PastaPastaPasta merged 1 commit intodashpay:developfrom
UdjinM6:feat/coin-control-stable-sort

Conversation

@UdjinM6
Copy link

@UdjinM6 UdjinM6 commented Feb 19, 2026

Issue being fixed or feature implemented

CCoinControlWidgetItem::operator< had no tiebreaker for equal numeric values (amount, date, confirmations, CoinJoin rounds), causing Qt's unstable sort to produce a different ordering on each updateView() call whenever coins with identical values were present.

Noticed while testing #7155 - clicking "(un)lock all" button shifted rows with the same amount when list was sorted by amounts.

What was done?

Add a secondary sort by outpoint (txid:vout), which is unique and stable across view rebuilds.

How Has This Been Tested?

Build it on top of #7155, run and click "(un)lock all" button in Coin Control dialog - should be stable now.

Breaking Changes

n/a

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone

CCoinControlWidgetItem::operator< had no tiebreaker for equal numeric
values (amount, date, confirmations, CoinJoin rounds), causing Qt's
unstable sort to produce a different ordering on each updateView() call
whenever coins with identical values were present.

Add a secondary sort by outpoint (txid:vout), which is unique and
stable across view rebuilds.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@UdjinM6 UdjinM6 added this to the 24 milestone Feb 19, 2026
@coderabbitai
Copy link

coderabbitai bot commented Feb 19, 2026

Walkthrough

The change modifies the sorting logic in the coin control dialog to ensure deterministic ordering of items. When primary sort keys (amount, date, confirmations, coinjoin rounds) are equal, the new logic introduces a stable tiebreaker by comparing items based on transaction ID and output index (txid:vout), then by output number (vout). This ensures consistent and reproducible sorting results across identical data.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main change: adding stable sorting for equal items in the Coin Control dialog by implementing a tiebreaker mechanism.
Description check ✅ Passed The description is directly related to the changeset, clearly explaining the sorting instability issue, the fix applied, and how it was tested.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/qt/coincontroldialog.cpp (1)

46-51: Optional: tiebreaker is inert for tree-mode parent nodes.

In tree mode, parent (itemWalletAddress) nodes have COLUMN_AMOUNT UserRole data (line 792) but never receive TxHashRole/VOutRole (those are set only on child items at lines 764-767). When two parent nodes share the same total amount, the tiebreaker compares empty strings and then 0 < 0, always returning false — so ordering among same-sum parents is still nondeterministic.

This is a minor edge case (parents represent distinct addresses, so collisions are rare) and doesn't undermine the primary fix. If you ever want full stability, you could fall back to the wallet-address string for parent nodes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/qt/coincontroldialog.cpp` around lines 46 - 51, The current tiebreaker in
coincontroldialog.cpp compares TxHashRole and VOutRole which are only set on
child items, so parent nodes (itemWalletAddress) with equal amounts compare
empty/zero and remain non-deterministic; update the comparison in the relevant
compare/operator (the block using data(..., TxHashRole) and VOutRole) to detect
missing/empty TxHashRole (or missing VOutRole) and, for those cases (i.e.,
parent nodes), fall back to comparing the address string from COLUMN_ADDRESS (or
another stable identifier like the item text) to produce a deterministic
ordering for parent nodes while keeping the existing child-item outpoint
tiebreaker.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/qt/coincontroldialog.cpp`:
- Around line 46-51: The current tiebreaker in coincontroldialog.cpp compares
TxHashRole and VOutRole which are only set on child items, so parent nodes
(itemWalletAddress) with equal amounts compare empty/zero and remain
non-deterministic; update the comparison in the relevant compare/operator (the
block using data(..., TxHashRole) and VOutRole) to detect missing/empty
TxHashRole (or missing VOutRole) and, for those cases (i.e., parent nodes), fall
back to comparing the address string from COLUMN_ADDRESS (or another stable
identifier like the item text) to produce a deterministic ordering for parent
nodes while keeping the existing child-item outpoint tiebreaker.

@github-actions
Copy link

✅ No Merge Conflicts Detected

This PR currently has no conflicts with other open PRs.

Copy link
Member

@PastaPastaPasta PastaPastaPasta left a comment

Choose a reason for hiding this comment

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

utACK

Copy link
Collaborator

@knst knst left a comment

Choose a reason for hiding this comment

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

utACK 49c3a72

@PastaPastaPasta PastaPastaPasta merged commit 9e0f169 into dashpay:develop Feb 23, 2026
44 of 47 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.

3 participants