@aztec/simulator 0.27.1 → 0.28.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 (55) hide show
  1. package/dest/acvm/oracle/oracle.d.ts +3 -3
  2. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  3. package/dest/acvm/oracle/oracle.js +7 -7
  4. package/dest/acvm/oracle/typed_oracle.d.ts +3 -3
  5. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  6. package/dest/acvm/oracle/typed_oracle.js +35 -30
  7. package/dest/avm/avm_memory_types.d.ts +1 -0
  8. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  9. package/dest/avm/avm_memory_types.js +6 -1
  10. package/dest/avm/opcodes/arithmetic.d.ts +13 -1
  11. package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
  12. package/dest/avm/opcodes/arithmetic.js +31 -2
  13. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  14. package/dest/avm/serialization/bytecode_serialization.js +3 -2
  15. package/dest/avm/serialization/instruction_serialization.d.ts +58 -57
  16. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  17. package/dest/avm/serialization/instruction_serialization.js +59 -58
  18. package/dest/avm/temporary_executor_migration.d.ts.map +1 -1
  19. package/dest/avm/temporary_executor_migration.js +6 -1
  20. package/dest/client/client_execution_context.d.ts +2 -1
  21. package/dest/client/client_execution_context.d.ts.map +1 -1
  22. package/dest/client/client_execution_context.js +5 -3
  23. package/dest/client/execution_result.js +2 -2
  24. package/dest/client/simulator.d.ts.map +1 -1
  25. package/dest/client/simulator.js +5 -6
  26. package/dest/common/side_effect_counter.d.ts +1 -0
  27. package/dest/common/side_effect_counter.d.ts.map +1 -1
  28. package/dest/common/side_effect_counter.js +5 -1
  29. package/dest/public/db.d.ts +19 -5
  30. package/dest/public/db.d.ts.map +1 -1
  31. package/dest/public/execution.d.ts +4 -0
  32. package/dest/public/execution.d.ts.map +1 -1
  33. package/dest/public/execution.js +1 -1
  34. package/dest/public/executor.d.ts +2 -2
  35. package/dest/public/executor.d.ts.map +1 -1
  36. package/dest/public/executor.js +12 -12
  37. package/dest/public/public_execution_context.d.ts +3 -1
  38. package/dest/public/public_execution_context.d.ts.map +1 -1
  39. package/dest/public/public_execution_context.js +22 -4
  40. package/package.json +5 -5
  41. package/src/acvm/oracle/oracle.ts +6 -4
  42. package/src/acvm/oracle/typed_oracle.ts +35 -28
  43. package/src/avm/avm_memory_types.ts +6 -0
  44. package/src/avm/opcodes/arithmetic.ts +33 -1
  45. package/src/avm/serialization/bytecode_serialization.ts +2 -0
  46. package/src/avm/serialization/instruction_serialization.ts +1 -0
  47. package/src/avm/temporary_executor_migration.ts +5 -0
  48. package/src/client/client_execution_context.ts +4 -0
  49. package/src/client/execution_result.ts +1 -1
  50. package/src/client/simulator.ts +6 -3
  51. package/src/common/side_effect_counter.ts +5 -0
  52. package/src/public/db.ts +22 -5
  53. package/src/public/execution.ts +4 -0
  54. package/src/public/executor.ts +16 -10
  55. package/src/public/public_execution_context.ts +23 -2
@@ -69,6 +69,12 @@ export class MessageLoadOracleInputs<N extends number> {
69
69
  }
70
70
  }
71
71
 
72
+ class OracleMethodNotAvailableError extends Error {
73
+ constructor(methodName: string) {
74
+ super(`Oracle method ${methodName} is not available.`);
75
+ }
76
+ }
77
+
72
78
  /**
73
79
  * Oracle with typed parameters and typed return values.
74
80
  * Methods that require read and/or write will have to be implemented based on the context (public, private, or view)
@@ -80,58 +86,58 @@ export abstract class TypedOracle {
80
86
  }
81
87
 
82
88
  packArguments(_args: Fr[]): Promise<Fr> {
83
- throw new Error('Not available.');
89
+ throw new OracleMethodNotAvailableError('packArguments');
84
90
  }
85
91
 
86
92
  getNullifierKeyPair(_accountAddress: AztecAddress): Promise<KeyPair> {
87
- throw new Error('Not available.');
93
+ throw new OracleMethodNotAvailableError('getNullifierKeyPair');
88
94
  }
89
95
 
90
96
  getPublicKeyAndPartialAddress(_address: AztecAddress): Promise<Fr[] | undefined> {
91
- throw new Error('Not available.');
97
+ throw new OracleMethodNotAvailableError('getPublicKeyAndPartialAddress');
92
98
  }
93
99
 
94
100
  getContractInstance(_address: AztecAddress): Promise<ContractInstance> {
95
- throw new Error('Not available.');
101
+ throw new OracleMethodNotAvailableError('getContractInstance');
96
102
  }
97
103
 
98
104
  getMembershipWitness(_blockNumber: number, _treeId: MerkleTreeId, _leafValue: Fr): Promise<Fr[] | undefined> {
99
- throw new Error('Not available.');
105
+ throw new OracleMethodNotAvailableError('getMembershipWitness');
100
106
  }
101
107
 
102
108
  getSiblingPath(_blockNumber: number, _treeId: MerkleTreeId, _leafIndex: Fr): Promise<Fr[]> {
103
- throw new Error('Not available.');
109
+ throw new OracleMethodNotAvailableError('getSiblingPath');
104
110
  }
105
111
 
106
112
  getNullifierMembershipWitness(_blockNumber: number, _nullifier: Fr): Promise<NullifierMembershipWitness | undefined> {
107
- throw new Error('Not available.');
113
+ throw new OracleMethodNotAvailableError('getNullifierMembershipWitness');
108
114
  }
109
115
 
110
116
  getPublicDataTreeWitness(_blockNumber: number, _leafSlot: Fr): Promise<PublicDataWitness | undefined> {
111
- throw new Error('Not available.');
117
+ throw new OracleMethodNotAvailableError('getPublicDataTreeWitness');
112
118
  }
113
119
 
114
120
  getLowNullifierMembershipWitness(
115
121
  _blockNumber: number,
116
122
  _nullifier: Fr,
117
123
  ): Promise<NullifierMembershipWitness | undefined> {
118
- throw new Error('Not available.');
124
+ throw new OracleMethodNotAvailableError('getLowNullifierMembershipWitness');
119
125
  }
120
126
 
121
127
  getHeader(_blockNumber: number): Promise<Header | undefined> {
122
- throw new Error('Not available.');
128
+ throw new OracleMethodNotAvailableError('getHeader');
123
129
  }
124
130
 
125
131
  getCompleteAddress(_address: AztecAddress): Promise<CompleteAddress> {
126
- throw new Error('Not available.');
132
+ throw new OracleMethodNotAvailableError('getCompleteAddress');
127
133
  }
128
134
 
129
135
  getAuthWitness(_messageHash: Fr): Promise<Fr[] | undefined> {
130
- throw new Error('Not available.');
136
+ throw new OracleMethodNotAvailableError('getAuthWitness');
131
137
  }
132
138
 
133
139
  popCapsule(): Promise<Fr[]> {
134
- throw new Error('Not available.');
140
+ throw new OracleMethodNotAvailableError('popCapsule');
135
141
  }
136
142
 
137
143
  getNotes(
@@ -146,35 +152,35 @@ export abstract class TypedOracle {
146
152
  _offset: number,
147
153
  _status: NoteStatus,
148
154
  ): Promise<NoteData[]> {
149
- throw new Error('Not available.');
155
+ throw new OracleMethodNotAvailableError('getNotes');
150
156
  }
151
157
 
152
158
  notifyCreatedNote(_storageSlot: Fr, _noteTypeId: Fr, _note: Fr[], _innerNoteHash: Fr): void {
153
- throw new Error('Not available.');
159
+ throw new OracleMethodNotAvailableError('notifyCreatedNote');
154
160
  }
155
161
 
156
162
  notifyNullifiedNote(_innerNullifier: Fr, _innerNoteHash: Fr): Promise<void> {
157
- throw new Error('Not available.');
163
+ throw new OracleMethodNotAvailableError('notifyNullifiedNote');
158
164
  }
159
165
 
160
166
  checkNullifierExists(_innerNullifier: Fr): Promise<boolean> {
161
- throw new Error('Not available.');
167
+ throw new OracleMethodNotAvailableError('checkNullifierExists');
162
168
  }
163
169
 
164
170
  getL1ToL2MembershipWitness(_entryKey: Fr): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>> {
165
- throw new Error('Not available.');
171
+ throw new OracleMethodNotAvailableError('getL1ToL2MembershipWitness');
166
172
  }
167
173
 
168
174
  getPortalContractAddress(_contractAddress: AztecAddress): Promise<EthAddress> {
169
- throw new Error('Not available.');
175
+ throw new OracleMethodNotAvailableError('getPortalContractAddress');
170
176
  }
171
177
 
172
178
  storageRead(_startStorageSlot: Fr, _numberOfElements: number): Promise<Fr[]> {
173
- throw new Error('Not available.');
179
+ throw new OracleMethodNotAvailableError('storageRead');
174
180
  }
175
181
 
176
182
  storageWrite(_startStorageSlot: Fr, _values: Fr[]): Promise<Fr[]> {
177
- throw new Error('Not available.');
183
+ throw new OracleMethodNotAvailableError('storageWrite');
178
184
  }
179
185
 
180
186
  emitEncryptedLog(
@@ -184,42 +190,43 @@ export abstract class TypedOracle {
184
190
  _publicKey: PublicKey,
185
191
  _log: Fr[],
186
192
  ): void {
187
- throw new Error('Not available.');
193
+ throw new OracleMethodNotAvailableError('emitEncryptedLog');
188
194
  }
189
195
 
190
196
  emitUnencryptedLog(_log: UnencryptedL2Log): void {
191
- throw new Error('Not available.');
197
+ throw new OracleMethodNotAvailableError('emitUnencryptedLog');
192
198
  }
193
199
 
194
200
  callPrivateFunction(
195
201
  _targetContractAddress: AztecAddress,
196
202
  _functionSelector: FunctionSelector,
197
203
  _argsHash: Fr,
198
- _sideffectCounter: number,
204
+ _sideEffectCounter: number,
199
205
  _isStaticCall: boolean,
200
206
  _isDelegateCall: boolean,
201
207
  ): Promise<PrivateCallStackItem> {
202
- throw new Error('Not available.');
208
+ throw new OracleMethodNotAvailableError('callPrivateFunction');
203
209
  }
204
210
 
205
211
  callPublicFunction(
206
212
  _targetContractAddress: AztecAddress,
207
213
  _functionSelector: FunctionSelector,
208
214
  _argsHash: Fr,
215
+ _sideEffectCounter: number,
209
216
  _isStaticCall: boolean,
210
217
  _isDelegateCall: boolean,
211
218
  ): Promise<Fr[]> {
212
- throw new Error('Not available.');
219
+ throw new OracleMethodNotAvailableError('callPublicFunction');
213
220
  }
214
221
 
215
222
  enqueuePublicFunctionCall(
216
223
  _targetContractAddress: AztecAddress,
217
224
  _functionSelector: FunctionSelector,
218
225
  _argsHash: Fr,
219
- _sideffectCounter: number,
226
+ _sideEffectCounter: number,
220
227
  _isStaticCall: boolean,
221
228
  _isDelegateCall: boolean,
222
229
  ): Promise<PublicCallRequest> {
223
- throw new Error('Not available.');
230
+ throw new OracleMethodNotAvailableError('enqueuePublicFunctionCall');
224
231
  }
225
232
  }
@@ -160,7 +160,13 @@ export class Field extends MemoryValue {
160
160
  return new Field(this.rep.mul(rhs.rep));
161
161
  }
162
162
 
163
+ // Euclidean division.
163
164
  public div(rhs: Field): Field {
165
+ return new Field(this.rep.ediv(rhs.rep));
166
+ }
167
+
168
+ // Field division.
169
+ public fdiv(rhs: Field): Field {
164
170
  return new Field(this.rep.div(rhs.rep));
165
171
  }
166
172
 
@@ -1,5 +1,7 @@
1
1
  import type { AvmContext } from '../avm_context.js';
2
- import { Opcode } from '../serialization/instruction_serialization.js';
2
+ import { Field, TypeTag } from '../avm_memory_types.js';
3
+ import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
4
+ import { Instruction } from './instruction.js';
3
5
  import { ThreeOperandInstruction } from './instruction_impl.js';
4
6
 
5
7
  export class Add extends ThreeOperandInstruction {
@@ -79,3 +81,33 @@ export class Div extends ThreeOperandInstruction {
79
81
  context.machineState.incrementPc();
80
82
  }
81
83
  }
84
+
85
+ export class FieldDiv extends Instruction {
86
+ static type: string = 'FDIV';
87
+ static readonly opcode = Opcode.FDIV;
88
+
89
+ // Informs (de)serialization. See Instruction.deserialize.
90
+ static readonly wireFormat: OperandType[] = [
91
+ OperandType.UINT8,
92
+ OperandType.UINT8,
93
+ OperandType.UINT32,
94
+ OperandType.UINT32,
95
+ OperandType.UINT32,
96
+ ];
97
+
98
+ constructor(private indirect: number, private aOffset: number, private bOffset: number, private dstOffset: number) {
99
+ super();
100
+ }
101
+
102
+ async execute(context: AvmContext): Promise<void> {
103
+ context.machineState.memory.checkTags(TypeTag.FIELD, this.aOffset, this.bOffset);
104
+
105
+ const a = context.machineState.memory.getAs<Field>(this.aOffset);
106
+ const b = context.machineState.memory.getAs<Field>(this.bOffset);
107
+
108
+ const dest = a.fdiv(b);
109
+ context.machineState.memory.set(this.dstOffset, dest);
110
+
111
+ context.machineState.incrementPc();
112
+ }
113
+ }
@@ -17,6 +17,7 @@ import {
17
17
  FeePerDAGas,
18
18
  FeePerL1Gas,
19
19
  FeePerL2Gas,
20
+ FieldDiv,
20
21
  InternalCall,
21
22
  InternalReturn,
22
23
  Jump,
@@ -66,6 +67,7 @@ const INSTRUCTION_SET = () =>
66
67
  [Sub.opcode, Sub],
67
68
  [Mul.opcode, Mul],
68
69
  [Div.opcode, Div],
70
+ [FieldDiv.opcode, FieldDiv],
69
71
  [Eq.opcode, Eq],
70
72
  [Lt.opcode, Lt],
71
73
  [Lte.opcode, Lte],
@@ -12,6 +12,7 @@ export enum Opcode {
12
12
  SUB,
13
13
  MUL,
14
14
  DIV,
15
+ FDIV,
15
16
  EQ,
16
17
  LT,
17
18
  LTE,
@@ -98,6 +98,9 @@ export function temporaryConvertAvmResults(
98
98
  const newNullifiers: SideEffectLinkedToNoteHash[] = [];
99
99
  const unencryptedLogs = FunctionL2Logs.empty();
100
100
  const newL2ToL1Messages = newWorldState.newL1Messages.map(() => L2ToL1Message.empty());
101
+ // TODO keep track of side effect counters
102
+ const startSideEffectCounter = Fr.ZERO;
103
+ const endSideEffectCounter = Fr.ZERO;
101
104
 
102
105
  return {
103
106
  execution,
@@ -105,6 +108,8 @@ export function temporaryConvertAvmResults(
105
108
  nullifierNonExistentReadRequests,
106
109
  newNoteHashes,
107
110
  newL2ToL1Messages,
111
+ startSideEffectCounter,
112
+ endSideEffectCounter,
108
113
  newNullifiers,
109
114
  contractStorageReads,
110
115
  contractStorageUpdateRequests,
@@ -75,6 +75,7 @@ export class ClientExecutionContext extends ViewDataOracle {
75
75
  protected readonly db: DBOracle,
76
76
  private readonly curve: Grumpkin,
77
77
  private node: AztecNode,
78
+ protected sideEffectCounter: number = 0,
78
79
  protected log = createDebugLogger('aztec:simulator:client_execution_context'),
79
80
  ) {
80
81
  super(contractAddress, authWitnesses, db, node, log);
@@ -103,6 +104,8 @@ export class ClientExecutionContext extends ViewDataOracle {
103
104
  this.txContext.chainId,
104
105
  this.txContext.version,
105
106
 
107
+ new Fr(this.sideEffectCounter),
108
+
106
109
  ...args,
107
110
  ];
108
111
 
@@ -366,6 +369,7 @@ export class ClientExecutionContext extends ViewDataOracle {
366
369
  this.db,
367
370
  this.curve,
368
371
  this.node,
372
+ sideEffectCounter,
369
373
  );
370
374
 
371
375
  const childExecutionResult = await executePrivateFunction(
@@ -85,5 +85,5 @@ export function collectEnqueuedPublicFunctionCalls(execResult: ExecutionResult):
85
85
  return [
86
86
  ...execResult.enqueuedPublicFunctionCalls,
87
87
  ...[...execResult.nestedExecutions].flatMap(collectEnqueuedPublicFunctionCalls),
88
- ].sort((a, b) => b.callContext.startSideEffectCounter - a.callContext.startSideEffectCounter);
88
+ ].sort((a, b) => b.callContext.sideEffectCounter - a.callContext.sideEffectCounter);
89
89
  }
@@ -85,6 +85,10 @@ export class AcirSimulator {
85
85
  const curve = new Grumpkin();
86
86
 
87
87
  const header = await this.db.getHeader();
88
+
89
+ // reserve the first side effect for the tx hash (inserted by the private kernel)
90
+ const startSideEffectCounter = 1;
91
+
88
92
  const callContext = new CallContext(
89
93
  msgSender,
90
94
  contractAddress,
@@ -92,9 +96,7 @@ export class AcirSimulator {
92
96
  FunctionSelector.fromNameAndParameters(entryPointArtifact.name, entryPointArtifact.parameters),
93
97
  false,
94
98
  false,
95
- // TODO: when contract deployment is done in-app, we should only reserve one counter for the tx hash
96
- // 2 counters are reserved for tx hash and contract deployment nullifier
97
- 1,
99
+ startSideEffectCounter,
98
100
  );
99
101
  const context = new ClientExecutionContext(
100
102
  contractAddress,
@@ -108,6 +110,7 @@ export class AcirSimulator {
108
110
  this.db,
109
111
  curve,
110
112
  this.node,
113
+ startSideEffectCounter,
111
114
  );
112
115
 
113
116
  try {
@@ -4,6 +4,11 @@
4
4
  export class SideEffectCounter {
5
5
  constructor(private value = 0) {}
6
6
 
7
+ // TODO(alexg) remove this once public side effect counters is fully accounted for on Noir side
8
+ current() {
9
+ return this.value;
10
+ }
11
+
7
12
  count() {
8
13
  const value = this.value;
9
14
  this.value++;
package/src/public/db.ts CHANGED
@@ -2,6 +2,7 @@ import { NullifierMembershipWitness } from '@aztec/circuit-types';
2
2
  import { EthAddress, FunctionSelector, L1_TO_L2_MSG_TREE_HEIGHT } from '@aztec/circuits.js';
3
3
  import { AztecAddress } from '@aztec/foundation/aztec-address';
4
4
  import { Fr } from '@aztec/foundation/fields';
5
+ import { ContractInstanceWithAddress } from '@aztec/types/contracts';
5
6
 
6
7
  import { MessageLoadOracleInputs } from '../acvm/index.js';
7
8
 
@@ -27,16 +28,25 @@ export interface PublicStateDB {
27
28
  storageWrite(contract: AztecAddress, slot: Fr, newValue: Fr): Promise<void>;
28
29
 
29
30
  /**
30
- * Commit the pending changes to the DB.
31
- * @returns Nothing.
31
+ * Mark the uncommitted changes in this TX as a checkpoint.
32
+ */
33
+ checkpoint(): Promise<void>;
34
+
35
+ /**
36
+ * Rollback to the last checkpoint.
37
+ */
38
+ rollbackToCheckpoint(): Promise<void>;
39
+
40
+ /**
41
+ * Commit the changes in this TX. Includes all changes since the last commit,
42
+ * even if they haven't been covered by a checkpoint.
32
43
  */
33
44
  commit(): Promise<void>;
34
45
 
35
46
  /**
36
- * Rollback the pending changes.
37
- * @returns Nothing.
47
+ * Rollback to the last commit.
38
48
  */
39
- rollback(): Promise<void>;
49
+ rollbackToCommit(): Promise<void>;
40
50
  }
41
51
 
42
52
  /**
@@ -65,6 +75,13 @@ export interface PublicContractsDB {
65
75
  * @returns The portal contract address or undefined if not found.
66
76
  */
67
77
  getPortalContractAddress(address: AztecAddress): Promise<EthAddress | undefined>;
78
+
79
+ /**
80
+ * Returns a publicly deployed contract instance.
81
+ * @param address - Address of the contract.
82
+ * @returns The contract instance or undefined if not found.
83
+ */
84
+ getContractInstance(address: AztecAddress): Promise<ContractInstanceWithAddress | undefined>;
68
85
  }
69
86
 
70
87
  /** Database interface for providing access to commitment tree, l1 to l2 message tree, and nullifier tree. */
@@ -26,6 +26,10 @@ export interface PublicExecutionResult {
26
26
  newNoteHashes: SideEffect[];
27
27
  /** The new l2 to l1 messages generated in this call. */
28
28
  newL2ToL1Messages: L2ToL1Message[];
29
+ /** The side effect counter at the start of the function call. */
30
+ startSideEffectCounter: Fr;
31
+ /** The side effect counter after executing this function call */
32
+ endSideEffectCounter: Fr;
29
33
  /** The new nullifiers to be inserted into the nullifier tree. */
30
34
  newNullifiers: SideEffectLinkedToNoteHash[];
31
35
  /** The nullifier read requests emitted in this call. */
@@ -1,5 +1,5 @@
1
1
  import { FunctionL2Logs } from '@aztec/circuit-types';
2
- import { GlobalVariables, Header, PublicCircuitPublicInputs } from '@aztec/circuits.js';
2
+ import { Fr, GlobalVariables, Header, PublicCircuitPublicInputs } from '@aztec/circuits.js';
3
3
  import { createDebugLogger } from '@aztec/foundation/log';
4
4
 
5
5
  import { spawn } from 'child_process';
@@ -83,6 +83,9 @@ export async function executePublicFunction(
83
83
  returnValues: [],
84
84
  newNoteHashes: [],
85
85
  newL2ToL1Messages: [],
86
+ // TODO (side effects) get these values in the revert case from the vm
87
+ startSideEffectCounter: Fr.ZERO,
88
+ endSideEffectCounter: Fr.ZERO,
86
89
  newNullifiers: [],
87
90
  nullifierReadRequests: [],
88
91
  nullifierNonExistentReadRequests: [],
@@ -107,6 +110,8 @@ export async function executePublicFunction(
107
110
  newL2ToL1Msgs,
108
111
  newNoteHashes: newNoteHashesPadded,
109
112
  newNullifiers: newNullifiersPadded,
113
+ startSideEffectCounter,
114
+ endSideEffectCounter,
110
115
  } = PublicCircuitPublicInputs.fromFields(returnWitness);
111
116
 
112
117
  const nullifierReadRequests = nullifierReadRequestsPadded.filter(v => !v.isEmpty());
@@ -136,6 +141,8 @@ export async function executePublicFunction(
136
141
  newNoteHashes,
137
142
  newL2ToL1Messages,
138
143
  newNullifiers,
144
+ startSideEffectCounter,
145
+ endSideEffectCounter,
139
146
  nullifierReadRequests,
140
147
  nullifierNonExistentReadRequests,
141
148
  contractStorageReads,
@@ -165,7 +172,11 @@ export class PublicExecutor {
165
172
  * @param globalVariables - The global variables to use.
166
173
  * @returns The result of the run plus all nested runs.
167
174
  */
168
- public async simulate(execution: PublicExecution, globalVariables: GlobalVariables): Promise<PublicExecutionResult> {
175
+ public async simulate(
176
+ execution: PublicExecution,
177
+ globalVariables: GlobalVariables,
178
+ sideEffectCounter: number = 0,
179
+ ): Promise<PublicExecutionResult> {
169
180
  const selector = execution.functionData.selector;
170
181
  const acir = await this.contractsDb.getBytecode(execution.contractAddress, selector);
171
182
  if (!acir) {
@@ -176,14 +187,12 @@ export class PublicExecutor {
176
187
  // We use this cache to hold the packed arguments.
177
188
  const packedArgs = PackedArgsCache.create([]);
178
189
 
179
- const sideEffectCounter = new SideEffectCounter();
180
-
181
190
  const context = new PublicExecutionContext(
182
191
  execution,
183
192
  this.header,
184
193
  globalVariables,
185
194
  packedArgs,
186
- sideEffectCounter,
195
+ new SideEffectCounter(sideEffectCounter),
187
196
  this.stateDb,
188
197
  this.contractsDb,
189
198
  this.commitmentsDb,
@@ -213,9 +222,10 @@ export class PublicExecutor {
213
222
  public async simulateAvm(
214
223
  execution: PublicExecution,
215
224
  globalVariables: GlobalVariables,
225
+ _sideEffectCounter = 0,
216
226
  ): Promise<PublicExecutionResult> {
217
227
  // Temporary code to construct the AVM context
218
- // These data structures will permiate across the simulator when the public executor is phased out
228
+ // These data structures will permeate across the simulator when the public executor is phased out
219
229
  const hostStorage = new HostStorage(this.stateDb, this.contractsDb, this.commitmentsDb);
220
230
  const worldStateJournal = new AvmPersistableStateManager(hostStorage);
221
231
  const executionEnv = temporaryCreateAvmExecutionEnvironment(execution, globalVariables);
@@ -244,8 +254,6 @@ export class PublicExecutor {
244
254
  */
245
255
  public async getAvmProof(avmExecution: PublicExecution): Promise<Buffer[]> {
246
256
  // The paths for the barretenberg binary and the write path are hardcoded for now.
247
- // We additionally need the path to a valid crs for proof generation.
248
- // const bbPath = '../../barretenberg/cpp';
249
257
  const bbPath = path.resolve('../../barretenberg/cpp');
250
258
  const artifactsPath = path.resolve('target');
251
259
 
@@ -273,8 +281,6 @@ export class PublicExecutor {
273
281
  bytecodePath,
274
282
  '-d',
275
283
  calldataPath,
276
- '-c',
277
- path.join(bbPath, 'srs_db', 'ignition'),
278
284
  '-o',
279
285
  proofPath,
280
286
  ]);
@@ -4,6 +4,7 @@ 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
6
  import { createDebugLogger } from '@aztec/foundation/log';
7
+ import { ContractInstance } from '@aztec/types/contracts';
7
8
 
8
9
  import { TypedOracle, toACVMWitness } from '../acvm/index.js';
9
10
  import { PackedArgsCache, SideEffectCounter } from '../common/index.js';
@@ -49,7 +50,13 @@ export class PublicExecutionContext extends TypedOracle {
49
50
  */
50
51
  public getInitialWitness(witnessStartIndex = 0) {
51
52
  const { callContext, args } = this.execution;
52
- const fields = [...callContext.toFields(), ...this.header.toFields(), ...this.globalVariables.toFields(), ...args];
53
+ const fields = [
54
+ ...callContext.toFields(),
55
+ ...this.header.toFields(),
56
+ ...this.globalVariables.toFields(),
57
+ new Fr(this.sideEffectCounter.current()),
58
+ ...args,
59
+ ];
53
60
 
54
61
  return toACVMWitness(witnessStartIndex, fields);
55
62
  }
@@ -160,6 +167,7 @@ export class PublicExecutionContext extends TypedOracle {
160
167
  targetContractAddress: AztecAddress,
161
168
  functionSelector: FunctionSelector,
162
169
  argsHash: Fr,
170
+ sideEffectCounter: number,
163
171
  isStaticCall: boolean,
164
172
  isDelegateCall: boolean,
165
173
  ) {
@@ -188,7 +196,7 @@ export class PublicExecutionContext extends TypedOracle {
188
196
  functionSelector,
189
197
  isDelegateCall,
190
198
  isStaticCall,
191
- startSideEffectCounter: 0, // TODO use counters in public execution
199
+ sideEffectCounter,
192
200
  });
193
201
 
194
202
  const nestedExecution: PublicExecution = {
@@ -237,4 +245,17 @@ export class PublicExecutionContext extends TypedOracle {
237
245
  }
238
246
  return await this.commitmentsDb.getNullifierMembershipWitnessAtLatestBlock(nullifier);
239
247
  }
248
+
249
+ public async getContractInstance(address: AztecAddress): Promise<ContractInstance> {
250
+ // Note to AVM implementor: The wrapper of the oracle call get_contract_instance in aztec-nr
251
+ // automatically checks that the returned instance is correct, by hashing it together back
252
+ // into the address. However, in the AVM, we also need to prove the negative, otherwise a malicious
253
+ // sequencer could just lie about not having the instance available in its local db. We can do this
254
+ // by using the prove_contract_non_deployment_at method if the contract is not found in the db.
255
+ const instance = await this.contractsDb.getContractInstance(address);
256
+ if (!instance) {
257
+ throw new Error(`Contract instance at ${address} not found`);
258
+ }
259
+ return instance;
260
+ }
240
261
  }