@aztec/pxe 0.0.1-commit.f5d02921e → 0.0.1-commit.f650c0a5c

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 (113) hide show
  1. package/dest/bin/check_oracle_version.js +4 -4
  2. package/dest/contract_function_simulator/contract_function_simulator.d.ts +3 -4
  3. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  4. package/dest/contract_function_simulator/ephemeral_array_service.d.ts +28 -0
  5. package/dest/contract_function_simulator/ephemeral_array_service.d.ts.map +1 -0
  6. package/dest/contract_function_simulator/ephemeral_array_service.js +78 -0
  7. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +1 -1
  8. package/dest/contract_function_simulator/noir-structs/event_validation_request.js +1 -1
  9. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.d.ts +1 -1
  10. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.js +1 -1
  11. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.d.ts +1 -1
  12. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.js +1 -1
  13. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +1 -1
  14. package/dest/contract_function_simulator/noir-structs/note_validation_request.js +1 -1
  15. package/dest/contract_function_simulator/oracle/interfaces.d.ts +13 -2
  16. package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
  17. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts +1 -1
  18. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts.map +1 -1
  19. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.js +10 -1
  20. package/dest/contract_function_simulator/oracle/oracle.d.ts +13 -2
  21. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  22. package/dest/contract_function_simulator/oracle/oracle.js +98 -3
  23. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +2 -3
  24. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  25. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +9 -0
  26. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +25 -12
  27. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  28. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +102 -34
  29. package/dest/contract_function_simulator/pick_notes.d.ts +1 -1
  30. package/dest/contract_function_simulator/pick_notes.d.ts.map +1 -1
  31. package/dest/contract_function_simulator/pick_notes.js +9 -2
  32. package/dest/contract_sync/contract_sync_service.d.ts +4 -6
  33. package/dest/contract_sync/contract_sync_service.d.ts.map +1 -1
  34. package/dest/contract_sync/contract_sync_service.js +7 -27
  35. package/dest/contract_sync/helpers.d.ts +2 -3
  36. package/dest/contract_sync/helpers.d.ts.map +1 -1
  37. package/dest/debug/pxe_debug_utils.d.ts +3 -3
  38. package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
  39. package/dest/entrypoints/client/bundle/index.d.ts +1 -2
  40. package/dest/entrypoints/client/bundle/index.d.ts.map +1 -1
  41. package/dest/entrypoints/client/bundle/index.js +0 -1
  42. package/dest/entrypoints/client/bundle/utils.d.ts +2 -2
  43. package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
  44. package/dest/entrypoints/client/bundle/utils.js +2 -2
  45. package/dest/entrypoints/client/lazy/index.d.ts +1 -2
  46. package/dest/entrypoints/client/lazy/index.d.ts.map +1 -1
  47. package/dest/entrypoints/client/lazy/index.js +0 -1
  48. package/dest/entrypoints/client/lazy/utils.d.ts +2 -2
  49. package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
  50. package/dest/entrypoints/client/lazy/utils.js +2 -2
  51. package/dest/entrypoints/pxe_creation_options.d.ts +3 -1
  52. package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
  53. package/dest/entrypoints/pxe_creation_options.js +3 -1
  54. package/dest/entrypoints/server/index.d.ts +2 -3
  55. package/dest/entrypoints/server/index.d.ts.map +1 -1
  56. package/dest/entrypoints/server/index.js +1 -2
  57. package/dest/entrypoints/server/utils.d.ts +2 -2
  58. package/dest/entrypoints/server/utils.d.ts.map +1 -1
  59. package/dest/entrypoints/server/utils.js +2 -2
  60. package/dest/logs/log_service.d.ts +4 -6
  61. package/dest/logs/log_service.d.ts.map +1 -1
  62. package/dest/logs/log_service.js +11 -20
  63. package/dest/notes/note_service.d.ts +3 -4
  64. package/dest/notes/note_service.d.ts.map +1 -1
  65. package/dest/notes_filter.d.ts +2 -3
  66. package/dest/notes_filter.d.ts.map +1 -1
  67. package/dest/oracle_version.d.ts +4 -3
  68. package/dest/oracle_version.d.ts.map +1 -1
  69. package/dest/oracle_version.js +20 -10
  70. package/dest/pxe.d.ts +4 -5
  71. package/dest/pxe.d.ts.map +1 -1
  72. package/dest/pxe.js +4 -4
  73. package/dest/storage/capsule_store/capsule_service.d.ts +2 -3
  74. package/dest/storage/capsule_store/capsule_service.d.ts.map +1 -1
  75. package/dest/storage/capsule_store/capsule_service.js +1 -1
  76. package/dest/storage/note_store/note_store.d.ts +1 -1
  77. package/dest/storage/note_store/note_store.d.ts.map +1 -1
  78. package/dest/storage/note_store/note_store.js +2 -2
  79. package/package.json +16 -16
  80. package/src/bin/check_oracle_version.ts +4 -4
  81. package/src/contract_function_simulator/contract_function_simulator.ts +2 -3
  82. package/src/contract_function_simulator/ephemeral_array_service.ts +110 -0
  83. package/src/contract_function_simulator/noir-structs/event_validation_request.ts +1 -1
  84. package/src/contract_function_simulator/noir-structs/log_retrieval_request.ts +1 -1
  85. package/src/contract_function_simulator/noir-structs/log_retrieval_response.ts +1 -1
  86. package/src/contract_function_simulator/noir-structs/note_validation_request.ts +1 -1
  87. package/src/contract_function_simulator/oracle/interfaces.ts +20 -1
  88. package/src/contract_function_simulator/oracle/legacy_oracle_mappings.ts +7 -1
  89. package/src/contract_function_simulator/oracle/oracle.ts +143 -3
  90. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +12 -3
  91. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +164 -63
  92. package/src/contract_function_simulator/pick_notes.ts +9 -2
  93. package/src/contract_sync/contract_sync_service.ts +15 -37
  94. package/src/contract_sync/helpers.ts +2 -3
  95. package/src/debug/pxe_debug_utils.ts +3 -3
  96. package/src/entrypoints/client/bundle/index.ts +0 -1
  97. package/src/entrypoints/client/bundle/utils.ts +2 -3
  98. package/src/entrypoints/client/lazy/index.ts +0 -1
  99. package/src/entrypoints/client/lazy/utils.ts +2 -3
  100. package/src/entrypoints/pxe_creation_options.ts +7 -0
  101. package/src/entrypoints/server/index.ts +1 -2
  102. package/src/entrypoints/server/utils.ts +2 -3
  103. package/src/logs/log_service.ts +19 -50
  104. package/src/notes/note_service.ts +2 -3
  105. package/src/notes_filter.ts +1 -3
  106. package/src/oracle_version.ts +20 -10
  107. package/src/pxe.ts +8 -10
  108. package/src/storage/capsule_store/capsule_service.ts +5 -6
  109. package/src/storage/note_store/note_store.ts +2 -5
  110. package/dest/access_scopes.d.ts +0 -9
  111. package/dest/access_scopes.d.ts.map +0 -1
  112. package/dest/access_scopes.js +0 -6
  113. package/src/access_scopes.ts +0 -9
@@ -1 +1 @@
1
- {"version":3,"file":"note_store.d.ts","sourceRoot":"","sources":["../../../src/storage/note_store/note_store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAqC,MAAM,iBAAiB,CAAC;AAC5F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAc,MAAM,oBAAoB,CAAC;AAEzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGzD;;;;;IAKI;AACJ,qBAAa,SAAU,YAAW,WAAW;;IAC3C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAU;IA+BpC,YAAY,KAAK,EAAE,iBAAiB,EAQnC;IAED;;;;;;;;;OASG;IACI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAarF;IAcD;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAgG/D;IAED;;;;;;;;;;;;;;OAcG;IACH,eAAe,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAyChF;IAED;;;;;;;;;;;OAWG;IACU,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMpF;IA6ED;;;;;;;;;OASG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzC;IAED,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1C;CAkCF"}
1
+ {"version":3,"file":"note_store.d.ts","sourceRoot":"","sources":["../../../src/storage/note_store/note_store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAqC,MAAM,iBAAiB,CAAC;AAC5F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAc,MAAM,oBAAoB,CAAC;AAEzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGzD;;;;;IAKI;AACJ,qBAAa,SAAU,YAAW,WAAW;;IAC3C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAU;IA+BpC,YAAY,KAAK,EAAE,iBAAiB,EAQnC;IAED;;;;;;;;;OASG;IACI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAarF;IAcD;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CA6F/D;IAED;;;;;;;;;;;;;;OAcG;IACH,eAAe,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAyChF;IAED;;;;;;;;;;;OAWG;IACU,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMpF;IA6ED;;;;;;;;;OASG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzC;IAED,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1C;CAkCF"}
@@ -75,7 +75,7 @@ import { StoredNote } from './stored_note.js';
75
75
  * @returns Filtered and deduplicated notes (a note might be present in multiple scopes - we ensure it is only
76
76
  * returned once if this is the case)
77
77
  */ getNotes(filter, jobId) {
78
- if (filter.scopes !== 'ALL_SCOPES' && filter.scopes.length === 0) {
78
+ if (filter.scopes.length === 0) {
79
79
  return Promise.resolve([]);
80
80
  }
81
81
  return this.#store.transactionAsync(async ()=>{
@@ -135,7 +135,7 @@ import { StoredNote } from './stored_note.js';
135
135
  if (filter.siloedNullifier && !note.noteDao.siloedNullifier.equals(filter.siloedNullifier)) {
136
136
  continue;
137
137
  }
138
- if (filter.scopes !== 'ALL_SCOPES' && note.scopes.intersection(new Set(filter.scopes.map((s)=>s.toString()))).size === 0) {
138
+ if (note.scopes.intersection(new Set(filter.scopes.map((s)=>s.toString()))).size === 0) {
139
139
  continue;
140
140
  }
141
141
  foundNotes.set(note.noteDao.siloedNullifier.toString(), note.noteDao);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/pxe",
3
- "version": "0.0.1-commit.f5d02921e",
3
+ "version": "0.0.1-commit.f650c0a5c",
4
4
  "type": "module",
5
5
  "typedocOptions": {
6
6
  "entryPoints": [
@@ -70,19 +70,19 @@
70
70
  ]
71
71
  },
72
72
  "dependencies": {
73
- "@aztec/bb-prover": "0.0.1-commit.f5d02921e",
74
- "@aztec/bb.js": "0.0.1-commit.f5d02921e",
75
- "@aztec/builder": "0.0.1-commit.f5d02921e",
76
- "@aztec/constants": "0.0.1-commit.f5d02921e",
77
- "@aztec/ethereum": "0.0.1-commit.f5d02921e",
78
- "@aztec/foundation": "0.0.1-commit.f5d02921e",
79
- "@aztec/key-store": "0.0.1-commit.f5d02921e",
80
- "@aztec/kv-store": "0.0.1-commit.f5d02921e",
81
- "@aztec/noir-protocol-circuits-types": "0.0.1-commit.f5d02921e",
82
- "@aztec/noir-types": "0.0.1-commit.f5d02921e",
83
- "@aztec/protocol-contracts": "0.0.1-commit.f5d02921e",
84
- "@aztec/simulator": "0.0.1-commit.f5d02921e",
85
- "@aztec/stdlib": "0.0.1-commit.f5d02921e",
73
+ "@aztec/bb-prover": "0.0.1-commit.f650c0a5c",
74
+ "@aztec/bb.js": "0.0.1-commit.f650c0a5c",
75
+ "@aztec/builder": "0.0.1-commit.f650c0a5c",
76
+ "@aztec/constants": "0.0.1-commit.f650c0a5c",
77
+ "@aztec/ethereum": "0.0.1-commit.f650c0a5c",
78
+ "@aztec/foundation": "0.0.1-commit.f650c0a5c",
79
+ "@aztec/key-store": "0.0.1-commit.f650c0a5c",
80
+ "@aztec/kv-store": "0.0.1-commit.f650c0a5c",
81
+ "@aztec/noir-protocol-circuits-types": "0.0.1-commit.f650c0a5c",
82
+ "@aztec/noir-types": "0.0.1-commit.f650c0a5c",
83
+ "@aztec/protocol-contracts": "0.0.1-commit.f650c0a5c",
84
+ "@aztec/simulator": "0.0.1-commit.f650c0a5c",
85
+ "@aztec/stdlib": "0.0.1-commit.f650c0a5c",
86
86
  "koa": "^2.16.1",
87
87
  "koa-router": "^13.1.1",
88
88
  "lodash.omit": "^4.5.0",
@@ -91,8 +91,8 @@
91
91
  "viem": "npm:@aztec/viem@2.38.2"
92
92
  },
93
93
  "devDependencies": {
94
- "@aztec/noir-test-contracts.js": "0.0.1-commit.f5d02921e",
95
- "@aztec/world-state": "0.0.1-commit.f5d02921e",
94
+ "@aztec/noir-test-contracts.js": "0.0.1-commit.f650c0a5c",
95
+ "@aztec/world-state": "0.0.1-commit.f650c0a5c",
96
96
  "@jest/globals": "^30.0.0",
97
97
  "@types/jest": "^30.0.0",
98
98
  "@types/lodash.omit": "^4.5.7",
@@ -13,8 +13,9 @@ import { ORACLE_INTERFACE_HASH } from '../oracle_version.js';
13
13
  *
14
14
  * The Oracle interface needs to be versioned to ensure compatibility between Aztec.nr and PXE. This function computes
15
15
  * a hash of the Oracle interface and compares it against a known hash. If they don't match, it means the interface has
16
- * changed and the ORACLE_VERSION constant needs to be incremented and the ORACLE_INTERFACE_HASH constant needs to be
17
- * updated.
16
+ * changed and the oracle version needs to be bumped:
17
+ * - If the change is backward-breaking (e.g. removing/renaming an oracle), bump ORACLE_VERSION_MAJOR.
18
+ * - If the change is an oracle addition (non-breaking), bump ORACLE_VERSION_MINOR.
18
19
  *
19
20
  * TODO(#16581): The following only takes into consideration changes to the oracles defined in Oracle.ts and omits TXE
20
21
  * oracles. Ensure this checks TXE oracles as well. This hasn't been implemented yet since we don't have a clean TXE
@@ -26,9 +27,8 @@ function assertOracleInterfaceMatches(): void {
26
27
  // We use keccak256 here just because we already have it in the dependencies.
27
28
  const oracleInterfaceHash = keccak256String(oracleInterfaceSignature);
28
29
  if (oracleInterfaceHash !== ORACLE_INTERFACE_HASH) {
29
- // This check exists only to notify you when you need to update the ORACLE_VERSION constant.
30
30
  throw new Error(
31
- `The Oracle interface has changed, which implies a breaking change in the aztec.nr/PXE oracle interface. Update ORACLE_INTERFACE_HASH to ${oracleInterfaceHash} and bump ORACLE_VERSION in pxe/src/oracle_version.ts.`,
31
+ `The Oracle interface has changed. Update ORACLE_INTERFACE_HASH to ${oracleInterfaceHash} in pxe/src/oracle_version.ts and bump the oracle version (ORACLE_VERSION_MAJOR for breaking changes, ORACLE_VERSION_MINOR for oracle additions).`,
32
32
  );
33
33
  }
34
34
  }
@@ -89,7 +89,6 @@ import {
89
89
  getFinalMinRevertibleSideEffectCounter,
90
90
  } from '@aztec/stdlib/tx';
91
91
 
92
- import type { AccessScopes } from '../access_scopes.js';
93
92
  import type { ContractSyncService } from '../contract_sync/contract_sync_service.js';
94
93
  import type { MessageContextService } from '../messages/message_context_service.js';
95
94
  import type { AddressStore } from '../storage/address_store/address_store.js';
@@ -123,7 +122,7 @@ export type ContractSimulatorRunOpts = {
123
122
  /** The address used as a tagging sender when emitting private logs. */
124
123
  senderForTags?: AztecAddress;
125
124
  /** The accounts whose notes we can access in this call. */
126
- scopes: AccessScopes;
125
+ scopes: AztecAddress[];
127
126
  /** The job ID for staged writes. */
128
127
  jobId: string;
129
128
  };
@@ -320,7 +319,7 @@ export class ContractFunctionSimulator {
320
319
  call: FunctionCall,
321
320
  authwits: AuthWitness[],
322
321
  anchorBlockHeader: BlockHeader,
323
- scopes: AccessScopes,
322
+ scopes: AztecAddress[],
324
323
  jobId: string,
325
324
  ): Promise<{ result: Fr[]; offchainEffects: OffchainEffect[] }> {
326
325
  const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
@@ -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,15 @@ 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
+
168
+ // Ephemeral array methods
169
+ pushEphemeral(slot: Fr, elements: Fr[]): number;
170
+ popEphemeral(slot: Fr): Fr[];
171
+ getEphemeral(slot: Fr, index: number): Fr[];
172
+ setEphemeral(slot: Fr, index: number, elements: Fr[]): void;
173
+ getEphemeralLen(slot: Fr): number;
174
+ removeEphemeral(slot: Fr, index: number): void;
175
+ clearEphemeral(slot: Fr): void;
157
176
  }
158
177
 
159
178
  /**
@@ -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
 
@@ -523,6 +579,12 @@ export class Oracle {
523
579
  return [];
524
580
  }
525
581
 
582
+ // eslint-disable-next-line camelcase
583
+ async aztec_utl_getPendingTaggedLogs_v2([scope]: ACVMField[]): Promise<ACVMField[]> {
584
+ const slot = await this.handlerAsUtility().getPendingTaggedLogsV2(AztecAddress.fromString(scope));
585
+ return [toACVMField(slot)];
586
+ }
587
+
526
588
  // eslint-disable-next-line camelcase
527
589
  async aztec_utl_validateAndStoreEnqueuedNotesAndEvents(
528
590
  [contractAddress]: ACVMField[],
@@ -544,6 +606,24 @@ export class Oracle {
544
606
  return [];
545
607
  }
546
608
 
609
+ // eslint-disable-next-line camelcase
610
+ async aztec_utl_validateAndStoreEnqueuedNotesAndEvents_v2(
611
+ [noteValidationRequestsArrayBaseSlot]: ACVMField[],
612
+ [eventValidationRequestsArrayBaseSlot]: ACVMField[],
613
+ [maxNotePackedLen]: ACVMField[],
614
+ [maxEventSerializedLen]: ACVMField[],
615
+ [scope]: ACVMField[],
616
+ ): Promise<ACVMField[]> {
617
+ await this.handlerAsUtility().validateAndStoreEnqueuedNotesAndEventsV2(
618
+ Fr.fromString(noteValidationRequestsArrayBaseSlot),
619
+ Fr.fromString(eventValidationRequestsArrayBaseSlot),
620
+ Fr.fromString(maxNotePackedLen).toNumber(),
621
+ Fr.fromString(maxEventSerializedLen).toNumber(),
622
+ AztecAddress.fromString(scope),
623
+ );
624
+ return [];
625
+ }
626
+
547
627
  // eslint-disable-next-line camelcase
548
628
  async aztec_utl_getLogsByTag(
549
629
  [contractAddress]: ACVMField[],
@@ -576,6 +656,20 @@ export class Oracle {
576
656
  return [];
577
657
  }
578
658
 
659
+ // eslint-disable-next-line camelcase
660
+ async aztec_utl_getLogsByTag_v2([requestArrayBaseSlot]: ACVMField[]): Promise<ACVMField[]> {
661
+ const responseSlot = await this.handlerAsUtility().getLogsByTagV2(Fr.fromString(requestArrayBaseSlot));
662
+ return [toACVMField(responseSlot)];
663
+ }
664
+
665
+ // eslint-disable-next-line camelcase
666
+ async aztec_utl_getMessageContextsByTxHash_v2([requestArrayBaseSlot]: ACVMField[]): Promise<ACVMField[]> {
667
+ const responseSlot = await this.handlerAsUtility().getMessageContextsByTxHashV2(
668
+ Fr.fromString(requestArrayBaseSlot),
669
+ );
670
+ return [toACVMField(responseSlot)];
671
+ }
672
+
579
673
  // eslint-disable-next-line camelcase
580
674
  aztec_utl_setCapsule(
581
675
  [contractAddress]: ACVMField[],
@@ -648,6 +742,52 @@ export class Oracle {
648
742
  return [];
649
743
  }
650
744
 
745
+ // eslint-disable-next-line camelcase
746
+ aztec_utl_pushEphemeral([slot]: ACVMField[], elements: ACVMField[]): Promise<ACVMField[]> {
747
+ const newLen = this.handlerAsUtility().pushEphemeral(Fr.fromString(slot), elements.map(Fr.fromString));
748
+ return Promise.resolve([toACVMField(newLen)]);
749
+ }
750
+
751
+ // eslint-disable-next-line camelcase
752
+ aztec_utl_popEphemeral([slot]: ACVMField[]): Promise<ACVMField[][]> {
753
+ const element = this.handlerAsUtility().popEphemeral(Fr.fromString(slot));
754
+ return Promise.resolve([element.map(toACVMField)]);
755
+ }
756
+
757
+ // eslint-disable-next-line camelcase
758
+ aztec_utl_getEphemeral([slot]: ACVMField[], [index]: ACVMField[]): Promise<ACVMField[][]> {
759
+ const element = this.handlerAsUtility().getEphemeral(Fr.fromString(slot), Fr.fromString(index).toNumber());
760
+ return Promise.resolve([element.map(toACVMField)]);
761
+ }
762
+
763
+ // eslint-disable-next-line camelcase
764
+ aztec_utl_setEphemeral([slot]: ACVMField[], [index]: ACVMField[], elements: ACVMField[]): Promise<ACVMField[]> {
765
+ this.handlerAsUtility().setEphemeral(
766
+ Fr.fromString(slot),
767
+ Fr.fromString(index).toNumber(),
768
+ elements.map(Fr.fromString),
769
+ );
770
+ return Promise.resolve([]);
771
+ }
772
+
773
+ // eslint-disable-next-line camelcase
774
+ aztec_utl_getEphemeralLen([slot]: ACVMField[]): Promise<ACVMField[]> {
775
+ const len = this.handlerAsUtility().getEphemeralLen(Fr.fromString(slot));
776
+ return Promise.resolve([toACVMField(len)]);
777
+ }
778
+
779
+ // eslint-disable-next-line camelcase
780
+ aztec_utl_removeEphemeral([slot]: ACVMField[], [index]: ACVMField[]): Promise<ACVMField[]> {
781
+ this.handlerAsUtility().removeEphemeral(Fr.fromString(slot), Fr.fromString(index).toNumber());
782
+ return Promise.resolve([]);
783
+ }
784
+
785
+ // eslint-disable-next-line camelcase
786
+ aztec_utl_clearEphemeral([slot]: ACVMField[]): Promise<ACVMField[]> {
787
+ this.handlerAsUtility().clearEphemeral(Fr.fromString(slot));
788
+ return Promise.resolve([]);
789
+ }
790
+
651
791
  // eslint-disable-next-line camelcase
652
792
  async aztec_utl_decryptAes128(
653
793
  ciphertextBVecStorage: ACVMField[],
@@ -25,7 +25,6 @@ import {
25
25
  type TxContext,
26
26
  } from '@aztec/stdlib/tx';
27
27
 
28
- import type { AccessScopes } from '../../access_scopes.js';
29
28
  import { NoteService } from '../../notes/note_service.js';
30
29
  import type { SenderTaggingStore } from '../../storage/tagging_store/sender_tagging_store.js';
31
30
  import { syncSenderTaggingIndexes } from '../../tagging/index.js';
@@ -43,7 +42,7 @@ export type PrivateExecutionOracleArgs = Omit<UtilityExecutionOracleArgs, 'contr
43
42
  txContext: TxContext;
44
43
  callContext: CallContext;
45
44
  /** Needed to trigger contract synchronization before nested calls */
46
- utilityExecutor: (call: FunctionCall, scopes: AccessScopes) => Promise<void>;
45
+ utilityExecutor: (call: FunctionCall, scopes: AztecAddress[]) => Promise<void>;
47
46
  executionCache: HashedValuesCache;
48
47
  noteCache: ExecutionNoteCache;
49
48
  taggingIndexCache: ExecutionTaggingIndexCache;
@@ -76,7 +75,7 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
76
75
  private readonly argsHash: Fr;
77
76
  private readonly txContext: TxContext;
78
77
  private readonly callContext: CallContext;
79
- private readonly utilityExecutor: (call: FunctionCall, scopes: AccessScopes) => Promise<void>;
78
+ private readonly utilityExecutor: (call: FunctionCall, scopes: AztecAddress[]) => Promise<void>;
80
79
  private readonly executionCache: HashedValuesCache;
81
80
  private readonly noteCache: ExecutionNoteCache;
82
81
  private readonly taggingIndexCache: ExecutionTaggingIndexCache;
@@ -210,6 +209,16 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
210
209
  recipient,
211
210
  );
212
211
 
212
+ if (!extendedSecret) {
213
+ // We'd only fail to compute an extended secret if the recipient is an invalid address. To prevent
214
+ // king-of-the-hill attacks, instead of failing we use a random tag. By including a correct-looking tag in the
215
+ // log, the transaction shape is preserved and no privacy is leaked, even if the tag is bogus.
216
+ this.logger.warn(`Computing a tag for invalid recipient ${recipient} - returning a random tag instead`, {
217
+ contractAddress: this.contractAddress,
218
+ });
219
+ return new Tag(Fr.random());
220
+ }
221
+
213
222
  const index = await this.#getIndexToUseForSecret(extendedSecret);
214
223
  this.logger.debug(
215
224
  `Incrementing tagging index for sender: ${sender}, recipient: ${recipient}, contract: ${this.contractAddress} to ${index}`,