-
Notifications
You must be signed in to change notification settings - Fork 0
Integrate LDK onchain events #245
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
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
There was a problem hiding this comment.
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 integrates LDK node onchain events to replace previous polling and full sync mechanisms for Bitcoin transaction management. It removes the AddressChecker utility class that relied on external API calls, and improves handling of RBF (Replace-By-Fee) transactions to properly distinguish them from CPFP (Child-Pays-For-Parent) transactions on both sender and receiver sides.
Key changes:
- Event-driven architecture for onchain transaction updates (received, confirmed, replaced, reorged, evicted)
- Removal of 1-second polling timer in favor of real-time LDK events
- Enhanced RBF transaction detection using
doesExistflag to differentiate from CPFP
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| BitkitNotification/NotificationService.swift | Added notification handling for new onchain transaction events |
| Bitkit/Views/Wallets/Sheets/BoostSheet.swift | Removed redundant LDK node payment sync after boost operation |
| Bitkit/Views/Wallets/Activity/ActivityItemView.swift | Enhanced boost button logic to differentiate between RBF and CPFP transactions |
| Bitkit/Views/Wallets/Activity/ActivityExplorerView.swift | Replaced AddressChecker API calls with LDK node transaction details |
| Bitkit/ViewModels/WalletViewModel.swift | Removed polling mechanism and added event-driven state updates for onchain transactions |
| Bitkit/ViewModels/AppViewModel.swift | Added comprehensive event handling for onchain transaction lifecycle |
| Bitkit/Utilities/AddressChecker.swift | Removed external API-dependent utility in favor of native LDK functionality |
| Bitkit/Services/LightningService.swift | Added transaction detail methods and event handlers for onchain events |
| Bitkit/Services/CoreService.swift | Refactored payment processing to handle LDK events and removed replacement tracking maps |
| Bitkit/AppScene.swift | Removed balance change observer and event-based activity sync |
| Bitkit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved | Updated bitkit-core and ldk-node dependencies |
| Bitkit.xcodeproj/project.pbxproj | Updated project references for LDK package |
587f507 to
c9c0f14
Compare
This comment was marked as outdated.
This comment was marked as outdated.
|
@piotr-iohk please note we will need to update the e2e tests to close the onchain received sheet. |
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utAck
Amazing work, I've been waiting for over a year to finally have this setup in place: event-based sync for transactions 🎉
Added a few small nit comments, the one about the localizable strings applies to all cases where we added new toast messages, not only the code where I added it.
I wanted to give you the time to already make some small updates as I am starting to test this, hence me approving without testing; but I trust you'll wait for my testing 🙏🏻
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
|
Let's handle CPFP separately 😅 We need to discuss what should the correct behavior be for it |
Behaviour is back to it showing the "Removed from mempool" activity item and a "Replaced tx" toast even if just for a short time. This will confuse users about the state of their transaction so that should be polished in the future. Tested a bunch of times and most of the times it behaves like this, a few times it did not. So that might point to some kind of race condition. But let's create a follow-up issue for this and move to wrapping up here imo. Simulator.Screen.Recording.-.iPhone.17.-.2025-11-27.at.16.43.19.mov |
|
Ok, updated e2e tests for current state (synonymdev/bitkit-e2e-tests#56). Re-running 🤞 |
|
@pwltr it's not due to race condition, it's just because the event of the new tx takes a few seconds to come in from the LDK node. We can solve it by immediately caching the "intermediate" state in memory until the event comes in. |
Sounds good yeah I think an optimistic UI like this would be the way to go. Assume everything went right and correct if needed when the event(s) come in from LDK. Still feel free to postpone for now. |
|
Actually had a simpler solution, fixed in: #247 |
pwltr
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tACK with follow-up task here
Also note @piotr-iohk's request to merge this together with the Android counterpart.
Fix RBF until events arrive
ab36651
PR Review: Integrate LDK onchain eventsThis is an excellent architectural improvement that modernizes the onchain transaction handling by leveraging LDK's event-driven architecture. The change from polling to event-driven updates should significantly improve performance and user experience. Summary of ChangesMajor Improvements:
Impact:
Code Quality & Best PracticesStrengths
Code OrganizationThe new event handlers follow a clean pattern:
Each handler properly delegates to ServiceQueue.background(.core) and updates the activity list appropriately. Potential Bugs & Issues1. Race Condition in handleOnchainTransactionReplacedLocation: CoreService.swift:346-433 Issue: When processing replacement transactions, there is a potential race condition between checking if replacementActivity exists and processing the payment. Another event handler could process the same transaction concurrently. Recommendation: Add a lock or transaction ID tracking to prevent concurrent processing of the same transaction. 2. Cache Invalidation IssueLocation: CoreService.swift:34-62 Issue: The cachedTxIdsInBoostTxIds cache is updated in insert and bulk refreshed in upsertList, but individual update operations don't update the cache. This could lead to stale cache data. Recommendation: Add cache update to the update method to keep cache consistent. 3. Potential Memory Leak in Event HandlersLocation: AppScene.swift:213-215 Issue: The event handler closure captures app weakly, but the closure itself is never removed when the scene is dismissed. Recommendation: Ensure event handlers are removed when the scene is dismissed. The addOnEvent API should support removal, or use a cleanup mechanism in deinit or onDisappear. 4. Missing nil-check in processOnchainTransactionLocation: CoreService.swift:315-332 Issue: The function logs a warning if payment is not found but doesn't throw an error. The calling code may not handle this gracefully. Recommendation: Consider throwing a specific error so callers can decide how to handle missing payments, or add metrics to track how often this occurs. Performance ConsiderationsStrengths
Concerns
Security ConcernsGood Practices
Recommendations
Test CoverageMissing Test Scenarios
Testing RecommendationsAdd integration tests that simulate these event sequences:
Final RecommendationsMust Fix (Before Merge)
Should Fix (High Priority)
Nice to Have
ConclusionThis is a high-quality PR that represents a significant architectural improvement. The event-driven approach is the correct design pattern and will eliminate polling overhead. The code quality is generally excellent with proper error handling, logging, and async patterns. Recommendation: Approve with minor changes. Address the cache invalidation and race condition issues before merge, and plan follow-up work for comprehensive testing and performance optimization. Great work! The videos demonstrating reorg and eviction handling are particularly impressive. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tAck
now it really shows the boosted TX update instantly every time I try it
Show CPFP txs as boost fee
PR Review: Integrate LDK onchain eventsSummaryThis PR successfully replaces polling-based transaction monitoring with event-driven LDK onchain events, removes the AddressChecker, and improves RBF transaction handling. This is a significant architectural improvement that makes the app more reactive and efficient. ✅ StrengthsArchitecture & Design
Code Quality
|
ovitrif
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tAck
now it really shows the boosted TX update instantly every time
|
Android PR should succeed e2e once Electrum on staging is fixed. Merging this. |
1 similar comment
|
Android PR should succeed e2e once Electrum on staging is fixed. Merging this. |
This PR integrates LDK node on chain events to replace the previous pollin and full syncs.
It also removes Address Checker, and improves handling on RBFed transactions to be recognized on both sides.
Testing:
Should test all actions, send, receive (onchain and LN), transfer to savings, transfer to spendings, etc.
Screen.Recording.2025-11-26.at.9.05.11.AM.mov
Reorg removes tx from blocks demo:
Screen.Recording.2025-11-26.at.5.13.45.PM.mov
Transaction removed from mempool demo:
Screen.Recording.2025-11-26.at.5.38.36.PM.mov