@aztec/pxe 0.0.1-commit.b1c78909e → 0.0.1-commit.b33fc05d0

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 (71) hide show
  1. package/dest/contract_function_simulator/contract_function_simulator.d.ts +4 -1
  2. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  3. package/dest/contract_function_simulator/contract_function_simulator.js +4 -0
  4. package/dest/contract_function_simulator/execution_tagging_index_cache.d.ts +5 -5
  5. package/dest/contract_function_simulator/execution_tagging_index_cache.d.ts.map +1 -1
  6. package/dest/contract_function_simulator/execution_tagging_index_cache.js +17 -9
  7. package/dest/contract_function_simulator/index.d.ts +2 -1
  8. package/dest/contract_function_simulator/index.d.ts.map +1 -1
  9. package/dest/contract_function_simulator/index.js +1 -0
  10. package/dest/contract_function_simulator/noir-structs/message_tx_context.d.ts +16 -0
  11. package/dest/contract_function_simulator/noir-structs/message_tx_context.d.ts.map +1 -0
  12. package/dest/contract_function_simulator/noir-structs/message_tx_context.js +57 -0
  13. package/dest/contract_function_simulator/oracle/interfaces.d.ts +2 -1
  14. package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
  15. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts +9 -0
  16. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts.map +1 -0
  17. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.js +52 -0
  18. package/dest/contract_function_simulator/oracle/oracle.d.ts +2 -1
  19. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  20. package/dest/contract_function_simulator/oracle/oracle.js +11 -1
  21. package/dest/contract_function_simulator/oracle/private_execution.js +2 -2
  22. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +4 -4
  23. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  24. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +4 -3
  25. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +5 -1
  26. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  27. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +35 -0
  28. package/dest/messages/message_context_service.d.ts +17 -0
  29. package/dest/messages/message_context_service.d.ts.map +1 -0
  30. package/dest/messages/message_context_service.js +36 -0
  31. package/dest/oracle_version.d.ts +2 -2
  32. package/dest/oracle_version.js +2 -2
  33. package/dest/pxe.d.ts +2 -1
  34. package/dest/pxe.d.ts.map +1 -1
  35. package/dest/pxe.js +14 -9
  36. package/dest/storage/metadata.d.ts +1 -1
  37. package/dest/storage/metadata.js +1 -1
  38. package/dest/storage/tagging_store/sender_tagging_store.d.ts +26 -25
  39. package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
  40. package/dest/storage/tagging_store/sender_tagging_store.js +141 -115
  41. package/dest/tagging/index.d.ts +2 -2
  42. package/dest/tagging/index.d.ts.map +1 -1
  43. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts +1 -1
  44. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts.map +1 -1
  45. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +10 -1
  46. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts +4 -3
  47. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts.map +1 -1
  48. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.js +20 -10
  49. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts +2 -1
  50. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts.map +1 -1
  51. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.js +24 -11
  52. package/package.json +16 -16
  53. package/src/contract_function_simulator/contract_function_simulator.ts +6 -0
  54. package/src/contract_function_simulator/execution_tagging_index_cache.ts +16 -11
  55. package/src/contract_function_simulator/index.ts +1 -0
  56. package/src/contract_function_simulator/noir-structs/message_tx_context.ts +55 -0
  57. package/src/contract_function_simulator/oracle/interfaces.ts +5 -0
  58. package/src/contract_function_simulator/oracle/legacy_oracle_mappings.ts +77 -0
  59. package/src/contract_function_simulator/oracle/oracle.ts +18 -1
  60. package/src/contract_function_simulator/oracle/private_execution.ts +2 -2
  61. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +5 -4
  62. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +62 -0
  63. package/src/messages/message_context_service.ts +45 -0
  64. package/src/oracle_version.ts +2 -2
  65. package/src/pxe.ts +12 -6
  66. package/src/storage/metadata.ts +1 -1
  67. package/src/storage/tagging_store/sender_tagging_store.ts +182 -135
  68. package/src/tagging/index.ts +1 -1
  69. package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +19 -1
  70. package/src/tagging/sender_sync/utils/get_status_change_of_pending.ts +26 -11
  71. package/src/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.ts +19 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/pxe",
3
- "version": "0.0.1-commit.b1c78909e",
3
+ "version": "0.0.1-commit.b33fc05d0",
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.b1c78909e",
74
- "@aztec/bb.js": "0.0.1-commit.b1c78909e",
75
- "@aztec/builder": "0.0.1-commit.b1c78909e",
76
- "@aztec/constants": "0.0.1-commit.b1c78909e",
77
- "@aztec/ethereum": "0.0.1-commit.b1c78909e",
78
- "@aztec/foundation": "0.0.1-commit.b1c78909e",
79
- "@aztec/key-store": "0.0.1-commit.b1c78909e",
80
- "@aztec/kv-store": "0.0.1-commit.b1c78909e",
81
- "@aztec/noir-protocol-circuits-types": "0.0.1-commit.b1c78909e",
82
- "@aztec/noir-types": "0.0.1-commit.b1c78909e",
83
- "@aztec/protocol-contracts": "0.0.1-commit.b1c78909e",
84
- "@aztec/simulator": "0.0.1-commit.b1c78909e",
85
- "@aztec/stdlib": "0.0.1-commit.b1c78909e",
73
+ "@aztec/bb-prover": "0.0.1-commit.b33fc05d0",
74
+ "@aztec/bb.js": "0.0.1-commit.b33fc05d0",
75
+ "@aztec/builder": "0.0.1-commit.b33fc05d0",
76
+ "@aztec/constants": "0.0.1-commit.b33fc05d0",
77
+ "@aztec/ethereum": "0.0.1-commit.b33fc05d0",
78
+ "@aztec/foundation": "0.0.1-commit.b33fc05d0",
79
+ "@aztec/key-store": "0.0.1-commit.b33fc05d0",
80
+ "@aztec/kv-store": "0.0.1-commit.b33fc05d0",
81
+ "@aztec/noir-protocol-circuits-types": "0.0.1-commit.b33fc05d0",
82
+ "@aztec/noir-types": "0.0.1-commit.b33fc05d0",
83
+ "@aztec/protocol-contracts": "0.0.1-commit.b33fc05d0",
84
+ "@aztec/simulator": "0.0.1-commit.b33fc05d0",
85
+ "@aztec/stdlib": "0.0.1-commit.b33fc05d0",
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/merkle-tree": "0.0.1-commit.b1c78909e",
95
- "@aztec/noir-test-contracts.js": "0.0.1-commit.b1c78909e",
94
+ "@aztec/merkle-tree": "0.0.1-commit.b33fc05d0",
95
+ "@aztec/noir-test-contracts.js": "0.0.1-commit.b33fc05d0",
96
96
  "@jest/globals": "^30.0.0",
97
97
  "@types/jest": "^30.0.0",
98
98
  "@types/lodash.omit": "^4.5.7",
@@ -89,6 +89,7 @@ import {
89
89
 
90
90
  import type { AccessScopes } from '../access_scopes.js';
91
91
  import type { ContractSyncService } from '../contract_sync/contract_sync_service.js';
92
+ import type { MessageContextService } from '../messages/message_context_service.js';
92
93
  import type { AddressStore } from '../storage/address_store/address_store.js';
93
94
  import type { CapsuleStore } from '../storage/capsule_store/capsule_store.js';
94
95
  import type { ContractStore } from '../storage/contract_store/contract_store.js';
@@ -138,6 +139,7 @@ export type ContractFunctionSimulatorArgs = {
138
139
  privateEventStore: PrivateEventStore;
139
140
  simulator: CircuitSimulator;
140
141
  contractSyncService: ContractSyncService;
142
+ messageContextService: MessageContextService;
141
143
  };
142
144
 
143
145
  /**
@@ -157,6 +159,7 @@ export class ContractFunctionSimulator {
157
159
  private readonly privateEventStore: PrivateEventStore;
158
160
  private readonly simulator: CircuitSimulator;
159
161
  private readonly contractSyncService: ContractSyncService;
162
+ private readonly messageContextService: MessageContextService;
160
163
 
161
164
  constructor(args: ContractFunctionSimulatorArgs) {
162
165
  this.contractStore = args.contractStore;
@@ -171,6 +174,7 @@ export class ContractFunctionSimulator {
171
174
  this.privateEventStore = args.privateEventStore;
172
175
  this.simulator = args.simulator;
173
176
  this.contractSyncService = args.contractSyncService;
177
+ this.messageContextService = args.messageContextService;
174
178
  this.log = createLogger('simulator');
175
179
  }
176
180
 
@@ -241,6 +245,7 @@ export class ContractFunctionSimulator {
241
245
  senderAddressBookStore: this.senderAddressBookStore,
242
246
  capsuleStore: this.capsuleStore,
243
247
  privateEventStore: this.privateEventStore,
248
+ messageContextService: this.messageContextService,
244
249
  contractSyncService: this.contractSyncService,
245
250
  jobId,
246
251
  totalPublicCalldataCount: 0,
@@ -335,6 +340,7 @@ export class ContractFunctionSimulator {
335
340
  senderAddressBookStore: this.senderAddressBookStore,
336
341
  capsuleStore: this.capsuleStore,
337
342
  privateEventStore: this.privateEventStore,
343
+ messageContextService: this.messageContextService,
338
344
  jobId,
339
345
  scopes,
340
346
  });
@@ -1,32 +1,37 @@
1
- import { ExtendedDirectionalAppTaggingSecret, type PreTag } from '@aztec/stdlib/logs';
1
+ import { ExtendedDirectionalAppTaggingSecret, type TaggingIndexRange } from '@aztec/stdlib/logs';
2
2
 
3
3
  /**
4
- * A map that stores the tagging index for a given extended directional app tagging secret.
4
+ * A map that stores the tagging index range for a given extended directional app tagging secret.
5
5
  * Note: The directional app tagging secret is unique for a (sender, recipient, contract) tuple while the direction
6
6
  * of sender -> recipient matters.
7
7
  */
8
8
  export class ExecutionTaggingIndexCache {
9
- private taggingIndexMap: Map<string, number> = new Map();
9
+ private taggingIndexMap: Map<string, { lowestIndex: number; highestIndex: number }> = new Map();
10
10
 
11
11
  public getLastUsedIndex(secret: ExtendedDirectionalAppTaggingSecret): number | undefined {
12
- return this.taggingIndexMap.get(secret.toString());
12
+ return this.taggingIndexMap.get(secret.toString())?.highestIndex;
13
13
  }
14
14
 
15
15
  public setLastUsedIndex(secret: ExtendedDirectionalAppTaggingSecret, index: number) {
16
16
  const currentValue = this.taggingIndexMap.get(secret.toString());
17
- if (currentValue !== undefined && currentValue !== index - 1) {
18
- throw new Error(`Invalid tagging index update. Current value: ${currentValue}, new value: ${index}`);
17
+ if (currentValue !== undefined && currentValue.highestIndex !== index - 1) {
18
+ throw new Error(`Invalid tagging index update. Current value: ${currentValue.highestIndex}, new value: ${index}`);
19
+ }
20
+ if (currentValue !== undefined) {
21
+ currentValue.highestIndex = index;
22
+ } else {
23
+ this.taggingIndexMap.set(secret.toString(), { lowestIndex: index, highestIndex: index });
19
24
  }
20
- this.taggingIndexMap.set(secret.toString(), index);
21
25
  }
22
26
 
23
27
  /**
24
- * Returns the pre-tags that were used in this execution (and that need to be stored in the db).
28
+ * Returns the tagging index ranges that were used in this execution (and that need to be stored in the db).
25
29
  */
26
- public getUsedPreTags(): PreTag[] {
27
- return Array.from(this.taggingIndexMap.entries()).map(([secret, index]) => ({
30
+ public getUsedTaggingIndexRanges(): TaggingIndexRange[] {
31
+ return Array.from(this.taggingIndexMap.entries()).map(([secret, { lowestIndex, highestIndex }]) => ({
28
32
  extendedSecret: ExtendedDirectionalAppTaggingSecret.fromString(secret),
29
- index,
33
+ lowestIndex,
34
+ highestIndex,
30
35
  }));
31
36
  }
32
37
  }
@@ -4,6 +4,7 @@ export { HashedValuesCache } from './hashed_values_cache.js';
4
4
  export { pickNotes } from './pick_notes.js';
5
5
  export type { NoteData, IMiscOracle, IUtilityExecutionOracle, IPrivateExecutionOracle } from './oracle/interfaces.js';
6
6
  export { MessageLoadOracleInputs } from './oracle/message_load_oracle_inputs.js';
7
+ export { MessageContextService } from '../messages/message_context_service.js';
7
8
  export { UtilityExecutionOracle } from './oracle/utility_execution_oracle.js';
8
9
  export { PrivateExecutionOracle } from './oracle/private_execution_oracle.js';
9
10
  export { Oracle } from './oracle/oracle.js';
@@ -0,0 +1,55 @@
1
+ import { MAX_NOTE_HASHES_PER_TX } from '@aztec/constants';
2
+ import { range } from '@aztec/foundation/array';
3
+ import { Fr } from '@aztec/foundation/curves/bn254';
4
+ import type { TxHash } from '@aztec/stdlib/tx';
5
+
6
+ /**
7
+ * Intermediate struct used to return resolved message contexts from PXE. The
8
+ * `utilityResolveMessageContexts` oracle stores values of this type in a CapsuleArray.
9
+ */
10
+ export class MessageTxContext {
11
+ constructor(
12
+ public txHash: TxHash,
13
+ public uniqueNoteHashesInTx: Fr[],
14
+ public firstNullifierInTx: Fr,
15
+ ) {}
16
+
17
+ toFields(): Fr[] {
18
+ return [
19
+ this.txHash.hash,
20
+ ...serializeBoundedVec(this.uniqueNoteHashesInTx, MAX_NOTE_HASHES_PER_TX),
21
+ this.firstNullifierInTx,
22
+ ];
23
+ }
24
+
25
+ static toEmptyFields(): Fr[] {
26
+ const serializationLen =
27
+ 1 /* txHash */ + MAX_NOTE_HASHES_PER_TX + 1 /* uniqueNoteHashesInTx BVec */ + 1; /* firstNullifierInTx */
28
+ return range(serializationLen).map(_ => Fr.zero());
29
+ }
30
+
31
+ static toSerializedOption(response: MessageTxContext | null): Fr[] {
32
+ if (response) {
33
+ return [new Fr(1), ...response.toFields()];
34
+ } else {
35
+ return [new Fr(0), ...MessageTxContext.toEmptyFields()];
36
+ }
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Helper function to serialize a bounded vector according to Noir's BoundedVec format
42
+ * @param values - The values to serialize
43
+ * @param maxLength - The maximum length of the bounded vector
44
+ * @returns The serialized bounded vector as Fr[]
45
+ */
46
+ function serializeBoundedVec(values: Fr[], maxLength: number): Fr[] {
47
+ if (values.length > maxLength) {
48
+ throw new Error(`Attempted to serialize ${values} values into a BoundedVec with max length ${maxLength}`);
49
+ }
50
+
51
+ const lengthDiff = maxLength - values.length;
52
+ const zeroPaddingArray = Array(lengthDiff).fill(Fr.ZERO);
53
+ const storage = values.concat(zeroPaddingArray);
54
+ return [...storage, new Fr(values.length)];
55
+ }
@@ -132,6 +132,11 @@ export interface IUtilityExecutionOracle {
132
132
  logRetrievalRequestsArrayBaseSlot: Fr,
133
133
  logRetrievalResponsesArrayBaseSlot: Fr,
134
134
  ): Promise<void>;
135
+ utilityResolveMessageContexts(
136
+ contractAddress: AztecAddress,
137
+ messageContextRequestsArrayBaseSlot: Fr,
138
+ messageContextResponsesArrayBaseSlot: Fr,
139
+ ): Promise<void>;
135
140
  storeCapsule(contractAddress: AztecAddress, key: Fr, capsule: Fr[]): Promise<void>;
136
141
  loadCapsule(contractAddress: AztecAddress, key: Fr): Promise<Fr[] | null>;
137
142
  deleteCapsule(contractAddress: AztecAddress, key: Fr): Promise<void>;
@@ -0,0 +1,77 @@
1
+ import { Fr } from '@aztec/foundation/curves/bn254';
2
+ import type { ACIRCallback, ACVMField } from '@aztec/simulator/client';
3
+
4
+ import type { Oracle } from './oracle.js';
5
+
6
+ /**
7
+ * Builds legacy oracle name callbacks for pinned protocol contracts whose artifacts are committed and cannot be
8
+ * changed.
9
+ * TODO(F-416): Remove these aliases on v5 when protocol contracts are redeployed.
10
+ */
11
+ export function buildLegacyOracleCallbacks(oracle: Oracle): ACIRCallback {
12
+ return {
13
+ // Simple prefix renames (privateXxx/utilityXxx → aztec_prv_/aztec_utl_)
14
+ utilityLog: (...args: ACVMField[][]) => oracle.aztec_utl_log(args[0], args[1], args[2], args[3]),
15
+ utilityAssertCompatibleOracleVersion: (...args: ACVMField[][]) =>
16
+ oracle.aztec_utl_assertCompatibleOracleVersion(args[0]),
17
+ utilityLoadCapsule: (...args: ACVMField[][]) => oracle.aztec_utl_loadCapsule(args[0], args[1], args[2]),
18
+ privateStoreInExecutionCache: (...args: ACVMField[][]) => oracle.aztec_prv_storeInExecutionCache(args[0], args[1]),
19
+ privateLoadFromExecutionCache: (...args: ACVMField[][]) => oracle.aztec_prv_loadFromExecutionCache(args[0]),
20
+ privateCallPrivateFunction: (...args: ACVMField[][]) =>
21
+ oracle.aztec_prv_callPrivateFunction(args[0], args[1], args[2], args[3], args[4]),
22
+ privateIsNullifierPending: (...args: ACVMField[][]) => oracle.aztec_prv_isNullifierPending(args[0], args[1]),
23
+ privateNotifyCreatedNullifier: (...args: ACVMField[][]) => oracle.aztec_prv_notifyCreatedNullifier(args[0]),
24
+ privateNotifyCreatedContractClassLog: (...args: ACVMField[][]) =>
25
+ oracle.aztec_prv_notifyCreatedContractClassLog(args[0], args[1], args[2], args[3]),
26
+ privateGetNextAppTagAsSender: (...args: ACVMField[][]) => oracle.aztec_prv_getNextAppTagAsSender(args[0], args[1]),
27
+ privateGetSenderForTags: () => oracle.aztec_prv_getSenderForTags(),
28
+ privateSetSenderForTags: (...args: ACVMField[][]) => oracle.aztec_prv_setSenderForTags(args[0]),
29
+ utilityGetUtilityContext: () => oracle.aztec_utl_getUtilityContext(),
30
+ utilityStorageRead: (...args: ACVMField[][]) => oracle.aztec_utl_storageRead(args[0], args[1], args[2], args[3]),
31
+ utilityStoreCapsule: (...args: ACVMField[][]) => oracle.aztec_utl_storeCapsule(args[0], args[1], args[2]),
32
+ utilityCopyCapsule: (...args: ACVMField[][]) => oracle.aztec_utl_copyCapsule(args[0], args[1], args[2], args[3]),
33
+ utilityDeleteCapsule: (...args: ACVMField[][]) => oracle.aztec_utl_deleteCapsule(args[0], args[1]),
34
+ utilityAes128Decrypt: (...args: ACVMField[][]) =>
35
+ oracle.aztec_utl_aes128Decrypt(args[0], args[1], args[2], args[3]),
36
+ utilityGetSharedSecret: (...args: ACVMField[][]) =>
37
+ oracle.aztec_utl_getSharedSecret(args[0], args[1], args[2], args[3]),
38
+ utilityFetchTaggedLogs: (...args: ACVMField[][]) => oracle.aztec_utl_fetchTaggedLogs(args[0]),
39
+ utilityBulkRetrieveLogs: (...args: ACVMField[][]) => oracle.aztec_utl_bulkRetrieveLogs(args[0], args[1], args[2]),
40
+ // Adapter: old 3-param signature → new 5-param with injected constants.
41
+ // Values derived from: MAX_MESSAGE_CONTENT_LEN(11) - RESERVED_FIELDS (3 for notes, 1 for events).
42
+ utilityValidateAndStoreEnqueuedNotesAndEvents: (
43
+ contractAddress: ACVMField[],
44
+ noteValidationRequestsArrayBaseSlot: ACVMField[],
45
+ eventValidationRequestsArrayBaseSlot: ACVMField[],
46
+ ) =>
47
+ oracle.aztec_utl_validateAndStoreEnqueuedNotesAndEvents(
48
+ contractAddress,
49
+ noteValidationRequestsArrayBaseSlot,
50
+ eventValidationRequestsArrayBaseSlot,
51
+ [new Fr(8).toString()],
52
+ [new Fr(10).toString()],
53
+ ),
54
+ utilityGetL1ToL2MembershipWitness: (...args: ACVMField[][]) =>
55
+ oracle.aztec_utl_getL1ToL2MembershipWitness(args[0], args[1], args[2]),
56
+ utilityCheckNullifierExists: (...args: ACVMField[][]) => oracle.aztec_utl_checkNullifierExists(args[0]),
57
+ utilityGetRandomField: () => oracle.aztec_utl_getRandomField(),
58
+ utilityEmitOffchainEffect: (...args: ACVMField[][]) => oracle.aztec_utl_emitOffchainEffect(args[0]),
59
+ // Renames (same signature, different oracle name)
60
+ privateNotifySetMinRevertibleSideEffectCounter: (...args: ACVMField[][]) =>
61
+ oracle.aztec_prv_notifyRevertiblePhaseStart(args[0]),
62
+ privateIsSideEffectCounterRevertible: (...args: ACVMField[][]) => oracle.aztec_prv_inRevertiblePhase(args[0]),
63
+ // Signature changes: old 4-param oracles → new 1-param validatePublicCalldata
64
+ privateNotifyEnqueuedPublicFunctionCall: (
65
+ [_contractAddress]: ACVMField[],
66
+ [calldataHash]: ACVMField[],
67
+ [_sideEffectCounter]: ACVMField[],
68
+ [_isStaticCall]: ACVMField[],
69
+ ) => oracle.aztec_prv_validatePublicCalldata([calldataHash]),
70
+ privateNotifySetPublicTeardownFunctionCall: (
71
+ [_contractAddress]: ACVMField[],
72
+ [calldataHash]: ACVMField[],
73
+ [_sideEffectCounter]: ACVMField[],
74
+ [_isStaticCall]: ACVMField[],
75
+ ) => oracle.aztec_prv_validatePublicCalldata([calldataHash]),
76
+ };
77
+ }
@@ -16,6 +16,7 @@ import { BlockHash } from '@aztec/stdlib/block';
16
16
  import { ContractClassLog, ContractClassLogFields } from '@aztec/stdlib/logs';
17
17
 
18
18
  import type { IMiscOracle, IPrivateExecutionOracle, IUtilityExecutionOracle } from './interfaces.js';
19
+ import { buildLegacyOracleCallbacks } from './legacy_oracle_mappings.js';
19
20
  import { packAsHintedNote } from './note_packing_utils.js';
20
21
 
21
22
  export class UnavailableOracleError extends Error {
@@ -85,11 +86,13 @@ export class Oracle {
85
86
  });
86
87
 
87
88
  // Build callback object and return it
88
- return oracleNames.reduce((acc, name) => {
89
+ const callback = oracleNames.reduce((acc, name) => {
89
90
  const method = this[name as keyof Omit<Oracle, (typeof excludedProps)[number]>];
90
91
  acc[name] = method.bind(this);
91
92
  return acc;
92
93
  }, {} as ACIRCallback);
94
+
95
+ return { ...callback, ...buildLegacyOracleCallbacks(this) };
93
96
  }
94
97
 
95
98
  // eslint-disable-next-line camelcase
@@ -526,6 +529,20 @@ export class Oracle {
526
529
  return [];
527
530
  }
528
531
 
532
+ // eslint-disable-next-line camelcase
533
+ async aztec_utl_utilityResolveMessageContexts(
534
+ [contractAddress]: ACVMField[],
535
+ [messageContextRequestsArrayBaseSlot]: ACVMField[],
536
+ [messageContextResponsesArrayBaseSlot]: ACVMField[],
537
+ ): Promise<ACVMField[]> {
538
+ await this.handlerAsUtility().utilityResolveMessageContexts(
539
+ AztecAddress.fromString(contractAddress),
540
+ Fr.fromString(messageContextRequestsArrayBaseSlot),
541
+ Fr.fromString(messageContextResponsesArrayBaseSlot),
542
+ );
543
+ return [];
544
+ }
545
+
529
546
  // eslint-disable-next-line camelcase
530
547
  async aztec_utl_storeCapsule(
531
548
  [contractAddress]: ACVMField[],
@@ -81,7 +81,7 @@ export async function executePrivateFunction(
81
81
  const newNotes = privateExecutionOracle.getNewNotes();
82
82
  const noteHashNullifierCounterMap = privateExecutionOracle.getNoteHashNullifierCounterMap();
83
83
  const offchainEffects = privateExecutionOracle.getOffchainEffects();
84
- const preTags = privateExecutionOracle.getUsedPreTags();
84
+ const taggingIndexRanges = privateExecutionOracle.getUsedTaggingIndexRanges();
85
85
  const nestedExecutionResults = privateExecutionOracle.getNestedExecutionResults();
86
86
 
87
87
  let timerSubtractionList = nestedExecutionResults;
@@ -104,7 +104,7 @@ export async function executePrivateFunction(
104
104
  noteHashNullifierCounterMap,
105
105
  rawReturnValues,
106
106
  offchainEffects,
107
- preTags,
107
+ taggingIndexRanges,
108
108
  nestedExecutionResults,
109
109
  contractClassLogs,
110
110
  {
@@ -14,7 +14,7 @@ import {
14
14
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
15
15
  import { siloNullifier } from '@aztec/stdlib/hash';
16
16
  import { PrivateContextInputs } from '@aztec/stdlib/kernel';
17
- import { type ContractClassLog, ExtendedDirectionalAppTaggingSecret, type PreTag } from '@aztec/stdlib/logs';
17
+ import { type ContractClassLog, ExtendedDirectionalAppTaggingSecret, type TaggingIndexRange } from '@aztec/stdlib/logs';
18
18
  import { Tag } from '@aztec/stdlib/logs';
19
19
  import { Note, type NoteStatus } from '@aztec/stdlib/note';
20
20
  import {
@@ -166,10 +166,10 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
166
166
  }
167
167
 
168
168
  /**
169
- * Returns the pre-tags that were used in this execution (and that need to be stored in the db).
169
+ * Returns the tagging index ranges that were used in this execution (and that need to be stored in the db).
170
170
  */
171
- public getUsedPreTags(): PreTag[] {
172
- return this.taggingIndexCache.getUsedPreTags();
171
+ public getUsedTaggingIndexRanges(): TaggingIndexRange[] {
172
+ return this.taggingIndexCache.getUsedTaggingIndexRanges();
173
173
  }
174
174
 
175
175
  /**
@@ -569,6 +569,7 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
569
569
  senderAddressBookStore: this.senderAddressBookStore,
570
570
  capsuleStore: this.capsuleStore,
571
571
  privateEventStore: this.privateEventStore,
572
+ messageContextService: this.messageContextService,
572
573
  contractSyncService: this.contractSyncService,
573
574
  jobId: this.jobId,
574
575
  totalPublicCalldataCount: this.totalPublicCalldataCount,
@@ -6,6 +6,7 @@ import { Point } from '@aztec/foundation/curves/grumpkin';
6
6
  import { LogLevels, type Logger, createLogger } from '@aztec/foundation/log';
7
7
  import type { MembershipWitness } from '@aztec/foundation/trees';
8
8
  import type { KeyStore } from '@aztec/key-store';
9
+ import { isProtocolContract } from '@aztec/protocol-contracts';
9
10
  import type { AuthWitness } from '@aztec/stdlib/auth-witness';
10
11
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
11
12
  import { BlockHash } from '@aztec/stdlib/block';
@@ -24,6 +25,7 @@ import type { AccessScopes } from '../../access_scopes.js';
24
25
  import { createContractLogger, logContractMessage } from '../../contract_logging.js';
25
26
  import { EventService } from '../../events/event_service.js';
26
27
  import { LogService } from '../../logs/log_service.js';
28
+ import { MessageContextService } from '../../messages/message_context_service.js';
27
29
  import { NoteService } from '../../notes/note_service.js';
28
30
  import { ORACLE_VERSION } from '../../oracle_version.js';
29
31
  import type { AddressStore } from '../../storage/address_store/address_store.js';
@@ -36,6 +38,7 @@ import type { SenderAddressBookStore } from '../../storage/tagging_store/sender_
36
38
  import { EventValidationRequest } from '../noir-structs/event_validation_request.js';
37
39
  import { LogRetrievalRequest } from '../noir-structs/log_retrieval_request.js';
38
40
  import { LogRetrievalResponse } from '../noir-structs/log_retrieval_response.js';
41
+ import { MessageTxContext } from '../noir-structs/message_tx_context.js';
39
42
  import { NoteValidationRequest } from '../noir-structs/note_validation_request.js';
40
43
  import { UtilityContext } from '../noir-structs/utility_context.js';
41
44
  import { pickNotes } from '../pick_notes.js';
@@ -58,6 +61,7 @@ export type UtilityExecutionOracleArgs = {
58
61
  senderAddressBookStore: SenderAddressBookStore;
59
62
  capsuleStore: CapsuleStore;
60
63
  privateEventStore: PrivateEventStore;
64
+ messageContextService: MessageContextService;
61
65
  jobId: string;
62
66
  log?: ReturnType<typeof createLogger>;
63
67
  scopes: AccessScopes;
@@ -85,6 +89,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
85
89
  protected readonly senderAddressBookStore: SenderAddressBookStore;
86
90
  protected readonly capsuleStore: CapsuleStore;
87
91
  protected readonly privateEventStore: PrivateEventStore;
92
+ protected readonly messageContextService: MessageContextService;
88
93
  protected readonly jobId: string;
89
94
  protected logger: ReturnType<typeof createLogger>;
90
95
  protected readonly scopes: AccessScopes;
@@ -103,12 +108,28 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
103
108
  this.senderAddressBookStore = args.senderAddressBookStore;
104
109
  this.capsuleStore = args.capsuleStore;
105
110
  this.privateEventStore = args.privateEventStore;
111
+ this.messageContextService = args.messageContextService;
106
112
  this.jobId = args.jobId;
107
113
  this.logger = args.log ?? createLogger('simulator:client_view_context');
108
114
  this.scopes = args.scopes;
109
115
  }
110
116
 
111
117
  public assertCompatibleOracleVersion(version: number): void {
118
+ // TODO(F-416): Remove this hack on v5 when protocol contracts are redeployed.
119
+ // Protocol contracts/canonical contracts shipped with committed bytecode that cannot be changed. Assert they use
120
+ // the expected pinned version or the current one. We want to allow for both the pinned and the current versions
121
+ // because we want this code to work with both the pinned and unpinned version since some branches do not have the
122
+ // pinned contracts (like e.g. next)
123
+ const LEGACY_ORACLE_VERSION = 12;
124
+ if (isProtocolContract(this.contractAddress)) {
125
+ if (version !== LEGACY_ORACLE_VERSION && version !== ORACLE_VERSION) {
126
+ throw new Error(
127
+ `Expected legacy oracle version ${LEGACY_ORACLE_VERSION} or current oracle version ${ORACLE_VERSION} for alpha payload contract at ${this.contractAddress}, got ${version}.`,
128
+ );
129
+ }
130
+ return;
131
+ }
132
+
112
133
  if (version !== ORACLE_VERSION) {
113
134
  throw new Error(`Incompatible oracle version. Expected version ${ORACLE_VERSION}, got ${version}.`);
114
135
  }
@@ -550,6 +571,47 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
550
571
  );
551
572
  }
552
573
 
574
+ public async utilityResolveMessageContexts(
575
+ contractAddress: AztecAddress,
576
+ messageContextRequestsArrayBaseSlot: Fr,
577
+ messageContextResponsesArrayBaseSlot: Fr,
578
+ ) {
579
+ try {
580
+ if (!this.contractAddress.equals(contractAddress)) {
581
+ throw new Error(`Got a message context request from ${contractAddress}, expected ${this.contractAddress}`);
582
+ }
583
+ const requestCapsules = await this.capsuleStore.readCapsuleArray(
584
+ contractAddress,
585
+ messageContextRequestsArrayBaseSlot,
586
+ this.jobId,
587
+ );
588
+
589
+ const txHashes = requestCapsules.map((fields, i) => {
590
+ if (fields.length !== 1) {
591
+ throw new Error(
592
+ `Malformed message context request at index ${i}: expected 1 field (tx hash), got ${fields.length}`,
593
+ );
594
+ }
595
+ return fields[0];
596
+ });
597
+
598
+ const maybeMessageContexts = await this.messageContextService.resolveMessageContexts(
599
+ txHashes,
600
+ this.anchorBlockHeader.getBlockNumber(),
601
+ );
602
+
603
+ // Leave response in response capsule array.
604
+ await this.capsuleStore.setCapsuleArray(
605
+ contractAddress,
606
+ messageContextResponsesArrayBaseSlot,
607
+ maybeMessageContexts.map(MessageTxContext.toSerializedOption),
608
+ this.jobId,
609
+ );
610
+ } finally {
611
+ await this.capsuleStore.setCapsuleArray(contractAddress, messageContextRequestsArrayBaseSlot, [], this.jobId);
612
+ }
613
+ }
614
+
553
615
  public storeCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[]): Promise<void> {
554
616
  if (!contractAddress.equals(this.contractAddress)) {
555
617
  // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
@@ -0,0 +1,45 @@
1
+ import { Fr } from '@aztec/foundation/curves/bn254';
2
+ import type { AztecNode } from '@aztec/stdlib/interfaces/server';
3
+ import { TxHash } from '@aztec/stdlib/tx';
4
+
5
+ import { MessageTxContext } from '../contract_function_simulator/noir-structs/message_tx_context.js';
6
+
7
+ /** Resolves transaction hashes into the context needed to process messages. */
8
+ export class MessageContextService {
9
+ constructor(private readonly aztecNode: AztecNode) {}
10
+
11
+ /**
12
+ * Resolves a list of tx hashes into their message contexts.
13
+ *
14
+ * For each tx hash, looks up the corresponding tx effect and extracts the note hashes and first nullifier needed to
15
+ * process messages that originated from that transaction. Returns `null` for tx hashes that are zero, not yet
16
+ * available, or in blocks beyond the anchor block.
17
+ */
18
+ resolveMessageContexts(txHashes: Fr[], anchorBlockNumber: number): Promise<(MessageTxContext | null)[]> {
19
+ // TODO: optimize, we might be hitting the node to get the same txHash repeatedly
20
+ return Promise.all(
21
+ txHashes.map(async txHashField => {
22
+ // A zero tx hash indicates a tx-less offchain message (e.g. one not tied to any onchain transaction).
23
+ // These messages don't have a transaction context to resolve, so we return null.
24
+ if (txHashField.isZero()) {
25
+ return null;
26
+ }
27
+
28
+ const txHash = TxHash.fromField(txHashField);
29
+ const txEffect = await this.aztecNode.getTxEffect(txHash);
30
+ if (!txEffect || txEffect.l2BlockNumber > anchorBlockNumber) {
31
+ return null;
32
+ }
33
+
34
+ // Every tx has at least one nullifier (the first nullifier derived from the tx hash). Hitting this condition
35
+ // would mean a buggy node, but since we need to access data.nullifiers[0], the defensive check does no harm.
36
+ const data = txEffect.data;
37
+ if (data.nullifiers.length === 0) {
38
+ throw new Error(`Tx effect for ${txHash} has no nullifiers`);
39
+ }
40
+
41
+ return new MessageTxContext(data.txHash, data.noteHashes, data.nullifiers[0]);
42
+ }),
43
+ );
44
+ }
45
+ }
@@ -4,9 +4,9 @@
4
4
  ///
5
5
  /// @dev Whenever a contract function or Noir test is run, the `aztec_utl_assertCompatibleOracleVersion` oracle is called
6
6
  /// and if the oracle version is incompatible an error is thrown.
7
- export const ORACLE_VERSION = 15;
7
+ export const ORACLE_VERSION = 16;
8
8
 
9
9
  /// This hash is computed as by hashing the Oracle interface and it is used to detect when the Oracle interface changes,
10
10
  /// which in turn implies that you need to update the ORACLE_VERSION constant in this file and in
11
11
  /// `noir-projects/aztec-nr/aztec/src/oracle/version.nr`.
12
- export const ORACLE_INTERFACE_HASH = '32b3efa9e08765a5fad5fba732df263f61ca13e7979e30c1843215914b76b97e';
12
+ export const ORACLE_INTERFACE_HASH = '73ccb2a24bc9fe7514108be9ff98d7ca8734bc316fb7c1ec4329d1d32f412a55';
package/src/pxe.ts CHANGED
@@ -68,6 +68,7 @@ import { PXEDebugUtils } from './debug/pxe_debug_utils.js';
68
68
  import { enrichPublicSimulationError, enrichSimulationError } from './error_enriching.js';
69
69
  import { PrivateEventFilterValidator } from './events/private_event_filter_validator.js';
70
70
  import { JobCoordinator } from './job_coordinator/job_coordinator.js';
71
+ import { MessageContextService } from './messages/message_context_service.js';
71
72
  import {
72
73
  PrivateKernelExecutionProver,
73
74
  type PrivateKernelExecutionProverConfig,
@@ -158,6 +159,7 @@ export class PXE {
158
159
  private addressStore: AddressStore,
159
160
  private privateEventStore: PrivateEventStore,
160
161
  private contractSyncService: ContractSyncService,
162
+ private messageContextService: MessageContextService,
161
163
  private simulator: CircuitSimulator,
162
164
  private proverEnabled: boolean,
163
165
  private proofCreator: PrivateKernelProver,
@@ -213,6 +215,8 @@ export class PXE {
213
215
  noteStore,
214
216
  createLogger('pxe:contract_sync', bindings),
215
217
  );
218
+ const messageContextService = new MessageContextService(node);
219
+
216
220
  const synchronizer = new BlockSynchronizer(
217
221
  node,
218
222
  store,
@@ -254,6 +258,7 @@ export class PXE {
254
258
  addressStore,
255
259
  privateEventStore,
256
260
  contractSyncService,
261
+ messageContextService,
257
262
  simulator,
258
263
  proverEnabled,
259
264
  proofCreator,
@@ -295,6 +300,7 @@ export class PXE {
295
300
  privateEventStore: this.privateEventStore,
296
301
  simulator: this.simulator,
297
302
  contractSyncService: this.contractSyncService,
303
+ messageContextService: this.messageContextService,
298
304
  });
299
305
  }
300
306
 
@@ -766,17 +772,17 @@ export class PXE {
766
772
  // transaction before this one is included in a block from this PXE, and that transaction contains a log with
767
773
  // a tag derived from the same secret, we would reuse the tag and the transactions would be linked. Hence
768
774
  // storing the tags here prevents linkage of txs sent from the same PXE.
769
- const preTagsUsedInTheTx = privateExecutionResult.entrypoint.preTags;
770
- if (preTagsUsedInTheTx.length > 0) {
775
+ const taggingIndexRangesUsedInTheTx = privateExecutionResult.entrypoint.taggingIndexRanges;
776
+ if (taggingIndexRangesUsedInTheTx.length > 0) {
771
777
  // TODO(benesjan): The following is an expensive operation. Figure out a way to avoid it.
772
778
  const txHash = (await txProvingResult.toTx()).txHash;
773
779
 
774
- await this.senderTaggingStore.storePendingIndexes(preTagsUsedInTheTx, txHash, jobId);
775
- this.log.debug(`Stored used pre-tags as sender for the tx`, {
776
- preTagsUsedInTheTx,
780
+ await this.senderTaggingStore.storePendingIndexes(taggingIndexRangesUsedInTheTx, txHash, jobId);
781
+ this.log.debug(`Stored used tagging index ranges as sender for the tx`, {
782
+ taggingIndexRangesUsedInTheTx,
777
783
  });
778
784
  } else {
779
- this.log.debug(`No pre-tags used in the tx`);
785
+ this.log.debug(`No tagging index ranges used in the tx`);
780
786
  }
781
787
 
782
788
  return txProvingResult;
@@ -1 +1 @@
1
- export const PXE_DATA_SCHEMA_VERSION = 3;
1
+ export const PXE_DATA_SCHEMA_VERSION = 4;