@aztec/simulator 0.42.0 → 0.43.0

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.
Files changed (145) hide show
  1. package/dest/acvm/oracle/oracle.d.ts +3 -2
  2. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  3. package/dest/acvm/oracle/oracle.js +17 -6
  4. package/dest/acvm/oracle/typed_oracle.d.ts +3 -2
  5. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  6. package/dest/acvm/oracle/typed_oracle.js +8 -5
  7. package/dest/avm/avm_gas.d.ts.map +1 -1
  8. package/dest/avm/avm_gas.js +3 -1
  9. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  10. package/dest/avm/avm_memory_types.js +2 -4
  11. package/dest/avm/fixtures/index.d.ts +4 -1
  12. package/dest/avm/fixtures/index.d.ts.map +1 -1
  13. package/dest/avm/fixtures/index.js +11 -6
  14. package/dest/avm/journal/journal.d.ts +3 -3
  15. package/dest/avm/journal/journal.d.ts.map +1 -1
  16. package/dest/avm/journal/journal.js +18 -13
  17. package/dest/avm/journal/trace.d.ts +3 -3
  18. package/dest/avm/journal/trace.d.ts.map +1 -1
  19. package/dest/avm/journal/trace.js +7 -6
  20. package/dest/avm/journal/trace_types.d.ts +4 -0
  21. package/dest/avm/journal/trace_types.d.ts.map +1 -1
  22. package/dest/avm/journal/trace_types.js +1 -5
  23. package/dest/avm/opcodes/accrued_substate.d.ts +2 -2
  24. package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
  25. package/dest/avm/opcodes/accrued_substate.js +36 -21
  26. package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
  27. package/dest/avm/opcodes/arithmetic.js +12 -9
  28. package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
  29. package/dest/avm/opcodes/bitwise.js +11 -8
  30. package/dest/avm/opcodes/comparators.d.ts.map +1 -1
  31. package/dest/avm/opcodes/comparators.js +7 -5
  32. package/dest/avm/opcodes/contract.d.ts.map +1 -1
  33. package/dest/avm/opcodes/contract.js +20 -24
  34. package/dest/avm/opcodes/control_flow.d.ts.map +1 -1
  35. package/dest/avm/opcodes/control_flow.js +4 -2
  36. package/dest/avm/opcodes/ec_add.d.ts +19 -0
  37. package/dest/avm/opcodes/ec_add.d.ts.map +1 -0
  38. package/dest/avm/opcodes/ec_add.js +78 -0
  39. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  40. package/dest/avm/opcodes/external_calls.js +8 -3
  41. package/dest/avm/opcodes/hashing.d.ts.map +1 -1
  42. package/dest/avm/opcodes/hashing.js +10 -2
  43. package/dest/avm/opcodes/instruction_impl.d.ts.map +1 -1
  44. package/dest/avm/opcodes/instruction_impl.js +4 -2
  45. package/dest/avm/opcodes/memory.d.ts +1 -1
  46. package/dest/avm/opcodes/memory.d.ts.map +1 -1
  47. package/dest/avm/opcodes/memory.js +14 -12
  48. package/dest/avm/opcodes/multi_scalar_mul.d.ts +16 -0
  49. package/dest/avm/opcodes/multi_scalar_mul.d.ts.map +1 -0
  50. package/dest/avm/opcodes/multi_scalar_mul.js +95 -0
  51. package/dest/avm/opcodes/storage.d.ts +1 -1
  52. package/dest/avm/opcodes/storage.d.ts.map +1 -1
  53. package/dest/avm/opcodes/storage.js +11 -8
  54. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  55. package/dest/avm/serialization/bytecode_serialization.js +5 -1
  56. package/dest/avm/serialization/instruction_serialization.d.ts +3 -1
  57. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  58. package/dest/avm/serialization/instruction_serialization.js +4 -2
  59. package/dest/client/client_execution_context.d.ts +15 -3
  60. package/dest/client/client_execution_context.d.ts.map +1 -1
  61. package/dest/client/client_execution_context.js +31 -17
  62. package/dest/client/simulator.d.ts +2 -1
  63. package/dest/client/simulator.d.ts.map +1 -1
  64. package/dest/client/simulator.js +17 -9
  65. package/dest/public/abstract_phase_manager.d.ts +10 -11
  66. package/dest/public/abstract_phase_manager.d.ts.map +1 -1
  67. package/dest/public/abstract_phase_manager.js +75 -53
  68. package/dest/public/app_logic_phase_manager.d.ts +3 -3
  69. package/dest/public/app_logic_phase_manager.d.ts.map +1 -1
  70. package/dest/public/app_logic_phase_manager.js +3 -3
  71. package/dest/public/db_interfaces.d.ts +1 -0
  72. package/dest/public/db_interfaces.d.ts.map +1 -1
  73. package/dest/public/execution.d.ts +1 -15
  74. package/dest/public/execution.d.ts.map +1 -1
  75. package/dest/public/execution.js +1 -51
  76. package/dest/public/executor.d.ts +1 -1
  77. package/dest/public/executor.d.ts.map +1 -1
  78. package/dest/public/executor.js +15 -8
  79. package/dest/public/hints_builder.d.ts +1 -1
  80. package/dest/public/index.d.ts +6 -6
  81. package/dest/public/index.d.ts.map +1 -1
  82. package/dest/public/index.js +7 -7
  83. package/dest/public/phase_manager_factory.d.ts +3 -3
  84. package/dest/public/phase_manager_factory.d.ts.map +1 -1
  85. package/dest/public/phase_manager_factory.js +5 -5
  86. package/dest/public/public_db_sources.d.ts +3 -1
  87. package/dest/public/public_db_sources.d.ts.map +1 -1
  88. package/dest/public/public_db_sources.js +54 -8
  89. package/dest/public/public_processor.d.ts.map +1 -1
  90. package/dest/public/public_processor.js +4 -5
  91. package/dest/public/setup_phase_manager.d.ts +3 -3
  92. package/dest/public/setup_phase_manager.d.ts.map +1 -1
  93. package/dest/public/setup_phase_manager.js +3 -3
  94. package/dest/public/tail_phase_manager.d.ts +3 -3
  95. package/dest/public/tail_phase_manager.d.ts.map +1 -1
  96. package/dest/public/tail_phase_manager.js +3 -3
  97. package/dest/public/teardown_phase_manager.d.ts +3 -3
  98. package/dest/public/teardown_phase_manager.d.ts.map +1 -1
  99. package/dest/public/teardown_phase_manager.js +3 -3
  100. package/dest/public/transitional_adaptors.d.ts +1 -1
  101. package/dest/public/transitional_adaptors.d.ts.map +1 -1
  102. package/dest/public/transitional_adaptors.js +9 -3
  103. package/package.json +8 -8
  104. package/src/acvm/oracle/oracle.ts +35 -6
  105. package/src/acvm/oracle/typed_oracle.ts +20 -4
  106. package/src/avm/avm_gas.ts +2 -0
  107. package/src/avm/avm_memory_types.ts +1 -3
  108. package/src/avm/fixtures/index.ts +12 -8
  109. package/src/avm/journal/journal.ts +26 -21
  110. package/src/avm/journal/trace.ts +8 -11
  111. package/src/avm/journal/trace_types.ts +3 -0
  112. package/src/avm/opcodes/accrued_substate.ts +53 -20
  113. package/src/avm/opcodes/arithmetic.ts +17 -8
  114. package/src/avm/opcodes/bitwise.ts +13 -8
  115. package/src/avm/opcodes/comparators.ts +9 -4
  116. package/src/avm/opcodes/contract.ts +22 -26
  117. package/src/avm/opcodes/control_flow.ts +3 -1
  118. package/src/avm/opcodes/ec_add.ts +92 -0
  119. package/src/avm/opcodes/external_calls.ts +8 -2
  120. package/src/avm/opcodes/hashing.ts +11 -1
  121. package/src/avm/opcodes/instruction_impl.ts +4 -1
  122. package/src/avm/opcodes/memory.ts +18 -11
  123. package/src/avm/opcodes/multi_scalar_mul.ts +114 -0
  124. package/src/avm/opcodes/storage.ts +10 -10
  125. package/src/avm/serialization/bytecode_serialization.ts +4 -0
  126. package/src/avm/serialization/instruction_serialization.ts +2 -0
  127. package/src/client/client_execution_context.ts +46 -18
  128. package/src/client/simulator.ts +18 -8
  129. package/src/public/abstract_phase_manager.ts +77 -59
  130. package/src/public/app_logic_phase_manager.ts +2 -2
  131. package/src/public/db_interfaces.ts +2 -0
  132. package/src/public/execution.ts +0 -69
  133. package/src/public/executor.ts +17 -8
  134. package/src/public/index.ts +6 -12
  135. package/src/public/phase_manager_factory.ts +6 -6
  136. package/src/public/public_db_sources.ts +62 -7
  137. package/src/public/public_processor.ts +4 -7
  138. package/src/public/setup_phase_manager.ts +2 -2
  139. package/src/public/tail_phase_manager.ts +2 -2
  140. package/src/public/teardown_phase_manager.ts +2 -2
  141. package/src/public/transitional_adaptors.ts +42 -2
  142. package/dest/public/utils.d.ts +0 -8
  143. package/dest/public/utils.d.ts.map +0 -1
  144. package/dest/public/utils.js +0 -38
  145. package/src/public/utils.ts +0 -39
@@ -184,15 +184,31 @@ export abstract class TypedOracle {
184
184
  throw new OracleMethodNotAvailableError('storageWrite');
185
185
  }
186
186
 
187
- emitEncryptedLog(_contractAddress: AztecAddress, _randomness: Fr, _encryptedNote: Buffer, _counter: number): void {
188
- throw new OracleMethodNotAvailableError('emitEncryptedLog');
187
+ emitEncryptedEventLog(
188
+ _contractAddress: AztecAddress,
189
+ _randomness: Fr,
190
+ _encryptedEvent: Buffer,
191
+ _counter: number,
192
+ ): void {
193
+ throw new OracleMethodNotAvailableError('emitEncryptedEventLog');
189
194
  }
190
195
 
191
196
  emitEncryptedNoteLog(_noteHashCounter: number, _encryptedNote: Buffer, _counter: number): void {
192
197
  throw new OracleMethodNotAvailableError('emitEncryptedNoteLog');
193
198
  }
194
199
 
195
- computeEncryptedLog(
200
+ computeEncryptedEventLog(
201
+ _contractAddress: AztecAddress,
202
+ _randomness: Fr,
203
+ _eventTypeId: Fr,
204
+ _ovKeys: KeyValidationRequest,
205
+ _ivpkM: PublicKey,
206
+ _preimage: Fr[],
207
+ ): Buffer {
208
+ throw new OracleMethodNotAvailableError('computeEncryptedEventLog');
209
+ }
210
+
211
+ computeEncryptedNoteLog(
196
212
  _contractAddress: AztecAddress,
197
213
  _storageSlot: Fr,
198
214
  _noteTypeId: Fr,
@@ -200,7 +216,7 @@ export abstract class TypedOracle {
200
216
  _ivpkM: PublicKey,
201
217
  _preimage: Fr[],
202
218
  ): Buffer {
203
- throw new OracleMethodNotAvailableError('computeEncryptedLog');
219
+ throw new OracleMethodNotAvailableError('computeEncryptedNoteLog');
204
220
  }
205
221
 
206
222
  emitUnencryptedLog(_log: UnencryptedL2Log, _counter: number): void {
@@ -122,6 +122,8 @@ const BaseGasCosts: Record<Opcode, Gas> = {
122
122
  [Opcode.POSEIDON2]: DefaultBaseGasCost,
123
123
  [Opcode.SHA256]: DefaultBaseGasCost,
124
124
  [Opcode.PEDERSEN]: DefaultBaseGasCost,
125
+ [Opcode.ECADD]: DefaultBaseGasCost,
126
+ [Opcode.MSM]: DefaultBaseGasCost,
125
127
  // Conversions
126
128
  [Opcode.TORADIXLE]: DefaultBaseGasCost,
127
129
  };
@@ -298,9 +298,7 @@ export class TaggedMemory implements TaggedMemoryInterface {
298
298
  }
299
299
 
300
300
  public checkIsValidMemoryOffsetTag(offset: number) {
301
- if (this.getTag(offset) > TypeTag.UINT64) {
302
- throw TagCheckError.forOffset(offset, TypeTag[this.getTag(offset)], 'UINT64');
303
- }
301
+ this.checkTag(TypeTag.UINT32, offset);
304
302
  }
305
303
 
306
304
  public static checkIsIntegralTag(tag: TypeTag) {
@@ -3,7 +3,8 @@ import { FunctionSelector } from '@aztec/foundation/abi';
3
3
  import { AztecAddress } from '@aztec/foundation/aztec-address';
4
4
  import { EthAddress } from '@aztec/foundation/eth-address';
5
5
  import { Fr } from '@aztec/foundation/fields';
6
- import { AvmNestedCallsTestContractArtifact, AvmTestContractArtifact } from '@aztec/noir-contracts.js';
6
+ import { AvmTestContractArtifact } from '@aztec/noir-contracts.js';
7
+ import { SerializableContractInstance } from '@aztec/types/contracts';
7
8
 
8
9
  import { strict as assert } from 'assert';
9
10
  import { mock } from 'jest-mock-extended';
@@ -16,6 +17,7 @@ import { AvmMachineState } from '../avm_machine_state.js';
16
17
  import { Field, Uint8 } from '../avm_memory_types.js';
17
18
  import { HostStorage } from '../journal/host_storage.js';
18
19
  import { AvmPersistableStateManager } from '../journal/journal.js';
20
+ import { type TracedContractInstance } from '../journal/trace_types.js';
19
21
 
20
22
  /**
21
23
  * Create a new AVM context with default values.
@@ -137,11 +139,13 @@ export function getAvmTestContractBytecode(functionName: string): Buffer {
137
139
  return artifact.bytecode;
138
140
  }
139
141
 
140
- export function getAvmNestedCallsTestContractBytecode(functionName: string): Buffer {
141
- const artifact = AvmNestedCallsTestContractArtifact.functions.find(f => f.name === functionName)!;
142
- assert(
143
- !!artifact?.bytecode,
144
- `No bytecode found for function ${functionName}. Try re-running bootstrap.sh on the repository root.`,
145
- );
146
- return artifact.bytecode;
142
+ export function randomTracedContractInstance(): TracedContractInstance {
143
+ const instance = SerializableContractInstance.random();
144
+ const address = AztecAddress.random();
145
+ return { exists: true, ...instance, address };
146
+ }
147
+
148
+ export function emptyTracedContractInstance(withAddress?: AztecAddress): TracedContractInstance {
149
+ const instance = SerializableContractInstance.empty().withAddress(withAddress ?? AztecAddress.zero());
150
+ return { exists: false, ...instance };
147
151
  }
@@ -14,6 +14,7 @@ import {
14
14
  import { EventSelector } from '@aztec/foundation/abi';
15
15
  import { Fr } from '@aztec/foundation/fields';
16
16
  import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
17
+ import { SerializableContractInstance } from '@aztec/types/contracts';
17
18
 
18
19
  import { type PublicExecutionResult } from '../../index.js';
19
20
  import { type HostStorage } from './host_storage.js';
@@ -21,6 +22,7 @@ import { Nullifiers } from './nullifiers.js';
21
22
  import { PublicStorage } from './public_storage.js';
22
23
  import { WorldStateAccessTrace } from './trace.js';
23
24
  import {
25
+ type TracedContractInstance,
24
26
  type TracedL1toL2MessageCheck,
25
27
  type TracedNoteHash,
26
28
  type TracedNoteHashCheck,
@@ -55,7 +57,7 @@ export type JournalData = {
55
57
  };
56
58
 
57
59
  // TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit
58
- type PartialPublicExecutionResult = {
60
+ export type PartialPublicExecutionResult = {
59
61
  noteHashReadRequests: ReadRequest[];
60
62
  nullifierReadRequests: ReadRequest[];
61
63
  nullifierNonExistentReadRequests: ReadRequest[];
@@ -147,15 +149,6 @@ export class AvmPersistableStateManager {
147
149
  this.publicStorage.write(storageAddress, slot, value);
148
150
 
149
151
  // TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit
150
- // The current info to the kernel clears any previous read or write request.
151
- this.transitionalExecutionResult.contractStorageReads =
152
- this.transitionalExecutionResult.contractStorageReads.filter(
153
- read => !read.storageSlot.equals(slot) || !read.contractAddress!.equals(storageAddress),
154
- );
155
- this.transitionalExecutionResult.contractStorageUpdateRequests =
156
- this.transitionalExecutionResult.contractStorageUpdateRequests.filter(
157
- update => !update.storageSlot.equals(slot) || !update.contractAddress!.equals(storageAddress),
158
- );
159
152
  this.transitionalExecutionResult.contractStorageUpdateRequests.push(
160
153
  new ContractStorageUpdateRequest(slot, value, this.trace.accessCounter, storageAddress),
161
154
  );
@@ -178,17 +171,9 @@ export class AvmPersistableStateManager {
178
171
  );
179
172
 
180
173
  // TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit
181
- // The current info to the kernel kernel does not consider cached reads.
182
- if (!cached) {
183
- // The current info to the kernel removes any previous reads to the same slot.
184
- this.transitionalExecutionResult.contractStorageReads =
185
- this.transitionalExecutionResult.contractStorageReads.filter(
186
- read => !read.storageSlot.equals(slot) || !read.contractAddress!.equals(storageAddress),
187
- );
188
- this.transitionalExecutionResult.contractStorageReads.push(
189
- new ContractStorageRead(slot, value, this.trace.accessCounter, storageAddress),
190
- );
191
- }
174
+ this.transitionalExecutionResult.contractStorageReads.push(
175
+ new ContractStorageRead(slot, value, this.trace.accessCounter, storageAddress),
176
+ );
192
177
 
193
178
  // We want to keep track of all performed reads (even reverted ones)
194
179
  this.trace.tracePublicStorageRead(storageAddress, slot, value, exists, cached);
@@ -208,6 +193,10 @@ export class AvmPersistableStateManager {
208
193
  const gotLeafIndex = await this.hostStorage.commitmentsDb.getCommitmentIndex(noteHash);
209
194
  const exists = gotLeafIndex === leafIndex.toBigInt();
210
195
  this.log.debug(`noteHashes(${storageAddress})@${noteHash} ?? leafIndex: ${leafIndex}, exists: ${exists}.`);
196
+
197
+ // TODO: include exists here also - This can for sure come from the trace???
198
+ this.transitionalExecutionResult.noteHashReadRequests.push(new ReadRequest(noteHash, this.trace.accessCounter));
199
+
211
200
  this.trace.traceNoteHashCheck(storageAddress, noteHash, exists, leafIndex);
212
201
  return Promise.resolve(exists);
213
202
  }
@@ -279,6 +268,9 @@ export class AvmPersistableStateManager {
279
268
  this.log.debug(
280
269
  `l1ToL2Messages(@${msgLeafIndex}) ?? exists: ${exists}, expected: ${msgHash}, found: ${valueAtIndex}.`,
281
270
  );
271
+
272
+ this.transitionalExecutionResult.l1ToL2MsgReadRequests.push(new ReadRequest(msgHash, this.trace.accessCounter));
273
+
282
274
  this.trace.traceL1ToL2MessageCheck(msgHash, msgLeafIndex, exists);
283
275
  return Promise.resolve(exists);
284
276
  }
@@ -322,6 +314,19 @@ export class AvmPersistableStateManager {
322
314
  this.trace.traceNewLog(logHash);
323
315
  }
324
316
 
317
+ public async getContractInstance(contractAddress: Fr): Promise<TracedContractInstance> {
318
+ let exists = true;
319
+ const aztecAddress = AztecAddress.fromField(contractAddress);
320
+ let instance = await this.hostStorage.contractsDb.getContractInstance(aztecAddress);
321
+ if (instance === undefined) {
322
+ instance = SerializableContractInstance.empty().withAddress(aztecAddress);
323
+ exists = false;
324
+ }
325
+ const tracedInstance = { ...instance, exists };
326
+ this.trace.traceGetContractInstance(tracedInstance);
327
+ return Promise.resolve(tracedInstance);
328
+ }
329
+
325
330
  /**
326
331
  * Accept nested world state modifications, merging in its trace and accrued substate
327
332
  */
@@ -1,7 +1,7 @@
1
- import { AvmExecutionHints, AvmHint, Vector } from '@aztec/circuits.js';
2
1
  import { Fr } from '@aztec/foundation/fields';
3
2
 
4
3
  import {
4
+ type TracedContractInstance,
5
5
  type TracedL1toL2MessageCheck,
6
6
  type TracedNoteHash,
7
7
  type TracedNoteHashCheck,
@@ -24,6 +24,7 @@ export class WorldStateAccessTrace {
24
24
  public newNullifiers: TracedNullifier[] = [];
25
25
  public l1ToL2MessageChecks: TracedL1toL2MessageCheck[] = [];
26
26
  public newLogsHashes: TracedUnencryptedL2Log[] = [];
27
+ public gotContractInstances: TracedContractInstance[] = [];
27
28
 
28
29
  //public contractCalls: TracedContractCall[] = [];
29
30
  //public archiveChecks: TracedArchiveLeafCheck[] = [];
@@ -148,6 +149,11 @@ export class WorldStateAccessTrace {
148
149
  this.incrementAccessCounter();
149
150
  }
150
151
 
152
+ public traceGetContractInstance(instance: TracedContractInstance) {
153
+ this.gotContractInstances.push(instance);
154
+ this.incrementAccessCounter();
155
+ }
156
+
151
157
  private incrementAccessCounter() {
152
158
  this.accessCounter++;
153
159
  }
@@ -168,17 +174,8 @@ export class WorldStateAccessTrace {
168
174
  this.newNullifiers.push(...incomingTrace.newNullifiers);
169
175
  this.l1ToL2MessageChecks.push(...incomingTrace.l1ToL2MessageChecks);
170
176
  this.newLogsHashes.push(...incomingTrace.newLogsHashes);
177
+ this.gotContractInstances.push(...incomingTrace.gotContractInstances);
171
178
  // it is assumed that the incoming trace was initialized with this as parent, so accept counter
172
179
  this.accessCounter = incomingTrace.accessCounter;
173
180
  }
174
-
175
- // TODO(dbanks12): should only return hints for one call.... shouldn't include nested calls (merged in traces)
176
- public toHints(): AvmExecutionHints {
177
- return new AvmExecutionHints(
178
- new Vector(this.publicStorageReads.map(read => new AvmHint(read.counter, read.value))),
179
- new Vector(this.noteHashChecks.map(check => new AvmHint(check.counter, new Fr(check.exists ? 1 : 0)))),
180
- new Vector(this.nullifierChecks.map(check => new AvmHint(check.counter, new Fr(check.exists ? 1 : 0)))),
181
- new Vector(this.l1ToL2MessageChecks.map(check => new AvmHint(check.counter, new Fr(check.exists ? 1 : 0)))),
182
- );
183
- }
184
181
  }
@@ -1,4 +1,5 @@
1
1
  import { type Fr } from '@aztec/foundation/fields';
2
+ import { type ContractInstanceWithAddress } from '@aztec/types/contracts';
2
3
 
3
4
  //export type TracedContractCall = {
4
5
  // callPointer: Fr;
@@ -86,3 +87,5 @@ export type TracedUnencryptedL2Log = {
86
87
  // leafIndex: Fr;
87
88
  // leaf: Fr;
88
89
  //};
90
+
91
+ export type TracedContractInstance = { exists: boolean } & ContractInstanceWithAddress;
@@ -1,5 +1,5 @@
1
1
  import type { AvmContext } from '../avm_context.js';
2
- import { Uint8 } from '../avm_memory_types.js';
2
+ import { TypeTag, Uint8 } from '../avm_memory_types.js';
3
3
  import { InstructionExecutionError, StaticCallAlterationError } from '../errors.js';
4
4
  import { NullifierCollisionError } from '../journal/nullifiers.js';
5
5
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
@@ -31,17 +31,22 @@ export class NoteHashExists extends Instruction {
31
31
  const memoryOperations = { reads: 2, writes: 1, indirect: this.indirect };
32
32
  const memory = context.machineState.memory.track(this.type);
33
33
  context.machineState.consumeGas(this.gasCost(memoryOperations));
34
+ const [noteHashOffset, leafIndexOffset, existsOffset] = Addressing.fromWire(this.indirect).resolve(
35
+ [this.noteHashOffset, this.leafIndexOffset, this.existsOffset],
36
+ memory,
37
+ );
38
+ memory.checkTags(TypeTag.FIELD, noteHashOffset, leafIndexOffset);
34
39
 
35
40
  // Note that this instruction accepts any type in memory, and converts to Field.
36
- const noteHash = memory.get(this.noteHashOffset).toFr();
37
- const leafIndex = memory.get(this.leafIndexOffset).toFr();
41
+ const noteHash = memory.get(noteHashOffset).toFr();
42
+ const leafIndex = memory.get(leafIndexOffset).toFr();
38
43
 
39
44
  const exists = await context.persistableState.checkNoteHashExists(
40
45
  context.environment.storageAddress,
41
46
  noteHash,
42
47
  leafIndex,
43
48
  );
44
- memory.set(this.existsOffset, exists ? new Uint8(1) : new Uint8(0));
49
+ memory.set(existsOffset, exists ? new Uint8(1) : new Uint8(0));
45
50
 
46
51
  memory.assert(memoryOperations);
47
52
  context.machineState.incrementPc();
@@ -63,11 +68,14 @@ export class EmitNoteHash extends Instruction {
63
68
  const memory = context.machineState.memory.track(this.type);
64
69
  context.machineState.consumeGas(this.gasCost(memoryOperations));
65
70
 
71
+ const [noteHashOffset] = Addressing.fromWire(this.indirect).resolve([this.noteHashOffset], memory);
72
+ memory.checkTag(TypeTag.FIELD, noteHashOffset);
73
+
66
74
  if (context.environment.isStaticCall) {
67
75
  throw new StaticCallAlterationError();
68
76
  }
69
77
 
70
- const noteHash = memory.get(this.noteHashOffset).toFr();
78
+ const noteHash = memory.get(noteHashOffset).toFr();
71
79
  context.persistableState.writeNoteHash(context.environment.storageAddress, noteHash);
72
80
 
73
81
  memory.assert(memoryOperations);
@@ -101,11 +109,17 @@ export class NullifierExists extends Instruction {
101
109
  const memory = context.machineState.memory.track(this.type);
102
110
  context.machineState.consumeGas(this.gasCost(memoryOperations));
103
111
 
104
- const nullifier = memory.get(this.nullifierOffset).toFr();
105
- const address = memory.get(this.addressOffset).toFr();
112
+ const [nullifierOffset, addressOffset, existsOffset] = Addressing.fromWire(this.indirect).resolve(
113
+ [this.nullifierOffset, this.addressOffset, this.existsOffset],
114
+ memory,
115
+ );
116
+ memory.checkTags(TypeTag.FIELD, nullifierOffset, addressOffset);
117
+
118
+ const nullifier = memory.get(nullifierOffset).toFr();
119
+ const address = memory.get(addressOffset).toFr();
106
120
  const exists = await context.persistableState.checkNullifierExists(address, nullifier);
107
121
 
108
- memory.set(this.existsOffset, exists ? new Uint8(1) : new Uint8(0));
122
+ memory.set(existsOffset, exists ? new Uint8(1) : new Uint8(0));
109
123
 
110
124
  memory.assert(memoryOperations);
111
125
  context.machineState.incrementPc();
@@ -131,7 +145,10 @@ export class EmitNullifier extends Instruction {
131
145
  const memory = context.machineState.memory.track(this.type);
132
146
  context.machineState.consumeGas(this.gasCost(memoryOperations));
133
147
 
134
- const nullifier = memory.get(this.nullifierOffset).toFr();
148
+ const [nullifierOffset] = Addressing.fromWire(this.indirect).resolve([this.nullifierOffset], memory);
149
+ memory.checkTag(TypeTag.FIELD, nullifierOffset);
150
+
151
+ const nullifier = memory.get(nullifierOffset).toFr();
135
152
  try {
136
153
  await context.persistableState.writeNullifier(context.environment.storageAddress, nullifier);
137
154
  } catch (e) {
@@ -176,10 +193,16 @@ export class L1ToL2MessageExists extends Instruction {
176
193
  const memory = context.machineState.memory.track(this.type);
177
194
  context.machineState.consumeGas(this.gasCost(memoryOperations));
178
195
 
179
- const msgHash = memory.get(this.msgHashOffset).toFr();
180
- const msgLeafIndex = memory.get(this.msgLeafIndexOffset).toFr();
196
+ const [msgHashOffset, msgLeafIndexOffset, existsOffset] = Addressing.fromWire(this.indirect).resolve(
197
+ [this.msgHashOffset, this.msgLeafIndexOffset, this.existsOffset],
198
+ memory,
199
+ );
200
+ memory.checkTags(TypeTag.FIELD, msgHashOffset, msgLeafIndexOffset);
201
+
202
+ const msgHash = memory.get(msgHashOffset).toFr();
203
+ const msgLeafIndex = memory.get(msgLeafIndexOffset).toFr();
181
204
  const exists = await context.persistableState.checkL1ToL2MessageExists(msgHash, msgLeafIndex);
182
- memory.set(this.existsOffset, exists ? new Uint8(1) : new Uint8(0));
205
+ memory.set(existsOffset, exists ? new Uint8(1) : new Uint8(0));
183
206
 
184
207
  memory.assert(memoryOperations);
185
208
  context.machineState.incrementPc();
@@ -202,7 +225,7 @@ export class EmitUnencryptedLog extends Instruction {
202
225
  private indirect: number,
203
226
  private eventSelectorOffset: number,
204
227
  private logOffset: number,
205
- private logSize: number,
228
+ private logSizeOffset: number,
206
229
  ) {
207
230
  super();
208
231
  }
@@ -212,18 +235,23 @@ export class EmitUnencryptedLog extends Instruction {
212
235
  throw new StaticCallAlterationError();
213
236
  }
214
237
 
215
- const memoryOperations = { reads: 1 + this.logSize, indirect: this.indirect };
216
238
  const memory = context.machineState.memory.track(this.type);
217
- context.machineState.consumeGas(this.gasCost(memoryOperations));
218
239
 
219
- const [eventSelectorOffset, logOffset] = Addressing.fromWire(this.indirect).resolve(
220
- [this.eventSelectorOffset, this.logOffset],
240
+ const [eventSelectorOffset, logOffset, logSizeOffset] = Addressing.fromWire(this.indirect).resolve(
241
+ [this.eventSelectorOffset, this.logOffset, this.logSizeOffset],
221
242
  memory,
222
243
  );
244
+ memory.checkTag(TypeTag.FIELD, eventSelectorOffset);
245
+ memory.checkTag(TypeTag.UINT32, logSizeOffset);
246
+ const logSize = memory.get(logSizeOffset).toNumber();
247
+ memory.checkTagsRange(TypeTag.FIELD, logOffset, logSize);
223
248
 
224
249
  const contractAddress = context.environment.address;
225
250
  const event = memory.get(eventSelectorOffset).toFr();
226
- const log = memory.getSlice(logOffset, this.logSize).map(f => f.toFr());
251
+
252
+ const memoryOperations = { reads: 2 + logSize, indirect: this.indirect };
253
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
254
+ const log = memory.getSlice(logOffset, logSize).map(f => f.toFr());
227
255
  context.persistableState.writeLog(contractAddress, event, log);
228
256
 
229
257
  memory.assert(memoryOperations);
@@ -250,8 +278,13 @@ export class SendL2ToL1Message extends Instruction {
250
278
  const memory = context.machineState.memory.track(this.type);
251
279
  context.machineState.consumeGas(this.gasCost(memoryOperations));
252
280
 
253
- const recipient = memory.get(this.recipientOffset).toFr();
254
- const content = memory.get(this.contentOffset).toFr();
281
+ const [recipientOffset, contentOffset] = Addressing.fromWire(this.indirect).resolve(
282
+ [this.recipientOffset, this.contentOffset],
283
+ memory,
284
+ );
285
+
286
+ const recipient = memory.get(recipientOffset).toFr();
287
+ const content = memory.get(contentOffset).toFr();
255
288
  context.persistableState.writeL1Message(recipient, content);
256
289
 
257
290
  memory.assert(memoryOperations);
@@ -1,6 +1,7 @@
1
1
  import type { AvmContext } from '../avm_context.js';
2
2
  import { type Field, type MemoryValue, TypeTag } from '../avm_memory_types.js';
3
3
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
4
+ import { Addressing } from './addressing_mode.js';
4
5
  import { Instruction } from './instruction.js';
5
6
  import { ThreeOperandInstruction } from './instruction_impl.js';
6
7
 
@@ -10,13 +11,17 @@ export abstract class ThreeOperandArithmeticInstruction extends ThreeOperandInst
10
11
  const memory = context.machineState.memory.track(this.type);
11
12
  context.machineState.consumeGas(this.gasCost(memoryOperations));
12
13
 
13
- memory.checkTags(this.inTag, this.aOffset, this.bOffset);
14
+ const [aOffset, bOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
15
+ [this.aOffset, this.bOffset, this.dstOffset],
16
+ memory,
17
+ );
18
+ memory.checkTags(this.inTag, aOffset, bOffset);
14
19
 
15
- const a = memory.get(this.aOffset);
16
- const b = memory.get(this.bOffset);
20
+ const a = memory.get(aOffset);
21
+ const b = memory.get(bOffset);
17
22
 
18
23
  const dest = this.compute(a, b);
19
- memory.set(this.dstOffset, dest);
24
+ memory.set(dstOffset, dest);
20
25
 
21
26
  memory.assert(memoryOperations);
22
27
  context.machineState.incrementPc();
@@ -83,13 +88,17 @@ export class FieldDiv extends Instruction {
83
88
  const memory = context.machineState.memory.track(this.type);
84
89
  context.machineState.consumeGas(this.gasCost(memoryOperations));
85
90
 
86
- memory.checkTags(TypeTag.FIELD, this.aOffset, this.bOffset);
91
+ const [aOffset, bOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
92
+ [this.aOffset, this.bOffset, this.dstOffset],
93
+ memory,
94
+ );
95
+ memory.checkTags(TypeTag.FIELD, aOffset, bOffset);
87
96
 
88
- const a = memory.getAs<Field>(this.aOffset);
89
- const b = memory.getAs<Field>(this.bOffset);
97
+ const a = memory.getAs<Field>(aOffset);
98
+ const b = memory.getAs<Field>(bOffset);
90
99
 
91
100
  const dest = a.fdiv(b);
92
- memory.set(this.dstOffset, dest);
101
+ memory.set(dstOffset, dest);
93
102
 
94
103
  memory.assert(memoryOperations);
95
104
  context.machineState.incrementPc();
@@ -1,6 +1,7 @@
1
1
  import type { AvmContext } from '../avm_context.js';
2
2
  import { type IntegralValue, type TaggedMemoryInterface, TypeTag } from '../avm_memory_types.js';
3
3
  import { Opcode } from '../serialization/instruction_serialization.js';
4
+ import { Addressing } from './addressing_mode.js';
4
5
  import { ThreeOperandInstruction, TwoOperandInstruction } from './instruction_impl.js';
5
6
 
6
7
  abstract class ThreeOperandBitwiseInstruction extends ThreeOperandInstruction {
@@ -9,13 +10,17 @@ abstract class ThreeOperandBitwiseInstruction extends ThreeOperandInstruction {
9
10
  const memory = context.machineState.memory.track(this.type);
10
11
  context.machineState.consumeGas(this.gasCost(memoryOperations));
11
12
 
12
- this.checkTags(memory, this.inTag, this.aOffset, this.bOffset);
13
+ const [aOffset, bOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
14
+ [this.aOffset, this.bOffset, this.dstOffset],
15
+ memory,
16
+ );
17
+ this.checkTags(memory, this.inTag, aOffset, bOffset);
13
18
 
14
- const a = memory.getAs<IntegralValue>(this.aOffset);
15
- const b = memory.getAs<IntegralValue>(this.bOffset);
19
+ const a = memory.getAs<IntegralValue>(aOffset);
20
+ const b = memory.getAs<IntegralValue>(bOffset);
16
21
 
17
22
  const res = this.compute(a, b);
18
- memory.set(this.dstOffset, res);
23
+ memory.set(dstOffset, res);
19
24
 
20
25
  memory.assert(memoryOperations);
21
26
  context.machineState.incrementPc();
@@ -93,12 +98,12 @@ export class Not extends TwoOperandInstruction {
93
98
  const memory = context.machineState.memory.track(this.type);
94
99
  context.machineState.consumeGas(this.gasCost(memoryOperations));
95
100
 
96
- memory.checkTags(this.inTag, this.aOffset);
97
-
98
- const a = memory.getAs<IntegralValue>(this.aOffset);
101
+ const [aOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve([this.aOffset, this.dstOffset], memory);
102
+ memory.checkTags(this.inTag, aOffset);
103
+ const a = memory.getAs<IntegralValue>(aOffset);
99
104
 
100
105
  const res = a.not();
101
- memory.set(this.dstOffset, res);
106
+ memory.set(dstOffset, res);
102
107
 
103
108
  memory.assert(memoryOperations);
104
109
  context.machineState.incrementPc();
@@ -1,6 +1,7 @@
1
1
  import type { AvmContext } from '../avm_context.js';
2
2
  import { type MemoryValue, Uint8 } from '../avm_memory_types.js';
3
3
  import { Opcode } from '../serialization/instruction_serialization.js';
4
+ import { Addressing } from './addressing_mode.js';
4
5
  import { ThreeOperandInstruction } from './instruction_impl.js';
5
6
 
6
7
  abstract class ComparatorInstruction extends ThreeOperandInstruction {
@@ -9,13 +10,17 @@ abstract class ComparatorInstruction extends ThreeOperandInstruction {
9
10
  const memory = context.machineState.memory.track(this.type);
10
11
  context.machineState.consumeGas(this.gasCost(memoryOperations));
11
12
 
12
- memory.checkTags(this.inTag, this.aOffset, this.bOffset);
13
+ const [aOffset, bOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
14
+ [this.aOffset, this.bOffset, this.dstOffset],
15
+ memory,
16
+ );
17
+ memory.checkTags(this.inTag, aOffset, bOffset);
13
18
 
14
- const a = memory.get(this.aOffset);
15
- const b = memory.get(this.bOffset);
19
+ const a = memory.get(aOffset);
20
+ const b = memory.get(bOffset);
16
21
 
17
22
  const dest = new Uint8(this.compare(a, b) ? 1 : 0);
18
- memory.set(this.dstOffset, dest);
23
+ memory.set(dstOffset, dest);
19
24
 
20
25
  memory.assert(memoryOperations);
21
26
  context.machineState.incrementPc();
@@ -1,7 +1,7 @@
1
- import { AztecAddress, Fr } from '@aztec/circuits.js';
1
+ import { Fr } from '@aztec/circuits.js';
2
2
 
3
3
  import type { AvmContext } from '../avm_context.js';
4
- import { Field } from '../avm_memory_types.js';
4
+ import { Field, TypeTag } from '../avm_memory_types.js';
5
5
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
6
6
  import { Addressing } from './addressing_mode.js';
7
7
  import { Instruction } from './instruction.js';
@@ -22,35 +22,31 @@ export class GetContractInstance extends Instruction {
22
22
  }
23
23
 
24
24
  async execute(context: AvmContext): Promise<void> {
25
+ const memoryOperations = { reads: 1, writes: 6, indirect: this.indirect };
26
+ const memory = context.machineState.memory.track(this.type);
27
+ context.machineState.consumeGas(this.gasCost(memoryOperations));
28
+
25
29
  const [addressOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve(
26
30
  [this.addressOffset, this.dstOffset],
27
- context.machineState.memory,
31
+ memory,
28
32
  );
33
+ memory.checkTag(TypeTag.FIELD, addressOffset);
34
+
35
+ const address = memory.get(addressOffset).toFr();
36
+ const instance = await context.persistableState.getContractInstance(address);
37
+
38
+ const data = [
39
+ new Fr(instance.exists),
40
+ instance.salt,
41
+ instance.deployer.toField(),
42
+ instance.contractClassId,
43
+ instance.initializationHash,
44
+ instance.publicKeysHash,
45
+ ].map(f => new Field(f));
29
46
 
30
- const address = AztecAddress.fromField(context.machineState.memory.get(addressOffset).toFr());
31
- const instance = await context.persistableState.hostStorage.contractsDb.getContractInstance(address);
32
-
33
- const data =
34
- instance === undefined
35
- ? [
36
- new Field(0), // not found
37
- new Field(0),
38
- new Field(0),
39
- new Field(0),
40
- new Field(0),
41
- new Field(0),
42
- ]
43
- : [
44
- new Fr(1), // found
45
- instance.salt,
46
- instance.deployer.toField(),
47
- instance.contractClassId,
48
- instance.initializationHash,
49
- instance.publicKeysHash,
50
- ].map(f => new Field(f));
51
-
52
- context.machineState.memory.setSlice(dstOffset, data);
47
+ memory.setSlice(dstOffset, data);
53
48
 
49
+ memory.assert(memoryOperations);
54
50
  context.machineState.incrementPc();
55
51
  }
56
52
  }
@@ -2,6 +2,7 @@ import type { AvmContext } from '../avm_context.js';
2
2
  import { type IntegralValue } from '../avm_memory_types.js';
3
3
  import { InstructionExecutionError } from '../errors.js';
4
4
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
5
+ import { Addressing } from './addressing_mode.js';
5
6
  import { Instruction } from './instruction.js';
6
7
 
7
8
  export class Jump extends Instruction {
@@ -44,7 +45,8 @@ export class JumpI extends Instruction {
44
45
  const memory = context.machineState.memory.track(this.type);
45
46
  context.machineState.consumeGas(this.gasCost(memoryOperations));
46
47
 
47
- const condition = memory.getAs<IntegralValue>(this.condOffset);
48
+ const [condOffset] = Addressing.fromWire(this.indirect).resolve([this.condOffset], memory);
49
+ const condition = memory.getAs<IntegralValue>(condOffset);
48
50
 
49
51
  // TODO: reconsider this casting
50
52
  if (condition.toBigInt() == 0n) {