|
1 | 1 | import { TypeTag } from './avm_memory_types.js'; |
| 2 | +import { Addressing, AddressingMode } from './opcodes/addressing_mode.js'; |
2 | 3 | import { Opcode } from './serialization/instruction_serialization.js'; |
3 | 4 |
|
4 | | -/** Gas cost in L1, L2, and DA for a given instruction. */ |
5 | | -export type GasCost = { |
| 5 | +/** Gas counters in L1, L2, and DA. */ |
| 6 | +export type Gas = { |
6 | 7 | l1Gas: number; |
7 | 8 | l2Gas: number; |
8 | 9 | daGas: number; |
9 | 10 | }; |
10 | 11 |
|
| 12 | +/** Maps a Gas struct to gasLeft properties. */ |
| 13 | +export function gasToGasLeft(gas: Gas) { |
| 14 | + return { l1GasLeft: gas.l1Gas, l2GasLeft: gas.l2Gas, daGasLeft: gas.daGas }; |
| 15 | +} |
| 16 | + |
| 17 | +/** Maps gasLeft properties to a gas struct. */ |
| 18 | +export function gasLeftToGas(gasLeft: { l1GasLeft: number; l2GasLeft: number; daGasLeft: number }) { |
| 19 | + return { l1Gas: gasLeft.l1GasLeft, l2Gas: gasLeft.l2GasLeft, daGas: gasLeft.daGasLeft }; |
| 20 | +} |
| 21 | + |
11 | 22 | /** Creates a new instance with all values set to zero except the ones set. */ |
12 | | -export function makeGasCost(gasCost: Partial<GasCost>) { |
13 | | - return { ...EmptyGasCost, ...gasCost }; |
| 23 | +export function makeGasCost(gasCost: Partial<Gas>) { |
| 24 | + return { ...EmptyGas, ...gasCost }; |
| 25 | +} |
| 26 | + |
| 27 | +/** Sums together multiple instances of Gas. */ |
| 28 | +export function sumGas(...gases: Partial<Gas>[]) { |
| 29 | + return gases.reduce( |
| 30 | + (acc: Gas, gas) => ({ |
| 31 | + l1Gas: acc.l1Gas + (gas.l1Gas ?? 0), |
| 32 | + l2Gas: acc.l2Gas + (gas.l2Gas ?? 0), |
| 33 | + daGas: acc.daGas + (gas.daGas ?? 0), |
| 34 | + }), |
| 35 | + EmptyGas, |
| 36 | + ); |
14 | 37 | } |
15 | 38 |
|
16 | | -/** Gas cost of zero across all gas dimensions. */ |
17 | | -export const EmptyGasCost = { |
| 39 | +/** Zero gas across all gas dimensions. */ |
| 40 | +export const EmptyGas: Gas = { |
18 | 41 | l1Gas: 0, |
19 | 42 | l2Gas: 0, |
20 | 43 | daGas: 0, |
@@ -103,12 +126,29 @@ export const GasCosts = { |
103 | 126 | [Opcode.PEDERSEN]: TemporaryDefaultGasCost, // temp - may be removed, but alot of contracts rely on i: TemporaryDefaultGasCost,t |
104 | 127 | } as const; |
105 | 128 |
|
| 129 | +/** Returns the fixed gas cost for a given opcode, or throws if set to dynamic. */ |
| 130 | +export function getFixedGasCost(opcode: Opcode): Gas { |
| 131 | + const cost = GasCosts[opcode]; |
| 132 | + if (cost === DynamicGasCost) { |
| 133 | + throw new Error(`Opcode ${Opcode[opcode]} has dynamic gas cost`); |
| 134 | + } |
| 135 | + return cost; |
| 136 | +} |
| 137 | + |
| 138 | +/** Returns the additional cost from indirect accesses to memory. */ |
| 139 | +export function getCostFromIndirectAccess(indirect: number): Partial<Gas> { |
| 140 | + const indirectCount = Addressing.fromWire(indirect).modePerOperand.filter( |
| 141 | + mode => mode === AddressingMode.INDIRECT, |
| 142 | + ).length; |
| 143 | + return { l2Gas: indirectCount * GasCostConstants.COST_PER_INDIRECT_ACCESS }; |
| 144 | +} |
| 145 | + |
106 | 146 | /** Constants used in base cost calculations. */ |
107 | 147 | export const GasCostConstants = { |
108 | 148 | SET_COST_PER_BYTE: 100, |
109 | 149 | CALLDATACOPY_COST_PER_BYTE: 10, |
110 | 150 | ARITHMETIC_COST_PER_BYTE: 10, |
111 | | - ARITHMETIC_COST_PER_INDIRECT_ACCESS: 5, |
| 151 | + COST_PER_INDIRECT_ACCESS: 5, |
112 | 152 | }; |
113 | 153 |
|
114 | 154 | /** Returns a multiplier based on the size of the type represented by the tag. Throws on uninitialized or invalid. */ |
|
0 commit comments