Skip to content

Migrate swift-secp256k1 to the P256K module (0.17.0 → 0.23.x) #659

Description

@jvsena42

Split out of #657, where the dependabot bump to 0.23.2 broke CI. Details in #657 (comment)swift-secp256k1 was reverted to 0.17.0 there so the CodeScanner and Lottie bumps could land.

Problem

0.23.2 renames the secp256k1 product to P256K and moves the raw C API into a separate libsecp256k1 product that the Swift wrapper imports internally rather than re-exporting. Bumping Package.resolved alone fails the project load on every target:

Bitkit.xcodeproj: error: Missing package product 'secp256k1'
  (in targets 'Bitkit', 'BitkitTests', 'BitkitNotification')

Required changes

  • Add both P256K and libsecp256k1 as product dependencies on Bitkit, BitkitTests and BitkitNotification, and bump the package requirement minimumVersion (dependabot leaves it at 0.17.0, a version that no longer vends the product)
  • Crypto.swift: import P256K for ECDH and libsecp256k1 for the C API (secp256k1_ecdsa_sign_recoverable, secp256k1_ec_pubkey_create); rename secp256k1.KeyAgreement.* to P256K.KeyAgreement.*. sharedSecretFromKeyAgreement is no longer throwing, so the try comes off
  • WatchOnlyAccountService.swift: import libsecp256k1 only — it uses just the C API
  • Add -skipPackagePluginValidation to every scripted xcodebuild invocation (unit-tests, integration-tests, e2e-tests ×2, e2e_migration, ai-device-tests, plus the build/archive commands in README.md, AGENTS.md, Docs/AI_DEVICE_TESTS.md, Docs/RELEASE.md, .agents/commands/release.md)

That last one is the easy one to miss: 0.23.2 also ships a SharedSourcesPlugin build-tool plugin, and xcodebuild refuses to run an untrusted plugin non-interactively. Xcode shows a one-time "Trust & Enable" prompt, so a local GUI build passes while CI fails with Validate plug-in "SharedSourcesPlugin" in package "swift-secp256k1". Worth a README troubleshooting entry.

Testing

This touches push-notification payload decryption and watch-only key parsing, so the migration should carry regression coverage for the paths that change modules. testBlocktankEncryptedPayload already pins ECDH to a known server vector, and testSerializedXpubRejectsWellFormedPayloadWithKeyOffTheCurve covers secp256k1_ec_pubkey_parse, but Crypto.getPublicKey and Crypto.sign have none. Suggested additions:

  • pin getPublicKey to private→compressed-pubkey vectors computed independently of the dependency (using privkey 0x01, whose answer is the curve generator, makes the vectors self-validating)
  • sign a Lightning message, then recover the signer's public key from the signature via P256K.Recovery and assert it matches getPublicKey — this catches a wrong recovery-id offset or a broken recovery module, which a length check alone would not

Notes

  • The package requires swift-tools 6.1 (Xcode 16.3+) and uses SwiftPM traits; CI runs Xcode 16.4
  • Dependabot will re-propose this bump monthly until the migration lands. If that becomes noisy, add a swift-secp256k1 ignore entry to .github/dependabot.yml in the meantime

A verified-green implementation of all of the above (build + 758 unit tests passing) was prototyped on #657 before the revert.

Metadata

Metadata

Assignees

No one assigned

    Labels

    dependenciesPull requests that update a dependency fileswift_package_managerPull requests that update swift_package_manager code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions