Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Felt(fromSigned) initializer; Support u128, i128, timestamp types in StarknetTypedData #174

Merged
merged 118 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
118 commits
Select commit Hold shift + click to select a range
cd299f8
Update `StarknetExecutionResources`; Add `StarknetComputationResources`
DelevoXDG Mar 18, 2024
d2d94df
Update prefund amounts and max fee for declare in DevnetClient
DelevoXDG Mar 18, 2024
e012d54
Adjust tx receipt tests
DelevoXDG Mar 18, 2024
96fc841
Update `StarknetFeeEstimate` and related logic
DelevoXDG Mar 18, 2024
24de548
Finish "Update prefund amounts and max fee for declare in DevnetClient"
DelevoXDG Mar 18, 2024
2a36b16
Fix docstring for `toResourceBounds`
DelevoXDG Mar 18, 2024
10c1bc3
Use ternary operator in `.toResourceBounds()`
DelevoXDG Mar 18, 2024
84c5dde
Bump devnet
DelevoXDG Mar 18, 2024
db69dba
Use Cairo 1 accounts for tests to pass
DelevoXDG Mar 21, 2024
ee0a9a2
Fix #147 (Specify transaction version in test cases names)
DelevoXDG Mar 21, 2024
5f87f2c
Add missing `segment_arena_builtin` to `StarknetComputationResources`…
DelevoXDG Mar 21, 2024
1ba4133
Add optional `executionResources` to `StarknetL1HandlerTransactionTrace`
DelevoXDG Mar 21, 2024
a606158
Empty
DelevoXDG Mar 22, 2024
d2bfbc8
Introduce `Domain` and `Revision`
DelevoXDG Mar 26, 2024
3f0409c
Add `HashMethod` enum; Use **poseidon** hash for rev 1 typed data
DelevoXDG Mar 26, 2024
49031c5
Update `encode(dependency)` logic in line with rev 1
DelevoXDG Mar 26, 2024
c681354
Update `encode` to take `revision` into account
DelevoXDG Mar 26, 2024
58c0c8d
Mark `Starknet` as `@testable` in `TypedDataTests`
DelevoXDG Mar 26, 2024
4bb69cc
Add rev 1 test case
DelevoXDG Mar 26, 2024
a32823d
Format
DelevoXDG Mar 26, 2024
e5f2e71
Review chnages
DelevoXDG Mar 26, 2024
b894924
Review changes
DelevoXDG Mar 26, 2024
19e5338
Make `HashMethod` public; Add `hash` for two elements
DelevoXDG Mar 27, 2024
efee210
Add `MerkleTree`
DelevoXDG Mar 27, 2024
1ac7a1f
Format
DelevoXDG Mar 27, 2024
b0d94a2
Fix tests
DelevoXDG Mar 27, 2024
0006110
Add `merkletree` to reserved type names
DelevoXDG Mar 27, 2024
371fac7
Add `MerkleTreeType`, `StandardType`; Convert `TypeDeclaration` to pr…
DelevoXDG Mar 27, 2024
cb2dd71
Move `StarknetTypedData.swift` to `TypedData/StarknetTypedData.swift`
DelevoXDG Mar 27, 2024
89c4d7e
Move `TypeDeclaration` related extension to `TypeDeclaration.swift`
DelevoXDG Mar 27, 2024
f38cc0d
Fix `TypeDeclarationWrapper` decoding of `merkletree`
DelevoXDG Mar 27, 2024
1d3f8e9
Support `merkletree` basic type in `StarknetTypedData`
DelevoXDG Mar 27, 2024
6822784
Split `testSignTypedData` into rev 0 and 1 tests
DelevoXDG Mar 27, 2024
1a19f30
Merge branch 'feat/159-snip-12' into feat/159-2-merkletree
DelevoXDG Mar 27, 2024
e330ede
Move build logic to `build` method
DelevoXDG Mar 27, 2024
403bffc
Review changes
DelevoXDG Mar 27, 2024
39f671e
Rename `HashMethod`->`StarknetHashMethod`
DelevoXDG Mar 27, 2024
481872c
Merge branch 'feat/159-snip-12' into feat/159-2-merkletree
DelevoXDG Mar 28, 2024
a939de5
Fix `build` bug post `e330ede93f329de682e02a842d5db010a4243758`
DelevoXDG Mar 28, 2024
1ed2e32
Review changes
DelevoXDG Mar 28, 2024
2ec8d5d
Add `String.isArray()` extension; Refactor `.strippingPointer()` exte…
DelevoXDG Mar 28, 2024
2890b67
Move type verification logic to `verifyTypes()` helper
DelevoXDG Mar 28, 2024
5673e04
Refactor `verifyTypes()`
DelevoXDG Mar 28, 2024
0716893
Restrict empty names; Refactor tests
DelevoXDG Mar 28, 2024
6c2ceaa
Refactor `revision` related logic
DelevoXDG Mar 28, 2024
e0cb126
Require domain type; Refactor tests
DelevoXDG Mar 28, 2024
350cadd
Remove `domainNotDefined`; Use `dependencyNotDefined` instead
DelevoXDG Mar 28, 2024
5b061d9
Disallow dangling types in `verifyTypes()`
DelevoXDG Mar 28, 2024
ddbfecb
Fix `testMissingDependency` after dangling types change
DelevoXDG Mar 28, 2024
1ea8094
Add extra info to `StarknetTypedDataError` errors
DelevoXDG Mar 28, 2024
495a06e
Merge branch 'main' into feat/159-snip-12
DelevoXDG Mar 28, 2024
7206647
Merge branch 'feat/159-snip-12' into feat/159-2-merkletree
DelevoXDG Mar 28, 2024
c6c4e79
Merge branch 'feat/159-2-merkletree' into feat/159-3-verify-types
DelevoXDG Mar 28, 2024
a8eced5
Bump swift version to 5.10.0
DelevoXDG Mar 28, 2024
b093f02
Bump `swift-tools-version` to 5.9
DelevoXDG Mar 28, 2024
5600de2
Bump runner from `macos-12` to `macos-14`
DelevoXDG Mar 28, 2024
b8390f9
Bump swift version to 5.10.0
DelevoXDG Mar 28, 2024
81fa2f3
Bump `swift-tools-version` to 5.9
DelevoXDG Mar 28, 2024
d8caa2f
Bump runner from `macos-12` to `macos-14`
DelevoXDG Mar 28, 2024
4c27593
Change version to `5.9.0` in `.swift-version`
DelevoXDG Mar 28, 2024
5db449a
Merge branch 'feat/171-bump-swift-version' into feat/159-snip-12
DelevoXDG Mar 28, 2024
e5486a5
Merge branch 'feat/159-snip-12' into feat/159-2-merkletree
DelevoXDG Mar 28, 2024
2891c5a
Format
DelevoXDG Mar 28, 2024
5a197d7
Merge branch 'feat/159-2-merkletree' into feat/159-3-verify-types
DelevoXDG Mar 28, 2024
43fbb0d
Bump version to 5.10.0
DelevoXDG Mar 28, 2024
04c743c
Setup `Xcode 15.3`
DelevoXDG Mar 28, 2024
3096f02
Refactor array hanlding logic
DelevoXDG Mar 29, 2024
ee05381
Rename `hash()` -> `hashArray()`
DelevoXDG Mar 29, 2024
d09d6d9
Merge branch 'feat/159-snip-12' into feat/159-2-merkletree
DelevoXDG Mar 29, 2024
a407d21
Merge branch 'feat/159-2-merkletree' into feat/159-3-verify-types
DelevoXDG Mar 29, 2024
503509c
Merge branch 'feat/159-3-verify-types' into feat/159-4-basic-types
DelevoXDG Mar 29, 2024
8302000
Support `bool` basic type
DelevoXDG Mar 29, 2024
6e7358b
Merge `encode()` cases relying on same `unwrap` methods
DelevoXDG Mar 29, 2024
25260c3
Update `verifyTypes()` to include `bool` and all rev 1 basic types
DelevoXDG Mar 29, 2024
b1f1ee9
Support `ContractAddress`, `ClassHash`
DelevoXDG Mar 29, 2024
219f25d
Add `Felt(fromSigned)` initializer
DelevoXDG Mar 29, 2024
2fdc240
Support `u128`, `i128`, `timestamp`
DelevoXDG Mar 29, 2024
c85a2e6
Remove unused import
DelevoXDG Mar 29, 2024
c015793
Don't verify types that are not yet added
DelevoXDG Mar 29, 2024
d431053
Merge branch 'feat/159-4-basic-types' into feat/159-5-int-basic-types
DelevoXDG Mar 29, 2024
01eb940
Verify `i128`, `u128`, `timestamp`
DelevoXDG Mar 29, 2024
5101ab5
Remove unnecessary `print()` in tests
DelevoXDG Mar 29, 2024
9feaf94
Merge branch 'feat/171-bump-swift-version' into feat/159-snip-12
DelevoXDG Apr 2, 2024
090763c
Merge branch 'feat/159-snip-12' into feat/159-2-merkletree
DelevoXDG Apr 2, 2024
932790c
Merge branch 'feat/159-2-merkletree' into feat/159-3-verify-types
DelevoXDG Apr 2, 2024
47563a9
Merge branch 'feat/159-3-verify-types' into feat/159-4-basic-types
DelevoXDG Apr 2, 2024
4ce61a6
Merge branch 'feat/159-4-basic-types' into feat/159-5-int-basic-types
DelevoXDG Apr 2, 2024
606a2bf
Add `testEncodeType`
DelevoXDG Apr 3, 2024
ddce0c3
Merge branch 'feat/159-snip-12' of https://github.com/software-mansio…
DelevoXDG Apr 3, 2024
3e0a5da
Merge branch 'feat/159-snip-12' into feat/159-2-merkletree
DelevoXDG Apr 3, 2024
8966f27
Add merkle tree encodeType tests
DelevoXDG Apr 3, 2024
0b9a346
Merge branch 'feat/159-2-merkletree' into feat/159-3-verify-types
DelevoXDG Apr 3, 2024
e8f8e20
Merge branch 'feat/159-3-verify-types' into feat/159-4-basic-types
DelevoXDG Apr 3, 2024
6015904
Merge branch 'feat/159-4-basic-types' into feat/159-5-int-basic-types
DelevoXDG Apr 3, 2024
e2e3002
Make `revision`, `hashMethod` and `hashArray()` private
DelevoXDG Apr 3, 2024
622b5c3
Add docstring
DelevoXDG Apr 4, 2024
093113d
Merge branch 'feat/159-snip-12' into feat/159-2-merkletree
DelevoXDG Apr 4, 2024
d426775
Merge branch 'feat/159-2-merkletree' into feat/159-3-verify-types
DelevoXDG Apr 4, 2024
ed61f7a
Merge branch 'feat/159-3-verify-types' into feat/159-4-basic-types
DelevoXDG Apr 4, 2024
465152a
Merge branch 'feat/159-4-basic-types' into feat/159-5-int-basic-types
DelevoXDG Apr 4, 2024
daf429b
Make `revision` public
DelevoXDG Apr 4, 2024
947ebd6
Merge branch 'feat/159-snip-12' into feat/159-2-merkletree
DelevoXDG Apr 4, 2024
1d61523
Merge branch 'feat/159-2-merkletree' into feat/159-3-verify-types
DelevoXDG Apr 4, 2024
759afd0
Merge branch 'feat/159-3-verify-types' into feat/159-4-basic-types
DelevoXDG Apr 4, 2024
3d4e7e5
Merge branch 'feat/159-4-basic-types' into feat/159-5-int-basic-types
DelevoXDG Apr 4, 2024
e201759
Make `StarknetHashMethod` methods public
DelevoXDG Apr 5, 2024
d62ceaf
Add `.invalidNumberError` to be used instead of `.decodingError`
DelevoXDG Apr 5, 2024
28b288e
Add `.invalidBool` to be used instead of `.decodingError`
DelevoXDG Apr 5, 2024
3ef48b0
Rename `invalidNumberError`->`invalidNumericValue`
DelevoXDG Apr 5, 2024
0ef4417
Merge branch 'main' into feat/159-2-merkletree
DelevoXDG Apr 5, 2024
5ebfeac
Fix merge anomaly
DelevoXDG Apr 5, 2024
4c0b593
Merge branch 'feat/159-2-merkletree' into feat/159-3-verify-types
DelevoXDG Apr 5, 2024
b1642be
Merge branch 'feat/159-3-verify-types' into feat/159-4-basic-types
DelevoXDG Apr 8, 2024
f903902
Merge branch 'main' into feat/159-3-verify-types
DelevoXDG Apr 8, 2024
2b5eefc
Merge branch 'feat/159-3-verify-types' into feat/159-4-basic-types
DelevoXDG Apr 8, 2024
a0118c1
Merge branch 'main' into feat/159-4-basic-types
DelevoXDG Apr 8, 2024
109c270
Merge branch 'feat/159-4-basic-types' into feat/159-5-int-basic-types
DelevoXDG Apr 8, 2024
8926f44
Merge branch 'main' into feat/159-5-int-basic-types
DelevoXDG Apr 8, 2024
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
15 changes: 15 additions & 0 deletions Sources/Starknet/Data/Numbers/Felt.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@ public struct Felt: NumAsHexProtocol {
self.value = value < Felt.prime ? value : Felt.prime - 1
}

/// Initializes a new Felt instance from a signed integer.
///
/// Calculated as `fromSigned mod Felt.prime`.
///
/// - Parameter fromSigned: The signed integer to convert to Felt. The integer must be greater than `-Felt.prime` and less than `Felt.prime`.
public init?(fromSigned exactly: some BinaryInteger) {
let value = BigInt(exactly: exactly)

guard let value, abs(value) < Felt.prime else {
return nil
DelevoXDG marked this conversation as resolved.
Show resolved Hide resolved
}

self.value = BigUInt(value.modulus(BigInt(Felt.prime)))
}

public init?(fromHex hex: String) {
guard hex.hasPrefix("0x") else { return nil }

Expand Down
47 changes: 46 additions & 1 deletion Sources/Starknet/Data/TypedData/StarknetTypedData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public enum StarknetTypedDataError: Error, Equatable {
case contextNotDefined
case parentNotDefined
case keyNotDefined
case invalidNumericValue(StarknetTypedData.Element)
case invalidBool(StarknetTypedData.Element)
case invalidMerkleTree
case invalidShortString
Expand Down Expand Up @@ -222,6 +223,10 @@ public struct StarknetTypedData: Codable, Equatable, Hashable {
switch (typeName, revision) {
case ("felt", _), ("string", .v0), ("shortstring", .v1), ("ContractAddress", .v1), ("ClassHash", .v1):
return try unwrapFelt(from: element)
case ("u128", .v1), ("timestamp", .v1):
return try unwrapU128(from: element)
case ("i128", .v1):
return try unwrapI128(from: element)
case ("bool", _):
return try unwrapBool(from: element)
case ("string", .v1):
Expand Down Expand Up @@ -340,6 +345,7 @@ public extension StarknetTypedData {
case array([Element])
case string(String)
case felt(Felt)
case signedFelt(Felt)
case bool(Bool)

public init(from decoder: Decoder) throws {
Expand All @@ -355,13 +361,21 @@ public extension StarknetTypedData {
let felt = Felt(uint)
{
self = .felt(felt)
} else if let int = try? container.decode(Int64.self),
let felt = Felt(fromSigned: int)
{
self = .signedFelt(felt)
} else if let bool = try? container.decode(Bool.self) {
self = .bool(bool)
} else if let string = try? container.decode(String.self) {
if let uint = BigUInt(string),
let felt = Felt(uint)
{
self = .felt(felt)
} else if let int = BigInt(string),
let felt = Felt(fromSigned: int)
{
self = .signedFelt(felt)
} else {
self = .string(string)
}
Expand All @@ -376,6 +390,8 @@ public extension StarknetTypedData {
try string.encode(to: encoder)
case let .felt(felt):
try felt.encode(to: encoder)
case let .signedFelt(felt):
try felt.encode(to: encoder)
case let .object(object):
try object.encode(to: encoder)
case let .array(array):
Expand All @@ -389,7 +405,7 @@ public extension StarknetTypedData {

private extension StarknetTypedData {
static let basicTypesV0: Set = ["felt", "bool", "string", "selector", "merkletree"]
static let basicTypesV1: Set = basicTypesV0.union(["ContractAddress", "ClassHash", "shortstring"])
static let basicTypesV1: Set = basicTypesV0.union(["u128", "i128", "ContractAddress", "ClassHash", "timestamp", "shortstring"])

func getBasicTypes() -> Set<String> {
switch revision {
Expand Down Expand Up @@ -437,6 +453,35 @@ extension StarknetTypedData {
}
}

func unwrapU128(from element: Element) throws -> Felt {
guard case let .felt(felt) = element else {
throw StarknetTypedDataError.invalidNumericValue(element)
}

guard felt.value < BigUInt(2).power(128) else {
throw StarknetTypedDataError.invalidNumericValue(element)
}

return felt
}

func unwrapI128(from element: Element) throws -> Felt {
let felt = switch element {
case let .felt(felt):
felt
case let .signedFelt(signedFelt):
signedFelt
default:
throw StarknetTypedDataError.invalidNumericValue(element)
}

guard felt.value < BigUInt(2).power(127) || felt.value >= Felt.prime - BigUInt(2).power(127) else {
throw StarknetTypedDataError.invalidNumericValue(element)
}

return felt
}

func unwrapSelector(from element: Element) throws -> Felt {
switch element {
case let .felt(felt):
Expand Down
15 changes: 15 additions & 0 deletions Tests/StarknetTests/Data/FeltTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,21 @@ final class FeltTests: XCTestCase {
XCTAssertEqual(numAsHex4, NumAsHex(0))
}

func testFromSigned() {
XCTAssertEqual(Felt(fromSigned: -1), Felt.max)
XCTAssertEqual(Felt(fromSigned: -BigInt(Felt.max.value)), Felt.one)
XCTAssertEqual(
Felt(fromSigned: -Int.max),
Felt(BigInt(Felt.prime) - BigInt(Int.max))
)
XCTAssertEqual(
Felt(fromSigned: -Int64.max),
Felt(BigInt(Felt.prime) - BigInt(Int64.max))
)
XCTAssertNil(Felt(fromSigned: Felt.prime))
XCTAssertNil(Felt(fromSigned: -BigInt(Felt.prime)))
}

func testShortStringEncoding() {
let encoded = Felt(fromHex: "0x68656c6c6f")!.toShortString()

Expand Down
75 changes: 74 additions & 1 deletion Tests/StarknetTests/Data/TypedDataTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//
// Created by Bartosz Rybarski on 14/02/2023.
//
import BigInt
@testable import Starknet
import XCTest

Expand Down Expand Up @@ -92,7 +93,7 @@ final class TypedDataTests: XCTestCase {
let basicTypesV0 = [
"felt", "bool", "string", "selector", "merkletree",
]
let basicTypesV1 = basicTypesV0 + ["ContractAddress", "ClassHash", "shortstring"]
let basicTypesV1 = basicTypesV0 + ["u128", "i128", "ContractAddress", "ClassHash", "timestamp", "shortstring"]

try XCTAssertNoThrow(makeTypedData("myType", .v0))
try basicTypesV0.forEach { type in
Expand Down Expand Up @@ -161,6 +162,78 @@ final class TypedDataTests: XCTestCase {
}
}

func testEncodeU128() throws {
let cases: [(any Encodable, Felt)] = [
(0, .zero),
(1, .one),
(1_000_000, 1_000_000),
("0x0", .zero),
("0x1", .one),
("0x3e8", 1000),
((BigUInt(2).power(128) - 1).description, Felt(BigUInt(2).power(128) - 1)!),
]

for (input, expected) in cases {
let element = try JSONDecoder().decode(StarknetTypedData.Element.self, from: JSONEncoder().encode(input))
let encodedValue = try CasesRev1.td.encode(element: element, forType: "u128")

XCTAssertEqual(encodedValue, expected)
}
}

func testEncodeInvalidU128() throws {
let cases: [any Encodable] = [
-1,
"-1",
"0x" + String(BigUInt(2).power(128), radix: 16),
(BigUInt(2).power(128) + 1).description,
]

for input in cases {
let element = try JSONDecoder().decode(StarknetTypedData.Element.self, from: JSONEncoder().encode(input))
XCTAssertThrowsError(try CasesRev1.td.encode(element: element, forType: "u128")) { error in
XCTAssertEqual(error as? StarknetTypedDataError, .invalidNumericValue(element))
}
}
}

func testEncodeI128() throws {
let cases: [(any Encodable, Felt)] = [
(0, .zero),
(1, .one),
(1_000_000, 1_000_000),
("0x0", .zero),
("0x1", .one),
("0x3e8", 1000),
((BigUInt(2).power(127) - 1).description, Felt(BigUInt(2).power(127) - 1)!),
(-1, Felt(fromSigned: -1)!),
(-1_000_000, Felt(fromSigned: -1_000_000)!),
("-1", Felt(fromSigned: -1)!),
((-BigInt(2).power(127)).description, Felt(fromSigned: -BigInt(2).power(127))!),
]

for (input, expected) in cases {
let element = try JSONDecoder().decode(StarknetTypedData.Element.self, from: JSONEncoder().encode(input))
let encodedValue = try CasesRev1.td.encode(element: element, forType: "i128")

XCTAssertEqual(encodedValue, expected)
}
}

func testEncodeInvalidI128() throws {
let cases: [any Encodable] = [
(-BigInt(2).power(127) - 1).description,
"0x" + String(BigUInt(2).power(127), radix: 16),
]

for input in cases {
let element = try JSONDecoder().decode(StarknetTypedData.Element.self, from: JSONEncoder().encode(input))
XCTAssertThrowsError(try CasesRev1.td.encode(element: element, forType: "i128")) { error in
XCTAssertEqual(error as? StarknetTypedDataError, .invalidNumericValue(element))
}
}
}

func testEncodeType() throws {
let cases: [(StarknetTypedData, String, String)] =
[
Expand Down
Loading