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

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions