@aztec/simulator 0.60.0 → 0.62.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 (133) hide show
  1. package/dest/acvm/oracle/oracle.d.ts +3 -0
  2. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  3. package/dest/acvm/oracle/oracle.js +12 -1
  4. package/dest/acvm/oracle/typed_oracle.d.ts +4 -1
  5. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  6. package/dest/acvm/oracle/typed_oracle.js +10 -1
  7. package/dest/avm/avm_gas.d.ts.map +1 -1
  8. package/dest/avm/avm_gas.js +8 -5
  9. package/dest/avm/avm_machine_state.d.ts +2 -0
  10. package/dest/avm/avm_machine_state.d.ts.map +1 -1
  11. package/dest/avm/avm_machine_state.js +3 -1
  12. package/dest/avm/avm_simulator.d.ts +15 -0
  13. package/dest/avm/avm_simulator.d.ts.map +1 -1
  14. package/dest/avm/avm_simulator.js +45 -4
  15. package/dest/avm/fixtures/index.d.ts +1 -1
  16. package/dest/avm/fixtures/index.d.ts.map +1 -1
  17. package/dest/avm/fixtures/index.js +7 -7
  18. package/dest/avm/journal/journal.d.ts +5 -6
  19. package/dest/avm/journal/journal.d.ts.map +1 -1
  20. package/dest/avm/journal/journal.js +42 -17
  21. package/dest/avm/opcodes/contract.d.ts +8 -1
  22. package/dest/avm/opcodes/contract.d.ts.map +1 -1
  23. package/dest/avm/opcodes/contract.js +41 -21
  24. package/dest/avm/opcodes/control_flow.js +5 -5
  25. package/dest/avm/opcodes/conversion.d.ts +1 -1
  26. package/dest/avm/opcodes/conversion.d.ts.map +1 -1
  27. package/dest/avm/opcodes/conversion.js +12 -9
  28. package/dest/avm/opcodes/environment_getters.d.ts +1 -1
  29. package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
  30. package/dest/avm/opcodes/environment_getters.js +5 -1
  31. package/dest/avm/opcodes/external_calls.d.ts +3 -6
  32. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  33. package/dest/avm/opcodes/external_calls.js +23 -43
  34. package/dest/avm/opcodes/memory.d.ts +20 -0
  35. package/dest/avm/opcodes/memory.d.ts.map +1 -1
  36. package/dest/avm/opcodes/memory.js +59 -3
  37. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  38. package/dest/avm/serialization/bytecode_serialization.js +5 -3
  39. package/dest/avm/serialization/instruction_serialization.d.ts +36 -34
  40. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  41. package/dest/avm/serialization/instruction_serialization.js +37 -35
  42. package/dest/avm/test_utils.d.ts +2 -1
  43. package/dest/avm/test_utils.d.ts.map +1 -1
  44. package/dest/avm/test_utils.js +4 -1
  45. package/dest/client/client_execution_context.d.ts +1 -8
  46. package/dest/client/client_execution_context.d.ts.map +1 -1
  47. package/dest/client/client_execution_context.js +4 -18
  48. package/dest/client/db_oracle.d.ts +24 -1
  49. package/dest/client/db_oracle.d.ts.map +1 -1
  50. package/dest/client/db_oracle.js +1 -1
  51. package/dest/client/view_data_oracle.d.ts +17 -1
  52. package/dest/client/view_data_oracle.d.ts.map +1 -1
  53. package/dest/client/view_data_oracle.js +21 -1
  54. package/dest/common/index.d.ts +0 -1
  55. package/dest/common/index.d.ts.map +1 -1
  56. package/dest/common/index.js +1 -2
  57. package/dest/public/dual_side_effect_trace.d.ts +3 -5
  58. package/dest/public/dual_side_effect_trace.d.ts.map +1 -1
  59. package/dest/public/dual_side_effect_trace.js +8 -4
  60. package/dest/public/enqueued_call_side_effect_trace.d.ts +4 -6
  61. package/dest/public/enqueued_call_side_effect_trace.d.ts.map +1 -1
  62. package/dest/public/enqueued_call_side_effect_trace.js +19 -7
  63. package/dest/public/enqueued_call_simulator.d.ts +2 -2
  64. package/dest/public/enqueued_call_simulator.d.ts.map +1 -1
  65. package/dest/public/enqueued_call_simulator.js +21 -29
  66. package/dest/public/enqueued_calls_processor.d.ts +2 -3
  67. package/dest/public/enqueued_calls_processor.d.ts.map +1 -1
  68. package/dest/public/enqueued_calls_processor.js +18 -25
  69. package/dest/public/public_db_sources.d.ts.map +1 -1
  70. package/dest/public/public_db_sources.js +10 -15
  71. package/dest/public/public_kernel.d.ts +0 -1
  72. package/dest/public/public_kernel.d.ts.map +1 -1
  73. package/dest/public/public_kernel.js +5 -8
  74. package/dest/public/public_kernel_tail_simulator.d.ts +1 -5
  75. package/dest/public/public_kernel_tail_simulator.d.ts.map +1 -1
  76. package/dest/public/public_kernel_tail_simulator.js +6 -12
  77. package/dest/public/public_processor.js +4 -4
  78. package/dest/public/side_effect_trace.d.ts +4 -3
  79. package/dest/public/side_effect_trace.d.ts.map +1 -1
  80. package/dest/public/side_effect_trace.js +27 -16
  81. package/dest/public/side_effect_trace_interface.d.ts +3 -3
  82. package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
  83. package/dest/test/utils.d.ts +2 -2
  84. package/dest/test/utils.d.ts.map +1 -1
  85. package/dest/test/utils.js +4 -4
  86. package/package.json +9 -9
  87. package/src/acvm/oracle/oracle.ts +20 -0
  88. package/src/acvm/oracle/typed_oracle.ts +13 -0
  89. package/src/avm/avm_gas.ts +7 -4
  90. package/src/avm/avm_machine_state.ts +2 -0
  91. package/src/avm/avm_simulator.ts +69 -6
  92. package/src/avm/fixtures/index.ts +7 -7
  93. package/src/avm/journal/journal.ts +62 -19
  94. package/src/avm/opcodes/contract.ts +45 -21
  95. package/src/avm/opcodes/control_flow.ts +5 -5
  96. package/src/avm/opcodes/conversion.ts +9 -6
  97. package/src/avm/opcodes/environment_getters.ts +7 -2
  98. package/src/avm/opcodes/external_calls.ts +21 -45
  99. package/src/avm/opcodes/memory.ts +69 -2
  100. package/src/avm/serialization/bytecode_serialization.ts +6 -2
  101. package/src/avm/serialization/instruction_serialization.ts +5 -3
  102. package/src/avm/test_utils.ts +5 -1
  103. package/src/client/client_execution_context.ts +4 -27
  104. package/src/client/db_oracle.ts +38 -0
  105. package/src/client/view_data_oracle.ts +31 -1
  106. package/src/common/index.ts +0 -1
  107. package/src/public/dual_side_effect_trace.ts +20 -6
  108. package/src/public/enqueued_call_side_effect_trace.ts +46 -8
  109. package/src/public/enqueued_call_simulator.ts +42 -26
  110. package/src/public/enqueued_calls_processor.ts +26 -38
  111. package/src/public/public_db_sources.ts +10 -15
  112. package/src/public/public_kernel.ts +9 -12
  113. package/src/public/public_kernel_tail_simulator.ts +6 -15
  114. package/src/public/public_processor.ts +3 -3
  115. package/src/public/side_effect_trace.ts +54 -15
  116. package/src/public/side_effect_trace_interface.ts +9 -4
  117. package/src/test/utils.ts +9 -2
  118. package/dest/client/test_utils.d.ts +0 -9
  119. package/dest/client/test_utils.d.ts.map +0 -1
  120. package/dest/client/test_utils.js +0 -27
  121. package/dest/common/side_effect_counter.d.ts +0 -10
  122. package/dest/common/side_effect_counter.d.ts.map +0 -1
  123. package/dest/common/side_effect_counter.js +0 -18
  124. package/dest/rollup/index.d.ts +0 -2
  125. package/dest/rollup/index.d.ts.map +0 -1
  126. package/dest/rollup/index.js +0 -2
  127. package/dest/rollup/rollup.d.ts +0 -101
  128. package/dest/rollup/rollup.d.ts.map +0 -1
  129. package/dest/rollup/rollup.js +0 -100
  130. package/src/client/test_utils.ts +0 -57
  131. package/src/common/side_effect_counter.ts +0 -17
  132. package/src/rollup/index.ts +0 -1
  133. package/src/rollup/rollup.ts +0 -228
@@ -1,10 +1,9 @@
1
- import { FunctionSelector, Gas } from '@aztec/circuits.js';
2
- import { padArrayEnd } from '@aztec/foundation/collection';
1
+ import { Fr, FunctionSelector, Gas, PUBLIC_DISPATCH_SELECTOR } from '@aztec/circuits.js';
3
2
 
4
3
  import type { AvmContext } from '../avm_context.js';
5
4
  import { type AvmContractCallResult } from '../avm_contract_call_result.js';
6
5
  import { gasLeftToGas } from '../avm_gas.js';
7
- import { Field, TypeTag, Uint8 } from '../avm_memory_types.js';
6
+ import { type Field, TypeTag, Uint1 } from '../avm_memory_types.js';
8
7
  import { AvmSimulator } from '../avm_simulator.js';
9
8
  import { RethrownError } from '../errors.js';
10
9
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
@@ -21,58 +20,39 @@ abstract class ExternalCall extends Instruction {
21
20
  OperandType.UINT16,
22
21
  OperandType.UINT16,
23
22
  OperandType.UINT16,
24
- OperandType.UINT16,
25
- OperandType.UINT16,
26
- OperandType.UINT16,
27
23
  ];
28
24
 
29
25
  constructor(
30
26
  private indirect: number,
31
- private gasOffset: number /* Unused due to no formal gas implementation at this moment */,
27
+ private gasOffset: number,
32
28
  private addrOffset: number,
33
29
  private argsOffset: number,
34
30
  private argsSizeOffset: number,
35
- private retOffset: number,
36
- private retSize: number,
37
31
  private successOffset: number,
38
- // NOTE: Function selector is likely temporary since eventually public contract bytecode will be one
39
- // blob containing all functions, and function selector will become an application-level mechanism
40
- // (e.g. first few bytes of calldata + compiler-generated jump table)
41
- private functionSelectorOffset: number,
42
32
  ) {
43
33
  super();
44
34
  }
45
35
 
46
36
  public async execute(context: AvmContext) {
47
37
  const memory = context.machineState.memory.track(this.type);
48
- const operands = [
49
- this.gasOffset,
50
- this.addrOffset,
51
- this.argsOffset,
52
- this.argsSizeOffset,
53
- this.retOffset,
54
- this.successOffset,
55
- this.functionSelectorOffset,
56
- ];
38
+ const operands = [this.gasOffset, this.addrOffset, this.argsOffset, this.argsSizeOffset, this.successOffset];
57
39
  const addressing = Addressing.fromWire(this.indirect, operands.length);
58
- const [gasOffset, addrOffset, argsOffset, argsSizeOffset, retOffset, successOffset, functionSelectorOffset] =
59
- addressing.resolve(operands, memory);
40
+ const [gasOffset, addrOffset, argsOffset, argsSizeOffset, successOffset] = addressing.resolve(operands, memory);
60
41
  memory.checkTags(TypeTag.FIELD, gasOffset, gasOffset + 1);
61
42
  memory.checkTag(TypeTag.FIELD, addrOffset);
62
43
  memory.checkTag(TypeTag.UINT32, argsSizeOffset);
63
- memory.checkTag(TypeTag.FIELD, functionSelectorOffset);
64
44
 
65
45
  const calldataSize = memory.get(argsSizeOffset).toNumber();
66
46
  memory.checkTagsRange(TypeTag.FIELD, argsOffset, calldataSize);
67
47
 
68
48
  const callAddress = memory.getAs<Field>(addrOffset);
69
49
  const calldata = memory.getSlice(argsOffset, calldataSize).map(f => f.toFr());
70
- const functionSelector = memory.getAs<Field>(functionSelectorOffset).toFr();
50
+ const functionSelector = new Fr(PUBLIC_DISPATCH_SELECTOR);
71
51
  // If we are already in a static call, we propagate the environment.
72
52
  const callType = context.environment.isStaticCall ? 'STATICCALL' : this.type;
73
53
 
74
54
  // First we consume the gas for this operation.
75
- context.machineState.consumeGas(this.gasCost(calldataSize + this.retSize));
55
+ context.machineState.consumeGas(this.gasCost(calldataSize));
76
56
  // Then we consume the gas allocated for the nested call. The excess will be refunded later.
77
57
  // Gas allocation is capped by the amount of gas left in the current context.
78
58
  // We have to do some dancing here because the gas allocation is a field,
@@ -106,18 +86,12 @@ abstract class ExternalCall extends Instruction {
106
86
  throw new RethrownError(nestedCallResults.revertReason.message, nestedCallResults.revertReason);
107
87
  }
108
88
 
109
- // We only take as much data as was specified in the return size and pad with zeroes if the return data is smaller
110
- // than the specified size in order to prevent that memory to be left with garbage
111
- const returnData = nestedCallResults.output.slice(0, this.retSize);
112
- const convertedReturnData = padArrayEnd(
113
- returnData.map(f => new Field(f)),
114
- new Field(0),
115
- this.retSize,
116
- );
89
+ // Save return/revert data for later.
90
+ const fullReturnData = nestedCallResults.output;
91
+ context.machineState.nestedReturndata = fullReturnData;
117
92
 
118
- // Write our return data into memory
119
- memory.set(successOffset, new Uint8(success ? 1 : 0));
120
- memory.setSlice(retOffset, convertedReturnData);
93
+ // Write our success flag into memory.
94
+ memory.set(successOffset, new Uint1(success ? 1 : 0));
121
95
 
122
96
  // Refund unused gas
123
97
  context.machineState.refundGas(gasLeftToGas(nestedContext.machineState));
@@ -132,7 +106,7 @@ abstract class ExternalCall extends Instruction {
132
106
  /*avmCallResults=*/ nestedCallResults,
133
107
  );
134
108
 
135
- memory.assert({ reads: calldataSize + 5, writes: 1 + this.retSize, addressing });
109
+ memory.assert({ reads: calldataSize + 4, writes: 1, addressing });
136
110
  context.machineState.incrementPc();
137
111
  }
138
112
 
@@ -204,22 +178,24 @@ export class Revert extends Instruction {
204
178
  OperandType.UINT16,
205
179
  ];
206
180
 
207
- constructor(private indirect: number, private returnOffset: number, private retSize: number) {
181
+ constructor(private indirect: number, private returnOffset: number, private retSizeOffset: number) {
208
182
  super();
209
183
  }
210
184
 
211
185
  public async execute(context: AvmContext): Promise<void> {
212
186
  const memory = context.machineState.memory.track(this.type);
213
- context.machineState.consumeGas(this.gasCost(this.retSize));
214
187
 
215
- const operands = [this.returnOffset];
188
+ const operands = [this.returnOffset, this.retSizeOffset];
216
189
  const addressing = Addressing.fromWire(this.indirect, operands.length);
217
- const [returnOffset] = addressing.resolve(operands, memory);
190
+ const [returnOffset, retSizeOffset] = addressing.resolve(operands, memory);
218
191
 
219
- const output = memory.getSlice(returnOffset, this.retSize).map(word => word.toFr());
192
+ memory.checkTag(TypeTag.UINT32, retSizeOffset);
193
+ const retSize = memory.get(retSizeOffset).toNumber();
194
+ context.machineState.consumeGas(this.gasCost(retSize));
195
+ const output = memory.getSlice(returnOffset, retSize).map(word => word.toFr());
220
196
 
221
197
  context.machineState.revert(output);
222
- memory.assert({ reads: this.retSize, addressing });
198
+ memory.assert({ reads: retSize + 1, addressing });
223
199
  }
224
200
  }
225
201
 
@@ -1,5 +1,5 @@
1
1
  import type { AvmContext } from '../avm_context.js';
2
- import { Field, TaggedMemory } from '../avm_memory_types.js';
2
+ import { Field, TaggedMemory, TypeTag, Uint32 } from '../avm_memory_types.js';
3
3
  import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
4
4
  import { Addressing } from './addressing_mode.js';
5
5
  import { Instruction } from './instruction.js';
@@ -179,11 +179,11 @@ export class CalldataCopy extends Instruction {
179
179
 
180
180
  public async execute(context: AvmContext): Promise<void> {
181
181
  const memory = context.machineState.memory.track(this.type);
182
- // We don't need to check tags here because: (1) the calldata is NOT in memory, and (2) we are the ones writing to destination.
183
182
  const operands = [this.cdStartOffset, this.copySizeOffset, this.dstOffset];
184
183
  const addressing = Addressing.fromWire(this.indirect, operands.length);
185
184
  const [cdStartOffset, copySizeOffset, dstOffset] = addressing.resolve(operands, memory);
186
185
 
186
+ memory.checkTags(TypeTag.UINT32, cdStartOffset, copySizeOffset);
187
187
  const cdStart = memory.get(cdStartOffset).toNumber();
188
188
  const copySize = memory.get(copySizeOffset).toNumber();
189
189
  context.machineState.consumeGas(this.gasCost(copySize));
@@ -196,3 +196,70 @@ export class CalldataCopy extends Instruction {
196
196
  context.machineState.incrementPc();
197
197
  }
198
198
  }
199
+
200
+ export class ReturndataSize extends Instruction {
201
+ static readonly type: string = 'RETURNDATASIZE';
202
+ static readonly opcode: Opcode = Opcode.RETURNDATASIZE;
203
+ // Informs (de)serialization. See Instruction.deserialize.
204
+ static readonly wireFormat: OperandType[] = [OperandType.UINT8, OperandType.UINT8, OperandType.UINT16];
205
+
206
+ constructor(private indirect: number, private dstOffset: number) {
207
+ super();
208
+ }
209
+
210
+ public async execute(context: AvmContext): Promise<void> {
211
+ const memory = context.machineState.memory.track(this.type);
212
+ const operands = [this.dstOffset];
213
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
214
+ const [dstOffset] = addressing.resolve(operands, memory);
215
+ context.machineState.consumeGas(this.gasCost());
216
+
217
+ memory.set(dstOffset, new Uint32(context.machineState.nestedReturndata.length));
218
+
219
+ memory.assert({ writes: 1, addressing });
220
+ context.machineState.incrementPc();
221
+ }
222
+ }
223
+
224
+ export class ReturndataCopy extends Instruction {
225
+ static readonly type: string = 'RETURNDATACOPY';
226
+ static readonly opcode: Opcode = Opcode.RETURNDATACOPY;
227
+ // Informs (de)serialization. See Instruction.deserialize.
228
+ static readonly wireFormat: OperandType[] = [
229
+ OperandType.UINT8,
230
+ OperandType.UINT8,
231
+ OperandType.UINT16,
232
+ OperandType.UINT16,
233
+ OperandType.UINT16,
234
+ ];
235
+
236
+ constructor(
237
+ private indirect: number,
238
+ private rdStartOffset: number,
239
+ private copySizeOffset: number,
240
+ private dstOffset: number,
241
+ ) {
242
+ super();
243
+ }
244
+
245
+ public async execute(context: AvmContext): Promise<void> {
246
+ const memory = context.machineState.memory.track(this.type);
247
+ const operands = [this.rdStartOffset, this.copySizeOffset, this.dstOffset];
248
+ const addressing = Addressing.fromWire(this.indirect, operands.length);
249
+ const [rdStartOffset, copySizeOffset, dstOffset] = addressing.resolve(operands, memory);
250
+
251
+ memory.checkTags(TypeTag.UINT32, rdStartOffset, copySizeOffset);
252
+ const rdStart = memory.get(rdStartOffset).toNumber();
253
+ const copySize = memory.get(copySizeOffset).toNumber();
254
+ context.machineState.consumeGas(this.gasCost(copySize));
255
+
256
+ const transformedData = context.machineState.nestedReturndata
257
+ .slice(rdStart, rdStart + copySize)
258
+ .map(f => new Field(f));
259
+
260
+ memory.setSlice(dstOffset, transformedData);
261
+
262
+ memory.assert({ reads: 2, writes: copySize, addressing });
263
+ context.machineState.incrementPc();
264
+ }
265
+ }
@@ -31,6 +31,8 @@ import {
31
31
  Or,
32
32
  Poseidon2,
33
33
  Return,
34
+ ReturndataCopy,
35
+ ReturndataSize,
34
36
  Revert,
35
37
  SLoad,
36
38
  SStore,
@@ -41,7 +43,7 @@ import {
41
43
  Shr,
42
44
  StaticCall,
43
45
  Sub,
44
- ToRadixLE,
46
+ ToRadixBE,
45
47
  Xor,
46
48
  } from '../opcodes/index.js';
47
49
  import { MultiScalarMul } from '../opcodes/multi_scalar_mul.js';
@@ -96,6 +98,8 @@ const INSTRUCTION_SET = () =>
96
98
  // Execution Environment
97
99
  [Opcode.GETENVVAR_16, GetEnvVar.as(GetEnvVar.wireFormat16).deserialize],
98
100
  [CalldataCopy.opcode, Instruction.deserialize.bind(CalldataCopy)],
101
+ [Opcode.RETURNDATASIZE, Instruction.deserialize.bind(ReturndataSize)],
102
+ [Opcode.RETURNDATACOPY, Instruction.deserialize.bind(ReturndataCopy)],
99
103
 
100
104
  // Machine State - Internal Control Flow
101
105
  [Jump.opcode, Instruction.deserialize.bind(Jump)],
@@ -141,7 +145,7 @@ const INSTRUCTION_SET = () =>
141
145
  [Sha256Compression.opcode, Instruction.deserialize.bind(Sha256Compression)],
142
146
  [MultiScalarMul.opcode, Instruction.deserialize.bind(MultiScalarMul)],
143
147
  // Conversions
144
- [ToRadixLE.opcode, Instruction.deserialize.bind(ToRadixLE)],
148
+ [ToRadixBE.opcode, Instruction.deserialize.bind(ToRadixBE)],
145
149
  // Future Gadgets -- pending changes in noir
146
150
  // SHA256COMPRESSION,
147
151
  [KeccakF1600.opcode, Instruction.deserialize.bind(KeccakF1600)],
@@ -41,9 +41,11 @@ export enum Opcode {
41
41
  // Execution environment
42
42
  GETENVVAR_16,
43
43
  CALLDATACOPY,
44
+ RETURNDATASIZE,
45
+ RETURNDATACOPY,
44
46
  // Control flow
45
- JUMP_16,
46
- JUMPI_16,
47
+ JUMP_32,
48
+ JUMPI_32,
47
49
  INTERNALCALL,
48
50
  INTERNALRETURN,
49
51
  // Memory
@@ -81,7 +83,7 @@ export enum Opcode {
81
83
  ECADD,
82
84
  MSM,
83
85
  // Conversion
84
- TORADIXLE,
86
+ TORADIXBE,
85
87
  }
86
88
 
87
89
  // Possible types for an instruction's operand in its wire format. (Keep in sync with CPP code.
@@ -1,4 +1,4 @@
1
- import { type ContractInstanceWithAddress, Fr } from '@aztec/circuits.js';
1
+ import { type ContractClassPublic, type ContractInstanceWithAddress, Fr } from '@aztec/circuits.js';
2
2
 
3
3
  import { type jest } from '@jest/globals';
4
4
  import { mock } from 'jest-mock-extended';
@@ -61,3 +61,7 @@ export function mockL1ToL2MessageExists(
61
61
  export function mockGetContractInstance(worldStateDB: WorldStateDB, contractInstance: ContractInstanceWithAddress) {
62
62
  (worldStateDB as jest.Mocked<WorldStateDB>).getContractInstance.mockResolvedValue(contractInstance);
63
63
  }
64
+
65
+ export function mockGetContractClass(worldStateDB: WorldStateDB, contractClass: ContractClassPublic) {
66
+ (worldStateDB as jest.Mocked<WorldStateDB>).getContractClass.mockResolvedValue(contractClass);
67
+ }
@@ -602,33 +602,6 @@ export class ClientExecutionContext extends ViewDataOracle {
602
602
  );
603
603
  }
604
604
 
605
- /**
606
- * Read the public storage data.
607
- * @param contractAddress - The address to read storage from.
608
- * @param startStorageSlot - The starting storage slot.
609
- * @param blockNumber - The block number to read storage at.
610
- * @param numberOfElements - Number of elements to read from the starting storage slot.
611
- */
612
- public override async storageRead(
613
- contractAddress: Fr,
614
- startStorageSlot: Fr,
615
- blockNumber: number,
616
- numberOfElements: number,
617
- ): Promise<Fr[]> {
618
- const values = [];
619
- for (let i = 0n; i < numberOfElements; i++) {
620
- const storageSlot = new Fr(startStorageSlot.value + i);
621
-
622
- const value = await this.aztecNode.getPublicStorageAt(contractAddress, storageSlot, blockNumber);
623
- this.log.debug(
624
- `Oracle storage read: slot=${storageSlot.toString()} address-${contractAddress.toString()} value=${value}`,
625
- );
626
-
627
- values.push(value);
628
- }
629
- return values;
630
- }
631
-
632
605
  public override debugLog(message: string, fields: Fr[]) {
633
606
  this.log.verbose(`debug_log ${applyStringFormatting(message, fields)}`);
634
607
  }
@@ -636,4 +609,8 @@ export class ClientExecutionContext extends ViewDataOracle {
636
609
  public getDebugFunctionName() {
637
610
  return this.db.getDebugFunctionName(this.contractAddress, this.callContext.functionSelector);
638
611
  }
612
+
613
+ public override async incrementAppTaggingSecret(sender: AztecAddress, recipient: AztecAddress) {
614
+ await this.db.incrementAppTaggingSecret(this.contractAddress, sender, recipient);
615
+ }
639
616
  }
@@ -9,6 +9,7 @@ import {
9
9
  type CompleteAddress,
10
10
  type ContractInstance,
11
11
  type Header,
12
+ type IndexedTaggingSecret,
12
13
  type KeyValidationRequest,
13
14
  } from '@aztec/circuits.js';
14
15
  import { type FunctionArtifact, type FunctionSelector } from '@aztec/foundation/abi';
@@ -193,4 +194,41 @@ export interface DBOracle extends CommitmentsDB {
193
194
  * @returns The block number.
194
195
  */
195
196
  getBlockNumber(): Promise<number>;
197
+
198
+ /**
199
+ * Returns the tagging secret for a given sender and recipient pair. For this to work, the ivpsk_m of the sender must be known.
200
+ * Includes the last known index used for tagging with this secret.
201
+ * @param contractAddress - The contract address to silo the secret for
202
+ * @param sender - The address sending the note
203
+ * @param recipient - The address receiving the note
204
+ * @returns A tagging secret that can be used to tag notes.
205
+ */
206
+ getAppTaggingSecret(
207
+ contractAddress: AztecAddress,
208
+ sender: AztecAddress,
209
+ recipient: AztecAddress,
210
+ ): Promise<IndexedTaggingSecret>;
211
+
212
+ /**
213
+ * Increments the tagging secret for a given sender and recipient pair. For this to work, the ivpsk_m of the sender must be known.
214
+ * @param contractAddress - The contract address to silo the secret for
215
+ * @param sender - The address sending the note
216
+ * @param recipient - The address receiving the note
217
+ */
218
+ incrementAppTaggingSecret(
219
+ contractAddress: AztecAddress,
220
+ sender: AztecAddress,
221
+ recipient: AztecAddress,
222
+ ): Promise<void>;
223
+
224
+ /**
225
+ * Returns the siloed tagging secrets for a given recipient and all the senders in the address book
226
+ * @param contractAddress - The contract address to silo the secret for
227
+ * @param recipient - The address receiving the notes
228
+ * @returns A list of siloed tagging secrets
229
+ */
230
+ getAppTaggingSecretsForSenders(
231
+ contractAddress: AztecAddress,
232
+ recipient: AztecAddress,
233
+ ): Promise<IndexedTaggingSecret[]>;
196
234
  }
@@ -7,7 +7,12 @@ import {
7
7
  type NullifierMembershipWitness,
8
8
  type PublicDataWitness,
9
9
  } from '@aztec/circuit-types';
10
- import { type ContractInstance, type Header, type KeyValidationRequest } from '@aztec/circuits.js';
10
+ import {
11
+ type ContractInstance,
12
+ type Header,
13
+ type IndexedTaggingSecret,
14
+ type KeyValidationRequest,
15
+ } from '@aztec/circuits.js';
11
16
  import { siloNullifier } from '@aztec/circuits.js/hash';
12
17
  import { type AztecAddress } from '@aztec/foundation/aztec-address';
13
18
  import { Fr } from '@aztec/foundation/fields';
@@ -288,4 +293,29 @@ export class ViewDataOracle extends TypedOracle {
288
293
  const formattedStr = applyStringFormatting(message, fields);
289
294
  this.log.verbose(`debug_log ${formattedStr}`);
290
295
  }
296
+
297
+ /**
298
+ * Returns the tagging secret for a given sender and recipient pair, siloed to the current contract address.
299
+ * Includes the last known index used for tagging with this secret.
300
+ * For this to work, the ivpsk_m of the sender must be known.
301
+ * @param sender - The address sending the note
302
+ * @param recipient - The address receiving the note
303
+ * @returns A tagging secret that can be used to tag notes.
304
+ */
305
+ public override async getAppTaggingSecret(
306
+ sender: AztecAddress,
307
+ recipient: AztecAddress,
308
+ ): Promise<IndexedTaggingSecret> {
309
+ return await this.db.getAppTaggingSecret(this.contractAddress, sender, recipient);
310
+ }
311
+
312
+ /**
313
+ * Returns the siloed tagging secrets for a given recipient and all the senders in the address book
314
+ * @param contractAddress - The contract address to silo the secret for
315
+ * @param recipient - The address receiving the notes
316
+ * @returns A list of siloed tagging secrets
317
+ */
318
+ public override async getAppTaggingSecretsForSenders(recipient: AztecAddress): Promise<IndexedTaggingSecret[]> {
319
+ return await this.db.getAppTaggingSecretsForSenders(this.contractAddress, recipient);
320
+ }
291
321
  }
@@ -1,3 +1,2 @@
1
1
  export * from './packed_values_cache.js';
2
2
  export * from './errors.js';
3
- export * from './side_effect_counter.js';
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  type CombinedConstantData,
3
- type ContractInstanceWithAddress,
3
+ type ContractClassIdPreimage,
4
4
  type Gas,
5
+ type SerializableContractInstance,
5
6
  type VMCircuitPublicInputs,
6
7
  } from '@aztec/circuits.js';
7
8
  import { type Fr } from '@aztec/foundation/fields';
@@ -15,8 +16,6 @@ import { type PublicExecutionResult } from './execution.js';
15
16
  import { type PublicSideEffectTrace } from './side_effect_trace.js';
16
17
  import { type PublicSideEffectTraceInterface } from './side_effect_trace_interface.js';
17
18
 
18
- export type TracedContractInstance = { exists: boolean } & ContractInstanceWithAddress;
19
-
20
19
  export class DualSideEffectTrace implements PublicSideEffectTraceInterface {
21
20
  constructor(
22
21
  public readonly innerCallTrace: PublicSideEffectTrace,
@@ -78,9 +77,24 @@ export class DualSideEffectTrace implements PublicSideEffectTraceInterface {
78
77
  this.enqueuedCallTrace.traceUnencryptedLog(contractAddress, log);
79
78
  }
80
79
 
81
- public traceGetContractInstance(instance: TracedContractInstance) {
82
- this.innerCallTrace.traceGetContractInstance(instance);
83
- this.enqueuedCallTrace.traceGetContractInstance(instance);
80
+ public traceGetContractInstance(
81
+ contractAddress: Fr,
82
+ exists: boolean,
83
+ instance: SerializableContractInstance | undefined,
84
+ ) {
85
+ this.innerCallTrace.traceGetContractInstance(contractAddress, exists, instance);
86
+ this.enqueuedCallTrace.traceGetContractInstance(contractAddress, exists, instance);
87
+ }
88
+
89
+ public traceGetBytecode(
90
+ contractAddress: Fr,
91
+ exists: boolean,
92
+ bytecode: Buffer,
93
+ contractInstance: SerializableContractInstance | undefined,
94
+ contractClass: ContractClassIdPreimage | undefined,
95
+ ) {
96
+ this.innerCallTrace.traceGetBytecode(contractAddress, exists, bytecode, contractInstance, contractClass);
97
+ this.enqueuedCallTrace.traceGetBytecode(contractAddress, exists, bytecode, contractInstance, contractClass);
84
98
  }
85
99
 
86
100
  /**
@@ -1,5 +1,6 @@
1
1
  import { UnencryptedL2Log } from '@aztec/circuit-types';
2
2
  import {
3
+ AvmContractBytecodeHints,
3
4
  AvmContractInstanceHint,
4
5
  AvmExecutionHints,
5
6
  AvmExternalCallHint,
@@ -7,7 +8,7 @@ import {
7
8
  AztecAddress,
8
9
  CallContext,
9
10
  type CombinedConstantData,
10
- type ContractInstanceWithAddress,
11
+ type ContractClassIdPreimage,
11
12
  ContractStorageRead,
12
13
  ContractStorageUpdateRequest,
13
14
  EthAddress,
@@ -44,6 +45,7 @@ import {
44
45
  ScopedNoteHash,
45
46
  type ScopedNullifier,
46
47
  ScopedReadRequest,
48
+ SerializableContractInstance,
47
49
  TreeLeafReadRequest,
48
50
  VMCircuitPublicInputs,
49
51
  } from '@aztec/circuits.js';
@@ -58,8 +60,6 @@ import { type AvmExecutionEnvironment } from '../avm/avm_execution_environment.j
58
60
  import { SideEffectLimitReachedError } from './side_effect_errors.js';
59
61
  import { type PublicSideEffectTraceInterface } from './side_effect_trace_interface.js';
60
62
 
61
- export type TracedContractInstance = { exists: boolean } & ContractInstanceWithAddress;
62
-
63
63
  /**
64
64
  * A struct containing just the side effects as regular arrays
65
65
  * as opposed to "Tuple" arrays used by circuit public inputs.
@@ -307,14 +307,17 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
307
307
  this.incrementSideEffectCounter();
308
308
  }
309
309
 
310
- public traceGetContractInstance(instance: TracedContractInstance) {
310
+ public traceGetContractInstance(
311
+ contractAddress: Fr,
312
+ exists: boolean,
313
+ instance: SerializableContractInstance = SerializableContractInstance.default(),
314
+ ) {
311
315
  this.enforceLimitOnNullifierChecks('(contract address nullifier from GETCONTRACTINSTANCE)');
312
- // TODO(dbanks12): should emit a nullifier read request
313
316
 
314
317
  this.avmCircuitHints.contractInstances.items.push(
315
318
  new AvmContractInstanceHint(
316
- instance.address,
317
- new Fr(instance.exists ? 1 : 0),
319
+ contractAddress,
320
+ exists,
318
321
  instance.salt,
319
322
  instance.deployer,
320
323
  instance.contractClassId,
@@ -326,6 +329,40 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
326
329
  this.incrementSideEffectCounter();
327
330
  }
328
331
 
332
+ // This tracing function gets called everytime we start simulation/execution.
333
+ // This happens both when starting a new top-level trace and the start of every nested trace
334
+ // We use this to collect the AvmContractBytecodeHints
335
+ public traceGetBytecode(
336
+ contractAddress: Fr,
337
+ exists: boolean,
338
+ bytecode: Buffer = Buffer.alloc(0),
339
+ contractInstance: SerializableContractInstance = SerializableContractInstance.default(),
340
+ contractClass: ContractClassIdPreimage = {
341
+ artifactHash: Fr.zero(),
342
+ privateFunctionsRoot: Fr.zero(),
343
+ publicBytecodeCommitment: Fr.zero(),
344
+ },
345
+ ) {
346
+ const instance = new AvmContractInstanceHint(
347
+ contractAddress,
348
+ exists,
349
+ contractInstance.salt,
350
+ contractInstance.deployer,
351
+ contractInstance.contractClassId,
352
+ contractInstance.initializationHash,
353
+ contractInstance.publicKeys,
354
+ );
355
+ // We need to deduplicate the contract instances based on addresses
356
+ this.avmCircuitHints.contractBytecodeHints.items.push(
357
+ new AvmContractBytecodeHints(bytecode, instance, contractClass),
358
+ );
359
+ this.log.debug(
360
+ `Bytecode retrieval for contract execution traced: exists=${exists}, instance=${JSON.stringify(
361
+ contractInstance,
362
+ )}`,
363
+ );
364
+ }
365
+
329
366
  /**
330
367
  * Trace a nested call.
331
368
  * Accept some results from a finished nested call's trace into this one.
@@ -334,7 +371,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
334
371
  /** The trace of the nested call. */
335
372
  nestedCallTrace: this,
336
373
  /** The execution environment of the nested call. */
337
- _nestedEnvironment: AvmExecutionEnvironment,
374
+ nestedEnvironment: AvmExecutionEnvironment,
338
375
  /** How much gas was available for this public execution. */
339
376
  startGasLeft: Gas,
340
377
  /** How much gas was left after this public execution. */
@@ -368,6 +405,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
368
405
  avmCallResults.output,
369
406
  gasUsed,
370
407
  endSideEffectCounter,
408
+ nestedEnvironment.address,
371
409
  ),
372
410
  );
373
411
  }