simplewallet: fix show_transfer confirmations
What changed, and why it matters
This commit fixes a display bug in Monero's command-line wallet. When showing details of a transfer, the number of 'confirmations' was previously calculated using the wrong block height (the spendable-unlock height instead of the transaction's own block height). This could mislead users about how deeply confirmed a transaction was, especially if the transaction had an unusual unlock time. There is no direct evidence this affects funds safety or can be exploited by an attacker.
No urgent security action. Treat as a normal bug-fix patch. Users relying on CLI confirmation counts for transactions with non-standard unlock times should update to a build containing this fix to avoid misleading display output.
Security signals we found
UI display bug in confirmation count
Incorrect use of unlock height instead of transaction block height for confirmations
No change to consensus or transaction validation logic
Evidence from the diff
In simple_wallet::show_transfer(), the confirmation count was computed as last_block_height - bh, where bh = max(pd.m_unlock_time, pd.m_block_height + CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE). For transactions with a custom unlock_time far above the default 10-block maturity, bh could be much larger than pd.m_block_height, producing a confirmation count smaller than the actual blockchain depth (last_block_height - pd.m_block_height). The patch introduces a separate confirmations variable equal to last_block_height - pd.m_block_height (floored at 0) and uses it in the two success_msg_writer outputs. This is a UI-only correction; consensus, validation, and spending logic are untouched.
Changed components
src/simplewallet/simplewallet.cppsimple_wallet::show_transfer()CLI wallet transfer displayInspect captured patch +3 / −2
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 4853a66..6f87a8d 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -10117,14 +10117,15 @@ bool simple_wallet::show_transfer(const std::vector<std::string> &args)
if (pd.m_unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER)
{
uint64_t bh = std::max(pd.m_unlock_time, pd.m_block_height + CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE);
+ const uint64_t confirmations = last_block_height > pd.m_block_height ? last_block_height - pd.m_block_height : 0;
uint64_t last_block_reward = m_wallet->get_last_block_reward();
uint64_t suggested_threshold = last_block_reward ? (pd.m_amount + last_block_reward - 1) / last_block_reward : 0;
if (bh >= last_block_height)
success_msg_writer() << "Locked: " << (bh - last_block_height) << " blocks to unlock";
else if (suggested_threshold > 0)
- success_msg_writer() << std::to_string(last_block_height - bh) << " confirmations (" << suggested_threshold << " suggested threshold)";
+ success_msg_writer() << std::to_string(confirmations) << " confirmations (" << suggested_threshold << " suggested threshold)";
else
- success_msg_writer() << std::to_string(last_block_height - bh) << " confirmations";
+ success_msg_writer() << std::to_string(confirmations) << " confirmations";
}
else
{
Why this scored 17/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.