@aztec/pxe 0.0.1-commit.e588bc7e5 → 0.0.1-commit.e5a3663dd

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 (134) hide show
  1. package/dest/bin/check_oracle_version.js +4 -4
  2. package/dest/block_synchronizer/block_stream_source.d.ts +10 -0
  3. package/dest/block_synchronizer/block_stream_source.d.ts.map +1 -0
  4. package/dest/block_synchronizer/block_stream_source.js +37 -0
  5. package/dest/block_synchronizer/block_synchronizer.d.ts +6 -2
  6. package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
  7. package/dest/block_synchronizer/block_synchronizer.js +24 -10
  8. package/dest/config/index.d.ts +1 -1
  9. package/dest/config/index.d.ts.map +1 -1
  10. package/dest/config/index.js +7 -14
  11. package/dest/contract_function_simulator/contract_function_simulator.d.ts +4 -1
  12. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  13. package/dest/contract_function_simulator/contract_function_simulator.js +8 -5
  14. package/dest/contract_function_simulator/ephemeral_array_service.d.ts +28 -0
  15. package/dest/contract_function_simulator/ephemeral_array_service.d.ts.map +1 -0
  16. package/dest/contract_function_simulator/ephemeral_array_service.js +78 -0
  17. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +1 -1
  18. package/dest/contract_function_simulator/noir-structs/event_validation_request.js +1 -1
  19. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.d.ts +1 -1
  20. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.js +1 -1
  21. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.d.ts +1 -1
  22. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.js +1 -1
  23. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +1 -1
  24. package/dest/contract_function_simulator/noir-structs/note_validation_request.js +1 -1
  25. package/dest/contract_function_simulator/oracle/interfaces.d.ts +15 -2
  26. package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
  27. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts +1 -1
  28. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts.map +1 -1
  29. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.js +10 -1
  30. package/dest/contract_function_simulator/oracle/oracle.d.ts +14 -2
  31. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  32. package/dest/contract_function_simulator/oracle/oracle.js +105 -3
  33. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +10 -11
  34. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  35. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +21 -17
  36. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +34 -13
  37. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  38. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +149 -28
  39. package/dest/contract_function_simulator/pick_notes.d.ts +1 -1
  40. package/dest/contract_function_simulator/pick_notes.d.ts.map +1 -1
  41. package/dest/contract_function_simulator/pick_notes.js +20 -3
  42. package/dest/contract_function_simulator/proxied_contract_data_source.d.ts +1 -1
  43. package/dest/contract_function_simulator/proxied_contract_data_source.d.ts.map +1 -1
  44. package/dest/contract_function_simulator/proxied_contract_data_source.js +3 -0
  45. package/dest/contract_sync/contract_sync_service.d.ts +1 -1
  46. package/dest/contract_sync/contract_sync_service.d.ts.map +1 -1
  47. package/dest/contract_sync/contract_sync_service.js +35 -23
  48. package/dest/entrypoints/client/bundle/utils.d.ts +2 -2
  49. package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
  50. package/dest/entrypoints/client/bundle/utils.js +2 -2
  51. package/dest/entrypoints/client/lazy/utils.d.ts +2 -2
  52. package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
  53. package/dest/entrypoints/client/lazy/utils.js +2 -2
  54. package/dest/entrypoints/pxe_creation_options.d.ts +3 -1
  55. package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
  56. package/dest/entrypoints/pxe_creation_options.js +3 -1
  57. package/dest/entrypoints/server/index.d.ts +2 -2
  58. package/dest/entrypoints/server/index.d.ts.map +1 -1
  59. package/dest/entrypoints/server/index.js +1 -1
  60. package/dest/entrypoints/server/utils.d.ts +2 -2
  61. package/dest/entrypoints/server/utils.d.ts.map +1 -1
  62. package/dest/entrypoints/server/utils.js +2 -2
  63. package/dest/events/event_service.d.ts +1 -1
  64. package/dest/events/event_service.d.ts.map +1 -1
  65. package/dest/events/event_service.js +10 -1
  66. package/dest/events/private_event_filter_validator.d.ts +3 -2
  67. package/dest/events/private_event_filter_validator.d.ts.map +1 -1
  68. package/dest/events/private_event_filter_validator.js +15 -0
  69. package/dest/logs/log_service.d.ts +6 -6
  70. package/dest/logs/log_service.d.ts.map +1 -1
  71. package/dest/logs/log_service.js +8 -20
  72. package/dest/oracle_version.d.ts +4 -3
  73. package/dest/oracle_version.d.ts.map +1 -1
  74. package/dest/oracle_version.js +20 -10
  75. package/dest/private_kernel/private_kernel_execution_prover.d.ts +1 -1
  76. package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
  77. package/dest/private_kernel/private_kernel_execution_prover.js +4 -7
  78. package/dest/private_kernel/private_kernel_oracle.d.ts +5 -5
  79. package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
  80. package/dest/private_kernel/private_kernel_oracle.js +12 -15
  81. package/dest/pxe.d.ts +16 -4
  82. package/dest/pxe.d.ts.map +1 -1
  83. package/dest/pxe.js +49 -20
  84. package/dest/storage/anchor_block_store/anchor_block_store.js +1 -1
  85. package/dest/storage/capsule_store/capsule_store.d.ts +1 -1
  86. package/dest/storage/capsule_store/capsule_store.d.ts.map +1 -1
  87. package/dest/storage/capsule_store/capsule_store.js +8 -5
  88. package/dest/storage/contract_store/contract_store.d.ts +1 -1
  89. package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
  90. package/dest/storage/contract_store/contract_store.js +4 -2
  91. package/dest/storage/private_event_store/private_event_store.d.ts +1 -1
  92. package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
  93. package/dest/storage/private_event_store/private_event_store.js +3 -0
  94. package/dest/storage/private_event_store/stored_private_event.js +1 -1
  95. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts +2 -2
  96. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts.map +1 -1
  97. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.js +2 -16
  98. package/package.json +16 -16
  99. package/src/bin/check_oracle_version.ts +4 -4
  100. package/src/block_synchronizer/block_stream_source.ts +52 -0
  101. package/src/block_synchronizer/block_synchronizer.ts +27 -11
  102. package/src/config/index.ts +2 -8
  103. package/src/contract_function_simulator/contract_function_simulator.ts +8 -4
  104. package/src/contract_function_simulator/ephemeral_array_service.ts +110 -0
  105. package/src/contract_function_simulator/noir-structs/event_validation_request.ts +1 -1
  106. package/src/contract_function_simulator/noir-structs/log_retrieval_request.ts +1 -1
  107. package/src/contract_function_simulator/noir-structs/log_retrieval_response.ts +1 -1
  108. package/src/contract_function_simulator/noir-structs/note_validation_request.ts +1 -1
  109. package/src/contract_function_simulator/oracle/interfaces.ts +30 -1
  110. package/src/contract_function_simulator/oracle/legacy_oracle_mappings.ts +7 -1
  111. package/src/contract_function_simulator/oracle/oracle.ts +157 -3
  112. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +34 -20
  113. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +241 -55
  114. package/src/contract_function_simulator/pick_notes.ts +22 -3
  115. package/src/contract_function_simulator/proxied_contract_data_source.ts +8 -1
  116. package/src/contract_sync/contract_sync_service.ts +57 -51
  117. package/src/entrypoints/client/bundle/utils.ts +2 -3
  118. package/src/entrypoints/client/lazy/utils.ts +2 -3
  119. package/src/entrypoints/pxe_creation_options.ts +7 -0
  120. package/src/entrypoints/server/index.ts +1 -1
  121. package/src/entrypoints/server/utils.ts +2 -3
  122. package/src/events/event_service.ts +13 -1
  123. package/src/events/private_event_filter_validator.ts +21 -1
  124. package/src/logs/log_service.ts +14 -50
  125. package/src/oracle_version.ts +20 -10
  126. package/src/private_kernel/private_kernel_execution_prover.ts +4 -9
  127. package/src/private_kernel/private_kernel_oracle.ts +14 -14
  128. package/src/pxe.ts +86 -24
  129. package/src/storage/anchor_block_store/anchor_block_store.ts +1 -1
  130. package/src/storage/capsule_store/capsule_store.ts +15 -5
  131. package/src/storage/contract_store/contract_store.ts +8 -6
  132. package/src/storage/private_event_store/private_event_store.ts +4 -0
  133. package/src/storage/private_event_store/stored_private_event.ts +1 -1
  134. package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +5 -15
@@ -0,0 +1,110 @@
1
+ import { Fr } from '@aztec/foundation/curves/bn254';
2
+
3
+ /** In-memory store for ephemeral arrays scoped to a single contract call frame. */
4
+ export class EphemeralArrayService {
5
+ /**
6
+ * Maps a slot to the elements of the array stored at that slot. Each element is a serialized representation of
7
+ * the original type.
8
+ */
9
+ #arrays: Map<string, Fr[][]> = new Map();
10
+
11
+ /** Returns all elements in the array, or an empty array if uninitialized. */
12
+ readArrayAt(slot: Fr): Fr[][] {
13
+ return this.#arrays.get(slot.toString()) ?? [];
14
+ }
15
+
16
+ #setArray(slot: Fr, array: Fr[][]): void {
17
+ this.#arrays.set(slot.toString(), array);
18
+ }
19
+
20
+ /** Returns the number of elements in the array at the given slot. */
21
+ len(slot: Fr): number {
22
+ return this.readArrayAt(slot).length;
23
+ }
24
+
25
+ /** Appends an element to the array and returns the new length. */
26
+ push(slot: Fr, elements: Fr[]): number {
27
+ const array = this.readArrayAt(slot);
28
+ array.push(elements);
29
+ this.#setArray(slot, array);
30
+ return array.length;
31
+ }
32
+
33
+ /** Removes and returns the last element. Throws if empty. */
34
+ pop(slot: Fr): Fr[] {
35
+ const array = this.readArrayAt(slot);
36
+ if (array.length === 0) {
37
+ throw new Error(`Ephemeral array at slot ${slot} is empty`);
38
+ }
39
+ const element = array.pop()!;
40
+ this.#setArray(slot, array);
41
+ return element;
42
+ }
43
+
44
+ /** Returns the element at the given index. Throws if out of bounds. */
45
+ get(slot: Fr, index: number): Fr[] {
46
+ const array = this.readArrayAt(slot);
47
+ if (index < 0 || index >= array.length) {
48
+ throw new Error(
49
+ `Ephemeral array index ${index} out of bounds for array of length ${array.length} at slot ${slot}`,
50
+ );
51
+ }
52
+ return array[index];
53
+ }
54
+
55
+ /** Overwrites the element at the given index. Throws if out of bounds. */
56
+ set(slot: Fr, index: number, value: Fr[]): void {
57
+ const array = this.readArrayAt(slot);
58
+ if (index < 0 || index >= array.length) {
59
+ throw new Error(
60
+ `Ephemeral array index ${index} out of bounds for array of length ${array.length} at slot ${slot}`,
61
+ );
62
+ }
63
+ array[index] = value;
64
+ }
65
+
66
+ /** Removes the element at the given index, shifting subsequent elements backward. Throws if out of bounds. */
67
+ remove(slot: Fr, index: number): void {
68
+ const array = this.readArrayAt(slot);
69
+ if (index < 0 || index >= array.length) {
70
+ throw new Error(
71
+ `Ephemeral array index ${index} out of bounds for array of length ${array.length} at slot ${slot}`,
72
+ );
73
+ }
74
+ array.splice(index, 1);
75
+ }
76
+
77
+ /** Removes all elements from the array. */
78
+ clear(slot: Fr): void {
79
+ this.#arrays.delete(slot.toString());
80
+ }
81
+
82
+ /** Allocates a fresh, unused slot for a new ephemeral array. */
83
+ allocateSlot(): Fr {
84
+ let slot: Fr;
85
+ do {
86
+ slot = Fr.random();
87
+ } while (this.#arrays.has(slot.toString()));
88
+ return slot;
89
+ }
90
+
91
+ /** Creates a new ephemeral array pre-populated with the given elements and returns its slot. */
92
+ newArray(elements: Fr[][]): Fr {
93
+ const slot = this.allocateSlot();
94
+ this.#setArray(slot, elements);
95
+ return slot;
96
+ }
97
+
98
+ /** Copies `count` elements from the source array to the destination array (overwrites destination). */
99
+ copy(srcSlot: Fr, dstSlot: Fr, count: number): void {
100
+ const srcArray = this.readArrayAt(srcSlot);
101
+ if (count > srcArray.length) {
102
+ throw new Error(
103
+ `Cannot copy ${count} elements from ephemeral array of length ${srcArray.length} at slot ${srcSlot}`,
104
+ );
105
+ }
106
+ // Deep copy the elements to avoid aliasing
107
+ const copied = srcArray.slice(0, count).map(el => [...el]);
108
+ this.#setArray(dstSlot, copied);
109
+ }
110
+ }
@@ -6,7 +6,7 @@ import { TxHash } from '@aztec/stdlib/tx';
6
6
 
7
7
  /**
8
8
  * Intermediate struct used to perform batch event validation by PXE. The `utilityValidateAndStoreEnqueuedNotesAndEvents` oracle
9
- * expects for values of this type to be stored in a `CapsuleArray`.
9
+ * expects for values of this type to be stored in a `EphemeralArray`.
10
10
  */
11
11
  export class EventValidationRequest {
12
12
  constructor(
@@ -5,7 +5,7 @@ import { Tag } from '@aztec/stdlib/logs';
5
5
 
6
6
  /**
7
7
  * Intermediate struct used to perform batch log retrieval by PXE. The `utilityBulkRetrieveLogs` oracle expects values of this
8
- * type to be stored in a `CapsuleArray`.
8
+ * type to be stored in a `EphemeralArray`.
9
9
  */
10
10
  export class LogRetrievalRequest {
11
11
  constructor(
@@ -7,7 +7,7 @@ const MAX_LOG_CONTENT_LEN = PRIVATE_LOG_CIPHERTEXT_LEN;
7
7
 
8
8
  /**
9
9
  * Intermediate struct used to perform batch log retrieval by PXE. The `utilityBulkRetrieveLogs` oracle stores values of this
10
- * type in a `CapsuleArray`.
10
+ * type in a `EphemeralArray`.
11
11
  */
12
12
  export class LogRetrievalResponse {
13
13
  constructor(
@@ -5,7 +5,7 @@ import { TxHash } from '@aztec/stdlib/tx';
5
5
 
6
6
  /**
7
7
  * Intermediate struct used to perform batch note validation by PXE. The `utilityValidateAndStoreEnqueuedNotesAndEvents` oracle
8
- * expects for values of this type to be stored in a `CapsuleArray`.
8
+ * expects for values of this type to be stored in a `EphemeralArray`.
9
9
  */
10
10
  export class NoteValidationRequest {
11
11
  constructor(
@@ -54,7 +54,7 @@ export interface IMiscOracle {
54
54
  isMisc: true;
55
55
 
56
56
  getRandomField(): Fr;
57
- assertCompatibleOracleVersion(version: number): void;
57
+ assertCompatibleOracleVersion(major: number, minor: number): void;
58
58
  log(level: number, message: string, fields: Fr[]): Promise<void>;
59
59
  }
60
60
 
@@ -120,6 +120,7 @@ export interface IUtilityExecutionOracle {
120
120
  numberOfElements: number,
121
121
  ): Promise<Fr[]>;
122
122
  getPendingTaggedLogs(pendingTaggedLogArrayBaseSlot: Fr, scope: AztecAddress): Promise<void>;
123
+ getPendingTaggedLogsV2(scope: AztecAddress): Promise<Fr>;
123
124
  validateAndStoreEnqueuedNotesAndEvents(
124
125
  contractAddress: AztecAddress,
125
126
  noteValidationRequestsArrayBaseSlot: Fr,
@@ -134,6 +135,15 @@ export interface IUtilityExecutionOracle {
134
135
  logRetrievalResponsesArrayBaseSlot: Fr,
135
136
  scope: AztecAddress,
136
137
  ): Promise<void>;
138
+ validateAndStoreEnqueuedNotesAndEventsV2(
139
+ noteValidationRequestsArrayBaseSlot: Fr,
140
+ eventValidationRequestsArrayBaseSlot: Fr,
141
+ maxNotePackedLen: number,
142
+ maxEventSerializedLen: number,
143
+ scope: AztecAddress,
144
+ ): Promise<void>;
145
+ getLogsByTagV2(requestArrayBaseSlot: Fr): Promise<Fr>;
146
+ getMessageContextsByTxHashV2(requestArrayBaseSlot: Fr): Promise<Fr>;
137
147
  getMessageContextsByTxHash(
138
148
  contractAddress: AztecAddress,
139
149
  messageContextRequestsArrayBaseSlot: Fr,
@@ -154,6 +164,20 @@ export interface IUtilityExecutionOracle {
154
164
  getSharedSecret(address: AztecAddress, ephPk: Point, contractAddress: AztecAddress): Promise<Fr>;
155
165
  setContractSyncCacheInvalid(contractAddress: AztecAddress, scopes: AztecAddress[]): void;
156
166
  emitOffchainEffect(data: Fr[]): Promise<void>;
167
+ callUtilityFunction(
168
+ targetContractAddress: AztecAddress,
169
+ functionSelector: FunctionSelector,
170
+ args: Fr[],
171
+ ): Promise<Fr[]>;
172
+
173
+ // Ephemeral array methods
174
+ pushEphemeral(slot: Fr, elements: Fr[]): number;
175
+ popEphemeral(slot: Fr): Fr[];
176
+ getEphemeral(slot: Fr, index: number): Fr[];
177
+ setEphemeral(slot: Fr, index: number, elements: Fr[]): void;
178
+ getEphemeralLen(slot: Fr): number;
179
+ removeEphemeral(slot: Fr, index: number): void;
180
+ clearEphemeral(slot: Fr): void;
157
181
  }
158
182
 
159
183
  /**
@@ -185,6 +209,11 @@ export interface IPrivateExecutionOracle {
185
209
  sideEffectCounter: number,
186
210
  isStaticCall: boolean,
187
211
  ): Promise<{ endSideEffectCounter: Fr; returnsHash: Fr }>;
212
+ callUtilityFunction(
213
+ targetContractAddress: AztecAddress,
214
+ functionSelector: FunctionSelector,
215
+ args: Fr[],
216
+ ): Promise<Fr[]>;
188
217
  assertValidPublicCalldata(calldataHash: Fr): Promise<void>;
189
218
  notifyRevertiblePhaseStart(minRevertibleSideEffectCounter: number): Promise<void>;
190
219
  isExecutionInRevertiblePhase(sideEffectCounter: number): Promise<boolean>;
@@ -10,6 +10,8 @@ import type { Oracle } from './oracle.js';
10
10
  * TODO(F-416): Remove these aliases on v5 when protocol contracts are redeployed.
11
11
  */
12
12
  export function buildLegacyOracleCallbacks(oracle: Oracle): ACIRCallback {
13
+ // If you are about to add a new mapping ensure that the old oracle name is different from the new one - this can
14
+ // commonly occur when only the args are getting modified.
13
15
  return {
14
16
  // Simple prefix renames (privateXxx/utilityXxx → aztec_prv_/aztec_utl_)
15
17
  utilityLog: (
@@ -19,7 +21,11 @@ export function buildLegacyOracleCallbacks(oracle: Oracle): ACIRCallback {
19
21
  fields: ACVMField[],
20
22
  ): Promise<ACVMField[]> => oracle.aztec_utl_log(level, message, _ignoredFieldsSize, fields),
21
23
  utilityAssertCompatibleOracleVersion: (version: ACVMField[]): Promise<ACVMField[]> =>
22
- oracle.aztec_utl_assertCompatibleOracleVersion(version),
24
+ oracle.aztec_utl_assertCompatibleOracleVersionV2(version, [toACVMField(0)]),
25
+ // Old 1-arg oracle before minor/major split. Maps to V2 with minor=0.
26
+ // eslint-disable-next-line camelcase
27
+ aztec_utl_assertCompatibleOracleVersion: (version: ACVMField[]): Promise<ACVMField[]> =>
28
+ oracle.aztec_utl_assertCompatibleOracleVersionV2(version, [toACVMField(0)]),
23
29
  utilityLoadCapsule: (
24
30
  contractAddress: ACVMField[],
25
31
  slot: ACVMField[],
@@ -15,6 +15,7 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address';
15
15
  import { BlockHash } from '@aztec/stdlib/block';
16
16
  import { ContractClassLog, ContractClassLogFields } from '@aztec/stdlib/logs';
17
17
 
18
+ import { ORACLE_VERSION_MAJOR, ORACLE_VERSION_MINOR } from '../../oracle_version.js';
18
19
  import type { IMiscOracle, IPrivateExecutionOracle, IUtilityExecutionOracle } from './interfaces.js';
19
20
  import { buildLegacyOracleCallbacks } from './legacy_oracle_mappings.js';
20
21
  import { packAsHintedNote } from './note_packing_utils.js';
@@ -111,12 +112,67 @@ export class Oracle {
111
112
  return acc;
112
113
  }, {} as ACIRCallback);
113
114
 
114
- return { ...callback, ...buildLegacyOracleCallbacks(this) };
115
+ const allCallbacks = { ...callback, ...buildLegacyOracleCallbacks(this) };
116
+
117
+ // Wrap in a Proxy to intercept access to missing oracle names and provide enhanced error messages when the
118
+ // contract's minor version is higher than the PXE's (i.e. the contract expects oracles that were added in a newer
119
+ // minor version).
120
+ const handler = this.handler;
121
+ return new Proxy(allCallbacks, {
122
+ get(target, prop: string) {
123
+ if (prop in target) {
124
+ return target[prop];
125
+ }
126
+ // Return a function that throws with an enhanced error message if applicable
127
+ return () => {
128
+ type NonOracleFunctionGetContractOracleVersion = {
129
+ nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined;
130
+ };
131
+
132
+ let contractVersion = undefined;
133
+ if ('nonOracleFunctionGetContractOracleVersion' in handler) {
134
+ contractVersion = (
135
+ handler as unknown as NonOracleFunctionGetContractOracleVersion
136
+ ).nonOracleFunctionGetContractOracleVersion();
137
+ }
138
+ if (!contractVersion) {
139
+ throw new Error(
140
+ `Oracle '${prop}' not found and the contract's oracle version is unknown (the version check oracle ` +
141
+ `was not called before '${prop}'). This usually means the contract was not compiled with the ` +
142
+ `#[aztec] macro, which injects the version check as the first oracle call in every private/utility ` +
143
+ `external function. If you're using a custom entry point, ensure assert_compatible_oracle_version() ` +
144
+ `is called before any other oracle calls. See https://docs.aztec.network/errors/8`,
145
+ );
146
+ } else if (contractVersion.minor > ORACLE_VERSION_MINOR) {
147
+ throw new Error(
148
+ `Oracle '${prop}' not found.` +
149
+ ` This usually means the contract requires a newer private execution environment than you have.` +
150
+ ` Upgrade your private execution environment to a compatible version. The contract was compiled with` +
151
+ ` Aztec.nr oracle version ${contractVersion.major}.${contractVersion.minor}, but this private` +
152
+ ` execution environment only supports up to ${ORACLE_VERSION_MAJOR}.${ORACLE_VERSION_MINOR}.` +
153
+ ` See https://docs.aztec.network/errors/8`,
154
+ );
155
+ } else {
156
+ throw new Error(
157
+ `Oracle '${prop}' not found.` +
158
+ ` The contract's oracle version (${contractVersion.major}.${contractVersion.minor}) is compatible` +
159
+ ` with this private execution environment (${ORACLE_VERSION_MAJOR}.${ORACLE_VERSION_MINOR}), so all` +
160
+ ` standard oracles should be available. This could mean the contract was compiled against a modified` +
161
+ ` version of Aztec.nr, or that it references an oracle that does not exist.` +
162
+ ` See https://docs.aztec.network/errors/8`,
163
+ );
164
+ }
165
+ };
166
+ },
167
+ });
115
168
  }
116
169
 
117
170
  // eslint-disable-next-line camelcase
118
- aztec_utl_assertCompatibleOracleVersion([version]: ACVMField[]) {
119
- this.handlerAsMisc().assertCompatibleOracleVersion(Fr.fromString(version).toNumber());
171
+ aztec_utl_assertCompatibleOracleVersionV2([major]: ACVMField[], [minor]: ACVMField[]) {
172
+ this.handlerAsMisc().assertCompatibleOracleVersion(
173
+ Fr.fromString(major).toNumber(),
174
+ Fr.fromString(minor).toNumber(),
175
+ );
120
176
  return Promise.resolve([]);
121
177
  }
122
178
 
@@ -434,6 +490,20 @@ export class Oracle {
434
490
  return [values.map(toACVMField)];
435
491
  }
436
492
 
493
+ // eslint-disable-next-line camelcase
494
+ async aztec_utl_callUtilityFunction(
495
+ [contractAddress]: ACVMField[],
496
+ [functionSelector]: ACVMField[],
497
+ args: ACVMField[],
498
+ ): Promise<ACVMField[][]> {
499
+ const result = await this.handlerAsUtility().callUtilityFunction(
500
+ AztecAddress.fromField(Fr.fromString(contractAddress)),
501
+ FunctionSelector.fromField(Fr.fromString(functionSelector)),
502
+ args.map(Fr.fromString),
503
+ );
504
+ return [result.map(toACVMField)];
505
+ }
506
+
437
507
  // eslint-disable-next-line camelcase
438
508
  aztec_prv_notifyCreatedContractClassLog(
439
509
  [contractAddress]: ACVMField[],
@@ -523,6 +593,12 @@ export class Oracle {
523
593
  return [];
524
594
  }
525
595
 
596
+ // eslint-disable-next-line camelcase
597
+ async aztec_utl_getPendingTaggedLogs_v2([scope]: ACVMField[]): Promise<ACVMField[]> {
598
+ const slot = await this.handlerAsUtility().getPendingTaggedLogsV2(AztecAddress.fromString(scope));
599
+ return [toACVMField(slot)];
600
+ }
601
+
526
602
  // eslint-disable-next-line camelcase
527
603
  async aztec_utl_validateAndStoreEnqueuedNotesAndEvents(
528
604
  [contractAddress]: ACVMField[],
@@ -544,6 +620,24 @@ export class Oracle {
544
620
  return [];
545
621
  }
546
622
 
623
+ // eslint-disable-next-line camelcase
624
+ async aztec_utl_validateAndStoreEnqueuedNotesAndEvents_v2(
625
+ [noteValidationRequestsArrayBaseSlot]: ACVMField[],
626
+ [eventValidationRequestsArrayBaseSlot]: ACVMField[],
627
+ [maxNotePackedLen]: ACVMField[],
628
+ [maxEventSerializedLen]: ACVMField[],
629
+ [scope]: ACVMField[],
630
+ ): Promise<ACVMField[]> {
631
+ await this.handlerAsUtility().validateAndStoreEnqueuedNotesAndEventsV2(
632
+ Fr.fromString(noteValidationRequestsArrayBaseSlot),
633
+ Fr.fromString(eventValidationRequestsArrayBaseSlot),
634
+ Fr.fromString(maxNotePackedLen).toNumber(),
635
+ Fr.fromString(maxEventSerializedLen).toNumber(),
636
+ AztecAddress.fromString(scope),
637
+ );
638
+ return [];
639
+ }
640
+
547
641
  // eslint-disable-next-line camelcase
548
642
  async aztec_utl_getLogsByTag(
549
643
  [contractAddress]: ACVMField[],
@@ -576,6 +670,20 @@ export class Oracle {
576
670
  return [];
577
671
  }
578
672
 
673
+ // eslint-disable-next-line camelcase
674
+ async aztec_utl_getLogsByTag_v2([requestArrayBaseSlot]: ACVMField[]): Promise<ACVMField[]> {
675
+ const responseSlot = await this.handlerAsUtility().getLogsByTagV2(Fr.fromString(requestArrayBaseSlot));
676
+ return [toACVMField(responseSlot)];
677
+ }
678
+
679
+ // eslint-disable-next-line camelcase
680
+ async aztec_utl_getMessageContextsByTxHash_v2([requestArrayBaseSlot]: ACVMField[]): Promise<ACVMField[]> {
681
+ const responseSlot = await this.handlerAsUtility().getMessageContextsByTxHashV2(
682
+ Fr.fromString(requestArrayBaseSlot),
683
+ );
684
+ return [toACVMField(responseSlot)];
685
+ }
686
+
579
687
  // eslint-disable-next-line camelcase
580
688
  aztec_utl_setCapsule(
581
689
  [contractAddress]: ACVMField[],
@@ -648,6 +756,52 @@ export class Oracle {
648
756
  return [];
649
757
  }
650
758
 
759
+ // eslint-disable-next-line camelcase
760
+ aztec_utl_pushEphemeral([slot]: ACVMField[], elements: ACVMField[]): Promise<ACVMField[]> {
761
+ const newLen = this.handlerAsUtility().pushEphemeral(Fr.fromString(slot), elements.map(Fr.fromString));
762
+ return Promise.resolve([toACVMField(newLen)]);
763
+ }
764
+
765
+ // eslint-disable-next-line camelcase
766
+ aztec_utl_popEphemeral([slot]: ACVMField[]): Promise<ACVMField[][]> {
767
+ const element = this.handlerAsUtility().popEphemeral(Fr.fromString(slot));
768
+ return Promise.resolve([element.map(toACVMField)]);
769
+ }
770
+
771
+ // eslint-disable-next-line camelcase
772
+ aztec_utl_getEphemeral([slot]: ACVMField[], [index]: ACVMField[]): Promise<ACVMField[][]> {
773
+ const element = this.handlerAsUtility().getEphemeral(Fr.fromString(slot), Fr.fromString(index).toNumber());
774
+ return Promise.resolve([element.map(toACVMField)]);
775
+ }
776
+
777
+ // eslint-disable-next-line camelcase
778
+ aztec_utl_setEphemeral([slot]: ACVMField[], [index]: ACVMField[], elements: ACVMField[]): Promise<ACVMField[]> {
779
+ this.handlerAsUtility().setEphemeral(
780
+ Fr.fromString(slot),
781
+ Fr.fromString(index).toNumber(),
782
+ elements.map(Fr.fromString),
783
+ );
784
+ return Promise.resolve([]);
785
+ }
786
+
787
+ // eslint-disable-next-line camelcase
788
+ aztec_utl_getEphemeralLen([slot]: ACVMField[]): Promise<ACVMField[]> {
789
+ const len = this.handlerAsUtility().getEphemeralLen(Fr.fromString(slot));
790
+ return Promise.resolve([toACVMField(len)]);
791
+ }
792
+
793
+ // eslint-disable-next-line camelcase
794
+ aztec_utl_removeEphemeral([slot]: ACVMField[], [index]: ACVMField[]): Promise<ACVMField[]> {
795
+ this.handlerAsUtility().removeEphemeral(Fr.fromString(slot), Fr.fromString(index).toNumber());
796
+ return Promise.resolve([]);
797
+ }
798
+
799
+ // eslint-disable-next-line camelcase
800
+ aztec_utl_clearEphemeral([slot]: ACVMField[]): Promise<ACVMField[]> {
801
+ this.handlerAsUtility().clearEphemeral(Fr.fromString(slot));
802
+ return Promise.resolve([]);
803
+ }
804
+
651
805
  // eslint-disable-next-line camelcase
652
806
  async aztec_utl_decryptAes128(
653
807
  ciphertextBVecStorage: ACVMField[],
@@ -2,7 +2,7 @@ import { MAX_FR_CALLDATA_TO_ALL_ENQUEUED_CALLS, PRIVATE_CONTEXT_INPUTS_LENGTH }
2
2
  import { Fr } from '@aztec/foundation/curves/bn254';
3
3
  import { createLogger } from '@aztec/foundation/log';
4
4
  import { Timer } from '@aztec/foundation/timer';
5
- import { type CircuitSimulator, toACVMWitness } from '@aztec/simulator/client';
5
+ import { toACVMWitness } from '@aztec/simulator/client';
6
6
  import {
7
7
  type FunctionAbi,
8
8
  type FunctionArtifact,
@@ -50,7 +50,6 @@ export type PrivateExecutionOracleArgs = Omit<UtilityExecutionOracleArgs, 'contr
50
50
  totalPublicCalldataCount?: number;
51
51
  sideEffectCounter?: number;
52
52
  senderForTags?: AztecAddress;
53
- simulator?: CircuitSimulator;
54
53
  };
55
54
 
56
55
  /**
@@ -81,9 +80,11 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
81
80
  private readonly taggingIndexCache: ExecutionTaggingIndexCache;
82
81
  private readonly senderTaggingStore: SenderTaggingStore;
83
82
  private totalPublicCalldataCount: number;
84
- protected sideEffectCounter: number;
85
- private senderForTags?: AztecAddress;
86
- private readonly simulator?: CircuitSimulator;
83
+ private readonly initialSideEffectCounter: number;
84
+ /** Sender for tags passed in at oracle construction time. Returned by `getSenderForTags` unless overridden. */
85
+ private readonly defaultSenderForTags: AztecAddress | undefined;
86
+ /** Per-call sender-for-tags override, set by `setSenderForTags`. Takes precedence over `defaultSenderForTags`. */
87
+ private currentSenderForTags: AztecAddress | undefined;
87
88
 
88
89
  constructor(args: PrivateExecutionOracleArgs) {
89
90
  super({
@@ -100,13 +101,17 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
100
101
  this.taggingIndexCache = args.taggingIndexCache;
101
102
  this.senderTaggingStore = args.senderTaggingStore;
102
103
  this.totalPublicCalldataCount = args.totalPublicCalldataCount ?? 0;
103
- this.sideEffectCounter = args.sideEffectCounter ?? 0;
104
- this.senderForTags = args.senderForTags;
105
- this.simulator = args.simulator;
104
+ this.initialSideEffectCounter = args.sideEffectCounter ?? 0;
105
+ this.defaultSenderForTags = args.senderForTags;
106
106
  }
107
107
 
108
108
  public getPrivateContextInputs(): PrivateContextInputs {
109
- return new PrivateContextInputs(this.callContext, this.anchorBlockHeader, this.txContext, this.sideEffectCounter);
109
+ return new PrivateContextInputs(
110
+ this.callContext,
111
+ this.anchorBlockHeader,
112
+ this.txContext,
113
+ this.initialSideEffectCounter,
114
+ );
110
115
  }
111
116
 
112
117
  // We still need this function until we can get user-defined ordering of structs for fn arguments
@@ -173,11 +178,10 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
173
178
  * for a tag in order to emit a log. Constrained tagging should not use this as there is no
174
179
  * guarantee that the recipient knows about the sender, and hence about the shared secret.
175
180
  *
176
- * The value persists through nested calls, meaning all calls down the stack will use the same
177
- * 'senderForTags' value (unless it is replaced).
181
+ * Returns `currentSenderForTags` if set (via `setSenderForTags`), otherwise `defaultSenderForTags`.
178
182
  */
179
183
  public getSenderForTags(): Promise<AztecAddress | undefined> {
180
- return Promise.resolve(this.senderForTags);
184
+ return Promise.resolve(this.currentSenderForTags ?? this.defaultSenderForTags);
181
185
  }
182
186
 
183
187
  /**
@@ -187,12 +191,14 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
187
191
  * for a tag in order to emit a log. Constrained tagging should not use this as there is no
188
192
  * guarantee that the recipient knows about the sender, and hence about the shared secret.
189
193
  *
190
- * Account contracts typically set this value before calling other contracts. The value persists
191
- * through nested calls, meaning all calls down the stack will use the same 'senderForTags'
192
- * value (unless it is replaced by another call to this setter).
194
+ * Overrides `defaultSenderForTags` for the remainder of this call. Each oracle instance is
195
+ * independent, so this has no effect on any other call in the execution.
193
196
  */
194
197
  public setSenderForTags(senderForTags: AztecAddress): Promise<void> {
195
- this.senderForTags = senderForTags;
198
+ this.logger.debug(
199
+ `Sender for tags switched to ${senderForTags} by contract ${this.contractAddress} (default was ${this.defaultSenderForTags})`,
200
+ );
201
+ this.currentSenderForTags = senderForTags;
196
202
  return Promise.resolve();
197
203
  }
198
204
 
@@ -216,7 +222,7 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
216
222
  this.logger.warn(`Computing a tag for invalid recipient ${recipient} - returning a random tag instead`, {
217
223
  contractAddress: this.contractAddress,
218
224
  });
219
- return new Tag(Fr.random());
225
+ return Tag.random();
220
226
  }
221
227
 
222
228
  const index = await this.#getIndexToUseForSecret(extendedSecret);
@@ -573,20 +579,24 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
573
579
  sideEffectCounter,
574
580
  log: this.logger,
575
581
  scopes: this.scopes,
576
- senderForTags: this.senderForTags,
577
- simulator: this.simulator!,
582
+ senderForTags: this.defaultSenderForTags,
583
+ simulator: this.simulator,
584
+ l2TipsStore: this.l2TipsStore,
578
585
  });
579
586
 
580
587
  const setupTime = simulatorSetupTimer.ms();
581
588
 
582
589
  const childExecutionResult = await executePrivateFunction(
583
- this.simulator!,
590
+ this.simulator,
584
591
  privateExecutionOracle,
585
592
  targetArtifact,
586
593
  targetContractAddress,
587
594
  functionSelector,
588
595
  );
589
596
 
597
+ // Propagate the nested call's calldata count so the parent sees its increments on subsequent enqueues.
598
+ this.totalPublicCalldataCount = privateExecutionOracle.getTotalPublicCalldataCount();
599
+
590
600
  if (isStaticCall) {
591
601
  this.#checkValidStaticCall(childExecutionResult);
592
602
  }
@@ -620,6 +630,10 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
620
630
  return Promise.resolve();
621
631
  }
622
632
 
633
+ public getTotalPublicCalldataCount(): number {
634
+ return this.totalPublicCalldataCount;
635
+ }
636
+
623
637
  public notifyRevertiblePhaseStart(minRevertibleSideEffectCounter: number): Promise<void> {
624
638
  return this.noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
625
639
  }