What changed, and why it matters
This commit fixes a display bug in the Monero GUI wallet's transaction history. Previously, when sorting transactions by block height, failed transactions were incorrectly treated like pending ones and shown at the top of the list. The fix ensures only genuinely pending (unconfirmed) transactions float to the top, while failed transactions are sorted by their actual block height like normal. There is no direct evidence this is a security vulnerability—it's primarily a user-experience and accuracy fix.
Treat as a routine bug fix. No urgent security action is warranted based on the diff alone. If a security advisory is later published by the vendor, reassess.
Security signals we found
UI display logic correction for transaction state classification
Tightened conditional for treating transactions as pending
No memory safety, cryptographic, or authorization changes observed
Evidence from the diff
The patch touches two files. In TransactionHistoryModel.cpp, the logic for the TransactionBlockHeightRole is tightened: a NULL QVariant (which sorts to the top) is now returned only when blockHeight == 0 AND the transaction is pending AND not failed. Previously, any transaction with blockHeight == 0 returned NULL, which would also promote failed transactions. In History.qml, the JavaScript sort comparator is updated so that when sorting by ‘blockheight’, pending transactions (those with undefined blockheight) are placed after confirmed ones, and pending transactions are then sorted among themselves by timestamp. This aligns the QML-side sorting with the model-side intent.
Changed components
Monero GUI transaction history viewsrc/model/TransactionHistoryModel.cpppages/History.qmlInspect captured patch +14 / −5
### pages/History.qml
@@ -1513,6 +1513,14 @@ Rectangle {
// applying sorts
root.txOffset = 0;
root.txData.sort(function(a, b) {
+ if (root.sortBy === "blockheight") {
+ var aPending = typeof a.blockheight === "undefined";
+ var bPending = typeof b.blockheight === "undefined";
+ if (aPending !== bPending)
+ return aPending ? 1 : -1;
+ if (aPending)
+ return a.timestamp - b.timestamp;
+ }
return a[root.sortBy] - b[root.sortBy];
});
### src/model/TransactionHistoryModel.cpp
@@ -79,13 +79,14 @@ QVariant TransactionHistoryModel::parseTransactionInfo(const TransactionInfo &tI
return tInfo.fee();
case TransactionBlockHeightRole:
{
- // Use NULL QVariant for transactions without height.
- // Forces them to be displayed at top when sorted by blockHeight.
- if (tInfo.blockHeight() != 0)
+ // Use NULL QVariant for pending transactions without height.
+ // Forces them to be displayed at top when sorted by blockHeight,
+ // without also promoting failed transactions.
+ if (tInfo.blockHeight() == 0 && tInfo.isPending() && !tInfo.isFailed())
{
- return tInfo.blockHeight();
+ return QVariant();
}
- return QVariant();
+ return tInfo.blockHeight();
}
case TransactionSubaddrIndexRole:
{Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.