Skip to content

Commit

Permalink
Adapt execution resources
Browse files Browse the repository at this point in the history
  • Loading branch information
franciszekjob committed Oct 25, 2024
1 parent fe40311 commit 4b56a9f
Show file tree
Hide file tree
Showing 13 changed files with 127 additions and 166 deletions.
14 changes: 8 additions & 6 deletions Sources/Starknet/Accounts/StarknetAccount.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ public class StarknetAccount: StarknetAccountProtocol {
}

private func makeInvokeTransactionV3(calldata: StarknetCalldata, signature: StarknetSignature, params: StarknetInvokeParamsV3, forFeeEstimation: Bool = false) -> StarknetInvokeTransactionV3 {
StarknetInvokeTransactionV3(senderAddress: address, calldata: calldata, signature: signature, l1ResourceBounds: params.resourceBounds.l1Gas, nonce: params.nonce, forFeeEstimation: forFeeEstimation)
StarknetInvokeTransactionV3(senderAddress: address, calldata: calldata, signature: signature, resourceBounds: params.resourceBounds, nonce: params.nonce, forFeeEstimation: forFeeEstimation)
}

private func makeDeployAccountTransactionV1(classHash: Felt, salt: Felt, calldata: StarknetCalldata, signature: StarknetSignature, params: StarknetDeployAccountParamsV1, forFeeEstimation: Bool) -> StarknetDeployAccountTransactionV1 {
StarknetDeployAccountTransactionV1(signature: signature, maxFee: params.maxFee, nonce: params.nonce, contractAddressSalt: salt, constructorCalldata: calldata, classHash: classHash, forFeeEstimation: forFeeEstimation)
}

private func makeDeployAccountTransactionV3(classHash: Felt, salt: Felt, calldata: StarknetCalldata, signature: StarknetSignature, params: StarknetDeployAccountParamsV3, forFeeEstimation: Bool) -> StarknetDeployAccountTransactionV3 {
StarknetDeployAccountTransactionV3(signature: signature, l1ResourceBounds: params.resourceBounds.l1Gas, nonce: params.nonce, contractAddressSalt: salt, constructorCalldata: calldata, classHash: classHash, forFeeEstimation: forFeeEstimation)
StarknetDeployAccountTransactionV3(signature: signature, resourceBounds: params.resourceBounds, nonce: params.nonce, contractAddressSalt: salt, constructorCalldata: calldata, classHash: classHash, forFeeEstimation: forFeeEstimation)
}

public func signV1(calls: [StarknetCall], params: StarknetInvokeParamsV1, forFeeEstimation: Bool) throws -> StarknetInvokeTransactionV1 {
Expand Down Expand Up @@ -126,7 +126,7 @@ public class StarknetAccount: StarknetAccountProtocol {
resourceBounds = feeEstimate.toResourceBounds()
}

let params = StarknetInvokeParamsV3(nonce: nonce, l1ResourceBounds: resourceBounds.l1Gas)
let params = StarknetInvokeParamsV3(nonce: nonce, resourceBounds: resourceBounds)
let signedTransaction = try signV3(calls: calls, params: params, forFeeEstimation: false)

return RequestBuilder.addInvokeTransaction(signedTransaction)
Expand All @@ -148,7 +148,7 @@ public class StarknetAccount: StarknetAccountProtocol {
let feeEstimate = try await provider.send(request: estimateFeeV3(calls: calls, nonce: nonce))[0]
let resourceBounds = feeEstimate.toResourceBounds(amountMultiplier: estimateAmountMultiplier, unitPriceMultiplier: estimateUnitPriceMultiplier)

let params = StarknetInvokeParamsV3(nonce: nonce, l1ResourceBounds: resourceBounds.l1Gas)
let params = StarknetInvokeParamsV3(nonce: nonce, resourceBounds: resourceBounds)
let signedTransaction = try signV3(calls: calls, params: params, forFeeEstimation: false)

return RequestBuilder.addInvokeTransaction(signedTransaction)
Expand All @@ -162,7 +162,8 @@ public class StarknetAccount: StarknetAccountProtocol {
}

public func estimateFeeV3(calls: [StarknetCall], nonce: Felt, skipValidate: Bool) async throws -> StarknetRequest<[StarknetFeeEstimate]> {
let params = StarknetInvokeParamsV3(nonce: nonce, l1ResourceBounds: .zero)
let resourceBounds = StarknetResourceBoundsMapping(l1Gas: StarknetResourceBounds.zero, l2Gas: StarknetResourceBounds.zero)
let params = StarknetInvokeParamsV3(nonce: nonce, resourceBounds: resourceBounds)
let signedTransaction = try signV3(calls: calls, params: params, forFeeEstimation: true)

return RequestBuilder.estimateFee(for: signedTransaction, simulationFlags: skipValidate ? [.skipValidate] : [])
Expand All @@ -176,7 +177,8 @@ public class StarknetAccount: StarknetAccountProtocol {
}

public func estimateDeployAccountFeeV3(classHash: Felt, calldata: StarknetCalldata, salt: Felt, nonce: Felt, skipValidate: Bool) async throws -> StarknetRequest<[StarknetFeeEstimate]> {
let params = StarknetDeployAccountParamsV3(nonce: nonce, l1ResourceBounds: .zero)
let resourceBounds = StarknetResourceBoundsMapping(l1Gas: StarknetResourceBounds.zero, l2Gas: StarknetResourceBounds.zero)
let params = StarknetDeployAccountParamsV3(nonce: nonce, resourceBounds: resourceBounds)
let signedTransaction = try signDeployAccountV3(classHash: classHash, calldata: calldata, salt: salt, params: params, forFeeEstimation: true)

return RequestBuilder.estimateFee(for: signedTransaction, simulationFlags: skipValidate ? [.skipValidate] : [])
Expand Down
6 changes: 3 additions & 3 deletions Sources/Starknet/Accounts/StarknetAccountProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -216,11 +216,11 @@ public extension StarknetAccountProtocol {
/// - classHash: class hash of account to be deployed
/// - calldata: constructor calldata
/// - salt: contract salt
/// - l1ResourceBounds: max acceptable l1 resource bounds
/// - resourceBounds: max acceptable l1 and l2 resource bounds
///
/// - Returns: Signed deploy account transaction v3
func signDeployAccountV3(classHash: Felt, calldata: StarknetCalldata, salt: Felt, l1ResourceBounds: StarknetResourceBounds) throws -> StarknetDeployAccountTransactionV3 {
try signDeployAccountV3(classHash: classHash, calldata: calldata, salt: salt, params: StarknetDeployAccountParamsV3(nonce: .zero, l1ResourceBounds: l1ResourceBounds), forFeeEstimation: false)
func signDeployAccountV3(classHash: Felt, calldata: StarknetCalldata, salt: Felt, resourceBounds: StarknetResourceBoundsMapping) throws -> StarknetDeployAccountTransactionV3 {
try signDeployAccountV3(classHash: classHash, calldata: calldata, salt: salt, params: StarknetDeployAccountParamsV3(nonce: .zero, resourceBounds: resourceBounds), forFeeEstimation: false)
}

/// Sign a call as invoke transaction v1
Expand Down
20 changes: 13 additions & 7 deletions Sources/Starknet/Crypto/FeeCalculation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,28 @@ import Foundation
public extension StarknetFeeEstimate {
/// Convert estimated fee to resource bounds with applied multipliers
///
/// Calculates `maxAmount = overallFee / gasPrice`, unless `gasPrice` is 0, then `maxAmount` is 0.
/// Calculates `maxPricePerUnit = gasPrice`.
/// Then multiplies `maxAmount` by **round((amountMultiplier) \* 100)** and `maxPricePerUnit` by **round((unitPriceMultiplier) \* 100)** and performs integer division by 100 on both.
/// Calculates `maxAmountL1 = overallFee / l1GasPrice`, unless `l1GasPrice` is 0, then `maxAmount` is 0.
/// Calculates `maxAmountL2 = overallFee / l2GasPrice`, unless `l2GasPrice` is 0, then `maxAmount` is 0.
/// Calculates `maxPricePerUnitL1 = gasPriceL1`.
/// Calculates `maxPricePerUnitL2 = gasPriceL2`.
/// Then multiplies `maxAmountL1` and `maxAmountL2` by **round((amountMultiplier) \* 100)** and `maxPricePerUnit` by **round((unitPriceMultiplier) \* 100)** and performs integer division by 100 on both.
///
///
/// - Parameters:
/// - amountMultiplier: multiplier for max amount, defaults to 1.5.
/// - unitPriceMultiplier: multiplier for max price per unit, defaults to 1.5.
///
/// - Returns: resource bounds with applied multipliers
func toResourceBounds(amountMultiplier: Double = 1.5, unitPriceMultiplier: Double = 1.5) -> StarknetResourceBoundsMapping {
let maxAmount = self.gasPrice == .zero ? UInt64AsHex.zero : (self.overallFee.value / self.gasPrice.value).applyMultiplier(amountMultiplier).toUInt64AsHexClamped()
let maxAmountL1 = self.l1GasPrice == .zero ? UInt64AsHex.zero : (self.overallFee.value / self.l1GasPrice.value).applyMultiplier(amountMultiplier).toUInt64AsHexClamped()
let maxAmountL2 = self.l2GasPrice == .zero ? UInt64AsHex.zero : (self.overallFee.value / self.l2GasPrice.value).applyMultiplier(amountMultiplier).toUInt64AsHexClamped()

let maxUnitPrice = self.gasPrice.value.applyMultiplier(unitPriceMultiplier).toUInt128AsHexClamped()
let maxUnitPriceL1 = self.l1GasPrice.value.applyMultiplier(unitPriceMultiplier).toUInt128AsHexClamped()
let maxUnitPriceL2 = self.l2GasPrice.value.applyMultiplier(unitPriceMultiplier).toUInt128AsHexClamped()

let l1Gas = StarknetResourceBounds(maxAmount: maxAmount, maxPricePerUnit: maxUnitPrice)
return StarknetResourceBoundsMapping(l1Gas: l1Gas)
let l1Gas = StarknetResourceBounds(maxAmount: maxAmountL1, maxPricePerUnit: maxUnitPriceL1)
let l2Gas = StarknetResourceBounds(maxAmount: maxAmountL2, maxPricePerUnit: maxUnitPriceL2)
return StarknetResourceBoundsMapping(l1Gas: l1Gas, l2Gas: l2Gas)
}

/// Convert estimated fee to max fee with applied multiplier.
Expand Down
19 changes: 8 additions & 11 deletions Sources/Starknet/Data/Execution.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,9 @@ public struct StarknetInvokeParamsV3 {
public let nonceDataAvailabilityMode: StarknetDAMode
public let feeDataAvailabilityMode: StarknetDAMode

public init(nonce: Felt, l1ResourceBounds: StarknetResourceBounds) {
public init(nonce: Felt, resourceBounds: StarknetResourceBoundsMapping) {
self.nonce = nonce
// As of Starknet 0.13, most of v3 fields have hardcoded values.
self.resourceBounds = StarknetResourceBoundsMapping(l1Gas: l1ResourceBounds)
self.resourceBounds = resourceBounds
self.tip = .zero
self.paymasterData = []
self.accountDeploymentData = []
Expand All @@ -53,10 +52,9 @@ public struct StarknetOptionalInvokeParamsV3 {
public let nonceDataAvailabilityMode: StarknetDAMode
public let feeDataAvailabilityMode: StarknetDAMode

public init(nonce: Felt? = nil, l1ResourceBounds: StarknetResourceBounds? = nil) {
public init(nonce: Felt? = nil, resourceBounds: StarknetResourceBoundsMapping? = nil) {
self.nonce = nonce
// As of Starknet 0.13, most of v3 fields have hardcoded values.
self.resourceBounds = l1ResourceBounds.map(StarknetResourceBoundsMapping.init)
self.resourceBounds = resourceBounds
self.tip = .zero
self.paymasterData = []
self.accountDeploymentData = []
Expand All @@ -73,18 +71,17 @@ public struct StarknetDeployAccountParamsV3 {
public let nonceDataAvailabilityMode: StarknetDAMode
public let feeDataAvailabilityMode: StarknetDAMode

public init(nonce: Felt, l1ResourceBounds: StarknetResourceBounds) {
public init(nonce: Felt, resourceBounds: StarknetResourceBoundsMapping) {
self.nonce = nonce
// As of Starknet 0.13, most of v3 fields have hardcoded values.
self.resourceBounds = StarknetResourceBoundsMapping(l1Gas: l1ResourceBounds)
self.resourceBounds = resourceBounds
self.tip = .zero
self.paymasterData = []
self.nonceDataAvailabilityMode = .l1
self.feeDataAvailabilityMode = .l1
}

public init(l1ResourceBounds: StarknetResourceBounds) {
self.init(nonce: .zero, l1ResourceBounds: l1ResourceBounds)
public init(resourceBounds: StarknetResourceBoundsMapping) {
self.init(nonce: .zero, resourceBounds: resourceBounds)
}
}

Expand Down
48 changes: 28 additions & 20 deletions Sources/Starknet/Data/Responses.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,45 @@ public struct StarknetInvokeTransactionResponse: Decodable, Equatable {
}

public struct StarknetFeeEstimate: Decodable, Equatable {
public let gasConsumed: Felt
public let gasPrice: Felt
public let dataGasConsumed: Felt
public let dataGasPrice: Felt
public let l1GasConsumed: Felt
public let l1GasPrice: Felt
public let l2GasConsumed: Felt
public let l2GasPrice: Felt
public let l1DataGasConsumed: Felt
public let l1DataGasPrice: Felt
public let overallFee: Felt
public let feeUnit: StarknetPriceUnit

enum CodingKeys: String, CodingKey {
case gasConsumed = "gas_consumed"
case gasPrice = "gas_price"
case dataGasConsumed = "data_gas_consumed"
case dataGasPrice = "data_gas_price"
case l1GasConsumed = "l1_gas_consumed"
case l1GasPrice = "l1_gas_price"
case l2GasConsumed = "l2_gas_consumed"
case l2GasPrice = "l2_gas_price"
case l1DataGasConsumed = "l1_data_gas_consumed"
case l1DataGasPrice = "l1_data_gas_price"
case overallFee = "overall_fee"
case feeUnit = "unit"
case feeUnit = "fee_unit"
}

public init(gasConsumed: Felt, gasPrice: Felt, dataGasConsumed: Felt, dataGasPrice: Felt, overallFee: Felt, feeUnit: StarknetPriceUnit) {
self.gasConsumed = gasConsumed
self.gasPrice = gasPrice
self.dataGasConsumed = dataGasConsumed
self.dataGasPrice = dataGasPrice
public init(l1GasConsumed: Felt, l1GasPrice: Felt, l2GasConsumed: Felt, l2GasPrice: Felt, l1DataGasConsumed: Felt, l1DataGasPrice: Felt, overallFee: Felt, feeUnit: StarknetPriceUnit) {
self.l1GasConsumed = l1GasConsumed
self.l1GasPrice = l1GasPrice
self.l2GasConsumed = l2GasConsumed
self.l2GasPrice = l2GasPrice
self.l1DataGasConsumed = l1DataGasConsumed
self.l1DataGasPrice = l1DataGasPrice
self.overallFee = overallFee
self.feeUnit = feeUnit
}

public init?(gasConsumed: Felt, gasPrice: Felt, dataGasConsumed: Felt, dataGasPrice: Felt, feeUnit: StarknetPriceUnit) {
self.gasConsumed = gasConsumed
self.gasPrice = gasPrice
self.dataGasConsumed = dataGasConsumed
self.dataGasPrice = dataGasPrice
self.overallFee = Felt(gasPrice.value * gasConsumed.value + dataGasPrice.value * dataGasConsumed.value)!
public init?(l1GasConsumed: Felt, l1GasPrice: Felt, l2GasConsumed: Felt, l2GasPrice: Felt, l1DataGasConsumed: Felt, l1DataGasPrice: Felt, feeUnit: StarknetPriceUnit) {
self.l1GasConsumed = l1GasConsumed
self.l1GasPrice = l1GasPrice
self.l2GasConsumed = l2GasConsumed
self.l2GasPrice = l2GasPrice
self.l1DataGasConsumed = l1DataGasConsumed
self.l1DataGasPrice = l1DataGasPrice
self.overallFee = Felt(l1GasPrice.value * l1GasConsumed.value + l2GasPrice.value * l2GasConsumed.value + l1DataGasPrice.value * l1DataGasConsumed.value)!
self.feeUnit = feeUnit
}
}
Expand Down
72 changes: 11 additions & 61 deletions Sources/Starknet/Data/Transaction/Data/ExecutionResources.swift
Original file line number Diff line number Diff line change
@@ -1,78 +1,28 @@
import Foundation

public protocol StarknetResources: Decodable, Equatable {
var steps: Int { get }
var memoryHoles: Int? { get }
var rangeCheckApplications: Int? { get }
var pedersenApplications: Int? { get }
var poseidonApplications: Int? { get }
var ecOpApplications: Int? { get }
var ecdsaApplications: Int? { get }
var bitwiseApplications: Int? { get }
var keccakApplications: Int? { get }
var segmentArena: Int? { get }
}

public struct StarknetComputationResources: StarknetResources {
public let steps: Int
public let memoryHoles: Int?
public let rangeCheckApplications: Int?
public let pedersenApplications: Int?
public let poseidonApplications: Int?
public let ecOpApplications: Int?
public let ecdsaApplications: Int?
public let bitwiseApplications: Int?
public let keccakApplications: Int?
public let segmentArena: Int?

enum CodingKeys: String, CodingKey {
case steps
case memoryHoles = "memory_holes"
case rangeCheckApplications = "range_check_builtin_applications"
case pedersenApplications = "pedersen_builtin_applications"
case poseidonApplications = "poseidon_builtin_applications"
case ecOpApplications = "ec_op_builtin_applications"
case ecdsaApplications = "ecdsa_builtin_applications"
case bitwiseApplications = "bitwise_builtin_applications"
case keccakApplications = "keccak_builtin_applications"
case segmentArena = "segment_arena_builtin"
}
var l1Gas: Int { get }
var l2Gas: Int { get }
}

public struct StarknetExecutionResources: StarknetResources {
public let steps: Int
public let memoryHoles: Int?
public let rangeCheckApplications: Int?
public let pedersenApplications: Int?
public let poseidonApplications: Int?
public let ecOpApplications: Int?
public let ecdsaApplications: Int?
public let bitwiseApplications: Int?
public let keccakApplications: Int?
public let segmentArena: Int?
public let dataAvailability: StarknetDataAvailability
public let l1Gas: Int
public let l1DataGas: Int
public let l2Gas: Int

enum CodingKeys: String, CodingKey {
case steps
case memoryHoles = "memory_holes"
case rangeCheckApplications = "range_check_builtin_applications"
case pedersenApplications = "pedersen_builtin_applications"
case poseidonApplications = "poseidon_builtin_applications"
case ecOpApplications = "ec_op_builtin_applications"
case ecdsaApplications = "ecdsa_builtin_applications"
case bitwiseApplications = "bitwise_builtin_applications"
case keccakApplications = "keccak_builtin_applications"
case segmentArena = "segment_arena_builtin"
case dataAvailability = "data_availability"
case l1Gas = "l1_gas"
case l1DataGas = "l1_data_gas"
case l2Gas = "l2_gas"
}
}

public struct StarknetDataAvailability: Decodable, Equatable {
public struct StarknetInnerCallExecutionResources: StarknetResources {
public let l1Gas: Int
public let l1DataGas: Int
public let l2Gas: Int

enum CodingKeys: String, CodingKey {
case l1Gas = "l1_gas"
case l1DataGas = "l1_data_gas"
case l2Gas = "l2_gas"
}
}
5 changes: 0 additions & 5 deletions Sources/Starknet/Data/Transaction/Data/ResourceBounds.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ public struct StarknetResourceBoundsMapping: Codable, Equatable, Hashable {
public let l1Gas: StarknetResourceBounds
public let l2Gas: StarknetResourceBounds

public init(l1Gas: StarknetResourceBounds) {
self.l1Gas = l1Gas
self.l2Gas = StarknetResourceBounds.zero
}

enum CodingKeys: String, CodingKey {
case l1Gas = "l1_gas"
case l2Gas = "l2_gas"
Expand Down
Loading

0 comments on commit 4b56a9f

Please sign in to comment.