Repository navigation
perf: search only loaded wallet accounts - #1084
ben-kaufman wants to merge 2 commits into
Conversation
|
Milestone 3.2.0: it is stacked on #1070 (3.2.0) and is the iOS twin of synonymdev/bitkit-android#1656 (3.2.0). |
talosmachina
left a comment
There was a problem hiding this comment.
No findings. Filters the account-zero address search to the address types LDK Node reports as loaded, reusing the same listOnchainWalletAccounts() call that already fed the companion accounts. Reviewed e8c835f, light tier on the stacked commit (base fix/paykit-inbox-observation, 10 lines of logic plus tests). Not built here: iOS does not build on Linux, so Run Tests is the gate and it was still pending when this was posted.
What I checked, and 4 candidates I ruled out
Read in full: AddressSearchCoordinator in Bitkit/Services/CoreService.swift, its caller findReceivingAddress and processOnchainPayment, LightningService.listOnchainWalletAccounts / addressInfosForType, AddressSearchCoordinatorTests.swift.
Traced into ldk-node at the pinned 0.7.0-rc.76 (e494969): Node::list_onchain_wallet_accounts returns wallet.loaded_keys(), and address_infos_for_account looks the same key up in that map, returning WalletNotFound when absent.
CI: SwiftFormat green; Run Tests pending.
Ruled out
- An unloaded account-zero type that holds a receive: before this change the derive call for it already threw (
WalletNotFoundmapped toWalletOperationFailed), the loop logged and broke, so it could never match. Skipping it up front returns the same result with fewer FFI round trips. - Listing fails: the
catchkeeps the original all-types primary list, covered bytestAccountListingFailureKeepsPrimaryFallbackfor both an app error andCancellationError. - Successful empty list: no derivation at all; every derive would have thrown anyway, and the next search re-reads the list (
testEmptyAccountListIsReadAgainForTheNextSearch). - Order and cache keys:
primaryAccountskeeps theprioritized(selected:)order because it filters, not rebuilds, and the key still depends only on type, keychain and account index.
Merge confidence: 4/5, no findings, but the change was not built or run here and Run Tests had not finished.
[Medium impact] The PR appears safe to merge. SummaryLimits primary address searches to accounts returned by
Reviews (1) · Last reviewed commit: "perf: search only loaded wallet accounts" · Reviewed by Greptile |
piotr-iohk
left a comment
There was a problem hiding this comment.
QA review
Scope: Full review of the complete PR diff against merge base b1d65a7, at e8c835f. GitHub’s base e16d13bc is ahead of that merge base; CoreService.swift and AddressSearchCoordinatorTests.swift are unchanged there, and the PR merges cleanly.
No new actionable code findings.
Account-zero search keeps address types returned by listOnchainWalletAccounts(). LDK Node 0.7.0-rc.76 (e494969) uses that list as the loaded-key set, and address_infos_for fails with WalletNotFound for any other account. Account 0 surfaces that as WalletOperationFailed, which the existing batch loop already stops on. A listing throw, including CancellationError, still searches every primary type and skips companions. A successful empty list derives nothing and is read again on the next search. Selected-type order, receive-before-change, primary-before-companion, cache keys, and the 1000-index window are unchanged. The loaded-account filter matches bitkit-android#1656 at b6a6078. Companion ordering on iOS remains index, then address-type name.
Validation: Run Tests and SwiftFormat passed on e8c835f. AddressSearchCoordinatorTests belongs to the synchronized BitkitTests target, which that workflow runs. This review did not rebuild or rerun the suite.
Device testing: not performed in this review. Ready for device testing.
There was a problem hiding this comment.
Verdict: ✅ Approve
Posted as a comment: not every planned case passed.
Findings: None. The loaded-account list and address derivation use the same wallet map in the pinned LDK implementation. Filtering preserves selected-type priority, primary-before-companion ordering, cache keys, search bounds, and existing error outcomes.
QA for b7561c0:
Check 1: exact-head build ✅ The unmodified head builds for arm64 iOS Simulator with Xcode 27.0.
I ran xcodebuild build against this head. No application launch or device journey was performed.
Check 2: automated coverage ✅ Current-head CI passes the address-search tests and SwiftFormat.
I inspected the Run Tests log: AddressSearchCoordinatorTests passes loaded-only lookup, ordering, scoped caches, bounded ownership lookup, empty-list refresh, and listing/derivation error cases. SwiftFormat also passes at b7561c0. I did not rerun the suite. The workflow retains its integration exclusions and unrelated UI skips.
No device run: the QA notes request no journeys or manual cases, and this optimization preserves user-visible behavior. Native timing was not measured.
Twin: synonymdev/bitkit-android#1656 perf: skip unloaded accounts in address search matches loaded-account selection at b6a6078; each platform retains its existing cancellation handling.
Full review of 7cd096f..b7561c0, including both changed files and the reached lookup/LDK paths. No changed runtime path was driven on a device. This agrees with the earlier code review, with the build and CI checks above verified at the current head.
Reviewer model: gpt-6.1-sol
Reasoning effort: high
Reviewed by gpt-6.1-sol-high via gh-pr-review-loop skill
Commands: @ovi-reviewer review · test · retest
piotr-iohk
left a comment
There was a problem hiding this comment.
QA review
Scope: Full reassessment of the complete PR diff against merge base 7cd096f4, at b7561c08. The merge base changed since the saved assessment, so this pass inherited no prior coverage.
No new actionable code findings.
Account-zero search retains the address types in a successful listOnchainWalletAccounts() result and keeps selected-type order. LDK Node 0.7.0-rc.76 (e494969) uses that list as the loaded wallet map; addressInfosForAccount fails for any other account, and account 0 becomes WalletOperationFailed, which the existing batch loop already stops on. A listing throw still searches every primary type and skips companions. A successful empty list derives nothing and is read again on the next search. Receive-before-change, primary-before-companion, cache keys, and the 1000-index window stay as they are.
bitkit-android#1656 at b6a6078 applies the same loaded-primary filter. iOS still sorts companions by account index, then address-type name. Android aborts when listing is cancelled; iOS keeps the existing primary fallback. Production listing returns the loaded accounts, or throws nodeNotSetup before the queue, so that cancellation path does not drop a derivable address.
Validation: Run Tests passed on b7561c08 and ran AddressSearchCoordinatorTests (9 tests, 0 failures). SwiftFormat passed on the same commit. This review did not rebuild or rerun the suite.
Device testing: not performed in this review. Ready for device testing.
This PR uses the existing loaded-account list to avoid address derivation for unloaded primary wallet types. Stacked on #1070.
Description
Out of Scope
None.
Design
N/A — no UI changes.
Preview
N/A — no user-visible behaviour change.
QA Notes
Setup
N/A — no device journeys or manual cases are requested for this change. Automated coverage is listed below; the shared journey guide remains the device-test reference.
Journeys
N/A — no user-visible behaviour change.
Manual Tests
N/A
Automated Checks
AddressSearchCoordinatorTests.swift— distinguishes successful empty lists from failure, observes newly loaded accounts on the next search, and preserves listing-failure fallback.AddressSearchCoordinatorTests.swift— checks loaded-only calls, search order, cache scope, bounded ownership lookup and unchanged cancellation-error outcomes.Evidence
Both exact-base negative controls failed on the expected unloaded/empty-account assertions.
Final integration validation
Integration with master
4530ff7batb7561c08retains both USDT-warning cancellation and the payment-review callback. Bottom #1025: all-target build passed (19 targets), 378 focused tests passed, 0 failures/skips. One combined #1070 + #1081 + #1084 + #1085 composition, tree8f1e72d3from #10707cd096f4plus #10818967dff8, #1084b7561c08and #1085310e689a, covers the stack and those sibling changes: all-target build passed (19 targets) and 2,779 tests passed, 0 failures/skips using the six existing CI exclusions. These are not eight independent full-suite runs.All eight heads passed SwiftFormat. Translation checks report 0 errors and 15 warnings, all matching master by key, language, file and occurrence count, including
security__use_pin. Final toolchain/runtime and complete diagnostic disposition: Xcode 26.1 / iOS 27.0 simulator, serial tests; complete diagnostics inspected, with six SDK-construction QoS warnings and retained fixture/appearance messages matching baseline evidence; no introduced finding. Final-head CI after publication: pending.Gaps
Loaded-account selection is covered by deterministic tests. No native timing improvement is claimed.
The final Android 206 / iOS 215 comparison cohort was blocked before financial authorization, with no debit. It supplies no final payment-latency result or native benefit claim. Native USDT-warning, PIN and biometric flows have not been verified by this integration validation.
Models used
gpt-6-astra(reasoning:xhigh)gpt-6-astra(reasoning:xhigh)gpt-6-astra(reasoning:xhigh)