@aztec/simulator 0.87.1 → 0.87.2-nightly.20250524
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/private/acvm/oracle/oracle.d.ts +1 -1
- package/dest/private/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/private/acvm/oracle/oracle.js +2 -2
- package/dest/private/acvm/oracle/typed_oracle.d.ts +1 -1
- package/dest/private/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/private/acvm/oracle/typed_oracle.js +2 -2
- package/dest/private/private_execution_oracle.d.ts +1 -1
- package/dest/private/private_execution_oracle.d.ts.map +1 -1
- package/dest/private/private_execution_oracle.js +1 -1
- package/dest/private/providers/circuit_recording/circuit_recorder.d.ts +1 -1
- package/dest/private/providers/circuit_recording/circuit_recorder.js +1 -1
- package/dest/private/utility_execution_oracle.d.ts +1 -1
- package/dest/private/utility_execution_oracle.d.ts.map +1 -1
- package/dest/private/utility_execution_oracle.js +1 -1
- package/dest/public/avm/avm_gas.d.ts +4 -5
- package/dest/public/avm/avm_gas.d.ts.map +1 -1
- package/dest/public/avm/avm_gas.js +28 -18
- package/dest/public/avm/fixtures/utils.js +1 -1
- package/dest/public/avm/opcodes/accrued_substate.d.ts.map +1 -1
- package/dest/public/avm/opcodes/accrued_substate.js +8 -7
- package/dest/public/avm/opcodes/addressing_mode.d.ts +2 -0
- package/dest/public/avm/opcodes/addressing_mode.d.ts.map +1 -1
- package/dest/public/avm/opcodes/addressing_mode.js +6 -0
- package/dest/public/avm/opcodes/arithmetic.d.ts.map +1 -1
- package/dest/public/avm/opcodes/arithmetic.js +1 -1
- package/dest/public/avm/opcodes/bitwise.d.ts +5 -1
- package/dest/public/avm/opcodes/bitwise.d.ts.map +1 -1
- package/dest/public/avm/opcodes/bitwise.js +17 -2
- package/dest/public/avm/opcodes/comparators.d.ts.map +1 -1
- package/dest/public/avm/opcodes/comparators.js +1 -1
- package/dest/public/avm/opcodes/contract.d.ts.map +1 -1
- package/dest/public/avm/opcodes/contract.js +1 -1
- package/dest/public/avm/opcodes/control_flow.d.ts.map +1 -1
- package/dest/public/avm/opcodes/control_flow.js +4 -4
- package/dest/public/avm/opcodes/conversion.d.ts +1 -0
- package/dest/public/avm/opcodes/conversion.d.ts.map +1 -1
- package/dest/public/avm/opcodes/conversion.js +263 -2
- package/dest/public/avm/opcodes/ec_add.d.ts.map +1 -1
- package/dest/public/avm/opcodes/ec_add.js +1 -1
- package/dest/public/avm/opcodes/environment_getters.d.ts.map +1 -1
- package/dest/public/avm/opcodes/environment_getters.js +1 -1
- package/dest/public/avm/opcodes/external_calls.d.ts.map +1 -1
- package/dest/public/avm/opcodes/external_calls.js +6 -8
- package/dest/public/avm/opcodes/hashing.d.ts.map +1 -1
- package/dest/public/avm/opcodes/hashing.js +3 -3
- package/dest/public/avm/opcodes/instruction.d.ts +9 -3
- package/dest/public/avm/opcodes/instruction.d.ts.map +1 -1
- package/dest/public/avm/opcodes/instruction.js +12 -7
- package/dest/public/avm/opcodes/memory.d.ts.map +1 -1
- package/dest/public/avm/opcodes/memory.js +8 -6
- package/dest/public/avm/opcodes/misc.js +1 -3
- package/dest/public/avm/opcodes/storage.d.ts.map +1 -1
- package/dest/public/avm/opcodes/storage.js +5 -3
- package/dest/public/fixtures/index.d.ts +1 -0
- package/dest/public/fixtures/index.d.ts.map +1 -1
- package/dest/public/fixtures/index.js +1 -0
- package/dest/public/fixtures/minimal_public_tx.d.ts +9 -0
- package/dest/public/fixtures/minimal_public_tx.d.ts.map +1 -0
- package/dest/public/fixtures/minimal_public_tx.js +43 -0
- package/dest/public/public_tx_simulator/apps_tests/amm_test.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/apps_tests/amm_test.js +32 -18
- package/dest/public/public_tx_simulator/public_tx_context.d.ts +1 -1
- package/dest/public/public_tx_simulator/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/public_tx_context.js +5 -4
- package/dest/public/side_effect_trace.d.ts +4 -1
- package/dest/public/side_effect_trace.d.ts.map +1 -1
- package/dest/public/side_effect_trace.js +13 -2
- package/dest/public/side_effect_trace_interface.d.ts +1 -0
- package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
- package/dest/public/state_manager/state_manager.d.ts +1 -0
- package/dest/public/state_manager/state_manager.d.ts.map +1 -1
- package/dest/public/state_manager/state_manager.js +3 -0
- package/package.json +15 -15
- package/src/private/acvm/oracle/oracle.ts +2 -2
- package/src/private/acvm/oracle/typed_oracle.ts +2 -2
- package/src/private/private_execution_oracle.ts +1 -1
- package/src/private/providers/circuit_recording/circuit_recorder.ts +1 -1
- package/src/private/utility_execution_oracle.ts +1 -1
- package/src/public/avm/avm_gas.ts +20 -14
- package/src/public/avm/fixtures/utils.ts +1 -1
- package/src/public/avm/opcodes/accrued_substate.ts +23 -7
- package/src/public/avm/opcodes/addressing_mode.ts +8 -0
- package/src/public/avm/opcodes/arithmetic.ts +3 -1
- package/src/public/avm/opcodes/bitwise.ts +26 -2
- package/src/public/avm/opcodes/comparators.ts +3 -1
- package/src/public/avm/opcodes/contract.ts +3 -1
- package/src/public/avm/opcodes/control_flow.ts +6 -4
- package/src/public/avm/opcodes/conversion.ts +21 -2
- package/src/public/avm/opcodes/ec_add.ts +3 -1
- package/src/public/avm/opcodes/environment_getters.ts +3 -1
- package/src/public/avm/opcodes/external_calls.ts +16 -8
- package/src/public/avm/opcodes/hashing.ts +11 -3
- package/src/public/avm/opcodes/instruction.ts +14 -7
- package/src/public/avm/opcodes/memory.ts +23 -6
- package/src/public/avm/opcodes/misc.ts +4 -4
- package/src/public/avm/opcodes/storage.ts +13 -3
- package/src/public/fixtures/index.ts +1 -0
- package/src/public/fixtures/minimal_public_tx.ts +57 -0
- package/src/public/public_tx_simulator/apps_tests/amm_test.ts +51 -20
- package/src/public/public_tx_simulator/public_tx_context.ts +26 -5
- package/src/public/side_effect_trace.ts +13 -0
- package/src/public/side_effect_trace_interface.ts +1 -0
- package/src/public/state_manager/state_manager.ts +4 -0
|
@@ -500,7 +500,7 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle {
|
|
|
500
500
|
await this.executionDataProvider.incrementAppTaggingSecretIndexAsSender(this.contractAddress, sender, recipient);
|
|
501
501
|
}
|
|
502
502
|
|
|
503
|
-
public override async
|
|
503
|
+
public override async fetchTaggedLogs(pendingTaggedLogArrayBaseSlot: Fr) {
|
|
504
504
|
await this.executionDataProvider.syncTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot, this.scopes);
|
|
505
505
|
|
|
506
506
|
await this.executionDataProvider.removeNullifiedNotes(this.contractAddress);
|
|
@@ -274,7 +274,7 @@ export class UtilityExecutionOracle extends TypedOracle {
|
|
|
274
274
|
return await this.executionDataProvider.getIndexedTaggingSecretAsSender(this.contractAddress, sender, recipient);
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
-
public override async
|
|
277
|
+
public override async fetchTaggedLogs(pendingTaggedLogArrayBaseSlot: Fr) {
|
|
278
278
|
await this.executionDataProvider.syncTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot, this.scopes);
|
|
279
279
|
|
|
280
280
|
await this.executionDataProvider.removeNullifiedNotes(this.contractAddress);
|
|
@@ -104,7 +104,7 @@ const BASE_GAS_COSTS: Record<Opcode, Gas> = {
|
|
|
104
104
|
[Opcode.MOV_8]: makeCost(c.AVM_MOV_BASE_L2_GAS, 0),
|
|
105
105
|
[Opcode.MOV_16]: makeCost(c.AVM_MOV_BASE_L2_GAS, 0),
|
|
106
106
|
[Opcode.SLOAD]: makeCost(c.AVM_SLOAD_BASE_L2_GAS, 0),
|
|
107
|
-
[Opcode.SSTORE]: makeCost(c.AVM_SSTORE_BASE_L2_GAS,
|
|
107
|
+
[Opcode.SSTORE]: makeCost(c.AVM_SSTORE_BASE_L2_GAS, 0), // DA gas is dynamic
|
|
108
108
|
[Opcode.NOTEHASHEXISTS]: makeCost(c.AVM_NOTEHASHEXISTS_BASE_L2_GAS, 0),
|
|
109
109
|
[Opcode.EMITNOTEHASH]: makeCost(c.AVM_EMITNOTEHASH_BASE_L2_GAS, c.AVM_EMITNOTEHASH_BASE_DA_GAS),
|
|
110
110
|
[Opcode.NULLIFIEREXISTS]: makeCost(c.AVM_NULLIFIEREXISTS_BASE_L2_GAS, 0),
|
|
@@ -129,13 +129,16 @@ const BASE_GAS_COSTS: Record<Opcode, Gas> = {
|
|
|
129
129
|
const DYNAMIC_GAS_COSTS = new Map<Opcode, Gas>([
|
|
130
130
|
[Opcode.CALLDATACOPY, makeCost(c.AVM_CALLDATACOPY_DYN_L2_GAS, 0)],
|
|
131
131
|
[Opcode.RETURNDATACOPY, makeCost(c.AVM_RETURNDATACOPY_DYN_L2_GAS, 0)],
|
|
132
|
+
// TODO: Call and static call based on bytecode length
|
|
132
133
|
[Opcode.EMITUNENCRYPTEDLOG, makeCost(c.AVM_EMITUNENCRYPTEDLOG_DYN_L2_GAS, c.AVM_EMITUNENCRYPTEDLOG_DYN_DA_GAS)],
|
|
133
|
-
[Opcode.CALL, makeCost(c.AVM_CALL_DYN_L2_GAS, 0)],
|
|
134
|
-
[Opcode.STATICCALL, makeCost(c.AVM_STATICCALL_DYN_L2_GAS, 0)],
|
|
135
|
-
[Opcode.RETURN, makeCost(c.AVM_RETURN_DYN_L2_GAS, 0)],
|
|
136
|
-
[Opcode.REVERT_8, makeCost(c.AVM_REVERT_DYN_L2_GAS, 0)],
|
|
137
|
-
[Opcode.REVERT_16, makeCost(c.AVM_REVERT_DYN_L2_GAS, 0)],
|
|
138
134
|
[Opcode.TORADIXBE, makeCost(c.AVM_TORADIXBE_DYN_L2_GAS, 0)],
|
|
135
|
+
[Opcode.AND_8, makeCost(c.AVM_BITWISE_DYN_L2_GAS, 0)],
|
|
136
|
+
[Opcode.AND_16, makeCost(c.AVM_BITWISE_DYN_L2_GAS, 0)],
|
|
137
|
+
[Opcode.OR_8, makeCost(c.AVM_BITWISE_DYN_L2_GAS, 0)],
|
|
138
|
+
[Opcode.OR_16, makeCost(c.AVM_BITWISE_DYN_L2_GAS, 0)],
|
|
139
|
+
[Opcode.XOR_8, makeCost(c.AVM_BITWISE_DYN_L2_GAS, 0)],
|
|
140
|
+
[Opcode.XOR_16, makeCost(c.AVM_BITWISE_DYN_L2_GAS, 0)],
|
|
141
|
+
[Opcode.SSTORE, makeCost(0, c.AVM_SSTORE_DYN_DA_GAS)],
|
|
139
142
|
]);
|
|
140
143
|
|
|
141
144
|
/** Returns the fixed base gas cost for a given opcode. */
|
|
@@ -143,17 +146,20 @@ export function getBaseGasCost(opcode: Opcode): Gas {
|
|
|
143
146
|
return BASE_GAS_COSTS[opcode];
|
|
144
147
|
}
|
|
145
148
|
|
|
146
|
-
export function
|
|
147
|
-
return
|
|
149
|
+
export function computeAddressingCost(indirectOperandsCount: number, relativeOperandsCount: number): Gas {
|
|
150
|
+
return makeCost(
|
|
151
|
+
indirectOperandsCount * c.AVM_ADDRESSING_INDIRECT_L2_GAS + relativeOperandsCount * c.AVM_ADDRESSING_RELATIVE_L2_GAS,
|
|
152
|
+
0,
|
|
153
|
+
);
|
|
148
154
|
}
|
|
149
155
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
return mulGas(baseCost, getGasCostMultiplierFromTypeTag(tag));
|
|
156
|
+
export function getDynamicGasCost(opcode: Opcode): Gas {
|
|
157
|
+
return DYNAMIC_GAS_COSTS.has(opcode) ? DYNAMIC_GAS_COSTS.get(opcode)! : makeCost(0, 0);
|
|
153
158
|
}
|
|
154
159
|
|
|
155
|
-
/** Returns a multiplier based on the size of the type represented by the tag.
|
|
156
|
-
|
|
160
|
+
/** Returns a multiplier based on the byte size of the type represented by the integer tag.
|
|
161
|
+
* Used to account for necessary rows in the bitwise trace. Throws on invalid. */
|
|
162
|
+
export function getBitwiseDynamicGasMultiplier(tag: TypeTag) {
|
|
157
163
|
switch (tag) {
|
|
158
164
|
case TypeTag.UINT1: // same as u8
|
|
159
165
|
return 1;
|
|
@@ -168,7 +174,7 @@ function getGasCostMultiplierFromTypeTag(tag: TypeTag) {
|
|
|
168
174
|
case TypeTag.UINT128:
|
|
169
175
|
return 16;
|
|
170
176
|
case TypeTag.FIELD:
|
|
171
|
-
return
|
|
177
|
+
return 0; // Field is not allowed for bitwise operations. However we don't fail in gas, since we'll fail in bitwise.
|
|
172
178
|
case TypeTag.INVALID:
|
|
173
179
|
throw new InstructionExecutionError(`Invalid tag type for gas cost multiplier: ${TypeTag[tag]}`);
|
|
174
180
|
}
|
|
@@ -122,7 +122,7 @@ export async function createContractClassAndInstance(
|
|
|
122
122
|
const contractClass = await makeContractClassPublic(seed, bytecode);
|
|
123
123
|
|
|
124
124
|
const constructorAbi = getContractFunctionAbi('constructor', contractArtifact);
|
|
125
|
-
const { publicKeys } = await deriveKeys(Fr
|
|
125
|
+
const { publicKeys } = await deriveKeys(new Fr(seed));
|
|
126
126
|
const initializationHash = await computeInitializationHash(constructorAbi, constructorArgs);
|
|
127
127
|
const contractInstance =
|
|
128
128
|
originalContractClassId === undefined
|
|
@@ -31,7 +31,9 @@ export class NoteHashExists extends Instruction {
|
|
|
31
31
|
const memory = context.machineState.memory;
|
|
32
32
|
const addressing = Addressing.fromWire(this.indirect);
|
|
33
33
|
|
|
34
|
-
context.machineState.consumeGas(
|
|
34
|
+
context.machineState.consumeGas(
|
|
35
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
36
|
+
);
|
|
35
37
|
const operands = [this.noteHashOffset, this.leafIndexOffset, this.existsOffset];
|
|
36
38
|
const [noteHashOffset, leafIndexOffset, existsOffset] = addressing.resolve(operands, memory);
|
|
37
39
|
memory.checkTags(TypeTag.FIELD, noteHashOffset, leafIndexOffset);
|
|
@@ -62,7 +64,9 @@ export class EmitNoteHash extends Instruction {
|
|
|
62
64
|
const memory = context.machineState.memory;
|
|
63
65
|
const addressing = Addressing.fromWire(this.indirect);
|
|
64
66
|
|
|
65
|
-
context.machineState.consumeGas(
|
|
67
|
+
context.machineState.consumeGas(
|
|
68
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
69
|
+
);
|
|
66
70
|
|
|
67
71
|
const operands = [this.noteHashOffset];
|
|
68
72
|
const [noteHashOffset] = addressing.resolve(operands, memory);
|
|
@@ -102,7 +106,9 @@ export class NullifierExists extends Instruction {
|
|
|
102
106
|
const memory = context.machineState.memory;
|
|
103
107
|
const addressing = Addressing.fromWire(this.indirect);
|
|
104
108
|
|
|
105
|
-
context.machineState.consumeGas(
|
|
109
|
+
context.machineState.consumeGas(
|
|
110
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
111
|
+
);
|
|
106
112
|
|
|
107
113
|
const operands = [this.nullifierOffset, this.addressOffset, this.existsOffset];
|
|
108
114
|
const [nullifierOffset, addressOffset, existsOffset] = addressing.resolve(operands, memory);
|
|
@@ -137,7 +143,9 @@ export class EmitNullifier extends Instruction {
|
|
|
137
143
|
const memory = context.machineState.memory;
|
|
138
144
|
const addressing = Addressing.fromWire(this.indirect);
|
|
139
145
|
|
|
140
|
-
context.machineState.consumeGas(
|
|
146
|
+
context.machineState.consumeGas(
|
|
147
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
148
|
+
);
|
|
141
149
|
|
|
142
150
|
const operands = [this.nullifierOffset];
|
|
143
151
|
const [nullifierOffset] = addressing.resolve(operands, memory);
|
|
@@ -184,7 +192,9 @@ export class L1ToL2MessageExists extends Instruction {
|
|
|
184
192
|
const memory = context.machineState.memory;
|
|
185
193
|
const addressing = Addressing.fromWire(this.indirect);
|
|
186
194
|
|
|
187
|
-
context.machineState.consumeGas(
|
|
195
|
+
context.machineState.consumeGas(
|
|
196
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
197
|
+
);
|
|
188
198
|
|
|
189
199
|
const operands = [this.msgHashOffset, this.msgLeafIndexOffset, this.existsOffset];
|
|
190
200
|
const [msgHashOffset, msgLeafIndexOffset, existsOffset] = addressing.resolve(operands, memory);
|
|
@@ -220,6 +230,10 @@ export class EmitUnencryptedLog extends Instruction {
|
|
|
220
230
|
const memory = context.machineState.memory;
|
|
221
231
|
const addressing = Addressing.fromWire(this.indirect);
|
|
222
232
|
|
|
233
|
+
context.machineState.consumeGas(
|
|
234
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
235
|
+
);
|
|
236
|
+
|
|
223
237
|
const operands = [this.logOffset, this.logSizeOffset];
|
|
224
238
|
const [logOffset, logSizeOffset] = addressing.resolve(operands, memory);
|
|
225
239
|
memory.checkTag(TypeTag.UINT32, logSizeOffset);
|
|
@@ -228,7 +242,7 @@ export class EmitUnencryptedLog extends Instruction {
|
|
|
228
242
|
|
|
229
243
|
const contractAddress = context.environment.address;
|
|
230
244
|
|
|
231
|
-
context.machineState.consumeGas(this.
|
|
245
|
+
context.machineState.consumeGas(this.dynamicGasCost(logSize));
|
|
232
246
|
const log = memory.getSlice(logOffset, logSize).map(f => f.toFr());
|
|
233
247
|
context.persistableState.writePublicLog(contractAddress, log);
|
|
234
248
|
}
|
|
@@ -256,7 +270,9 @@ export class SendL2ToL1Message extends Instruction {
|
|
|
256
270
|
const memory = context.machineState.memory;
|
|
257
271
|
const addressing = Addressing.fromWire(this.indirect);
|
|
258
272
|
|
|
259
|
-
context.machineState.consumeGas(
|
|
273
|
+
context.machineState.consumeGas(
|
|
274
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
275
|
+
);
|
|
260
276
|
|
|
261
277
|
const operands = [this.recipientOffset, this.contentOffset];
|
|
262
278
|
const [recipientOffset, contentOffset] = addressing.resolve(operands, memory);
|
|
@@ -54,6 +54,14 @@ export class Addressing {
|
|
|
54
54
|
return wire;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
public indirectOperandsCount(): number {
|
|
58
|
+
return this.modePerOperand.filter(mode => mode & AddressingMode.INDIRECT).length;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public relativeOperandsCount(): number {
|
|
62
|
+
return this.modePerOperand.filter(mode => mode & AddressingMode.RELATIVE).length;
|
|
63
|
+
}
|
|
64
|
+
|
|
57
65
|
/**
|
|
58
66
|
* Resolves the offsets using the addressing mode.
|
|
59
67
|
* @param offsets The offsets to resolve.
|
|
@@ -16,7 +16,9 @@ export abstract class ThreeOperandArithmeticInstruction extends ThreeOperandInst
|
|
|
16
16
|
const memory = context.machineState.memory;
|
|
17
17
|
const addressing = Addressing.fromWire(this.indirect);
|
|
18
18
|
|
|
19
|
-
context.machineState.consumeGas(
|
|
19
|
+
context.machineState.consumeGas(
|
|
20
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
21
|
+
);
|
|
20
22
|
|
|
21
23
|
const operands = [this.aOffset, this.bOffset, this.dstOffset];
|
|
22
24
|
const [aOffset, bOffset, dstOffset] = addressing.resolve(operands, memory);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AvmContext } from '../avm_context.js';
|
|
2
|
+
import { getBitwiseDynamicGasMultiplier } from '../avm_gas.js';
|
|
2
3
|
import { type IntegralValue, TaggedMemory, type TaggedMemoryInterface, TypeTag } from '../avm_memory_types.js';
|
|
3
4
|
import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
|
|
4
5
|
import { Addressing } from './addressing_mode.js';
|
|
@@ -10,12 +11,17 @@ abstract class ThreeOperandBitwiseInstruction extends ThreeOperandInstruction {
|
|
|
10
11
|
const memory = context.machineState.memory;
|
|
11
12
|
const addressing = Addressing.fromWire(this.indirect);
|
|
12
13
|
|
|
13
|
-
context.machineState.consumeGas(
|
|
14
|
+
context.machineState.consumeGas(
|
|
15
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
16
|
+
);
|
|
14
17
|
|
|
15
18
|
const operands = [this.aOffset, this.bOffset, this.dstOffset];
|
|
16
19
|
const [aOffset, bOffset, dstOffset] = addressing.resolve(operands, memory);
|
|
17
20
|
this.checkTags(memory, aOffset, bOffset);
|
|
18
21
|
|
|
22
|
+
const multiplier = this.getDynamicMultiplier(memory.getTag(aOffset));
|
|
23
|
+
context.machineState.consumeGas(this.dynamicGasCost(multiplier));
|
|
24
|
+
|
|
19
25
|
const a = memory.getAs<IntegralValue>(aOffset);
|
|
20
26
|
const b = memory.getAs<IntegralValue>(bOffset);
|
|
21
27
|
|
|
@@ -28,6 +34,10 @@ abstract class ThreeOperandBitwiseInstruction extends ThreeOperandInstruction {
|
|
|
28
34
|
TaggedMemory.checkIsIntegralTag(memory.getTag(aOffset));
|
|
29
35
|
memory.checkTagsAreSame(aOffset, bOffset);
|
|
30
36
|
}
|
|
37
|
+
|
|
38
|
+
protected getDynamicMultiplier(_lhsTag: TypeTag): number {
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
export class And extends ThreeOperandBitwiseInstruction {
|
|
@@ -37,6 +47,10 @@ export class And extends ThreeOperandBitwiseInstruction {
|
|
|
37
47
|
protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
38
48
|
return a.and(b);
|
|
39
49
|
}
|
|
50
|
+
|
|
51
|
+
protected override getDynamicMultiplier(lhsTag: TypeTag): number {
|
|
52
|
+
return getBitwiseDynamicGasMultiplier(lhsTag);
|
|
53
|
+
}
|
|
40
54
|
}
|
|
41
55
|
|
|
42
56
|
export class Or extends ThreeOperandBitwiseInstruction {
|
|
@@ -46,6 +60,10 @@ export class Or extends ThreeOperandBitwiseInstruction {
|
|
|
46
60
|
protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
47
61
|
return a.or(b);
|
|
48
62
|
}
|
|
63
|
+
|
|
64
|
+
protected override getDynamicMultiplier(lhsTag: TypeTag): number {
|
|
65
|
+
return getBitwiseDynamicGasMultiplier(lhsTag);
|
|
66
|
+
}
|
|
49
67
|
}
|
|
50
68
|
|
|
51
69
|
export class Xor extends ThreeOperandBitwiseInstruction {
|
|
@@ -55,6 +73,10 @@ export class Xor extends ThreeOperandBitwiseInstruction {
|
|
|
55
73
|
protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
56
74
|
return a.xor(b);
|
|
57
75
|
}
|
|
76
|
+
|
|
77
|
+
protected override getDynamicMultiplier(lhsTag: TypeTag): number {
|
|
78
|
+
return getBitwiseDynamicGasMultiplier(lhsTag);
|
|
79
|
+
}
|
|
58
80
|
}
|
|
59
81
|
|
|
60
82
|
export class Shl extends ThreeOperandBitwiseInstruction {
|
|
@@ -102,7 +124,9 @@ export class Not extends Instruction {
|
|
|
102
124
|
const memory = context.machineState.memory;
|
|
103
125
|
const addressing = Addressing.fromWire(this.indirect);
|
|
104
126
|
|
|
105
|
-
context.machineState.consumeGas(
|
|
127
|
+
context.machineState.consumeGas(
|
|
128
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
129
|
+
);
|
|
106
130
|
|
|
107
131
|
const operands = [this.srcOffset, this.dstOffset];
|
|
108
132
|
const [srcOffset, dstOffset] = addressing.resolve(operands, memory);
|
|
@@ -9,7 +9,9 @@ abstract class ComparatorInstruction extends ThreeOperandInstruction {
|
|
|
9
9
|
const memory = context.machineState.memory;
|
|
10
10
|
const addressing = Addressing.fromWire(this.indirect);
|
|
11
11
|
|
|
12
|
-
context.machineState.consumeGas(
|
|
12
|
+
context.machineState.consumeGas(
|
|
13
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
14
|
+
);
|
|
13
15
|
|
|
14
16
|
const operands = [this.aOffset, this.bOffset, this.dstOffset];
|
|
15
17
|
const [aOffset, bOffset, dstOffset] = addressing.resolve(operands, memory);
|
|
@@ -36,7 +36,9 @@ export class GetContractInstance extends Instruction {
|
|
|
36
36
|
const memory = context.machineState.memory;
|
|
37
37
|
const addressing = Addressing.fromWire(this.indirect);
|
|
38
38
|
|
|
39
|
-
context.machineState.consumeGas(
|
|
39
|
+
context.machineState.consumeGas(
|
|
40
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
41
|
+
);
|
|
40
42
|
|
|
41
43
|
if (!(this.memberEnum in ContractInstanceMember)) {
|
|
42
44
|
throw new InstructionExecutionError(`Invalid GETCONSTRACTINSTANCE member enum ${this.memberEnum}`);
|
|
@@ -16,7 +16,7 @@ export class Jump extends Instruction {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
public async execute(context: AvmContext): Promise<void> {
|
|
19
|
-
context.machineState.consumeGas(this.
|
|
19
|
+
context.machineState.consumeGas(this.baseGasCost(0, 0));
|
|
20
20
|
|
|
21
21
|
context.machineState.pc = this.jumpOffset;
|
|
22
22
|
}
|
|
@@ -50,7 +50,9 @@ export class JumpI extends Instruction {
|
|
|
50
50
|
const memory = context.machineState.memory;
|
|
51
51
|
const addressing = Addressing.fromWire(this.indirect);
|
|
52
52
|
|
|
53
|
-
context.machineState.consumeGas(
|
|
53
|
+
context.machineState.consumeGas(
|
|
54
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
55
|
+
);
|
|
54
56
|
|
|
55
57
|
const operands = [this.condOffset];
|
|
56
58
|
const [condOffset] = addressing.resolve(operands, memory);
|
|
@@ -79,7 +81,7 @@ export class InternalCall extends Instruction {
|
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
public async execute(context: AvmContext): Promise<void> {
|
|
82
|
-
context.machineState.consumeGas(this.
|
|
84
|
+
context.machineState.consumeGas(this.baseGasCost(0, 0));
|
|
83
85
|
|
|
84
86
|
context.machineState.internalCallStack.push({
|
|
85
87
|
callPc: context.machineState.pc,
|
|
@@ -104,7 +106,7 @@ export class InternalReturn extends Instruction {
|
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
public async execute(context: AvmContext): Promise<void> {
|
|
107
|
-
context.machineState.consumeGas(this.
|
|
109
|
+
context.machineState.consumeGas(this.baseGasCost(0, 0));
|
|
108
110
|
|
|
109
111
|
const stackEntry = context.machineState.internalCallStack.pop();
|
|
110
112
|
if (stackEntry === undefined) {
|
|
@@ -35,6 +35,10 @@ export class ToRadixBE extends Instruction {
|
|
|
35
35
|
const memory = context.machineState.memory;
|
|
36
36
|
const addressing = Addressing.fromWire(this.indirect);
|
|
37
37
|
|
|
38
|
+
context.machineState.consumeGas(
|
|
39
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
40
|
+
);
|
|
41
|
+
|
|
38
42
|
const operands = [this.srcOffset, this.radixOffset, this.numLimbsOffset, this.outputBitsOffset, this.dstOffset];
|
|
39
43
|
const [srcOffset, radixOffset, numLimbsOffset, outputBitsOffset, dstOffset] = addressing.resolve(operands, memory);
|
|
40
44
|
|
|
@@ -45,11 +49,13 @@ export class ToRadixBE extends Instruction {
|
|
|
45
49
|
memory.checkTag(TypeTag.UINT1, outputBitsOffset);
|
|
46
50
|
|
|
47
51
|
const numLimbs = memory.get(numLimbsOffset).toNumber();
|
|
48
|
-
|
|
52
|
+
const radix: bigint = memory.get(radixOffset).toBigInt();
|
|
53
|
+
context.machineState.consumeGas(
|
|
54
|
+
this.dynamicGasCost(Math.max(numLimbs, radix > 256n ? 32 : MODULUS_LIMBS_PER_RADIX[Number(radix)])),
|
|
55
|
+
);
|
|
49
56
|
const outputBits = memory.get(outputBitsOffset).toNumber();
|
|
50
57
|
|
|
51
58
|
let value: bigint = memory.get(srcOffset).toBigInt();
|
|
52
|
-
const radix: bigint = memory.get(radixOffset).toBigInt();
|
|
53
59
|
|
|
54
60
|
if (radix < 2 || radix > 256) {
|
|
55
61
|
throw new InvalidToRadixInputsError(`ToRadixBE instruction's radix should be in range [2,256] (was ${radix}).`);
|
|
@@ -79,3 +85,16 @@ export class ToRadixBE extends Instruction {
|
|
|
79
85
|
memory.setSlice(dstOffset, res);
|
|
80
86
|
}
|
|
81
87
|
}
|
|
88
|
+
|
|
89
|
+
// First two are for radix = 0 and 1, which are invalid, so we have 0 limbs for those cases.
|
|
90
|
+
export const MODULUS_LIMBS_PER_RADIX: number[] = [
|
|
91
|
+
0, 0, 254, 161, 127, 110, 99, 91, 85, 81, 77, 74, 71, 69, 67, 65, 64, 63, 61, 60, 59, 58, 57, 57, 56, 55, 54, 54, 53,
|
|
92
|
+
53, 52, 52, 51, 51, 50, 50, 50, 49, 49, 48, 48, 48, 48, 47, 47, 47, 46, 46, 46, 46, 45, 45, 45, 45, 45, 44, 44, 44,
|
|
93
|
+
44, 44, 43, 43, 43, 43, 43, 43, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40,
|
|
94
|
+
40, 40, 40, 40, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
|
95
|
+
37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
|
|
96
|
+
36, 36, 36, 36, 36, 36, 36, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
|
97
|
+
35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
|
|
98
|
+
34, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
|
|
99
|
+
33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
|
|
100
|
+
];
|
|
@@ -41,7 +41,9 @@ export class EcAdd extends Instruction {
|
|
|
41
41
|
const memory = context.machineState.memory;
|
|
42
42
|
const addressing = Addressing.fromWire(this.indirect);
|
|
43
43
|
|
|
44
|
-
context.machineState.consumeGas(
|
|
44
|
+
context.machineState.consumeGas(
|
|
45
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
46
|
+
);
|
|
45
47
|
|
|
46
48
|
const operands = [
|
|
47
49
|
this.p1XOffset,
|
|
@@ -73,7 +73,9 @@ export class GetEnvVar extends Instruction {
|
|
|
73
73
|
const memory = context.machineState.memory;
|
|
74
74
|
const addressing = Addressing.fromWire(this.indirect);
|
|
75
75
|
|
|
76
|
-
context.machineState.consumeGas(
|
|
76
|
+
context.machineState.consumeGas(
|
|
77
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
78
|
+
);
|
|
77
79
|
|
|
78
80
|
if (!(this.varEnum in EnvironmentVariable)) {
|
|
79
81
|
throw new InstructionExecutionError(`Invalid GETENVVAR var enum ${this.varEnum}`);
|
|
@@ -32,11 +32,15 @@ abstract class ExternalCall extends Instruction {
|
|
|
32
32
|
const memory = context.machineState.memory;
|
|
33
33
|
const addressing = Addressing.fromWire(this.indirect);
|
|
34
34
|
|
|
35
|
+
context.machineState.consumeGas(
|
|
36
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
37
|
+
);
|
|
38
|
+
|
|
35
39
|
const operands = [this.l2GasOffset, this.daGasOffset, this.addrOffset, this.argsSizeOffset, this.argsOffset];
|
|
36
40
|
const [l2GasOffset, daGasOffset, addrOffset, argsSizeOffset, argsOffset] = addressing.resolve(operands, memory);
|
|
37
|
-
|
|
38
|
-
memory.checkTags(TypeTag.
|
|
39
|
-
memory.checkTags(TypeTag.
|
|
41
|
+
|
|
42
|
+
memory.checkTags(TypeTag.UINT32, l2GasOffset);
|
|
43
|
+
memory.checkTags(TypeTag.UINT32, daGasOffset);
|
|
40
44
|
memory.checkTag(TypeTag.FIELD, addrOffset);
|
|
41
45
|
memory.checkTag(TypeTag.UINT32, argsSizeOffset);
|
|
42
46
|
|
|
@@ -48,9 +52,7 @@ abstract class ExternalCall extends Instruction {
|
|
|
48
52
|
// If we are already in a static call, we propagate the environment.
|
|
49
53
|
const callType = context.environment.isStaticCall ? 'STATICCALL' : this.type;
|
|
50
54
|
|
|
51
|
-
//
|
|
52
|
-
context.machineState.consumeGas(this.gasCost(calldataSize));
|
|
53
|
-
// Then we consume the gas allocated for the nested call. The excess will be refunded later.
|
|
55
|
+
// We consume the gas allocated for the nested call. The excess will be refunded later.
|
|
54
56
|
// Gas allocation is capped by the amount of gas left in the current context.
|
|
55
57
|
// We have to do some dancing here because the gas allocation is a field,
|
|
56
58
|
// but in the machine state we track gas as a number.
|
|
@@ -179,12 +181,15 @@ export class Return extends Instruction {
|
|
|
179
181
|
const memory = context.machineState.memory;
|
|
180
182
|
const addressing = Addressing.fromWire(this.indirect);
|
|
181
183
|
|
|
184
|
+
context.machineState.consumeGas(
|
|
185
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
186
|
+
);
|
|
187
|
+
|
|
182
188
|
const operands = [this.returnSizeOffset, this.returnOffset];
|
|
183
189
|
const [returnSizeOffset, returnOffset] = addressing.resolve(operands, memory);
|
|
184
190
|
|
|
185
191
|
memory.checkTag(TypeTag.UINT32, returnSizeOffset);
|
|
186
192
|
const returnSize = memory.get(returnSizeOffset).toNumber();
|
|
187
|
-
context.machineState.consumeGas(this.gasCost(returnSize));
|
|
188
193
|
|
|
189
194
|
const output = memory.getSlice(returnOffset, returnSize).map(word => word.toFr());
|
|
190
195
|
|
|
@@ -225,12 +230,15 @@ export class Revert extends Instruction {
|
|
|
225
230
|
const memory = context.machineState.memory;
|
|
226
231
|
const addressing = Addressing.fromWire(this.indirect);
|
|
227
232
|
|
|
233
|
+
context.machineState.consumeGas(
|
|
234
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
235
|
+
);
|
|
236
|
+
|
|
228
237
|
const operands = [this.retSizeOffset, this.returnOffset];
|
|
229
238
|
const [retSizeOffset, returnOffset] = addressing.resolve(operands, memory);
|
|
230
239
|
|
|
231
240
|
memory.checkTag(TypeTag.UINT32, retSizeOffset);
|
|
232
241
|
const retSize = memory.get(retSizeOffset).toNumber();
|
|
233
|
-
context.machineState.consumeGas(this.gasCost(retSize));
|
|
234
242
|
const output = memory.getSlice(returnOffset, retSize).map(word => word.toFr());
|
|
235
243
|
|
|
236
244
|
context.machineState.revert(output);
|
|
@@ -31,7 +31,9 @@ export class Poseidon2 extends Instruction {
|
|
|
31
31
|
const memory = context.machineState.memory;
|
|
32
32
|
const addressing = Addressing.fromWire(this.indirect);
|
|
33
33
|
|
|
34
|
-
context.machineState.consumeGas(
|
|
34
|
+
context.machineState.consumeGas(
|
|
35
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
36
|
+
);
|
|
35
37
|
|
|
36
38
|
const operands = [this.inputStateOffset, this.outputStateOffset];
|
|
37
39
|
|
|
@@ -74,9 +76,12 @@ export class KeccakF1600 extends Instruction {
|
|
|
74
76
|
const memory = context.machineState.memory;
|
|
75
77
|
const addressing = Addressing.fromWire(this.indirect);
|
|
76
78
|
|
|
79
|
+
context.machineState.consumeGas(
|
|
80
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
81
|
+
);
|
|
82
|
+
|
|
77
83
|
const operands = [this.dstOffset, this.inputOffset];
|
|
78
84
|
const [dstOffset, inputOffset] = addressing.resolve(operands, memory);
|
|
79
|
-
context.machineState.consumeGas(this.gasCost());
|
|
80
85
|
|
|
81
86
|
const stateData = memory.getSlice(inputOffset, inputSize).map(word => word.toBigInt());
|
|
82
87
|
memory.checkTagsRange(TypeTag.UINT64, inputOffset, inputSize);
|
|
@@ -117,11 +122,14 @@ export class Sha256Compression extends Instruction {
|
|
|
117
122
|
const memory = context.machineState.memory;
|
|
118
123
|
const addressing = Addressing.fromWire(this.indirect);
|
|
119
124
|
|
|
125
|
+
context.machineState.consumeGas(
|
|
126
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
127
|
+
);
|
|
128
|
+
|
|
120
129
|
const operands = [this.outputOffset, this.stateOffset, this.inputsOffset];
|
|
121
130
|
const [outputOffset, stateOffset, inputsOffset] = addressing.resolve(operands, memory);
|
|
122
131
|
|
|
123
132
|
// Note: size of output is same as size of state
|
|
124
|
-
context.machineState.consumeGas(this.gasCost());
|
|
125
133
|
const inputs = Uint32Array.from(memory.getSlice(inputsOffset, INPUTS_SIZE).map(word => word.toNumber()));
|
|
126
134
|
const state = Uint32Array.from(memory.getSlice(stateOffset, STATE_SIZE).map(word => word.toNumber()));
|
|
127
135
|
|
|
@@ -3,7 +3,7 @@ import type { Bufferable } from '@aztec/foundation/serialize';
|
|
|
3
3
|
import { strict as assert } from 'assert';
|
|
4
4
|
|
|
5
5
|
import type { AvmContext } from '../avm_context.js';
|
|
6
|
-
import { type Gas, getBaseGasCost, getDynamicGasCost, mulGas, sumGas } from '../avm_gas.js';
|
|
6
|
+
import { type Gas, computeAddressingCost, getBaseGasCost, getDynamicGasCost, mulGas, sumGas } from '../avm_gas.js';
|
|
7
7
|
import type { BufferCursor } from '../serialization/buffer_cursor.js';
|
|
8
8
|
import { Opcode, type OperandType, deserialize, serializeAs } from '../serialization/instruction_serialization.js';
|
|
9
9
|
|
|
@@ -92,13 +92,20 @@ export abstract class Instruction {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
/**
|
|
95
|
-
*
|
|
96
|
-
* @returns
|
|
95
|
+
* Returns the base gas cost for the instruction.
|
|
96
|
+
* @returns The base gas cost.
|
|
97
97
|
*/
|
|
98
|
-
protected
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
98
|
+
protected baseGasCost(indirectOperandsCount: number, relativeOperandsCount: number): Gas {
|
|
99
|
+
return sumGas(getBaseGasCost(this.opcode), computeAddressingCost(indirectOperandsCount, relativeOperandsCount));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Computes the dynamic gas cost for the instruction
|
|
104
|
+
* @param dynMultiplier - The multiplier for the dynamic gas cost.
|
|
105
|
+
* @returns The dynamic gas cost.
|
|
106
|
+
*/
|
|
107
|
+
protected dynamicGasCost(dynMultiplier: number = 0): Gas {
|
|
108
|
+
return mulGas(getDynamicGasCost(this.opcode), dynMultiplier);
|
|
102
109
|
}
|
|
103
110
|
|
|
104
111
|
/**
|
|
@@ -68,7 +68,9 @@ export class Set extends Instruction {
|
|
|
68
68
|
const memory = context.machineState.memory;
|
|
69
69
|
const addressing = Addressing.fromWire(this.indirect);
|
|
70
70
|
|
|
71
|
-
context.machineState.consumeGas(
|
|
71
|
+
context.machineState.consumeGas(
|
|
72
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
73
|
+
);
|
|
72
74
|
|
|
73
75
|
const operands = [this.dstOffset];
|
|
74
76
|
const [dstOffset] = addressing.resolve(operands, memory);
|
|
@@ -108,7 +110,9 @@ export class Cast extends Instruction {
|
|
|
108
110
|
const memory = context.machineState.memory;
|
|
109
111
|
const addressing = Addressing.fromWire(this.indirect);
|
|
110
112
|
|
|
111
|
-
context.machineState.consumeGas(
|
|
113
|
+
context.machineState.consumeGas(
|
|
114
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
115
|
+
);
|
|
112
116
|
|
|
113
117
|
const operands = [this.srcOffset, this.dstOffset];
|
|
114
118
|
const [srcOffset, dstOffset] = addressing.resolve(operands, memory);
|
|
@@ -151,7 +155,9 @@ export class Mov extends Instruction {
|
|
|
151
155
|
const memory = context.machineState.memory;
|
|
152
156
|
const addressing = Addressing.fromWire(this.indirect);
|
|
153
157
|
|
|
154
|
-
context.machineState.consumeGas(
|
|
158
|
+
context.machineState.consumeGas(
|
|
159
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
160
|
+
);
|
|
155
161
|
|
|
156
162
|
const operands = [this.srcOffset, this.dstOffset];
|
|
157
163
|
const [srcOffset, dstOffset] = addressing.resolve(operands, memory);
|
|
@@ -185,13 +191,17 @@ export class CalldataCopy extends Instruction {
|
|
|
185
191
|
const memory = context.machineState.memory;
|
|
186
192
|
const addressing = Addressing.fromWire(this.indirect);
|
|
187
193
|
|
|
194
|
+
context.machineState.consumeGas(
|
|
195
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
196
|
+
);
|
|
197
|
+
|
|
188
198
|
const operands = [this.copySizeOffset, this.cdStartOffset, this.dstOffset];
|
|
189
199
|
const [copySizeOffset, cdStartOffset, dstOffset] = addressing.resolve(operands, memory);
|
|
190
200
|
|
|
191
201
|
memory.checkTags(TypeTag.UINT32, cdStartOffset, copySizeOffset);
|
|
192
202
|
const cdStart = memory.get(cdStartOffset).toNumber();
|
|
193
203
|
const copySize = memory.get(copySizeOffset).toNumber();
|
|
194
|
-
context.machineState.consumeGas(this.
|
|
204
|
+
context.machineState.consumeGas(this.dynamicGasCost(copySize));
|
|
195
205
|
|
|
196
206
|
// Values which are out-of-range of the calldata array will be set with Field(0);
|
|
197
207
|
const slice = context.environment.calldata.slice(cdStart, cdStart + copySize).map(f => new Field(f));
|
|
@@ -219,9 +229,12 @@ export class ReturndataSize extends Instruction {
|
|
|
219
229
|
const memory = context.machineState.memory;
|
|
220
230
|
const addressing = Addressing.fromWire(this.indirect);
|
|
221
231
|
|
|
232
|
+
context.machineState.consumeGas(
|
|
233
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
234
|
+
);
|
|
235
|
+
|
|
222
236
|
const operands = [this.dstOffset];
|
|
223
237
|
const [dstOffset] = addressing.resolve(operands, memory);
|
|
224
|
-
context.machineState.consumeGas(this.gasCost());
|
|
225
238
|
|
|
226
239
|
memory.set(dstOffset, new Uint32(context.machineState.nestedReturndata.length));
|
|
227
240
|
}
|
|
@@ -252,13 +265,17 @@ export class ReturndataCopy extends Instruction {
|
|
|
252
265
|
const memory = context.machineState.memory;
|
|
253
266
|
const addressing = Addressing.fromWire(this.indirect);
|
|
254
267
|
|
|
268
|
+
context.machineState.consumeGas(
|
|
269
|
+
this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()),
|
|
270
|
+
);
|
|
271
|
+
|
|
255
272
|
const operands = [this.copySizeOffset, this.rdStartOffset, this.dstOffset];
|
|
256
273
|
const [copySizeOffset, rdStartOffset, dstOffset] = addressing.resolve(operands, memory);
|
|
257
274
|
|
|
258
275
|
memory.checkTags(TypeTag.UINT32, rdStartOffset, copySizeOffset);
|
|
259
276
|
const rdStart = memory.get(rdStartOffset).toNumber();
|
|
260
277
|
const copySize = memory.get(copySizeOffset).toNumber();
|
|
261
|
-
context.machineState.consumeGas(this.
|
|
278
|
+
context.machineState.consumeGas(this.dynamicGasCost(copySize));
|
|
262
279
|
|
|
263
280
|
// Values which are out-of-range of the returndata array will be set with Field(0);
|
|
264
281
|
const slice = context.machineState.nestedReturndata.slice(rdStart, rdStart + copySize).map(f => new Field(f));
|