Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,7 @@ fastlane/test_output
iOSInjectionProject/

# Tuist
**/Derived/*
**/Derived/*

# mcp
.mcp_data/
106 changes: 86 additions & 20 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,25 @@

import PackageDescription

let moduleDefines: [(trait: String, define: String)] = [
("ecdh", "ENABLE_MODULE_ECDH"),
("ellswift", "ENABLE_MODULE_ELLSWIFT"),
("musig", "ENABLE_MODULE_MUSIG"),
("recovery", "ENABLE_MODULE_RECOVERY"),
("schnorrsig", "ENABLE_MODULE_SCHNORRSIG")
]

let zkpModuleDefines: [(trait: String, define: String)] = [
("bppp", "ENABLE_MODULE_BPPP"),
("ecdsaAdaptor", "ENABLE_MODULE_ECDSA_ADAPTOR"),
("ecdsaS2C", "ENABLE_MODULE_ECDSA_S2C"),
("generator", "ENABLE_MODULE_GENERATOR"),
("rangeproof", "ENABLE_MODULE_RANGEPROOF"),
("schnorrsigHalfagg", "ENABLE_MODULE_SCHNORRSIG_HALFAGG"),
("surjectionproof", "ENABLE_MODULE_SURJECTIONPROOF"),
("whitelist", "ENABLE_MODULE_WHITELIST")
]

let package = Package(
name: "swift-secp256k1",
products: [
Expand All @@ -11,6 +30,26 @@ let package = Package(
.library(name: "P256K", targets: ["P256K"]),
.library(name: "ZKP", targets: ["ZKP"])
],
traits: [
.default(enabledTraits: ["ecdh", "musig", "recovery", "schnorrsig"]),
.trait(name: "ecdh"),
.trait(name: "ellswift"),
.trait(name: "recovery"),
.trait(name: "schnorrsig"),
.trait(name: "musig", enabledTraits: ["schnorrsig"]),
.trait(name: "bppp"),
.trait(name: "ecdsaAdaptor"),
.trait(name: "ecdsaS2C"),
.trait(name: "generator"),
.trait(name: "rangeproof"),
.trait(name: "schnorrsigHalfagg"),
.trait(name: "surjectionproof"),
.trait(name: "whitelist"),
.trait(name: "zkp", enabledTraits: [
"bppp", "ecdsaAdaptor", "ecdsaS2C", "ellswift", "generator",
"rangeproof", "schnorrsigHalfagg", "surjectionproof", "whitelist"
])
],
dependencies: [
// Dependencies used for package development
.package(url: "https://github.com/csjones/lefthook-plugin.git", exact: "2.1.2"),
Expand All @@ -32,48 +71,75 @@ let package = Package(
.target(
name: "P256K",
dependencies: ["libsecp256k1"],
swiftSettings: PackageDescription.SwiftSetting.moduleSettings,
plugins: ["SharedSourcesPlugin"]
),
.target(
name: "ZKP",
dependencies: ["libsecp256k1_zkp"],
swiftSettings: PackageDescription.SwiftSetting.moduleSettings
+ PackageDescription.SwiftSetting.zkpModuleSettings,
plugins: ["SharedSourcesPlugin"]
),
.target(
name: "libsecp256k1",
cSettings: PackageDescription.CSetting.baseSettings
+ PackageDescription.CSetting.moduleSettings
),
.target(
name: "libsecp256k1_zkp",
cSettings: PackageDescription.CSetting.baseSettings + [
.define("ENABLE_MODULE_BPPP"),
.define("ENABLE_MODULE_ECDSA_ADAPTOR"),
.define("ENABLE_MODULE_ECDSA_S2C"),
.define("ENABLE_MODULE_GENERATOR"),
.define("ENABLE_MODULE_RANGEPROOF"),
.define("ENABLE_MODULE_SCHNORRSIG_HALFAGG"),
.define("ENABLE_MODULE_SURJECTIONPROOF"),
.define("ENABLE_MODULE_WHITELIST")
]
cSettings: PackageDescription.CSetting.baseSettings
+ PackageDescription.CSetting.moduleSettings
+ PackageDescription.CSetting.zkpModuleSettings
),
.testTarget(
name: "libsecp256k1zkpTests",
dependencies: ["ZKP", "libsecp256k1_zkp"],
swiftSettings: PackageDescription.SwiftSetting.moduleSettings
+ PackageDescription.SwiftSetting.zkpModuleSettings
),
.testTarget(name: "libsecp256k1zkpTests", dependencies: ["ZKP", "libsecp256k1_zkp"]),
.testTarget(name: "ZKPTests", dependencies: ["ZKP"])
.testTarget(
name: "ZKPTests",
dependencies: ["ZKP"],
swiftSettings: PackageDescription.SwiftSetting.moduleSettings
+ PackageDescription.SwiftSetting.zkpModuleSettings
)
],
swiftLanguageModes: [.v6],
cLanguageStandard: .c89
)

extension PackageDescription.CSetting {
/// Basic config values that are universal and require no dependencies.
static let baseSettings: [Self] = [
// Basic config values that are universal and require no dependencies.
.define("ECMULT_GEN_PREC_BITS", to: "4"),
.define("ECMULT_WINDOW_SIZE", to: "15"),
// Enabling additional secp256k1 modules.
.define("ENABLE_MODULE_ECDH"),
.define("ENABLE_MODULE_ELLSWIFT"),
.define("ENABLE_MODULE_EXTRAKEYS"),
.define("ENABLE_MODULE_MUSIG"),
.define("ENABLE_MODULE_RECOVERY"),
.define("ENABLE_MODULE_SCHNORRSIG")
.define("ENABLE_MODULE_EXTRAKEYS")
]

/// Trait-conditional settings for secp256k1 modules.
static let moduleSettings: [Self] = moduleDefines.map {
.define($0.define, .when(traits: [$0.trait]))
}

/// Trait-conditional settings for ZKP-only modules.
static let zkpModuleSettings: [Self] = zkpModuleDefines.map {
.define($0.define, .when(traits: [$0.trait]))
}
}

extension PackageDescription.SwiftSetting {
/// Trait-conditional settings for secp256k1 modules.
///
/// - Note: Xcode does not resolve `.when(traits:)` conditions for Swift settings,
/// so Swift source files use `#if Xcode || ENABLE_MODULE_*` guards as a workaround.
/// Xcode automatically defines `Xcode` in all Swift compilations.
static let moduleSettings: [Self] = moduleDefines.map {
.define($0.define, .when(traits: [$0.trait]))
}

/// Trait-conditional settings for ZKP-only modules.
static let zkpModuleSettings: [Self] = zkpModuleDefines.map {
.define($0.define, .when(traits: [$0.trait]))
}
}
8 changes: 6 additions & 2 deletions Projects/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ let project = Project(
settings: .settings(
configurations: [
.debug(name: "Debug", xcconfig: "Resources/Project/Debug.xcconfig"),
.debug(name: "Release", xcconfig: "Resources/Project/Release.xcconfig")
.release(name: "Release", xcconfig: "Resources/Project/Release.xcconfig")
]
),
targets: [
Expand All @@ -33,6 +33,7 @@ let project = Project(
],
settings: .settings(
base: [
"SWIFT_ACTIVE_COMPILATION_CONDITIONS": "$(inherited) Xcode",
"BUILD_LIBRARY_FOR_DISTRIBUTION": "YES",
"MACOSX_DEPLOYMENT_TARGET": "13.0"
],
Expand Down Expand Up @@ -67,7 +68,10 @@ let project = Project(
bundleId: "dev.21.BindingsTests",
deploymentTargets: deploymentTargets,
sources: ["Sources/BindingsTests/**"],
dependencies: [.package(product: "libsecp256k1")],
dependencies: [
.target(name: "P256K"),
.package(product: "libsecp256k1")
],
settings: .settings(
configurations: [
.debug(name: "Debug", xcconfig: "Resources/BindingsTests/Debug.xcconfig"),
Expand Down
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,35 @@ Use [SPI Playgrounds app](https://swiftpackageindex.com/try-in-a-playground):
arena 21-DOT-DEV/swift-secp256k1
```

## Package Traits

This package uses [SE-0450 Package Traits](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0450-swiftpm-package-traits.md) (Swift 6.1+) to enable fine-grained module selection. By default, the following traits are enabled: `ecdh`, `musig`, `recovery`, and `schnorrsig`.

To use only specific modules, specify traits in your dependency:

```swift
.package(
url: "https://github.com/21-DOT-DEV/swift-secp256k1",
from: "0.21.1",
traits: ["schnorrsig"]
),
```

To enable all ZKP modules, use the `zkp` bundle trait:

```swift
.package(
url: "https://github.com/21-DOT-DEV/swift-secp256k1",
from: "0.21.1",
traits: ["zkp"]
),
```

Available traits: `ecdh`, `ellswift`, `musig`, `recovery`, `schnorrsig`, `bppp`, `ecdsaAdaptor`, `ecdsaS2C`, `generator`, `rangeproof`, `schnorrsigHalfagg`, `surjectionproof`, `whitelist`, `zkp`.

> [!NOTE]
> Xcode does not currently resolve SwiftPM package trait conditions for Swift settings. As a workaround, all optional modules are compiled when building in Xcode. Package traits are fully supported when building with `swift build` from the command line.

## Swift Versions

| swift-secp256k1 | Minimum Swift Version | Minimum Xcode Version |
Expand Down
Loading