Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed NSInternalInconsistencyException & Swift runtime failure: arithmetic overflow #267

Merged
merged 6 commits into from
Dec 27, 2024

Conversation

azisramdhan
Copy link
Contributor

@azisramdhan azisramdhan commented Dec 21, 2024

Litewallet internal issues

13
16

Xcode Organizer

Screenshot 2024-12-22 at 08 46 23 Screenshot 2024-12-22 at 08 45 39

@azisramdhan azisramdhan changed the title Fixed NSInternalInconsistencyException Fixed NSInternalInconsistencyException & Swift runtime failure: arithmetic overflow Dec 22, 2024
@azisramdhan azisramdhan marked this pull request as ready for review December 22, 2024 01:26
@azisramdhan azisramdhan self-assigned this Dec 22, 2024
@azisramdhan azisramdhan added the 🐛 bug Something isn't working as expected label Dec 22, 2024
@azisramdhan azisramdhan force-pushed the bugfix/issues-13-16 branch 3 times, most recently from c140d82 to 3d7829e Compare December 22, 2024 02:32
@@ -558,3 +558,17 @@ extension Dictionary where Key: ExpressibleByStringLiteral, Value: Any {
return jstring
}
}

extension UInt64 {
Copy link
Contributor

@hassanashraf92 hassanashraf92 Dec 24, 2024

Choose a reason for hiding this comment

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

It's recommended to move the UInt64 extension to a dedicated file named something like UInt64+SafeArithmetic.swift or UInt64+Extension.swift.

@@ -558,3 +558,17 @@ extension Dictionary where Key: ExpressibleByStringLiteral, Value: Any {
return jstring
}
}

extension UInt64 {
/// Performs a safe addition, returning `nil` if overflow occurs.
Copy link
Contributor

Choose a reason for hiding this comment

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

While the existing documentation is clear, it can include more details about when these methods are useful.
/// Adds two UInt64 values safely, returning nil if overflow occurs.
/// - Parameter value: The value to add.
/// - Returns: The sum of the two values or nil if the operation overflows.

@@ -558,3 +558,17 @@ extension Dictionary where Key: ExpressibleByStringLiteral, Value: Any {
return jstring
}
}

extension UInt64 {
Copy link
Contributor

@hassanashraf92 hassanashraf92 Dec 24, 2024

Choose a reason for hiding this comment

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

Consider Extending a Protocol (Optional): If similar safe arithmetic methods are needed for other numeric types (e.g., Int, Double), you could introduce a protocol for safe arithmetic. This promotes code reuse and reduces duplication.

protocol SafeArithmetic {
    func safeAddition(_ value: Self) -> Self?
    func safeSubtraction(_ value: Self) -> Self?
}

return overflow ? nil : result
}

/// Performs a safe subtraction, returning `nil` if underflow occurs.
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment for documentation above.


// Safely calculate fee = fee + opsAmount
guard let safeFee = fee.safeAddition(opsAmount) else { return nil }
self.fee = safeFee
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems that the same value (fee) is used multiple times across the class functions. We can cache fee in a local variable if it's not modified between operations.

guard let safeFee = fee.safeAddition(opsAmount) else { return nil }
self.fee = safeFee

let cachedFee = safeFee // Cache for reuse


self.fee = fee + opsAmount

// Safely calculate fee = fee + opsAmount
Copy link
Contributor

Choose a reason for hiding this comment

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

While comments like // Safely calculate fee = fee + opsAmount provide context, they are overly verbose and repeat what the code already expresses.
For example; // Ensure the new fee calculation doesn't overflow

self.fee = fee + opsAmount

// Safely calculate fee = fee + opsAmount
guard let safeFee = fee.safeAddition(opsAmount) else { return nil }
Copy link
Contributor

Choose a reason for hiding this comment

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

Some variable names (e.g., safeSum, safeFee) are generic and don't convey their specific role in the calculation. Use more descriptive names for better understanding.

guard let totalReceivedAndFee = amountReceived.safeAddition(fee) else { return nil }


if amountSent > 0, (amountReceived + fee) == amountSent {
// Safely calculate amountSent = wallet.amountSentByTx(tx) - opsAmount
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment for documentation.

satoshis = safeAmountSent
} else if safeAmountSent > 0 {
// Safely calculate (safeAmountSent - amountReceived - fee)
guard let safeSatoshis = safeAmountSent
Copy link
Contributor

Choose a reason for hiding this comment

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

Multi-line guard statements can be difficult to read and debug. Break these into smaller, intermediate steps for clarity.

guard let intermediateSatoshis = safeAmountSent.safeSubtraction(amountReceived),
      let finalSatoshis = intermediateSatoshis.safeSubtraction(fee) else { return nil }
direction = .sent
satoshis = finalSatoshis

@@ -22,11 +22,14 @@ class DefaultCurrencyViewController: UITableViewController, Subscriber {
didSet {
Copy link
Contributor

@hassanashraf92 hassanashraf92 Dec 24, 2024

Choose a reason for hiding this comment

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

The didSet block contains too much logic. It's better to extract this logic into helper functions to make the didSet block cleaner and more focused.

updateCurrencyRows(oldCurrencyCode: oldValue)

(Optional but Recommended): Avoid UI Updates in didSet

setExchangeRateLabel()

Task { @MainActor in
tableView.beginUpdates()
Copy link
Contributor

Choose a reason for hiding this comment

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

(Optional): Use performBatchUpdates for Table View Changes.

Copy link
Contributor

@hassanashraf92 hassanashraf92 left a comment

Choose a reason for hiding this comment

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

General Comment: The indentation in the provided code appears inconsistent with standard Swift style guidelines.
Make sure to use control + i to fix any inconsistent indentation.

@azisramdhan
Copy link
Contributor Author

Thank you, @hassanashraf92, for the valuable feedback. I have updated the code based on your suggestions.

Copy link
Contributor

@hassanashraf92 hassanashraf92 left a comment

Choose a reason for hiding this comment

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

Great Job!

- Added detailed explanations of use cases for safeAddition and safeSubtraction methods in UInt64 extension.
- Clarified the behavior of these methods when handling overflow and underflow.
- Highlighted their importance in contexts requiring safe and predictable arithmetic operations.
- Applied consistent indentation using Xcode's Ctrl + I shortcut to improve code readability.
- No functional changes were made.
… clarity

- Cache the total fee in a local variable for reuse.
- Safely calculate the amount sent by subtracting opsAmount to prevent underflow.
- Ensure the total received and fee are within bounds during the calculation.
- Simplify the process of determining transaction direction (moved, sent, received) by using safe arithmetic.
- Moved the logic for updating currency rows into a separate helper function () to improve readability and maintainability.
- Cleaned up the didSet block to focus on calling the helper function.
@azisramdhan azisramdhan merged commit 670c800 into develop Dec 27, 2024
@losh11 losh11 deleted the bugfix/issues-13-16 branch January 4, 2025 04:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 bug Something isn't working as expected
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants