Skip to content

Add weekly background Kyoto CBF sync task (#352)#354

Open
Aniket-pd wants to merge 3 commits intobitcoindevkit:mainfrom
Aniket-pd:352-background-cbf-sync
Open

Add weekly background Kyoto CBF sync task (#352)#354
Aniket-pd wants to merge 3 commits intobitcoindevkit:mainfrom
Aniket-pd:352-background-cbf-sync

Conversation

@Aniket-pd
Copy link

Description

This PR implements the background CBF sync flow discussed in #352.

In short, the app now registers a BGProcessingTask and schedules it to run roughly once a week (with network + external power requirements). When the task runs, it attempts to load the wallet and perform a Kyoto sync if the wallet exists and Kyoto is the selected backend.

I also added the required Info.plist entries for background processing and updated keychain accessibility to .afterFirstUnlock so background execution can still read wallet backup data while the device is locked.

Notes to the reviewers

I kept this intentionally narrow to the core pieces needed for background sync:

  • task registration/scheduling,
  • task execution path,
  • plist configuration,
  • keychain accessibility prerequisite.

I did not add product-level logging in this PR, since #351 tracks that separately.

Changelog notice

Add weekly background Kyoto CBF sync using BGProcessingTask, including required background task configuration and keychain access changes needed for locked-device execution.

Checklists

All Submissions:

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature
  • UI changes tested on small, medium, and large devices to ensure layout consistency

Bugfixes:

  • This pull request breaks the existing API
  • I've added tests to reproduce the issue which are now passing
  • I'm linking the issue being fixed by this PR

@r1b2ns
Copy link
Collaborator

r1b2ns commented Feb 20, 2026

Hi @Aniket-pd, I’m trying to review this PR but I’m running into a crash during kyoto sync. Have you ever seen this issue?

`[Kyoto] Preparing CBF components – network: signet, dataDir: /Users/rubensmachion/Library/Developer/CoreSimulator/Devices/5D32E5C5-1662-4F90-966F-55371A6EAF07/data/Containers/Data/Application/648B220A-17C8-4CA5-9431-5539C1598899/Documents/wallet_data/kyoto, peers: 2, scanType: recovery(usedScriptIndex: 1000, checkpoint: BitcoinDevKit.RecoveryPoint.taprootActivation)

thread '' panicked at /Users/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bdk_kyoto-0.15.3/src/lib.rs:160:43:
there is no reactor running, must be called from the context of a Tokio 1.x runtime
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace
CoreSimulator 1051.9.4 - Device: iPhone 17 (5D32E5C5-1662-4F90-966F-55371A6EAF07) - Runtime: iOS 26.1 (23B86) - DeviceType: iPhone 17

Can't show file for stack frame : <DBGLLDBStackFrame: 0x93f04e800> - stackNumber:3 - name:panic_abort::__rust_start_panic::abort::h158a95d7d8b6f370. The file path does not exist on the file system: /rustc/4eb161250e340c8f48f66e2b929ef4a5bed7c181/library/panic_abort/src/lib.rs`

@reez
Copy link
Collaborator

reez commented Feb 20, 2026

just fyi, android saw a crash (I dont know where crash logs are so im not able to compare to know if this is same crash as that) on kyoto in bdk-ffi 2.3.0, so there will be an upcoming 2.3.1 patch release with kyoto patch bitcoindevkit/bdk-ffi#953

@Aniket-pd
Copy link
Author

Thanks for testing and reporting this crash.
I’ll pause this PR until the upstream Kyoto crash fix is released through bdk-swift (maintainer referenced upcoming bdk-ffi 2.3.1 patch). Once available, I’ll bump the dependency in this PR, rerun Kyoto sync validation, and update here.

@r1b2ns
Copy link
Collaborator

r1b2ns commented Feb 21, 2026

Nice!!! Tks guys

@reez
Copy link
Collaborator

reez commented Feb 25, 2026

just cc'ing @rustaceanrob , no pressure for him to check it out or review, but he opened up the Issue (and is the brains behind kyoto) so if he wanted to weigh in on this just want him to have viz

@rustaceanrob
Copy link
Contributor

Will review when 2.3.1 is released but looks great at first glance

let request = BGProcessingTaskRequest(identifier: identifier)
request.requiresNetworkConnectivity = true
request.requiresExternalPower = true
request.earliestBeginDate = Date(timeIntervalSinceNow: minimumInterval)
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps we could be a bit stricter here and target around 2am. It's possible the user may be charging and at home, however they are using their phone to watch a movie or similar. In this case we don't want to take CPU time

@reez
Copy link
Collaborator

reez commented Feb 26, 2026

just published http://github.com/bitcoindevkit/bdk-swift/releases/tag/2.3.1 if anyone wants to test on this branch

@Aniket-pd
Copy link
Author

I updated this branch to bdk-swift 2.3.1.

Validation on my side:

  • project builds successfully
  • full XCTest suite passes on iPhone 16 simulator

I haven’t added an automated reproduction for the Kyoto runtime path, but the branch is now using the upstream patch release and is ready for another round of review/testing

Copy link
Collaborator

@reez reez left a comment

Choose a reason for hiding this comment

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

I haven't tested this on device yet, but this is coming along nicely and the approach looks solid so thanks for this PR, added one comment

}
}

task.expirationHandler = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Im seeing expirationHandler currently only calls syncTask.cancel() and never explicitly calls task.setTaskCompleted(success:). Apple’s BGTask contract expects expiration handlers to cancel work and then mark the task complete otherwise the app can be terminated for overrunning background time. Also the polling path may not stop promptly from Swift task cancellation alone, so cancel() might not be enough here?

@Aniket-pd
Copy link
Author

Great catch, thanks. I’ll update the handler so expiration cancels work and explicitly calls setTaskCompleted(success: false), with a one-time completion guard to avoid double completion if the async task returns later.

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.

4 participants