Skip to content

[Bug]: Continue on Let your contacts pay you does not finish #1406

Open

Description

@piotr-iohk

What happened?

After importing a Pubky Ring profile with 61 contacts, Continue on "Let your contacts pay you" stays busy for a long time. It does finish. The session log shows why it takes that long.

Saving the 61 contacts was the shorter part. On 1 Oct 2026 at 15:38:02 the app had already discovered 61 follows. Import finished at 15:39:28. The following work is a walk of Paykit receiver paths. From 15:35:49 through 15:57:28 the log records 68 failures, all transport_error / list_paykit_receiver_paths, and all for the same 7 pubkys (about 9–10 failures each). Those are the same 7 keys whose profile fetch had just failed with transport_error / fetch profile while the import preview was loading. The log ends while those retries are still going, which matches Continue staying on screen for many minutes.

Expected behavior

Continue finishes promptly after the contacts are saved, with visible progress while any remaining work runs. A contact whose profile lookup already failed should not be retried for the rest of the session.

Steps to Reproduce

  1. Use Pubky Ring with an identity that follows 61 pubkys, and a Bitkit wallet that has not saved those contacts yet.
  2. In Bitkit, adopt that Ring identity and wait until the import preview lists the contacts.
  3. Import the contacts.
  4. On "Let your contacts pay you", tap Continue.
  5. Continue stays busy for many minutes, then finishes.

Logs / Screenshots / Recordings

From bitkit_2026-10-01_15-33-29.log (device local time):

  • 15:38:02 Discovered '61' contacts for import
  • 15:38:08–15:39:01 seven Retrying contact profile resolution warnings, transport_error / fetch profile
  • 15:39:28 Imported '61' contacts
  • 15:35:49–15:57:28 sixty-eight Failed to refresh Paykit receiver paths, all list_paykit_receiver_paths, only those same seven pubkys

The full log could not be attached from the command line:

2026-10-01-pay-contacts-continue-hang.log

Bitkit Version

2.5.0 dev, pull request #1395 at faae845c. Confirm this was the build on the phone.

Device / OS

Samsung SM-S901B. OS version TBD. Pubky Ring 2.0 was installed from bitkit-e2e-tests/aut/pubkyring-83834e7.apk.

Reproducibility

Often (>50%)

Additional context

  • One 61-contact Ring import on this build. Device log times are local. Continue was still in the receiver-path retries at the end of the exported log. The reporter later saw that step finish.
  • The same seven pubkys fail both fetch profile during preview and list_paykit_receiver_paths afterward. The other follows are not in those failure lines.
  • Loading the contact list and avatars is separate and already covered by fix: speed up pubky profile loading #1399 and fix: speed up pubky profile loading bitkit-ios#854. This report is only the Continue / receiver-path walk.
  • fix: save contacts without repeated remote lookups #1395 lists this Continue path as out of scope.
  • Environment: regtest app build, staging Pubky.
  • Twin: iOS issue filed in the same batch and linked after both numbers exist.

Activity

  1. piotr-iohk commented on Oct 1, 2026

    @piotr-iohk
    CollaboratorAuthor
  2. added theissue type on Oct 1, 2026
  3. ben-kaufman commented on Oct 1, 2026

    @ben-kaufman
    Contributor

    This matches iOS #861. Could you retest with #1401? It removes the receiver-folder discovery producing these warnings. #1395 fixes saving imported contacts, but does not address this later Continue delay. If it persists, please include logs covering the Continue tap through completion or failure.

  4. piotr-iohk commented on Oct 2, 2026

    @piotr-iohk
    CollaboratorAuthor

    Checked on #1401 latest revision 5fb0193.

    Test: import profile from Pubky Ring with 61 contacts.
    Performance seems deteriorated from testing against #1395 - not only continue, but all 3 steps: create, import, continue.

    Logs and recording (continue never finished after 15mins +):

    Screen.Recording.2026-10-02.at.09.57.00.mp4

    logs.zip

  5. added this to the 2.6.0 milestone on Oct 2, 2026
  6. Jasonvdb commented on Oct 2, 2026

    @Jasonvdb
    Contributor

    @ben-kaufman, here are measurements for this issue from our 61-follow test, in case they help with #1401.

    Setup: emulator, staging network, piotr's Pubky Ring follow list (61 follows, 7 of them never published). Builds: master 6ba44a4, and #1399 at 58d5c53, which already runs public reads outside the operation lock. Line numbers are at 58d5c53.

    Continue (tap → setEnabled done): 339 s on master, 154–167 s on #1399.

    • Breakdown of fix: speed up pubky profile loading #1399's 167 s:
      • Public endpoint sync: 2.0 s.
      • Private walk: 137.8 s, 83% of the total. Of that, receiver-folder discovery (discoverRelevantReceiverPaths) took 93.9 s, marker selection 29.4 s and ensureLinkWithPeer 13.7 s.
      • syncLists: 4.9 s.
      • Message drain: 21.7 s.
    • The walk handles one contact at a time (preparePrivatePaymentListReservations, PrivatePaykitRepo.kt:853). The 7 unpublished follows cost about 8 s each, 54–58 s in total; every other contact cost about 1.5 s.
    • Each walk fetches every receiver marker twice: once during discovery and again in privateReceiverPathSelection (PaykitSdkService.kt:697).
    • When the import ends, the contact sync (AppViewModel.kt:771) starts a second walk over the same 61 contacts (148 s). It runs alongside Continue and competes for read slots and the operation lock.

    After Continue, walks over all 61 contacts keep running back to back for more than 10 minutes, on both builds.

    • Payment request polling took 290 s, link burst round 1 took 378 s, and so on. The initial link burst schedules 15 rounds (PrivatePaykitRepo.kt:94).
    • In 13.6 minutes, each contact's discovery and marker selection ran about 5 times.
    • ensureLinkWithPeer holds the operation lock during network I/O, 179 s in total (PaykitSdkService.kt:773-784).

    Delete Profile with 61 contacts: 551 s on #1399.

    • 520.7 s of that was waiting for publicationMutex (PrivatePaykitRepo.kt:1360-1361, taken through removePublishedEndpointsForCleanup). It waited behind a 362 s foreground publish walk and a polling walk queued ahead of it.
    • The delete work itself took about 30 s: deleteAllContacts was 24 s (61 × 0.4 s).
    • On master, removing the 61 contacts right after launch took 930 s, queued on the operation lock behind profile reads.

    Import All → saved: 28–41 s on both builds.

    • About 70% of it is the Kotlin storage callbacks. Each saveContact does about 8.5 full state loads plus one full save. Each load is a Room walletIndex query, a DataStore read and a Keystore AES-GCM decrypt.
    • The state is only 12.6 KB with 61 contacts, so the cost comes from the number of calls, not the size.

    The 7 failing follows:

    • Six have no pkarr record on the relays. The seventh points to a homeserver key that has no record either.
    • They fail in 5–9 s on the emulator and in 5–15 s on piotr's Samsung.
    • piotr once saw them take about 5 minutes. A slow DHT is the likely cause, because the pkarr and DHT lookups have no overall deadline.

    Ideas, in case they're useful (none of them are in #1399):

    • Let Continue return after the public sync, and finish the private preparation in the background.
    • Reuse the markers fetched during discovery.
    • Read 3–4 contacts at a time on the bulk lane.
    • Cancel or merge the contact-sync walk when Continue starts.
    • Skip keys that just failed to resolve for a few minutes.
    • Cancel background publication work before Delete takes publicationMutex.
    • Cache walletIndex in Keychain.

    Separately, #1399 now gives each import-preview lookup a 10 s deadline, and Contacts no longer looks up every contact again on each visit.

  7. ben-kaufman commented on Oct 2, 2026

    @ben-kaufman
    Contributor

    Addressed the blocking contact-preparation path in #1401, commit eaf6a09; matching iOS changes are in 27e921a3.

    Continue now finishes public setup and starts private preparation in the background. Repeated preparations are coalesced, established links are reused, and unavailable lookups have a five-minute cooldown. Link preparation no longer holds the publication lock for the entire contact walk; cleanup invalidates the remaining work, and removed contacts are checked again before publication.

    All 3,186 Android unit tests passed, including stalled lookup/cleanup, removed contacts and duplicate preparation. An in-flight SDK call can still take time, and public setup still needs the network. Please retest the 61-contact fixture on the new head; keeping this issue open until that device run confirms the Continue and Delete timings.

  8. ben-kaufman commented on Oct 3, 2026

    @ben-kaufman
    Contributor

    Updated #1401 through 09e224c and tested a local build with Paykit #171:

    • Public request-capability discovery runs eight contacts at a time, outside the SDK mutation queue. Contact Pay resolves its target before reciprocal publication; intake and discovery no longer wait for all-contact preparation. Retry drains only process affected peers.
    • Full private cleanup refreshes the app registry once, keeping retry state until it succeeds. Public cleanup still runs independently after a private failure.
    • Warm Contact Pay reached Amount in 3.9 seconds. Sharing OFF improved from 16.8 to 14.2 seconds after the duplicate refresh was removed, then to 12.5 seconds with the additional SDK read reductions. Sharing ON took 4.4 seconds. These are individual local runs, not statistical before/after results.

    Android withdrawal is still above the few-second target. In the final run the sharing gate was acquired immediately; time was spread across private-list withdrawal and registry/public cleanup. Paykit #171 reduces this work but does not make it free. It remains a separate SDK improvement to consume after merge/release; #1401 still uses rc59.

    Full scope and timings. This is one saved contact on a local homeserver, not the affected staging contact set. Keep the 61-contact import, request delays and backup stalls open for retesting. The latest request payment produced a success log but was absent from Bitcoin/Electrum; it is not counted as completed. The broadcast-outcome dependency remains #1384.

    3,210 unit tests passed, with no introduced lint findings. Current build/lint CI is green; device performance still needs the staging repeat.

  9. ben-kaufman commented on Oct 3, 2026

    @ben-kaufman
    Contributor

    Both mobile PRs now use published Paykit rc60, including SDK #169/#170/#171 (Android dc73b29, iOS 10b85a1e). The Android branch also includes current master’s profile/import and prioritized public-read changes.

    A fresh staging iOS-to-Android test delivered a 1,000-sat request into Android’s request list; contact-sharing withdrawal completed on both platforms. However, initial linking still took minutes and iOS sending/withdrawal still exceeded the targets tracked in synonymdev/bitkit-ios#868. This does not close the performance issue, the 61-contact case, or the full payment journey. No transaction was broadcast in this run. Further work needs timings for the remaining active shared-state operations, rather than simply increasing probe concurrency.

  10. ben-kaufman commented on Oct 3, 2026

    @ben-kaufman
    Contributor

    Latest staging measurements used the published rc61 binaries with one linked, unfunded iOS/Android pair:

    • Warm iOS Request or Pay opened in under one second.
    • A 5,000-sat request sent at approximately 15:23:20 UTC completed between 23.2 and 25.6 seconds after Send.
    • Android's open request list was still missing it at 4.9 minutes and showed the matching request by 6.4 minutes. This is the observed display interval, not an exact network-delivery timestamp.
    • Android's private withdrawal phase took about 49 seconds in an earlier rc61 run. That is not the full public/private cleanup duration.

    Both PRs now use published rc62. It retains the batching and polling improvements and fixes a separate SDK issue where four concurrent outbound peers could consume each other's leases while waiting on shared storage. It does not explain or establish a fix for the one-peer delay above. No rc62 staging latency result is claimed here.

    Keep this open. We need timings for repository/SDK queue waits, outbound work, intake and request-list updates before attributing the remaining delay to Bitkit or the homeserver. Android also queues overlapping refreshes instead of coalescing them as iOS does; its impact in this run is unmeasured. No safety timeout was reduced.

    No payment was broadcast in these unfunded-wallet runs. Full payment/unlock, the 61-contact case, cold start and backup-stall QA remain unverified. The separate wallet broadcast dependency is still tracked in iOS #844 and Android #1384.

  11. ben-kaufman commented on Oct 5, 2026

    @ben-kaufman
    Contributor

    I profiled one linked, unfunded staging pair using a local #171 build at 13feb12a, before the later registry/endpoint optimizations. This was not the published rc62 artifact or a measurement of the final PR head.

    Sharing OFF took 84.006s from the action marker to the last awaited SDK call:

    Operation Queue wait Execution
    Initial peer lookup 10.386s 1.648s
    Batched private withdrawal 2.363s 23.112s
    Pending-outbound check <0.001s 0.903s
    First registry update <0.001s 13.433s
    Public endpoint cleanup 2.942s 13.692s
    Second registry update 2.791s 10.844s

    Background poll/backup work interleaved, so these rows do not cover the entire critical path. Execution includes wrapper checks, not just network time. No outbound drain ran because its queue was already empty.

    Sharing ON completed its public work in 31.668s; private publication finished by 68.009s. Warm request-list opening was observed within 0.9s. Both requests sent from iOS arrived, but receiver restarts prevent a clean delivery-latency claim. No payment was made.

    A separate cold-start failure was reproduced and fixed in b4b21418e: wallet crypto temporarily removed a security provider needed by the TLS verifier. With that fix and published rc62, a cold launch had no verifier errors, but session restoration still took 98.9s. That remaining delay is not explained by the provider fix.

    The newer SDK-only results reduce more repeated state reads. They still need a comparable mobile retest, and the performance target remains unmet.

  12. ben-kaufman commented on Oct 5, 2026

    @ben-kaufman
    Contributor

    Tested current #171 source in Android, not published rc62: measured breakdown. One inbox refresh held the request-repository mutex for 111.7s, including 65.3s waiting for the SDK queue while receive itself took 1.8s. Presentation-marker persistence then waited 46.7s behind that refresh. The exact SDK lock holder was not tagged, so this does not establish the whole delay as one SDK call or a homeserver problem. The request was visible later; exact automatic presentation timing and full payment/unlock remain unverified. Keeping this open.

  13. ben-kaufman commented on Oct 5, 2026

    @ben-kaufman
    Contributor

    New same-identity staging measurements with the FFI batching fix: request send 30.6s -> 15.3s; full sharing withdrawal 73.3s -> 50.0s. Warm Contact Pay still took about 10.4s SDK execution plus 3.5s queued behind backup/peer/request reads. Automatic incoming preparation took 38.2s, with 24 lock/load cycles and nine commits, so that path remains under investigation. Detailed results and limitations: pubky/paykit-rs#171 (comment) . These are individual unfunded runs, not a full payment or final-head sign-off. Keeping this open.

  14. 4 remaining items

  15. piotr-iohk commented on Oct 6, 2026

    @piotr-iohk
    CollaboratorAuthor

    Android retest on 6 Oct 2026, PR #1401 at 51e26b0b710fb00edacfb7aada8bb0f5e57743fb (Bitkit 2.5.0 / 190, Pixel 6 emulator, Android 13, staging Pubky / regtest, E2E hooks enabled). Installed APK fingerprint matched the build.

    This run failed at Import All, before reaching the Continue step from this ticket:

    • Ring identity stag3: preview showed 62 friends after approximately 24.9s.
    • Import All stayed busy for at least 10m20s during observation, then failed. The failure log is 16m07.5s after the tap-command start.
    • The reporter saw a transport-error toast. A later UI inspection showed the same import preview with 62 friends and Import All available again. The transient toast and exact UI failure time were not captured by automation.
    • Continue and the imported contact list could not be verified. No retry or app restart was performed.

    Relevant log (UTC):

    2026-10-06 16:57:35.778 ERROR [PubkyRepo.kt:1270] Failed to import contacts [AppError='code=transport_error, context=write encrypted Pubky shared state could not be confirmed']
    

    Later incoming-request refreshes also logged transport_error / acquire Pubky write lock at 16:59:57.480 and 17:00:37.552 UTC.

    Fixture caveat: this was the same stag3 identity previously imported and then deleted on iOS (90799f2). iOS deletion completed before Android started, but took ~13m33s and reported one failed contact cleanup. Prior shared state may be a factor; this is not a proven cause and this is not a fresh-identity baseline.

    I will repeat with a fresh Pubky identity with the same 62 follows on the newest PR head. At this check, #1401 still points to 51e26b0, the tested revision; no newer head was visible.

    Timings include automation overhead. Scoped Pubky/Paykit logs and build/timing evidence have been collected for attachment. This is a related import-path observation, not confirmation of the original Continue failure.

    android-stag3-import-logs.zip

  16. piotr-iohk commented on Oct 6, 2026

    @piotr-iohk
    CollaboratorAuthor

    Fresh-profile retest on Android 51e26b0: all three import steps completed successfully.

    Uninstalled Bitkit and installed the verified staging/regtest APK with E2E hooks, then prepared a new empty wallet on Pixel_6 / Android 13 (emulator-5554). Used stag4, fresh to Bitkit/Paykit, with the same 62 followed public keys as stag3.

    Step Observed time
    Select Ring identity → profile/contact preview 24.7s
    Import All → Let your contacts pay you 3.4s
    Continue → profile screen 24.1s

    The log confirmed Imported '62' contacts. All 62 contact row IDs were verified against the fixture, with no missing or extra contacts. Profile, Contacts and wallet Home remained usable.

    The earlier stag3 Import All transport-error stall did not reproduce. Both runs used the same APK/revision; this run differed in having clean Bitkit data, a fresh identity and an empty wallet, so it does not establish which factor caused the earlier failure.

    One sample. Timings are automation tap-command start to polling detection of the destination, include UI-dump overhead, and exclude pauses between steps. Two profile lookups timed out during preview. Background Paykit contact preparation continued after visible completion, with warnings for contacts lacking Paykit authorization; its full completion was not verified.

    The profile is retained. Profile deletion is the next test and has not been exercised in this run.

  17. piotr-iohk commented on Oct 6, 2026

    @piotr-iohk
    CollaboratorAuthor

    Profile-deletion follow-up after the successful fresh stag4 import, on Android 51e26b0b710fb00edacfb7aada8bb0f5e57743fb (Pixel_6 emulator / Android 13, staging Pubky / network regtest, E2E hooks, empty wallet, 62 imported contacts).

    Deletion eventually completed:

    • Deleted all contacts logged 6m29s after confirming Yes, Delete.
    • Paykit session removal logged 6m40s after confirmation.
    • Ring identity chooser detected by 7m17s, including UI-inspection overhead.
    • Edit controls remained dimmed with the Delete spinner during the wait. Contacts subsequently showed the empty Dynamic Contacts introductory screen; wallet Home remained accessible with zero balance and no profile name.

    No contact-deletion error was found in the captured logs. Private Paykit contact preparation continued after deletion confirmation, with missing-authorization and transport-fetch warnings, so this is not an idle deletion baseline. No restart, retry or disconnect was used. Exact UI completion time and remote profile removal were not independently verified.

    This observed run was faster than the earlier iOS deletion (~13m33s to session removal), but the single samples and different runtime conditions are not a controlled platform comparison. A 6–7-minute blocking deletion is still slow. We can track profile-deletion optimization in a separate follow-up rather than treat it as a critical blocker for #1401. This does not change the successful import result.

    Next: repeat iOS deletion using fresh stag5 with the same 62 follows. Logs and timing evidence are collected for attachment.

  18. ben-kaufman commented on Oct 6, 2026

    @ben-kaufman
    Contributor

    Updated #1401 in fe364a5 to published rc64, with the matching iOS fix in #856.

    The per-contact deletion loop is replaced by one bulk SDK operation. Deletion stops scheduling contact preparation and batches local cleanup, while preserving subscription, lease and public-marker protections.

    A fresh staging run with 62 unregistered contacts and active background preparation took 48.5s total: 18.8s withdrawal/waiting, 5.4s contact cleanup, and 24.4s remaining profile/public cleanup and sign-out. The app returned to the signed-out profile screen. iOS completed in 34.3s.

    Full results and limits. These are different contacts from Stag4, not a controlled before/after comparison. The remaining sign-out time is not fully attributed, and uncertain-write safety waits are unchanged. Please repeat the 62-follow journey on this head; I haven't closed the performance issue.

  19. piotr-iohk commented on Oct 6, 2026

    @piotr-iohk
    CollaboratorAuthor

    Retested the rc64 fix on Android fe364a5cd234648081c72c5dbb38973fb464cc62, Bitkit 2.5.0 (190), Pixel_6 / emulator-5554 / Android 13, staging Pubky + regtest network backend + E2E hooks. The already installed APK matched the current-head local universal artifact (SHA256 04d1c2a52c381adc86c05452a439391ea7250b30f98b14403f12ca7f09460897); no reinstall or wallet reset was performed.

    Fresh Stag7 (pubkyzga7nprh39641yde48qwurekj6up3mp95e8qkijdsra17wafmyio) followed the exact same 62 contacts as our previous Stag3/Stag4/Stag5 fixture. This is the delete immediately after import, with background preparation active variant requested in the fix note.

    Operation Measured elapsed
    Select Ring identity → import preview showing 62 friends 32.001s
    Import All → Let your contacts pay you / Continue 3.632s
    Continue → Profile available 18.902s
    Confirm Yes, Delete → Deleted all contacts log 10.008s
    Confirm Yes, Delete → PAYKIT_SESSION deleted log 19.496s
    Confirm Yes, Delete → Profile deleted toast + Ring chooser observed 23.380s

    The app log confirms Imported '62' contacts at 18:53:38.398 UTC. Delete was confirmed at 18:54:10.087712 UTC, 9.947s after Profile became available, with only navigation through Edit Profile, scroll and confirmation in between. UI inspection adds overhead to that navigation delay.

    Preparation was still active: contact preparation warnings appeared at 18:54:07.961 UTC before confirmation and 18:54:11.929 UTC after it. Contact cleanup completed at 18:54:20.096 UTC, and session deletion at 18:54:29.584 UTC. No deletion error, retry, restart or connectivity intervention was observed. Two remote follow-profile fetches timed out during preview, but all 62 contacts imported.

    After deletion, Profile returned to the Ring chooser, Contacts showed the empty Dynamic Contacts introduction, and the wallet remained usable with 100,000 sats savings / 0 spending.

    This is a substantial improvement over our earlier active-preparation Android run on 51e26b0 (~400.390s to session deletion, chooser observed by 437.487s). These are individual fresh-identity runs with the same contact list, not controlled benchmarks. UI values are observed upper bounds including polling/tool overhead; log milestones provide separate cleanup timings. Remote cleanup was not independently audited. The settled/idle deletion repeat remains to be tested, and this narrow test does not sign off the full PR.

  20. piotr-iohk commented on Oct 6, 2026

    @piotr-iohk
    CollaboratorAuthor

    android-stag7-reimport-pending-logs.zip

    Follow-up on the same Android fe364a5cd / Paykit rc64 build: the intended settled-deletion repeat is blocked by re-import of the just-deleted identity.

    After the successful fresh Stag7 import and active-preparation deletion, selected the same Stag7 identity from Ring again, with the same 62 follows. No rebuild, reinstall, wallet reset, retry or restart was used. Environment remains Pixel_6 / Android 13 / emulator-5554, Bitkit 2.5.0 (190), staging Pubky + regtest network backend + E2E hooks.

    • Ring selection → preview showing Stag7 and 62 friends: 23.304s (observed upper bound).
    • Tapped Import All at 19:02:04.394 UTC.
    • At 19:12:23 UTC, more than 10m18s later, the preview still showed disabled Select and the Import All spinner. Continue was never reached.
    • Captured app logs, including .part_002.log, contain neither a completed import nor a final Failed to import contacts error for this attempt. Two follow-profile fetch warnings occurred during preview; no terminal transport-error result is claimed here.

    We therefore did not start deletion and cannot report a settled-deletion timing. The app was left running on the pending import screen when this observation window ended.

    A read-only JDWP probe found the background preparation/retry jobs absent and their pending sets empty while import was still pending. That does not satisfy the settled-after-import condition: the contacts had not finished importing. The probe invoked no app methods, made no state changes and detached before ending observation.

    Possible investigation point, not an established cause: this build's saveContacts identifies blocked peers and restorePrivateContacts unblocks them one by one before saving the contacts. Profile deletion blocks those peers. The pending re-import may involve that restoration path; this run alone does not locate the active SDK call or establish the cause.

    This is a re-import after deletion observation, separate from the successful first-use import/deletion result above. Logs and screenshot are retained for attachment. A fresh identity is needed to independently exercise the intended settled-deletion case while this re-import issue is investigated.

  21. ben-kaufman commented on Oct 6, 2026

    @ben-kaufman
    Contributor

    The re-import fix is pushed in 9083227 on #1401, using published Paykit rc65. Selected contacts are saved and unblocked in one atomic SDK operation; the per-contact write and rollback loops are gone on both platforms. A local-homeserver SDK comparison for 62 contacts took 3.019s with the loop versus 56ms with the batch, but that is not a staging/mobile result. Please repeat the same Stag7 import after deletion on this build. The reported ten-minute stall and settled-deletion measurement remain open; uncertain-write safety waits are unchanged.

  22. ben-kaufman commented on Oct 7, 2026

    @ben-kaufman
    Contributor

    Published rc66 check on Android fd04581 with a fresh staging identity: a 5,000-sat request payment completed to iOS, with receiver credit and independently confirmed regtest transaction. The reverse payment also completed and Android showed the sending contact. This predates the newer link-preparation commit and is one run, not a matched speedup claim.

    Android payment timing:

    • App swipe event to sendOnChain entry: 15.382s, covering preparation/acceptance; individual SDK stages were not timed.
    • Awaited pre-send LDK wallet sync: 6.627s.
    • UTXO selection to service Sending: 8.101s, containing proof-start persistence and final authorization, without per-call timings.
    • Service Sending to successful broadcast: 0.224s.
    • Total: 30.568s from the app swipe event, or 32.722s from the automation command. Sent was observed later; that observation gap is not measured UI latency.

    Warm Contact Pay opened Request-or-Pay within 2.19s. The initial preparation attempt was still busy at 41.3s and reached Amount by 86.6s. Send Request was busy at 9.1s and Sent by 65.9s; these are observation bounds. A backup reminder interrupted reverse-request presentation, so it is not a clean delivery-to-ready measurement.

    The remaining SDK queue/lock/network breakdown is unmeasured. Linking, onboarding, cold-start and many-contact performance stay open, as do the historical Try Again and controlled-failure journeys. Transaction: 41d37956c0b3ce19dd9709d95107f351634378ad19d99088d14c4c83beba28b0, confirmed at regtest height 216161.

  23. ben-kaufman commented on Oct 7, 2026

    @ben-kaufman
    Contributor

    Fresh paired measurements using the runtime source now in rc67: Send Request 12.11s and swipe to native wallet send 21.76s, including 5.42s in the SDK queue, 13.26s SDK execution and 1.86s pre-send wallet work. The payment confirmed on regtest. Sharing OFF completed in 42.96s (11.22s queue); fresh first-returned LINKED was about 81.2s after Save. After a separate 56.4s outage the saved session recovered without reauthorization, and Contact Pay preparation took 5.54s. One sample each, not a statistical speedup or exact UI-frame measurement. Full comparison and remaining gaps: pubky/paykit-rs#171 (comment) . The later queued-delivery fix in 90177b5 is tested but not in these timing builds. Keeping this open; the 62-contact re-import and cold-start cases are not resolved by this run.

  24. piotr-iohk commented on Oct 7, 2026

    @piotr-iohk
    CollaboratorAuthor

    Android Stag8 import → delete → repeat-import checks on 804e754, published Paykit rc68 (2026-10-07).

    User-installed Bitkit 2.5.0 (190), staging Pubky/regtest/E2E hooks, Pixel 6 Android 13 emulator. Installed APK SHA256 9add8f767f04c95843a56c446c23b1e889a6fdac3a0a33802dbdd28b69d36415 matches the local dev universal artifact at that HEAD; no embedded commit metadata independently verified. Stag8: pubkyfhbjpghs4y6uiwni1sx5u9q3mynkr65ut66q485f4n4n45rxkymy, exact same 62 followed contacts as earlier Stag6/Stag7 fixtures.

    Case Ring → preview Import All → Continue Continue → profile
    Initial import ≤63.20s* 3.13s 18.43s
    Re-import after immediate deletion 24.53s 3.14s 15.02s
    Re-import after delayed deletion 103.51s 5.78s 22.51s

    *Initial preview timing polling was interrupted by a transient Android layout parser failure; 63.20s is a recovered observation upper bound, not a precise duration. Import was not retried. All timings include UI dump polling overhead.

    Deletion Contacts removed Paykit session removed Onboarding visible
    During active preparation 6.54s 16.00s 20.56s
    Delayed, with preparation/retries still active 4.66s 15.27s 17.34s

    Immediate deletion confirmed 16.66s after profile was observed (Android UI dump/navigation/log collection overhead); preparation warnings immediately before/after prove the requested overlap. Initial import logged 62 contacts saved, with two profile fetch transport warnings (placeholder profiles), but no contact-import failure.

    For the second case, the main preparation job was observed null at 08:05:40.782 UTC, then reappeared. After another 5m17.771s, preparation remained active for 62 peers / retry queue with 62 peers. Following the user's five-minute fallback instruction, deletion was confirmed 08:11:39.841 UTC, 8m59.439s after contacts saved. This is a successful delayed deletion with background work still active, not a strict settled-deletion pass. Missing signed Paykit Noise authorization for many fixture contacts and private-endpoint preparation warnings persisted. The fully idle trigger was never achieved.

    After delayed deletion, Contacts showed the empty DynamicContacts intro, the profile was signed out, and the wallet retained 100,000 sats Savings / 0 Spending. Final re-import imported 62 again and leaves Stag8 imported. However, 45 contact profile resolutions timed out at 10s during preview, so many imported entries use placeholder metadata. The 103.51s preview delay and failed metadata resolution are an observation to investigate; this is not a clean metadata import pass. No payment was attempted. The previous multi-minute contact-save/rollback stall did not recur in these samples.

    Evidence: Android full-cycle logs, timings and screenshots. Immediate-phase results are separately locked with SHA256. Read-only JDWP field inspection was used to verify preparation/retry state; no app methods invoked, no VM pause; forwarding removed after each probe.

    Requested import/delete scope only; single samples, no full PR device coverage, no merge/release signoff. Strict idle deletion, remote-peer cleanup semantics, cold-start/restoration and payment journeys remain unverified.

    The cause of the final metadata timeouts is not established: staging/network conditions and app behavior still need to be distinguished. Missing authorization may be expected for contacts without Paykit enabled; whether the ongoing retries are expected also remains to be clarified. These observations can be tracked in separate follow-up tickets if appropriate.

  25. ben-kaufman commented on Oct 7, 2026

    @ben-kaufman
    Contributor

    Thanks, this separates the fixed contact-save/re-import stall from the remaining slow preview. The original 62-contact fixture completed all imports and both overlapping deletions on rc68, but the final 103.51s preview and 45 profile timeouts remain unresolved. Import All itself took 5.78s in that run. The evidence does not yet distinguish staging/network failures from app scheduling, so I would not attribute those timeouts to either side. Keeping metadata loading, ongoing preparation retries and strictly idle deletion open; this is not overall performance sign-off.

  26. modified the milestones: 2.6.0, 2.7.0 on Oct 14, 2026
  27. ovitrif commented on Oct 14, 2026

    @ovitrif
    Collaborator

    Moved to 2.7.0. The contact-save stall is fixed (#1395), and RC1 testing showed contact payments working; what remains is the slow import preview and profile timeouts, which are not yet attributed to the app or to staging, so this does not block 2.6.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions