Skip to content

Commit

Permalink
Remove Sequencer transaction in favor of Transaction with an optional…
Browse files Browse the repository at this point in the history
… hash (#127)
  • Loading branch information
DelevoXDG committed Jan 10, 2024
1 parent 70065e1 commit d7c0aff
Show file tree
Hide file tree
Showing 12 changed files with 78 additions and 221 deletions.
24 changes: 11 additions & 13 deletions Sources/Starknet/Accounts/StarknetAccount.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,43 +30,41 @@ public class StarknetAccount: StarknetAccountProtocol {
self.cairoVersion = cairoVersion
}

private func makeSequencerInvokeTransaction(calldata: StarknetCalldata, signature: StarknetSignature, params: StarknetExecutionParams, forFeeEstimation: Bool = false) -> StarknetSequencerInvokeTransaction {
StarknetSequencerInvokeTransaction(senderAddress: address, calldata: calldata, signature: signature, maxFee: params.maxFee, nonce: params.nonce, forFeeEstimation: forFeeEstimation)
private func makeInvokeTransaction(calldata: StarknetCalldata, signature: StarknetSignature, params: StarknetExecutionParams, forFeeEstimation: Bool = false) -> StarknetInvokeTransactionV1 {
StarknetInvokeTransactionV1(senderAddress: address, calldata: calldata, signature: signature, maxFee: params.maxFee, nonce: params.nonce, forFeeEstimation: forFeeEstimation)
}

private func makeSequencerDeployAccountTransaction(classHash: Felt, salt: Felt, calldata: StarknetCalldata, signature: StarknetSignature, params: StarknetExecutionParams, version: Felt) -> StarknetSequencerDeployAccountTransaction {
StarknetSequencerDeployAccountTransaction(
private func makeDeployAccountTransaction(classHash: Felt, salt: Felt, calldata: StarknetCalldata, signature: StarknetSignature, params: StarknetExecutionParams) -> StarknetDeployAccountTransactionV1 {
StarknetDeployAccountTransactionV1(
signature: signature,
maxFee: params.maxFee,
nonce: params.nonce,
contractAddressSalt: salt,
constructorCalldata: calldata,
classHash: classHash,
version: version
classHash: classHash
)
}

public func sign(calls: [StarknetCall], params: StarknetExecutionParams, forFeeEstimation: Bool) throws -> StarknetSequencerInvokeTransaction {
public func sign(calls: [StarknetCall], params: StarknetExecutionParams, forFeeEstimation: Bool) throws -> StarknetInvokeTransactionV1 {
let calldata = starknetCallsToExecuteCalldata(calls: calls, cairoVersion: cairoVersion)

let sequencerTransaction = makeSequencerInvokeTransaction(calldata: calldata, signature: [], params: params, forFeeEstimation: forFeeEstimation)
let sequencerTransaction = makeInvokeTransaction(calldata: calldata, signature: [], params: params, forFeeEstimation: forFeeEstimation)

let hash = StarknetTransactionHashCalculator.computeHash(of: sequencerTransaction, chainId: provider.starknetChainId)

let signature = try signer.sign(transactionHash: hash)

return makeSequencerInvokeTransaction(calldata: calldata, signature: signature, params: params, forFeeEstimation: forFeeEstimation)
return makeInvokeTransaction(calldata: calldata, signature: signature, params: params, forFeeEstimation: forFeeEstimation)
}

public func signDeployAccount(classHash: Felt, calldata: StarknetCalldata, salt: Felt, params: StarknetExecutionParams, forFeeEstimation: Bool) throws -> StarknetSequencerDeployAccountTransaction {
let version = forFeeEstimation ? estimateVersion : version
let sequencerTransaction = makeSequencerDeployAccountTransaction(classHash: classHash, salt: salt, calldata: calldata, signature: [], params: params, version: version)
public func signDeployAccount(classHash: Felt, calldata: StarknetCalldata, salt: Felt, params: StarknetExecutionParams, forFeeEstimation _: Bool) throws -> StarknetDeployAccountTransactionV1 {
let sequencerTransaction = makeDeployAccountTransaction(classHash: classHash, salt: salt, calldata: calldata, signature: [], params: params)

let hash = StarknetTransactionHashCalculator.computeHash(of: sequencerTransaction, chainId: provider.starknetChainId)

let signature = try signer.sign(transactionHash: hash)

return makeSequencerDeployAccountTransaction(classHash: classHash, salt: salt, calldata: calldata, signature: signature, params: params, version: version)
return makeDeployAccountTransaction(classHash: classHash, salt: salt, calldata: calldata, signature: signature, params: params)
}

public func execute(calls: [StarknetCall], params: StarknetOptionalExecutionParams) async throws -> StarknetInvokeTransactionResponse {
Expand Down
10 changes: 5 additions & 5 deletions Sources/Starknet/Accounts/StarknetAccountProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public protocol StarknetAccountProtocol {
/// - forFeeEstimation: Flag indicating whether the different version of transaction should be used; such transaction can only be used for fee estimation
///
/// - Returns: Signed SequencerInvokeTransaction
func sign(calls: [StarknetCall], params: StarknetExecutionParams, forFeeEstimation: Bool) throws -> StarknetSequencerInvokeTransaction
func sign(calls: [StarknetCall], params: StarknetExecutionParams, forFeeEstimation: Bool) throws -> StarknetInvokeTransactionV1

/// Create and sign deploy account transaction
///
Expand All @@ -23,7 +23,7 @@ public protocol StarknetAccountProtocol {
/// - params: additional params for a given transaction
/// - forFeeEstimation: Flag indicating whether the different version of transaction should be used; such transaction can only be used for fee estimation
/// - Returns: Signed sequencer deploy account transaction
func signDeployAccount(classHash: Felt, calldata: StarknetCalldata, salt: Felt, params: StarknetExecutionParams, forFeeEstimation: Bool) throws -> StarknetSequencerDeployAccountTransaction
func signDeployAccount(classHash: Felt, calldata: StarknetCalldata, salt: Felt, params: StarknetExecutionParams, forFeeEstimation: Bool) throws -> StarknetDeployAccountTransactionV1

/// Sign TypedData for off-chain usage with this account's privateKey.
///
Expand Down Expand Up @@ -87,7 +87,7 @@ public extension StarknetAccountProtocol {
/// - params: additional params for a given transaction
///
/// - Returns: Signed SequencerInvokeTransaction
func sign(calls: [StarknetCall], params: StarknetExecutionParams) throws -> StarknetSequencerInvokeTransaction {
func sign(calls: [StarknetCall], params: StarknetExecutionParams) throws -> StarknetInvokeTransactionV1 {
try sign(calls: calls, params: params, forFeeEstimation: false)
}

Expand All @@ -100,7 +100,7 @@ public extension StarknetAccountProtocol {
/// - maxFee: max acceptable fee for the transaction
/// - forFeeEstimation: Flag indicating whether the different version of transaction should be used; such transaction can only be used for fee estimation
/// - Returns: Signed sequencer deploy account transaction
func signDeployAccount(classHash: Felt, calldata: StarknetCalldata, salt: Felt, params: StarknetExecutionParams) throws -> StarknetSequencerDeployAccountTransaction {
func signDeployAccount(classHash: Felt, calldata: StarknetCalldata, salt: Felt, params: StarknetExecutionParams) throws -> StarknetDeployAccountTransactionV1 {
try signDeployAccount(classHash: classHash, calldata: calldata, salt: salt, params: params, forFeeEstimation: false)
}

Expand All @@ -111,7 +111,7 @@ public extension StarknetAccountProtocol {
/// - params: additional params for a given transaction
///
/// - Returns: Signed SequencerInvokeTransaction
func sign(call: StarknetCall, params: StarknetExecutionParams, forFeeEstimation: Bool = false) throws -> StarknetSequencerInvokeTransaction {
func sign(call: StarknetCall, params: StarknetExecutionParams, forFeeEstimation: Bool = false) throws -> StarknetInvokeTransactionV1 {
try sign(calls: [call], params: params, forFeeEstimation: forFeeEstimation)
}

Expand Down
129 changes: 0 additions & 129 deletions Sources/Starknet/Data/Transaction/SequencerTransaction.swift

This file was deleted.

66 changes: 37 additions & 29 deletions Sources/Starknet/Data/Transaction/Transaction.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import BigInt
import Foundation

public struct StarknetInvokeTransactionV1: StarknetTransaction {
Expand All @@ -17,28 +18,16 @@ public struct StarknetInvokeTransactionV1: StarknetTransaction {

public let hash: Felt?

public init(senderAddress: Felt, calldata: StarknetCalldata, signature: StarknetSignature, maxFee: Felt, nonce: Felt, version: Felt = .one, hash: Felt? = nil) {
public init(senderAddress: Felt, calldata: StarknetCalldata, signature: StarknetSignature, maxFee: Felt, nonce: Felt, forFeeEstimation: Bool = false, hash: Felt? = nil) {
self.senderAddress = senderAddress
self.calldata = calldata
self.signature = signature
self.maxFee = maxFee
self.nonce = nonce
self.version = version
self.version = StarknetInvokeTransactionV1.computeVersion(1, forFeeEstimation: forFeeEstimation)
self.hash = hash
}

public init(sequencerTransaction: StarknetSequencerInvokeTransaction, hash: Felt) {
self.init(
senderAddress: sequencerTransaction.senderAddress,
calldata: sequencerTransaction.calldata,
signature: sequencerTransaction.signature,
maxFee: sequencerTransaction.maxFee,
nonce: sequencerTransaction.nonce,
version: sequencerTransaction.version,
hash: hash
)
}

enum CodingKeys: String, CodingKey {
case type
case version
Expand Down Expand Up @@ -121,7 +110,7 @@ public typealias StarknetDeployAccountTransaction = StarknetDeployAccountTransac
public struct StarknetDeployAccountTransactionV1: StarknetTransaction {
public let type: StarknetTransactionType = .deployAccount

public let version: Felt = .one
public let version: Felt

public let signature: StarknetSignature

Expand All @@ -137,28 +126,17 @@ public struct StarknetDeployAccountTransactionV1: StarknetTransaction {

public let hash: Felt?

public init(signature: StarknetSignature, maxFee: Felt, nonce: Felt, contractAddressSalt: Felt, constructorCalldata: StarknetCalldata, classHash: Felt, hash: Felt? = nil) {
public init(signature: StarknetSignature, maxFee: Felt, nonce: Felt, contractAddressSalt: Felt, constructorCalldata: StarknetCalldata, classHash: Felt, forFeeEstimation: Bool = false, hash: Felt? = nil) {
self.signature = signature
self.maxFee = maxFee
self.nonce = nonce
self.contractAddressSalt = contractAddressSalt
self.constructorCalldata = constructorCalldata
self.classHash = classHash
self.version = StarknetDeployAccountTransactionV1.computeVersion(1, forFeeEstimation: forFeeEstimation)
self.hash = hash
}

public init(sequencerTransaction: StarknetSequencerDeployAccountTransaction, hash: Felt) {
self.init(
signature: sequencerTransaction.signature,
maxFee: sequencerTransaction.maxFee,
nonce: sequencerTransaction.nonce,
contractAddressSalt: sequencerTransaction.contractAddressSalt,
constructorCalldata: sequencerTransaction.constructorCalldata,
classHash: sequencerTransaction.classHash,
hash: hash
)
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.signature = try container.decode(StarknetSignature.self, forKey: .signature)
Expand All @@ -167,10 +145,10 @@ public struct StarknetDeployAccountTransactionV1: StarknetTransaction {
self.contractAddressSalt = try container.decode(Felt.self, forKey: .contractAddressSalt)
self.constructorCalldata = try container.decode(StarknetCalldata.self, forKey: .constructorCalldata)
self.classHash = try container.decode(Felt.self, forKey: .classHash)
self.version = try container.decode(Felt.self, forKey: .version)
self.hash = try container.decodeIfPresent(Felt.self, forKey: .hash)

try verifyTransactionType(container: container, codingKeysType: CodingKeys.self)
try verifyTransactionVersion(container: container, codingKeysType: CodingKeys.self)
}

enum CodingKeys: String, CodingKey {
Expand Down Expand Up @@ -430,3 +408,33 @@ public enum StarknetTransactionDecodingError: Error {
case invalidVersion
case invalidType
}

extension StarknetTransaction {
private static func estimateVersion(_ version: Felt) -> Felt {
Felt(BigUInt(2).power(128).advanced(by: BigInt(version.value)))!
}

static func computeVersion(_ version: Felt, forFeeEstimation: Bool) -> Felt {
forFeeEstimation ? estimateVersion(version) : version
}
}

// Default deserializer doesn't check if the fields with default values match what is deserialized.
// It's an extension that resolves this.
extension StarknetTransaction {
func verifyTransactionType<T>(container: KeyedDecodingContainer<T>, codingKeysType _: T.Type) throws where T: CodingKey {
let type = try container.decode(StarknetTransactionType.self, forKey: T(stringValue: "type")!)

guard type == self.type else {
throw StarknetTransactionDecodingError.invalidType
}
}

func verifyTransactionVersion<T>(container: KeyedDecodingContainer<T>, codingKeysType _: T.Type) throws where T: CodingKey {
let version = try container.decode(Felt.self, forKey: T(stringValue: "version")!)

guard version == self.version else {
throw StarknetTransactionDecodingError.invalidVersion
}
}
}
4 changes: 2 additions & 2 deletions Sources/Starknet/Data/Transaction/TransactionHash.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class StarknetTransactionHashCalculator {
)
}

public class func computeHash(of transaction: StarknetSequencerInvokeTransaction, chainId: StarknetChainId) -> Felt {
public class func computeHash(of transaction: StarknetInvokeTransactionV1, chainId: StarknetChainId) -> Felt {
computeHashCommon(
transactionType: transaction.type,
version: transaction.version,
Expand All @@ -36,7 +36,7 @@ public class StarknetTransactionHashCalculator {
)
}

public class func computeHash(of transaction: StarknetSequencerDeployAccountTransaction, chainId: StarknetChainId) -> Felt {
public class func computeHash(of transaction: StarknetDeployAccountTransactionV1, chainId: StarknetChainId) -> Felt {
let contractAddress = StarknetContractAddressCalculator.calculateFrom(
classHash: transaction.classHash,
calldata: transaction.constructorCalldata,
Expand Down
5 changes: 1 addition & 4 deletions Sources/Starknet/Data/Transaction/TransactionProtocol.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@

public protocol StarknetSequencerTransaction: Codable, Hashable, Equatable {
public protocol StarknetTransaction: Codable, Hashable, Equatable {
var type: StarknetTransactionType { get }
var version: Felt { get }
}

public protocol StarknetTransaction: StarknetSequencerTransaction {
var hash: Felt? { get }
}
Loading

0 comments on commit d7c0aff

Please sign in to comment.