Skip to content

fix(models): make XRPAmount and IssuedCurrencyAmount Ord consistent with PartialEq - #345

Closed
e-desouza wants to merge 1 commit into
mainfrom
fix/amount-ord-eq-inconsistency
Closed

fix(models): make XRPAmount and IssuedCurrencyAmount Ord consistent with PartialEq#345
e-desouza wants to merge 1 commit into
mainfrom
fix/amount-ord-eq-inconsistency

Conversation

@e-desouza

Copy link
Copy Markdown
Collaborator

Why

XRPAmount::cmp called .expect("cannot compare invalid XRPAmount values"), which panicked when the inner string was non-numeric (e.g. from a malformed server fee response). check_txn_fee, called by autofill and sign_and_submit, uses > on XRPAmount and would crash on any non-numeric fee value returned from a connected node.

IssuedCurrencyAmount::cmp compared only the value field while PartialEq compared all three fields (currency, issuer, value). This violated the Ord/Eq contract: two amounts with the same value but different issuers were Ord-equal but PartialEq-unequal, causing silent data loss when these values were used as BTreeMap keys.

What changed

  • XRPAmount::cmp: replaced .expect(...) with .unwrap_or_else(|_| self.0.cmp(&other.0)) — falls back to lexicographic comparison for non-numeric values instead of panicking.
  • IssuedCurrencyAmount::cmp: now compares all three fields (numeric value, then currency, then issuer), consistent with PartialEq.

How to validate

cargo test --release

…encyAmount Ord/Eq consistency

XRPAmount::cmp previously called .expect() on checked_cmp, causing a
panic whenever a non-numeric value was encountered (e.g. a malformed
server response). The implementation now falls back to lexicographic
string comparison, keeping Ord total and non-panicking. The
should_panic test is replaced with one that verifies the fallback.

IssuedCurrencyAmount::cmp previously compared only value, violating
the Ord/Eq contract since PartialEq (derived) compares all three
fields (currency, issuer, value). The Ord impl now performs numeric
value comparison with a string fallback, then breaks ties by currency
and issuer, making the total order consistent with equality.
@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 27.27273% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.69%. Comparing base (c83df4f) to head (406d856).

Files with missing lines Patch % Lines
src/models/amount/issued_currency_amount.rs 0.00% 8 Missing ⚠️

❌ Your patch check has failed because the patch coverage (27.27%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #345      +/-   ##
==========================================
- Coverage   86.71%   86.69%   -0.02%     
==========================================
  Files         252      252              
  Lines       32630    32638       +8     
==========================================
+ Hits        28296    28297       +1     
- Misses       4334     4341       +7     
Flag Coverage Δ
integration 71.32% <ø> (ø)
unit 87.31% <27.27%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/models/amount/xrp_amount.rs 89.37% <100.00%> (+0.06%) ⬆️
src/models/amount/issued_currency_amount.rs 51.85% <0.00%> (-18.15%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts ordering semantics for amount model types to avoid panics on malformed numeric strings and to better align Ord behavior with equality semantics when these types are used in ordered collections.

Changes:

  • Updated XRPAmount::cmp to avoid panicking on non-numeric values by falling back to lexicographic ordering.
  • Updated IssuedCurrencyAmount::cmp to incorporate currency and issuer when ordering, rather than comparing only value.
  • Updated XRPAmount tests to reflect non-panicking behavior on malformed inputs.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/models/amount/xrp_amount.rs Makes Ord::cmp non-panicking via fallback ordering and updates unit tests accordingly.
src/models/amount/issued_currency_amount.rs Expands cmp to consider additional fields (currency/issuer) and adds numeric-parse fallback behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 170 to 172
self.checked_cmp(other)
.expect("cannot compare invalid XRPAmount values")
.unwrap_or_else(|_| self.0.cmp(&other.0))
}
Comment on lines +53 to 63
let value_cmp = match (
self.value.parse::<BigDecimal>(),
other.value.parse::<BigDecimal>(),
) {
(Ok(a), Ok(b)) => a.partial_cmp(&b).unwrap_or(core::cmp::Ordering::Equal),
_ => self.value.cmp(&other.value),
};
value_cmp
.then_with(|| self.currency.cmp(&other.currency))
.then_with(|| self.issuer.cmp(&other.issuer))
}
Comment on lines +225 to +229
// Must not panic — result is determined by string order
let _ = valid.cmp(&malformed);

// Reflexivity: same non-numeric string compares equal to itself
assert_eq!(malformed.cmp(&malformed), Ordering::Equal);
@e-desouza

Copy link
Copy Markdown
Collaborator Author

This PR has been superseded by #353 (XRPAmount: enforce non-negative integer drops via u64 parse, Ordering::Equal fallback) and #354 (IssuedCurrencyAmount: align Ord with 3-field Eq), which address the same issues with a more complete implementation. The Copilot feedback about the remaining Eq/Ord gap is resolved in those PRs. Closing this in favor of the newer branches.

@e-desouza

Copy link
Copy Markdown
Collaborator Author

Closing — superseded by #353 and #354.

@e-desouza e-desouza closed this Jul 14, 2026
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.

2 participants