Sign the iOS app for real devices and stop bundling the static archives

This commit is contained in:
2026-09-19 19:25:01 +08:00
parent 6d50566f37
commit f4037a188a
2 changed files with 30 additions and 17 deletions
+24 -15
View File
@@ -9,16 +9,27 @@ enum SelfTest {
/// Writes to both stdout and the unified log so results are visible however /// Writes to both stdout and the unified log so results are visible however
/// the app was launched. /// the app was launched.
private static var report: [String] = []
private static func emit(_ line: String) { private static func emit(_ line: String) {
print(line) print(line)
os_log("%{public}@", log: log, type: .default, line) os_log("%{public}@", log: log, type: .default, line)
report.append(line)
}
/// Writes the collected lines into the app container so the result can be
/// read back off the device (console output is not always reachable).
private static func flushReport() {
guard let documents = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let url = documents.appendingPathComponent("koins-selftest.txt")
try? report.joined(separator: "\n").write(to: url, atomically: true, encoding: .utf8)
} }
static func runIfRequested() { static func runIfRequested() {
if ProcessInfo.processInfo.arguments.contains("-koinsSelfTest") { if ProcessInfo.processInfo.arguments.contains("-koinsSelfTest") {
print("KOINS_SELFTEST begin") emit("KOINS_SELFTEST begin")
run() run()
print("KOINS_SELFTEST end") emit("KOINS_SELFTEST end")
} }
if ProcessInfo.processInfo.arguments.contains("-koinsSelfTestNetwork") { if ProcessInfo.processInfo.arguments.contains("-koinsSelfTestNetwork") {
runNetwork() runNetwork()
@@ -88,6 +99,7 @@ enum SelfTest {
restoreWallets() restoreWallets()
emit("KOINS_NET end") emit("KOINS_NET end")
flushReport()
} }
} }
@@ -97,9 +109,7 @@ enum SelfTest {
func expect(_ name: String, _ actual: String, _ wanted: String) { func expect(_ name: String, _ actual: String, _ wanted: String) {
let ok = actual.lowercased() == wanted.lowercased() let ok = actual.lowercased() == wanted.lowercased()
if !ok { failures += 1 } if !ok { failures += 1 }
let line = "KOINS_SELFTEST \(name): \(ok ? "PASS" : "FAIL") \(actual)" emit("KOINS_SELFTEST \(name): \(ok ? "PASS" : "FAIL") \(actual)")
print(line)
os_log("%{public}@", log: log, type: .default, line)
} }
expect("ripemd160", Hex.encode(RIPEMD160.hash(Array("abc".utf8))), expect("ripemd160", Hex.encode(RIPEMD160.hash(Array("abc".utf8))),
@@ -114,7 +124,7 @@ enum SelfTest {
expect("ed25519 address", keypair.address, edAddress) expect("ed25519 address", keypair.address, edAddress)
} else { } else {
failures += 1 failures += 1
print("KOINS_SELFTEST ed25519: FAIL keypair threw") emit("KOINS_SELFTEST ed25519: FAIL keypair threw")
} }
// secp256k1 vector: exercises the OpenSSL-backed derivation on device. // secp256k1 vector: exercises the OpenSSL-backed derivation on device.
@@ -128,7 +138,7 @@ enum SelfTest {
expect("secp256k1 address", keypair.address, secpAddress) expect("secp256k1 address", keypair.address, secpAddress)
} catch { } catch {
failures += 1 failures += 1
print("KOINS_SELFTEST secp256k1: FAIL \(error)") emit("KOINS_SELFTEST secp256k1: FAIL \(error)")
} }
// Serialization + hashing reference vector. // Serialization + hashing reference vector.
@@ -189,12 +199,12 @@ enum SelfTest {
expect("bip32 level \(level)", Hex.encode(child.privateKey), expected) expect("bip32 level \(level)", Hex.encode(child.privateKey), expected)
} else { } else {
failures += 1 failures += 1
print("KOINS_SELFTEST bip32 level \(level): FAIL derivation returned nil") emit("KOINS_SELFTEST bip32 level \(level): FAIL derivation returned nil")
} }
} }
} else { } else {
failures += 1 failures += 1
print("KOINS_SELFTEST bip32 master: FAIL") emit("KOINS_SELFTEST bip32 master: FAIL")
} }
let mnemonicCases: [(String, String, String)] = [ let mnemonicCases: [(String, String, String)] = [
@@ -212,7 +222,7 @@ enum SelfTest {
expect("bip44 address #\(position)", keypair.address, vector.2) expect("bip44 address #\(position)", keypair.address, vector.2)
} catch { } catch {
failures += 1 failures += 1
print("KOINS_SELFTEST bip44 #\(position): FAIL \(error)") emit("KOINS_SELFTEST bip44 #\(position): FAIL \(error)")
} }
} }
@@ -227,15 +237,14 @@ enum SelfTest {
let s = DER.signatureScalar(signature) { let s = DER.signatureScalar(signature) {
expect("secp256k1 signature is low-S", s.lessThanOrEqual(half) ? "yes" : "no", "yes") expect("secp256k1 signature is low-S", s.lessThanOrEqual(half) ? "yes" : "no", "yes")
} }
print("KOINS_SELFTEST secp256k1 signature len: \(signature.count)") emit("KOINS_SELFTEST secp256k1 signature len: \(signature.count)")
} else { } else {
failures += 1 failures += 1
print("KOINS_SELFTEST secp256k1 sign: FAIL") emit("KOINS_SELFTEST secp256k1 sign: FAIL")
} }
let summary = "KOINS_SELFTEST summary: \(failures == 0 ? "ALL PASS" : "\(failures) FAILURE(S)")" emit("KOINS_SELFTEST summary: \(failures == 0 ? "ALL PASS" : "\(failures) FAILURE(S)")")
print(summary) flushReport()
os_log("%{public}@", log: log, type: .default, summary)
} }
} }
+6 -2
View File
@@ -18,13 +18,17 @@ targets:
type: application type: application
platform: iOS platform: iOS
sources: sources:
- Koins - path: Koins
excludes:
# Static archives are linked via LIBRARY_SEARCH_PATHS, not bundled.
- "Monero/libs"
settings: settings:
base: base:
PRODUCT_BUNDLE_IDENTIFIER: com.koins.app PRODUCT_BUNDLE_IDENTIFIER: com.koins.app
INFOPLIST_FILE: Koins/Info.plist INFOPLIST_FILE: Koins/Info.plist
CODE_SIGN_STYLE: Automatic CODE_SIGN_STYLE: Automatic
CODE_SIGNING_ALLOWED: NO DEVELOPMENT_TEAM: RX6767S6BW
CODE_SIGNING_ALLOWED[sdk=iphonesimulator*]: NO
SWIFT_OBJC_BRIDGING_HEADER: Koins/Bridge/Koins-Bridging-Header.h SWIFT_OBJC_BRIDGING_HEADER: Koins/Bridge/Koins-Bridging-Header.h
OTHER_LDFLAGS[sdk=iphoneos*]: OTHER_LDFLAGS[sdk=iphoneos*]:
- "$(inherited)" - "$(inherited)"