From 0ab9b0e4eeaf377930cf340b66fc1ba49dbfa714 Mon Sep 17 00:00:00 2001 From: Mark Xue Date: Wed, 19 Aug 2026 00:17:13 -0700 Subject: [PATCH 1/4] Run swift-format across the tree .swift-format already matched jxl-encoder-swift's config byte-for- byte but wasn't enforced anywhere. Reformatted (swift format format -i --recursive) and fixed the two real lint failures it surfaced: a snake_case constant (sha2_256 -> sha2256) and an over-length end-of-line comment in Point.swift, moved above the line. Co-Authored-By: Claude Sonnet 5 --- Sources/AtprotoTypesVerify/CAR/CARv1.swift | 3 +- .../ContentIdentifier.swift | 6 ++-- .../DAGCBOR/DAGCBORDecoder.swift | 3 +- Sources/AtprotoTypesVerify/ProofError.swift | 3 +- .../Signing/RepoSigningKey.swift | 12 ++++--- .../Signing/Secp256k1/ECDSA.swift | 15 ++++++--- .../Signing/Secp256k1/Field.swift | 8 +++-- .../Signing/Secp256k1/Limbs256.swift | 11 +++++-- .../Signing/Secp256k1/Point.swift | 19 +++++++++--- .../Signing/Secp256k1/Scalar.swift | 4 ++- .../AtprotoTypesVerifyMocks/RepoFixture.swift | 10 ++++-- .../DAGCBORTests.swift | 5 ++- .../MerkleSearchTreeTests.swift | 3 +- .../RepoProofVerifierTests.swift | 22 ++++++++++--- .../Secp256k1ECDSADifferentialTests.swift | 12 ++++--- .../Secp256k1FieldTests.swift | 31 ++++++++++++++----- .../Secp256k1PointTests.swift | 21 +++++++++---- .../Secp256k1ScalarTests.swift | 13 +++++--- .../Secp256k1WycheproofTests.swift | 29 ++++++++++++----- 19 files changed, 167 insertions(+), 63 deletions(-) diff --git a/Sources/AtprotoTypesVerify/CAR/CARv1.swift b/Sources/AtprotoTypesVerify/CAR/CARv1.swift index af5e230..953ae9e 100644 --- a/Sources/AtprotoTypesVerify/CAR/CARv1.swift +++ b/Sources/AtprotoTypesVerify/CAR/CARv1.swift @@ -43,7 +43,8 @@ public struct CARv1: Sendable { throw Atproto.Repo.ProofError.badCARHeader } guard version == 1 else { - throw Atproto.Repo.ProofError.unsupportedCARVersion(UInt64(clamping: version)) + throw Atproto.Repo.ProofError.unsupportedCARVersion( + UInt64(clamping: version)) } guard let rawRoots = header["roots"]?.arrayValue else { throw Atproto.Repo.ProofError.badCARHeader diff --git a/Sources/AtprotoTypesVerify/ContentIdentifier.swift b/Sources/AtprotoTypesVerify/ContentIdentifier.swift index dfa6ffc..4ffa203 100644 --- a/Sources/AtprotoTypesVerify/ContentIdentifier.swift +++ b/Sources/AtprotoTypesVerify/ContentIdentifier.swift @@ -24,7 +24,7 @@ public struct ContentIdentifier: Sendable, Hashable { } //multicodec sha2-256, and the only digest atproto uses - static let sha2_256: UInt64 = 0x12 + static let sha2256: UInt64 = 0x12 static let digestLength = 32 public let codec: Codec @@ -44,7 +44,7 @@ public struct ContentIdentifier: Sendable, Hashable { public var bytes: Data { var out = Self.varint(1) out += Self.varint(codec.rawValue) - out += Self.varint(Self.sha2_256) + out += Self.varint(Self.sha2256) out += Self.varint(UInt64(Self.digestLength)) out += digest return Data(out) @@ -86,7 +86,7 @@ public struct ContentIdentifier: Sendable, Hashable { } let hash = try reader.readUnsignedVarint() - guard hash == Self.sha2_256 else { + guard hash == Self.sha2256 else { throw Atproto.Repo.ProofError.unsupportedHash(hash) } diff --git a/Sources/AtprotoTypesVerify/DAGCBOR/DAGCBORDecoder.swift b/Sources/AtprotoTypesVerify/DAGCBOR/DAGCBORDecoder.swift index 2829c6f..d61c84b 100644 --- a/Sources/AtprotoTypesVerify/DAGCBOR/DAGCBORDecoder.swift +++ b/Sources/AtprotoTypesVerify/DAGCBOR/DAGCBORDecoder.swift @@ -114,7 +114,8 @@ public enum DAGCBORDecoder { throw Atproto.Repo.ProofError.duplicateMapKey(key) } guard canonicallyPrecedes(previousKey, key) else { - throw Atproto.Repo.ProofError.unorderedMapKeys(previousKey, key) + throw Atproto.Repo.ProofError.unorderedMapKeys( + previousKey, key) } } previousKey = key diff --git a/Sources/AtprotoTypesVerify/ProofError.swift b/Sources/AtprotoTypesVerify/ProofError.swift index 55dc642..c282127 100644 --- a/Sources/AtprotoTypesVerify/ProofError.swift +++ b/Sources/AtprotoTypesVerify/ProofError.swift @@ -91,7 +91,8 @@ extension Atproto.Repo { case .unsupportedSimpleValue(let v): "Unsupported CBOR simple value \(v)" case .nonStringMapKey: "DAG-CBOR map keys must be strings" case .duplicateMapKey(let k): "Duplicate map key \(k)" - case .unorderedMapKeys(let a, let b): "Map keys out of order: \(a) before \(b)" + case .unorderedMapKeys(let a, let b): + "Map keys out of order: \(a) before \(b)" case .badCIDLink: "Malformed CID link" case .invalidUTF8: "Invalid UTF-8 in text string" case .nestingTooDeep: "DAG-CBOR nesting too deep" diff --git a/Sources/AtprotoTypesVerify/Signing/RepoSigningKey.swift b/Sources/AtprotoTypesVerify/Signing/RepoSigningKey.swift index d59071b..f990561 100644 --- a/Sources/AtprotoTypesVerify/Signing/RepoSigningKey.swift +++ b/Sources/AtprotoTypesVerify/Signing/RepoSigningKey.swift @@ -101,7 +101,8 @@ public struct RepoSigningKey: Sendable { var reader = ByteReader(decoded) let code = try reader.readUnsignedVarint() guard let curve = Curve.named(code) else { - throw Atproto.Repo.ProofError.unsupportedCurve("multicodec 0x\(String(code, radix: 16))") + throw Atproto.Repo.ProofError.unsupportedCurve( + "multicodec 0x\(String(code, radix: 16))") } let pointLength = reader.remaining @@ -126,14 +127,16 @@ public struct RepoSigningKey: Sendable { case .secp256k1: //same low-S rule as p256, against this curve's own order — atproto //requires it network-wide, not just for the curve swift-crypto backs - guard Self.isLowS(Array(signature.suffix(32)), order: Self.secp256k1Order) else { + guard Self.isLowS(Array(signature.suffix(32)), order: Self.secp256k1Order) + else { throw Atproto.Repo.ProofError.nonCanonicalSignature } let digest = SHA256.hash(data: message) guard Secp256k1.ECDSA.verify( - signature: signature, digest: Data(digest), compressedPublicKey: compressedPoint) + signature: signature, digest: Data(digest), + compressedPublicKey: compressedPoint) else { throw Atproto.Repo.ProofError.signatureDidNotVerify } @@ -152,7 +155,8 @@ public struct RepoSigningKey: Sendable { key = try P256.Signing.PublicKey( compressedRepresentation: compressedPoint ) - parsed = try P256.Signing.ECDSASignature(rawRepresentation: signature) + parsed = try P256.Signing.ECDSASignature( + rawRepresentation: signature) } catch { throw Atproto.Repo.ProofError.badMultibaseKey } diff --git a/Sources/AtprotoTypesVerify/Signing/Secp256k1/ECDSA.swift b/Sources/AtprotoTypesVerify/Signing/Secp256k1/ECDSA.swift index 788ec67..0cd3b76 100644 --- a/Sources/AtprotoTypesVerify/Signing/Secp256k1/ECDSA.swift +++ b/Sources/AtprotoTypesVerify/Signing/Secp256k1/ECDSA.swift @@ -21,7 +21,8 @@ extension Secp256k1 { ///point at infinity all collapse to a plain refusal rather than a ///distinguished error, matching how Wycheproof's "other invalid" ///bucket expects these to be indistinguishable from a wrong signature. - static func verify(signature: Data, digest: Data, compressedPublicKey: Data) -> Bool { + static func verify(signature: Data, digest: Data, compressedPublicKey: Data) -> Bool + { //not reachable from `RepoSigningKey.verify` today (always a //32-byte SHA-256 output) — guarded anyway, because //`Scalar(reducingBigEndian:)` folds any other length to zero, @@ -30,13 +31,19 @@ extension Secp256k1 { //any t, R = t·G, r = R.x mod n, s = r·t⁻¹ mod n. guard digest.count == 32 else { return false } guard signature.count == 64 else { return false } - guard let r = Scalar(canonicalBigEndian: Array(signature.prefix(32))), !r.isZero else { + guard let r = Scalar(canonicalBigEndian: Array(signature.prefix(32))), + !r.isZero + else { return false } - guard let s = Scalar(canonicalBigEndian: Array(signature.suffix(32))), !s.isZero else { + guard let s = Scalar(canonicalBigEndian: Array(signature.suffix(32))), + !s.isZero + else { + return false + } + guard let publicKey = Point(compressed: compressedPublicKey) else { return false } - guard let publicKey = Point(compressed: compressedPublicKey) else { return false } let z = Scalar(reducingBigEndian: Array(digest)) let w = s.inverted diff --git a/Sources/AtprotoTypesVerify/Signing/Secp256k1/Field.swift b/Sources/AtprotoTypesVerify/Signing/Secp256k1/Field.swift index 729e0d5..569f348 100644 --- a/Sources/AtprotoTypesVerify/Signing/Secp256k1/Field.swift +++ b/Sources/AtprotoTypesVerify/Signing/Secp256k1/Field.swift @@ -94,7 +94,9 @@ extension Secp256k1 { } var negated: Field { - isZero ? self : Field(unchecked: Limbs256.subtracting(Self.modulus, value).0) + isZero + ? self + : Field(unchecked: Limbs256.subtracting(Self.modulus, value).0) } ///Folds a 512-bit product down using 2^256 ≡ 2^32 + 977 (mod p): each @@ -108,7 +110,9 @@ extension Secp256k1 { var buffer = wide var pass = 0 - while !(buffer[4] == 0 && buffer[5] == 0 && buffer[6] == 0 && buffer[7] == 0) { + while !(buffer[4] == 0 && buffer[5] == 0 && buffer[6] == 0 + && buffer[7] == 0) + { pass += 1 precondition(pass < 8, "field reduction did not converge") diff --git a/Sources/AtprotoTypesVerify/Signing/Secp256k1/Limbs256.swift b/Sources/AtprotoTypesVerify/Signing/Secp256k1/Limbs256.swift index 1dd2714..27cc5bd 100644 --- a/Sources/AtprotoTypesVerify/Signing/Secp256k1/Limbs256.swift +++ b/Sources/AtprotoTypesVerify/Signing/Secp256k1/Limbs256.swift @@ -106,12 +106,17 @@ extension Secp256k1 { ///believed so: a hand-fused add can undercount by exactly one in a ///narrow edge case (large product, both inputs already near ///`UInt64.max`), and that is not a bug a quick reading catches. - static func rippleAdd(_ value: UInt64, at position: Int, into accumulator: inout [UInt64]) { + static func rippleAdd( + _ value: UInt64, at position: Int, into accumulator: inout [UInt64] + ) { var carry = value var index = position while carry != 0 { - precondition(index < accumulator.count, "carry overflowed the accumulator") - let (sum, overflow) = accumulator[index].addingReportingOverflow(carry) + precondition( + index < accumulator.count, + "carry overflowed the accumulator") + let (sum, overflow) = accumulator[index].addingReportingOverflow( + carry) accumulator[index] = sum carry = overflow ? 1 : 0 index += 1 diff --git a/Sources/AtprotoTypesVerify/Signing/Secp256k1/Point.swift b/Sources/AtprotoTypesVerify/Signing/Secp256k1/Point.swift index c5f47df..b9ce3dc 100644 --- a/Sources/AtprotoTypesVerify/Signing/Secp256k1/Point.swift +++ b/Sources/AtprotoTypesVerify/Signing/Secp256k1/Point.swift @@ -42,10 +42,14 @@ extension Secp256k1 { static let generator: Point = { let x = Field( bigEndian: Array( - hex: "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"))! + hex: + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" + ))! let y = Field( bigEndian: Array( - hex: "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"))! + hex: + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8" + ))! return .jacobian(x: x, y: y, z: Field.one) }() @@ -53,8 +57,11 @@ extension Secp256k1 { ///Standard Jacobian doubling for a = 0 curves. func doubled() -> Point { - guard case .affinePoint(let x1, let y1, let z1) = self else { return .infinity } - if y1.isZero { return .infinity } //a point of order 2, which secp256k1 has none of except this degenerate input + guard case .affinePoint(let x1, let y1, let z1) = self else { + return .infinity + } + //a point of order 2, which secp256k1 has none of except this degenerate input + if y1.isZero { return .infinity } let a = x1.squared() let b = y1.squared() @@ -107,7 +114,9 @@ extension Secp256k1 { } var negated: Point { - guard case .affinePoint(let x, let y, let z) = self else { return .infinity } + guard case .affinePoint(let x, let y, let z) = self else { + return .infinity + } return .jacobian(x: x, y: y.negated, z: z) } diff --git a/Sources/AtprotoTypesVerify/Signing/Secp256k1/Scalar.swift b/Sources/AtprotoTypesVerify/Signing/Secp256k1/Scalar.swift index 769471c..a784049 100644 --- a/Sources/AtprotoTypesVerify/Signing/Secp256k1/Scalar.swift +++ b/Sources/AtprotoTypesVerify/Signing/Secp256k1/Scalar.swift @@ -92,7 +92,9 @@ extension Secp256k1 { var buffer = wide var pass = 0 - while !(buffer[4] == 0 && buffer[5] == 0 && buffer[6] == 0 && buffer[7] == 0) { + while !(buffer[4] == 0 && buffer[5] == 0 && buffer[6] == 0 + && buffer[7] == 0) + { pass += 1 precondition(pass < 12, "scalar reduction did not converge") diff --git a/Sources/AtprotoTypesVerifyMocks/RepoFixture.swift b/Sources/AtprotoTypesVerifyMocks/RepoFixture.swift index 2729526..5d53d1c 100644 --- a/Sources/AtprotoTypesVerifyMocks/RepoFixture.swift +++ b/Sources/AtprotoTypesVerifyMocks/RepoFixture.swift @@ -53,7 +53,9 @@ extension P256.Signing.PublicKey: RepoFixturePublicKey { extension P256.Signing.PrivateKey: RepoFixtureSigningKey { public func repoFixtureSignature(for message: Data) throws -> Data { - RepoFixture.lowS(try signature(for: message).rawRepresentation, order: RepoSigningKey.p256Order) + RepoFixture.lowS( + try signature(for: message).rawRepresentation, + order: RepoSigningKey.p256Order) } } @@ -129,7 +131,11 @@ public enum RepoFixture { .map([ ("k", .bytes(Data(key.dropFirst(shared)))), ("p", .integer(Int64(shared))), - ("t", subtrees[entry.key].map { DAGCBORValue.link($0) } ?? .null), + ( + "t", + subtrees[entry.key].map { DAGCBORValue.link($0) } + ?? .null + ), ("v", .link(entry.value)), ]) ) diff --git a/Tests/AtprotoTypesVerifyTests/DAGCBORTests.swift b/Tests/AtprotoTypesVerifyTests/DAGCBORTests.swift index d0ce4be..548281e 100644 --- a/Tests/AtprotoTypesVerifyTests/DAGCBORTests.swift +++ b/Tests/AtprotoTypesVerifyTests/DAGCBORTests.swift @@ -55,7 +55,10 @@ struct DAGCBORTests { let value = DAGCBORValue.map([ ("did", .string("did:plc:example")), ("rev", .string("3lbw")), - ("data", .link(try ContentIdentifier.compute(codec: .dagCBOR, block: Data()))), + ( + "data", + .link(try ContentIdentifier.compute(codec: .dagCBOR, block: Data())) + ), ("prev", .null), ("nested", .array([.integer(-1), .bytes(Data([0, 1, 2])), .bool(true)])), ("version", .integer(3)), diff --git a/Tests/AtprotoTypesVerifyTests/MerkleSearchTreeTests.swift b/Tests/AtprotoTypesVerifyTests/MerkleSearchTreeTests.swift index 98188e7..52b9901 100644 --- a/Tests/AtprotoTypesVerifyTests/MerkleSearchTreeTests.swift +++ b/Tests/AtprotoTypesVerifyTests/MerkleSearchTreeTests.swift @@ -72,7 +72,8 @@ struct MerkleSearchTreeTests { for (key, expected) in tree.values { #expect( - try MerkleSearchTree.find(key: key, root: tree.root, in: tree.archive) + try MerkleSearchTree.find( + key: key, root: tree.root, in: tree.archive) == expected, "looking up \(key)" ) diff --git a/Tests/AtprotoTypesVerifyTests/RepoProofVerifierTests.swift b/Tests/AtprotoTypesVerifyTests/RepoProofVerifierTests.swift index 3255cc5..8cd05ab 100644 --- a/Tests/AtprotoTypesVerifyTests/RepoProofVerifierTests.swift +++ b/Tests/AtprotoTypesVerifyTests/RepoProofVerifierTests.swift @@ -60,9 +60,16 @@ struct RepoProofVerifierTests { ) if let mutateSignature, let existing = commit["sig"]?.bytesValue { commit = commit.removing(key: "sig") - guard case .map(let fields) = commit else { fatalError("unreachable") } + guard case .map(let fields) = commit else { + fatalError("unreachable") + } commit = .map( - fields + [(key: "sig", value: .bytes(mutateSignature(existing)))] + fields + [ + ( + key: "sig", + value: .bytes(mutateSignature(existing)) + ) + ] ) } let commitBlock = try RepoFixture.block(commit) @@ -272,13 +279,18 @@ struct RepoProofVerifierTests { let node = try RepoFixture.block( RepoFixture.node( entries: [ - (key: RepoProofVerifierTests.path.mstKey, value: recordBlock.cid) + ( + key: RepoProofVerifierTests.path.mstKey, + value: recordBlock.cid + ) ] ) ) - let commit = try RepoFixture.commit(did: did, dataRoot: node.cid, signedBy: signer) + let commit = try RepoFixture.commit( + did: did, dataRoot: node.cid, signedBy: signer) let commitBlock = try RepoFixture.block(commit) - return RepoFixture.car(root: commitBlock.cid, blocks: [recordBlock, node, commitBlock]) + return RepoFixture.car( + root: commitBlock.cid, blocks: [recordBlock, node, commitBlock]) } func document() throws -> Atproto.DIDDocument { diff --git a/Tests/AtprotoTypesVerifyTests/Secp256k1ECDSADifferentialTests.swift b/Tests/AtprotoTypesVerifyTests/Secp256k1ECDSADifferentialTests.swift index 36d5425..7eeb8f9 100644 --- a/Tests/AtprotoTypesVerifyTests/Secp256k1ECDSADifferentialTests.swift +++ b/Tests/AtprotoTypesVerifyTests/Secp256k1ECDSADifferentialTests.swift @@ -41,12 +41,14 @@ struct Secp256k1ECDSADifferentialTests { let signature = key.signature(for: message).compactRepresentation let oracleAccepts = key.publicKey.isValidSignature( - try P256K.Signing.ECDSASignature(compactRepresentation: signature), for: message) + try P256K.Signing.ECDSASignature(compactRepresentation: signature), + for: message) #expect(oracleAccepts) //sanity: P256K agrees with itself let digest = Crypto.SHA256.hash(data: message) let oursAccepts = Secp256k1.ECDSA.verify( - signature: signature, digest: Data(digest), compressedPublicKey: publicKeyBytes) + signature: signature, digest: Data(digest), + compressedPublicKey: publicKeyBytes) #expect(oursAccepts) } } @@ -92,9 +94,11 @@ struct Secp256k1ECDSADifferentialTests { if let parsedSignature = try? P256K.Signing.ECDSASignature( compactRepresentation: testCase.signature), let parsedKey = try? P256K.Signing.PublicKey( - dataRepresentation: testCase.key, format: .compressed) + dataRepresentation: testCase.key, + format: .compressed) { - parsedKey.isValidSignature(parsedSignature, for: testCase.message) + parsedKey.isValidSignature( + parsedSignature, for: testCase.message) } else { false } diff --git a/Tests/AtprotoTypesVerifyTests/Secp256k1FieldTests.swift b/Tests/AtprotoTypesVerifyTests/Secp256k1FieldTests.swift index a701ed4..40b1b5d 100644 --- a/Tests/AtprotoTypesVerifyTests/Secp256k1FieldTests.swift +++ b/Tests/AtprotoTypesVerifyTests/Secp256k1FieldTests.swift @@ -45,7 +45,8 @@ struct Secp256k1FieldTests { @Test("0 - 1 == p - 1") func subtractionUnderflowsCorrectly() { let direct = Field.zero - Field.one - let expected = Self.field("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E") + let expected = Self.field( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E") #expect(direct == expected) } @@ -67,7 +68,8 @@ struct Secp256k1FieldTests { ///drop a carry. @Test("multiplying two near-maximal field elements does not lose a carry") func multiplicationOfLargeValuesRoundTrips() { - let pMinus1 = Self.field("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E") + let pMinus1 = Self.field( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E") let product = pMinus1 * pMinus1 //p-1 ≡ -1 (mod p), so (p-1)^2 ≡ (-1)^2 == 1 #expect(product == Field.one) @@ -75,7 +77,8 @@ struct Secp256k1FieldTests { //a second, less degenerate near-maximal case: p-2 ≡ -2, so //(p-2)^2 ≡ 4 — a non-trivial answer a dropped carry is less likely //to accidentally still land on - let pMinus2 = Self.field("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2D") + let pMinus2 = Self.field( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2D") #expect(pMinus2 * pMinus2 == Self.small(4)) } @@ -93,7 +96,8 @@ struct Secp256k1FieldTests { @Test("square root: sqrt(a^2) squares back to a^2") func squareRootRoundTrips() throws { - let value = Self.field("0000000000000000000000000000000000000000000000000000000000000005") + let value = Self.field( + "0000000000000000000000000000000000000000000000000000000000000005") let squared = value.squared() let root = try #require(squared.squareRoot) #expect(root.squared() == squared) @@ -103,13 +107,26 @@ struct Secp256k1FieldTests { func squareRootOfNonResidueIsNil() { //3 is a quadratic non-residue mod secp256k1's p (p ≡ 3 mod 4, and 3's //Legendre symbol here is -1 — verified against a reference computation) - let three = Self.field("0000000000000000000000000000000000000000000000000000000000000003") + let three = Self.field( + "0000000000000000000000000000000000000000000000000000000000000003") #expect(three.squareRoot == nil) } @Test("canonical init rejects a value equal to or above the modulus") func rejectsNonCanonicalValues() { - #expect(Field(bigEndian: Array(Data(hex: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"))) == nil) //== p - #expect(Field(bigEndian: Array(Data(hex: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"))) == nil) //> p + #expect( + Field( + bigEndian: Array( + Data( + hex: + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F" + ))) == nil) //== p + #expect( + Field( + bigEndian: Array( + Data( + hex: + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + ))) == nil) //> p } } diff --git a/Tests/AtprotoTypesVerifyTests/Secp256k1PointTests.swift b/Tests/AtprotoTypesVerifyTests/Secp256k1PointTests.swift index b75a75e..f3d03c8 100644 --- a/Tests/AtprotoTypesVerifyTests/Secp256k1PointTests.swift +++ b/Tests/AtprotoTypesVerifyTests/Secp256k1PointTests.swift @@ -41,11 +41,13 @@ struct Secp256k1PointTests { #expect( x == Self.field( - "C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5")) + "C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5" + )) #expect( y == Self.field( - "1AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A")) + "1AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A" + )) //routed through addition and through scalar multiplication too, since //doubling is a distinct code path from both @@ -65,11 +67,13 @@ struct Secp256k1PointTests { #expect( x == Self.field( - "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9")) + "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9" + )) #expect( y == Self.field( - "388F7B0F632DE8140FE337E62A37F3566500A99934C2231B6CB9FD7584B8E672")) + "388F7B0F632DE8140FE337E62A37F3566500A99934C2231B6CB9FD7584B8E672" + )) let viaMultiply = Point.generator.multiplied(by: Self.scalar(3)) #expect(viaMultiply.affine?.x == x) @@ -109,7 +113,10 @@ struct Secp256k1PointTests { func scalarMultiplicationByOrderMinusOneNegatesTheGenerator() throws { let nMinus1 = Scalar( canonicalBigEndian: Array( - Data(hex: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140")))! + Data( + hex: + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140" + )))! let result = try #require(Point.generator.multiplied(by: nMinus1).affine) let expected = try #require(Point.generator.negated.affine) #expect(result.x == expected.x) @@ -161,7 +168,9 @@ struct Secp256k1PointTests { var compressed = Data([0x02]) compressed.append( contentsOf: Data( - hex: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F")) //== p + hex: + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F" + )) //== p #expect(Point(compressed: compressed) == nil) } diff --git a/Tests/AtprotoTypesVerifyTests/Secp256k1ScalarTests.swift b/Tests/AtprotoTypesVerifyTests/Secp256k1ScalarTests.swift index 30c4c7e..89e3411 100644 --- a/Tests/AtprotoTypesVerifyTests/Secp256k1ScalarTests.swift +++ b/Tests/AtprotoTypesVerifyTests/Secp256k1ScalarTests.swift @@ -34,7 +34,8 @@ struct Secp256k1ScalarTests { @Test("n - 1 + 1 wraps to zero") func wrapsAtOrder() { - let nMinus1 = Self.scalar("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140") + let nMinus1 = Self.scalar( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140") #expect(Self.adding(nMinus1, Scalar.one) == Scalar.zero) } @@ -61,10 +62,12 @@ struct Secp256k1ScalarTests { ///constant is a different opportunity to drop a carry across more limbs. @Test("multiplying two near-maximal scalars does not lose a carry") func multiplicationOfLargeValuesRoundTrips() { - let nMinus1 = Self.scalar("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140") + let nMinus1 = Self.scalar( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140") #expect(nMinus1 * nMinus1 == Scalar.one) //(-1)^2 == 1 - let nMinus2 = Self.scalar("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413F") + let nMinus2 = Self.scalar( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413F") #expect(nMinus2 * nMinus2 == Self.small(4)) //(-2)^2 == 4 } @@ -102,7 +105,9 @@ struct Secp256k1ScalarTests { Scalar( canonicalBigEndian: Array( Data( - hex: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141")) + hex: + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141" + )) ) == nil) //== n } } diff --git a/Tests/AtprotoTypesVerifyTests/Secp256k1WycheproofTests.swift b/Tests/AtprotoTypesVerifyTests/Secp256k1WycheproofTests.swift index 92799af..22a10d0 100644 --- a/Tests/AtprotoTypesVerifyTests/Secp256k1WycheproofTests.swift +++ b/Tests/AtprotoTypesVerifyTests/Secp256k1WycheproofTests.swift @@ -82,9 +82,16 @@ struct Secp256k1WycheproofTests { static func signingKey(uncompressedHex: String) throws -> RepoSigningKey { let bytes = try data(hex: uncompressedHex) - precondition(bytes.count == 65 && bytes.first == 0x04, "not a SEC1 uncompressed point") - let x = bytes.subdata(in: bytes.index(bytes.startIndex, offsetBy: 1).. Date: Wed, 19 Aug 2026 00:17:35 -0700 Subject: [PATCH 2/4] Add .git-blame-ignore-revs for the swift-format reformat commit Keeps git blame (and GitHub's blame view) attributing lines to their original author instead of the mass-reformat commit. Co-Authored-By: Claude Sonnet 5 --- .git-blame-ignore-revs | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..2f165fc --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,3 @@ +# Mass-reformat with swift-format; use this file to skip it in blame. +# git config blame.ignoreRevsFile .git-blame-ignore-revs +0ab9b0e4eeaf377930cf340b66fc1ba49dbfa714 From 75a9e4c5c054da8e85eb45b9222d158fc0ec3b5e Mon Sep 17 00:00:00 2001 From: Mark Xue Date: Wed, 19 Aug 2026 00:17:59 -0700 Subject: [PATCH 3/4] Enforce swift-format lint in CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New standalone job in ci-linux.yml, since linting only needs the Swift toolchain — no package resolution, private SSH deploy keys, or Xcode pinning like the other workflows. Co-Authored-By: Claude Sonnet 5 --- .github/workflows/ci-linux.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/ci-linux.yml b/.github/workflows/ci-linux.yml index eb96101..164bd92 100644 --- a/.github/workflows/ci-linux.yml +++ b/.github/workflows/ci-linux.yml @@ -16,6 +16,18 @@ concurrency: cancel-in-progress: true jobs: + lint: + name: Lint + runs-on: ubuntu-latest + container: + image: swift:6.2 + timeout-minutes: 30 + steps: + - name: Checkout + uses: actions/checkout@v6 + - name: Lint + run: swift format lint --recursive --configuration .swift-format --strict Sources Tests + linux_test: name: Test Linux runs-on: ubuntu-latest From be5fa3fc06b7a4ceb43996e65991133ce89bd563 Mon Sep 17 00:00:00 2001 From: Mark Xue Date: Wed, 19 Aug 2026 09:05:10 -0700 Subject: [PATCH 4/4] Fix lowerCamelCase rename: sha2256 -> sha256 The strict-lint fix for sha2_256 dropped the underscore literally instead of using the conventional name. Co-Authored-By: Claude Sonnet 5 --- Sources/AtprotoTypesVerify/ContentIdentifier.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/AtprotoTypesVerify/ContentIdentifier.swift b/Sources/AtprotoTypesVerify/ContentIdentifier.swift index 4ffa203..4334a6e 100644 --- a/Sources/AtprotoTypesVerify/ContentIdentifier.swift +++ b/Sources/AtprotoTypesVerify/ContentIdentifier.swift @@ -24,7 +24,7 @@ public struct ContentIdentifier: Sendable, Hashable { } //multicodec sha2-256, and the only digest atproto uses - static let sha2256: UInt64 = 0x12 + static let sha256: UInt64 = 0x12 static let digestLength = 32 public let codec: Codec @@ -44,7 +44,7 @@ public struct ContentIdentifier: Sendable, Hashable { public var bytes: Data { var out = Self.varint(1) out += Self.varint(codec.rawValue) - out += Self.varint(Self.sha2256) + out += Self.varint(Self.sha256) out += Self.varint(UInt64(Self.digestLength)) out += digest return Data(out) @@ -86,7 +86,7 @@ public struct ContentIdentifier: Sendable, Hashable { } let hash = try reader.readUnsignedVarint() - guard hash == Self.sha2256 else { + guard hash == Self.sha256 else { throw Atproto.Repo.ProofError.unsupportedHash(hash) }