@aztec/pxe 0.0.1-commit.381b1a9 → 0.0.1-commit.3a4ae741b
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.
- package/dest/config/index.d.ts +2 -2
- package/dest/config/index.d.ts.map +1 -1
- package/dest/config/index.js +1 -1
- package/dest/config/package_info.js +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.d.ts +9 -3
- package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.js +28 -6
- package/dest/contract_function_simulator/execution_tagging_index_cache.d.ts +5 -5
- package/dest/contract_function_simulator/execution_tagging_index_cache.d.ts.map +1 -1
- package/dest/contract_function_simulator/execution_tagging_index_cache.js +17 -9
- package/dest/contract_function_simulator/index.d.ts +2 -1
- package/dest/contract_function_simulator/index.d.ts.map +1 -1
- package/dest/contract_function_simulator/index.js +1 -0
- package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +2 -3
- package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/event_validation_request.js +5 -4
- package/dest/contract_function_simulator/noir-structs/log_retrieval_response.d.ts +1 -1
- package/dest/contract_function_simulator/noir-structs/log_retrieval_response.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/log_retrieval_response.js +1 -3
- package/dest/contract_function_simulator/noir-structs/message_tx_context.d.ts +16 -0
- package/dest/contract_function_simulator/noir-structs/message_tx_context.d.ts.map +1 -0
- package/dest/contract_function_simulator/noir-structs/message_tx_context.js +57 -0
- package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +2 -4
- package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/note_validation_request.js +3 -5
- package/dest/contract_function_simulator/oracle/interfaces.d.ts +45 -44
- package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts +9 -0
- package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts.map +1 -0
- package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.js +42 -0
- package/dest/contract_function_simulator/oracle/oracle.d.ts +45 -44
- package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/oracle.js +163 -94
- package/dest/contract_function_simulator/oracle/private_execution.js +5 -3
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +22 -47
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.js +32 -72
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +46 -32
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +91 -40
- package/dest/contract_sync/contract_sync_service.d.ts +5 -3
- package/dest/contract_sync/contract_sync_service.d.ts.map +1 -1
- package/dest/contract_sync/contract_sync_service.js +47 -30
- package/dest/messages/message_context_service.d.ts +17 -0
- package/dest/messages/message_context_service.d.ts.map +1 -0
- package/dest/messages/message_context_service.js +36 -0
- package/dest/oracle_version.d.ts +2 -2
- package/dest/oracle_version.js +3 -3
- package/dest/pxe.d.ts +8 -4
- package/dest/pxe.d.ts.map +1 -1
- package/dest/pxe.js +41 -23
- package/dest/storage/metadata.d.ts +1 -1
- package/dest/storage/metadata.js +1 -1
- package/dest/storage/tagging_store/sender_tagging_store.d.ts +26 -25
- package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
- package/dest/storage/tagging_store/sender_tagging_store.js +141 -115
- package/dest/tagging/index.d.ts +2 -2
- package/dest/tagging/index.d.ts.map +1 -1
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts +1 -1
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts.map +1 -1
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +10 -1
- package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts +4 -3
- package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts.map +1 -1
- package/dest/tagging/sender_sync/utils/get_status_change_of_pending.js +20 -10
- package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts +2 -1
- package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts.map +1 -1
- package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.js +24 -11
- package/package.json +16 -16
- package/src/config/index.ts +1 -1
- package/src/config/package_info.ts +1 -1
- package/src/contract_function_simulator/contract_function_simulator.ts +39 -7
- package/src/contract_function_simulator/execution_tagging_index_cache.ts +16 -11
- package/src/contract_function_simulator/index.ts +1 -0
- package/src/contract_function_simulator/noir-structs/event_validation_request.ts +8 -5
- package/src/contract_function_simulator/noir-structs/log_retrieval_response.ts +1 -4
- package/src/contract_function_simulator/noir-structs/message_tx_context.ts +55 -0
- package/src/contract_function_simulator/noir-structs/note_validation_request.ts +3 -6
- package/src/contract_function_simulator/oracle/interfaces.ts +50 -53
- package/src/contract_function_simulator/oracle/legacy_oracle_mappings.ts +135 -0
- package/src/contract_function_simulator/oracle/oracle.ts +176 -138
- package/src/contract_function_simulator/oracle/private_execution.ts +4 -4
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +34 -91
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +125 -48
- package/src/contract_sync/contract_sync_service.ts +67 -38
- package/src/messages/message_context_service.ts +45 -0
- package/src/oracle_version.ts +3 -3
- package/src/pxe.ts +59 -22
- package/src/storage/metadata.ts +1 -1
- package/src/storage/tagging_store/sender_tagging_store.ts +182 -135
- package/src/tagging/index.ts +1 -1
- package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +19 -1
- package/src/tagging/sender_sync/utils/get_status_change_of_pending.ts +26 -11
- package/src/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.ts +19 -9
|
@@ -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';
|
|
@@ -18,12 +19,14 @@ import { deriveEcdhSharedSecret } from '@aztec/stdlib/logs';
|
|
|
18
19
|
import { getNonNullifiedL1ToL2MessageWitness } from '@aztec/stdlib/messaging';
|
|
19
20
|
import type { NoteStatus } from '@aztec/stdlib/note';
|
|
20
21
|
import { MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
|
|
21
|
-
import type { BlockHeader, Capsule } from '@aztec/stdlib/tx';
|
|
22
|
+
import type { BlockHeader, Capsule, OffchainEffect } from '@aztec/stdlib/tx';
|
|
22
23
|
|
|
23
24
|
import type { AccessScopes } from '../../access_scopes.js';
|
|
24
25
|
import { createContractLogger, logContractMessage } from '../../contract_logging.js';
|
|
26
|
+
import type { ContractSyncService } from '../../contract_sync/contract_sync_service.js';
|
|
25
27
|
import { EventService } from '../../events/event_service.js';
|
|
26
28
|
import { LogService } from '../../logs/log_service.js';
|
|
29
|
+
import { MessageContextService } from '../../messages/message_context_service.js';
|
|
27
30
|
import { NoteService } from '../../notes/note_service.js';
|
|
28
31
|
import { ORACLE_VERSION } from '../../oracle_version.js';
|
|
29
32
|
import type { AddressStore } from '../../storage/address_store/address_store.js';
|
|
@@ -36,6 +39,7 @@ import type { SenderAddressBookStore } from '../../storage/tagging_store/sender_
|
|
|
36
39
|
import { EventValidationRequest } from '../noir-structs/event_validation_request.js';
|
|
37
40
|
import { LogRetrievalRequest } from '../noir-structs/log_retrieval_request.js';
|
|
38
41
|
import { LogRetrievalResponse } from '../noir-structs/log_retrieval_response.js';
|
|
42
|
+
import { MessageTxContext } from '../noir-structs/message_tx_context.js';
|
|
39
43
|
import { NoteValidationRequest } from '../noir-structs/note_validation_request.js';
|
|
40
44
|
import { UtilityContext } from '../noir-structs/utility_context.js';
|
|
41
45
|
import { pickNotes } from '../pick_notes.js';
|
|
@@ -58,6 +62,8 @@ export type UtilityExecutionOracleArgs = {
|
|
|
58
62
|
senderAddressBookStore: SenderAddressBookStore;
|
|
59
63
|
capsuleStore: CapsuleStore;
|
|
60
64
|
privateEventStore: PrivateEventStore;
|
|
65
|
+
messageContextService: MessageContextService;
|
|
66
|
+
contractSyncService: ContractSyncService;
|
|
61
67
|
jobId: string;
|
|
62
68
|
log?: ReturnType<typeof createLogger>;
|
|
63
69
|
scopes: AccessScopes;
|
|
@@ -71,6 +77,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
71
77
|
isUtility = true as const;
|
|
72
78
|
|
|
73
79
|
private contractLogger: Logger | undefined;
|
|
80
|
+
private offchainEffects: OffchainEffect[] = [];
|
|
74
81
|
|
|
75
82
|
protected readonly contractAddress: AztecAddress;
|
|
76
83
|
protected readonly authWitnesses: AuthWitness[];
|
|
@@ -85,8 +92,10 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
85
92
|
protected readonly senderAddressBookStore: SenderAddressBookStore;
|
|
86
93
|
protected readonly capsuleStore: CapsuleStore;
|
|
87
94
|
protected readonly privateEventStore: PrivateEventStore;
|
|
95
|
+
protected readonly messageContextService: MessageContextService;
|
|
96
|
+
protected readonly contractSyncService: ContractSyncService;
|
|
88
97
|
protected readonly jobId: string;
|
|
89
|
-
protected
|
|
98
|
+
protected logger: ReturnType<typeof createLogger>;
|
|
90
99
|
protected readonly scopes: AccessScopes;
|
|
91
100
|
|
|
92
101
|
constructor(args: UtilityExecutionOracleArgs) {
|
|
@@ -103,22 +112,39 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
103
112
|
this.senderAddressBookStore = args.senderAddressBookStore;
|
|
104
113
|
this.capsuleStore = args.capsuleStore;
|
|
105
114
|
this.privateEventStore = args.privateEventStore;
|
|
115
|
+
this.messageContextService = args.messageContextService;
|
|
116
|
+
this.contractSyncService = args.contractSyncService;
|
|
106
117
|
this.jobId = args.jobId;
|
|
107
|
-
this.
|
|
118
|
+
this.logger = args.log ?? createLogger('simulator:client_view_context');
|
|
108
119
|
this.scopes = args.scopes;
|
|
109
120
|
}
|
|
110
121
|
|
|
111
|
-
public
|
|
122
|
+
public assertCompatibleOracleVersion(version: number): void {
|
|
123
|
+
// TODO(F-416): Remove this hack on v5 when protocol contracts are redeployed.
|
|
124
|
+
// Protocol contracts/canonical contracts shipped with committed bytecode that cannot be changed. Assert they use
|
|
125
|
+
// the expected pinned version or the current one. We want to allow for both the pinned and the current versions
|
|
126
|
+
// because we want this code to work with both the pinned and unpinned version since some branches do not have the
|
|
127
|
+
// pinned contracts (like e.g. next)
|
|
128
|
+
const LEGACY_ORACLE_VERSION = 12;
|
|
129
|
+
if (isProtocolContract(this.contractAddress)) {
|
|
130
|
+
if (version !== LEGACY_ORACLE_VERSION && version !== ORACLE_VERSION) {
|
|
131
|
+
throw new Error(
|
|
132
|
+
`Expected legacy oracle version ${LEGACY_ORACLE_VERSION} or current oracle version ${ORACLE_VERSION} for alpha payload contract at ${this.contractAddress}, got ${version}.`,
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
112
138
|
if (version !== ORACLE_VERSION) {
|
|
113
139
|
throw new Error(`Incompatible oracle version. Expected version ${ORACLE_VERSION}, got ${version}.`);
|
|
114
140
|
}
|
|
115
141
|
}
|
|
116
142
|
|
|
117
|
-
public
|
|
143
|
+
public getRandomField(): Fr {
|
|
118
144
|
return Fr.random();
|
|
119
145
|
}
|
|
120
146
|
|
|
121
|
-
public
|
|
147
|
+
public getUtilityContext(): UtilityContext {
|
|
122
148
|
return new UtilityContext(this.anchorBlockHeader, this.contractAddress);
|
|
123
149
|
}
|
|
124
150
|
|
|
@@ -129,7 +155,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
129
155
|
* @throws If the keys are not registered in the key store.
|
|
130
156
|
* @throws If scopes are defined and the account is not in the scopes.
|
|
131
157
|
*/
|
|
132
|
-
public async
|
|
158
|
+
public async getKeyValidationRequest(pkMHash: Fr): Promise<KeyValidationRequest> {
|
|
133
159
|
// If scopes are defined, check that the key belongs to an account in the scopes.
|
|
134
160
|
if (this.scopes !== 'ALL_SCOPES' && this.scopes.length > 0) {
|
|
135
161
|
let hasAccess = false;
|
|
@@ -152,7 +178,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
152
178
|
* @param noteHash - The note hash to find in the note hash tree.
|
|
153
179
|
* @returns The membership witness containing the leaf index and sibling path
|
|
154
180
|
*/
|
|
155
|
-
public
|
|
181
|
+
public getNoteHashMembershipWitness(
|
|
156
182
|
anchorBlockHash: BlockHash,
|
|
157
183
|
noteHash: Fr,
|
|
158
184
|
): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT> | undefined> {
|
|
@@ -170,7 +196,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
170
196
|
* @param blockHash - The block hash to find in the archive tree.
|
|
171
197
|
* @returns The membership witness containing the leaf index and sibling path
|
|
172
198
|
*/
|
|
173
|
-
public
|
|
199
|
+
public getBlockHashMembershipWitness(
|
|
174
200
|
anchorBlockHash: BlockHash,
|
|
175
201
|
blockHash: BlockHash,
|
|
176
202
|
): Promise<MembershipWitness<typeof ARCHIVE_HEIGHT> | undefined> {
|
|
@@ -183,7 +209,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
183
209
|
* @param nullifier - Nullifier we try to find witness for.
|
|
184
210
|
* @returns The nullifier membership witness (if found).
|
|
185
211
|
*/
|
|
186
|
-
public
|
|
212
|
+
public getNullifierMembershipWitness(
|
|
187
213
|
blockHash: BlockHash,
|
|
188
214
|
nullifier: Fr,
|
|
189
215
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
@@ -199,7 +225,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
199
225
|
* list structure" of leaves and proving that a lower nullifier is pointing to a bigger next value than the nullifier
|
|
200
226
|
* we are trying to prove non-inclusion for.
|
|
201
227
|
*/
|
|
202
|
-
public
|
|
228
|
+
public getLowNullifierMembershipWitness(
|
|
203
229
|
blockHash: BlockHash,
|
|
204
230
|
nullifier: Fr,
|
|
205
231
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
@@ -212,7 +238,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
212
238
|
* @param leafSlot - The slot of the public data tree to get the witness for.
|
|
213
239
|
* @returns - The witness
|
|
214
240
|
*/
|
|
215
|
-
public
|
|
241
|
+
public getPublicDataWitness(blockHash: BlockHash, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
|
|
216
242
|
return this.aztecNode.getPublicDataWitness(blockHash, leafSlot);
|
|
217
243
|
}
|
|
218
244
|
|
|
@@ -221,7 +247,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
221
247
|
* @param blockNumber - The number of a block of which to get the block header.
|
|
222
248
|
* @returns Block extracted from a block with block number `blockNumber`.
|
|
223
249
|
*/
|
|
224
|
-
public async
|
|
250
|
+
public async getBlockHeader(blockNumber: BlockNumber): Promise<BlockHeader | undefined> {
|
|
225
251
|
const anchorBlockNumber = this.anchorBlockHeader.getBlockNumber();
|
|
226
252
|
if (blockNumber > anchorBlockNumber) {
|
|
227
253
|
throw new Error(`Block number ${blockNumber} is higher than current block ${anchorBlockNumber}`);
|
|
@@ -236,7 +262,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
236
262
|
* @param account - The account address.
|
|
237
263
|
* @returns The public keys and partial address, or `undefined` if the account is not registered.
|
|
238
264
|
*/
|
|
239
|
-
public async
|
|
265
|
+
public async tryGetPublicKeysAndPartialAddress(
|
|
240
266
|
account: AztecAddress,
|
|
241
267
|
): Promise<{ publicKeys: PublicKeys; partialAddress: PartialAddress } | undefined> {
|
|
242
268
|
const completeAddress = await this.addressStore.getCompleteAddress(account);
|
|
@@ -262,11 +288,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
262
288
|
* @param address - Address.
|
|
263
289
|
* @returns A contract instance.
|
|
264
290
|
*/
|
|
265
|
-
public
|
|
266
|
-
return this.getContractInstance(address);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
protected async getContractInstance(address: AztecAddress): Promise<ContractInstance> {
|
|
291
|
+
public async getContractInstance(address: AztecAddress): Promise<ContractInstance> {
|
|
270
292
|
const instance = await this.contractStore.getContractInstance(address);
|
|
271
293
|
if (!instance) {
|
|
272
294
|
throw new Error(`No contract instance found for address ${address.toString()}`);
|
|
@@ -280,7 +302,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
280
302
|
* @param messageHash - Hash of the message to authenticate.
|
|
281
303
|
* @returns Authentication witness for the requested message hash.
|
|
282
304
|
*/
|
|
283
|
-
public
|
|
305
|
+
public getAuthWitness(messageHash: Fr): Promise<Fr[] | undefined> {
|
|
284
306
|
return Promise.resolve(this.authWitnesses.find(w => w.requestHash.equals(messageHash))?.witness);
|
|
285
307
|
}
|
|
286
308
|
|
|
@@ -306,7 +328,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
306
328
|
* @param status - The status of notes to fetch.
|
|
307
329
|
* @returns Array of note data.
|
|
308
330
|
*/
|
|
309
|
-
public async
|
|
331
|
+
public async getNotes(
|
|
310
332
|
owner: AztecAddress | undefined,
|
|
311
333
|
storageSlot: Fr,
|
|
312
334
|
numSelects: number,
|
|
@@ -346,7 +368,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
346
368
|
* @param innerNullifier - The inner nullifier.
|
|
347
369
|
* @returns A boolean indicating whether the nullifier exists in the tree or not.
|
|
348
370
|
*/
|
|
349
|
-
public async
|
|
371
|
+
public async checkNullifierExists(innerNullifier: Fr) {
|
|
350
372
|
const [nullifier, anchorBlockHash] = await Promise.all([
|
|
351
373
|
siloNullifier(this.contractAddress, innerNullifier!),
|
|
352
374
|
this.anchorBlockHeader.hash(),
|
|
@@ -365,7 +387,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
365
387
|
* @dev Contract address and secret are only used to compute the nullifier to get non-nullified messages
|
|
366
388
|
* @returns The l1 to l2 membership witness (index of message in the tree and sibling path).
|
|
367
389
|
*/
|
|
368
|
-
public async
|
|
390
|
+
public async getL1ToL2MembershipWitness(contractAddress: AztecAddress, messageHash: Fr, secret: Fr) {
|
|
369
391
|
const [messageIndex, siblingPath] = await getNonNullifiedL1ToL2MessageWitness(
|
|
370
392
|
this.aztecNode,
|
|
371
393
|
contractAddress,
|
|
@@ -383,7 +405,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
383
405
|
* @param startStorageSlot - The starting storage slot.
|
|
384
406
|
* @param numberOfElements - Number of elements to read from the starting storage slot.
|
|
385
407
|
*/
|
|
386
|
-
public async
|
|
408
|
+
public async storageRead(
|
|
387
409
|
blockHash: BlockHash,
|
|
388
410
|
contractAddress: AztecAddress,
|
|
389
411
|
startStorageSlot: Fr,
|
|
@@ -397,7 +419,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
397
419
|
slots.map(storageSlot => this.aztecNode.getPublicStorageAt(blockHash, contractAddress, storageSlot)),
|
|
398
420
|
);
|
|
399
421
|
|
|
400
|
-
this.
|
|
422
|
+
this.logger.debug(
|
|
401
423
|
`Oracle storage read: slots=[${slots.map(slot => slot.toString()).join(', ')}] address=${contractAddress.toString()} values=[${values.join(', ')}]`,
|
|
402
424
|
);
|
|
403
425
|
|
|
@@ -420,7 +442,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
420
442
|
return this.contractLogger;
|
|
421
443
|
}
|
|
422
444
|
|
|
423
|
-
public async
|
|
445
|
+
public async log(level: number, message: string, fields: Fr[]): Promise<void> {
|
|
424
446
|
if (!LogLevels[level]) {
|
|
425
447
|
throw new Error(`Invalid log level: ${level}`);
|
|
426
448
|
}
|
|
@@ -428,7 +450,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
428
450
|
logContractMessage(logger, LogLevels[level], message, fields);
|
|
429
451
|
}
|
|
430
452
|
|
|
431
|
-
public async
|
|
453
|
+
public async fetchTaggedLogs(pendingTaggedLogArrayBaseSlot: Fr) {
|
|
432
454
|
const logService = new LogService(
|
|
433
455
|
this.aztecNode,
|
|
434
456
|
this.anchorBlockHeader,
|
|
@@ -438,7 +460,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
438
460
|
this.senderAddressBookStore,
|
|
439
461
|
this.addressStore,
|
|
440
462
|
this.jobId,
|
|
441
|
-
this.
|
|
463
|
+
this.logger.getBindings(),
|
|
442
464
|
);
|
|
443
465
|
|
|
444
466
|
await logService.fetchTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot, this.scopes);
|
|
@@ -454,10 +476,12 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
454
476
|
* @param noteValidationRequestsArrayBaseSlot - The base slot of capsule array containing note validation requests.
|
|
455
477
|
* @param eventValidationRequestsArrayBaseSlot - The base slot of capsule array containing event validation requests.
|
|
456
478
|
*/
|
|
457
|
-
public async
|
|
479
|
+
public async validateAndStoreEnqueuedNotesAndEvents(
|
|
458
480
|
contractAddress: AztecAddress,
|
|
459
481
|
noteValidationRequestsArrayBaseSlot: Fr,
|
|
460
482
|
eventValidationRequestsArrayBaseSlot: Fr,
|
|
483
|
+
maxNotePackedLen: number,
|
|
484
|
+
maxEventSerializedLen: number,
|
|
461
485
|
) {
|
|
462
486
|
// TODO(#10727): allow other contracts to store notes
|
|
463
487
|
if (!this.contractAddress.equals(contractAddress)) {
|
|
@@ -468,11 +492,11 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
468
492
|
// faster as we don't need to wait for the network round-trip.
|
|
469
493
|
const noteValidationRequests = (
|
|
470
494
|
await this.capsuleStore.readCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot, this.jobId)
|
|
471
|
-
).map(NoteValidationRequest.fromFields);
|
|
495
|
+
).map(fields => NoteValidationRequest.fromFields(fields, maxNotePackedLen));
|
|
472
496
|
|
|
473
497
|
const eventValidationRequests = (
|
|
474
498
|
await this.capsuleStore.readCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, this.jobId)
|
|
475
|
-
).map(EventValidationRequest.fromFields);
|
|
499
|
+
).map(fields => EventValidationRequest.fromFields(fields, maxEventSerializedLen));
|
|
476
500
|
|
|
477
501
|
const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockHeader, this.jobId);
|
|
478
502
|
const noteStorePromises = noteValidationRequests.map(request =>
|
|
@@ -510,7 +534,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
510
534
|
await this.capsuleStore.setCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, [], this.jobId);
|
|
511
535
|
}
|
|
512
536
|
|
|
513
|
-
public async
|
|
537
|
+
public async bulkRetrieveLogs(
|
|
514
538
|
contractAddress: AztecAddress,
|
|
515
539
|
logRetrievalRequestsArrayBaseSlot: Fr,
|
|
516
540
|
logRetrievalResponsesArrayBaseSlot: Fr,
|
|
@@ -535,7 +559,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
535
559
|
this.senderAddressBookStore,
|
|
536
560
|
this.addressStore,
|
|
537
561
|
this.jobId,
|
|
538
|
-
this.
|
|
562
|
+
this.logger.getBindings(),
|
|
539
563
|
);
|
|
540
564
|
|
|
541
565
|
const maybeLogRetrievalResponses = await logService.bulkRetrieveLogs(logRetrievalRequests);
|
|
@@ -552,7 +576,48 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
552
576
|
);
|
|
553
577
|
}
|
|
554
578
|
|
|
555
|
-
public
|
|
579
|
+
public async utilityResolveMessageContexts(
|
|
580
|
+
contractAddress: AztecAddress,
|
|
581
|
+
messageContextRequestsArrayBaseSlot: Fr,
|
|
582
|
+
messageContextResponsesArrayBaseSlot: Fr,
|
|
583
|
+
) {
|
|
584
|
+
try {
|
|
585
|
+
if (!this.contractAddress.equals(contractAddress)) {
|
|
586
|
+
throw new Error(`Got a message context request from ${contractAddress}, expected ${this.contractAddress}`);
|
|
587
|
+
}
|
|
588
|
+
const requestCapsules = await this.capsuleStore.readCapsuleArray(
|
|
589
|
+
contractAddress,
|
|
590
|
+
messageContextRequestsArrayBaseSlot,
|
|
591
|
+
this.jobId,
|
|
592
|
+
);
|
|
593
|
+
|
|
594
|
+
const txHashes = requestCapsules.map((fields, i) => {
|
|
595
|
+
if (fields.length !== 1) {
|
|
596
|
+
throw new Error(
|
|
597
|
+
`Malformed message context request at index ${i}: expected 1 field (tx hash), got ${fields.length}`,
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
return fields[0];
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
const maybeMessageContexts = await this.messageContextService.resolveMessageContexts(
|
|
604
|
+
txHashes,
|
|
605
|
+
this.anchorBlockHeader.getBlockNumber(),
|
|
606
|
+
);
|
|
607
|
+
|
|
608
|
+
// Leave response in response capsule array.
|
|
609
|
+
await this.capsuleStore.setCapsuleArray(
|
|
610
|
+
contractAddress,
|
|
611
|
+
messageContextResponsesArrayBaseSlot,
|
|
612
|
+
maybeMessageContexts.map(MessageTxContext.toSerializedOption),
|
|
613
|
+
this.jobId,
|
|
614
|
+
);
|
|
615
|
+
} finally {
|
|
616
|
+
await this.capsuleStore.setCapsuleArray(contractAddress, messageContextRequestsArrayBaseSlot, [], this.jobId);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
public storeCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[]): Promise<void> {
|
|
556
621
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
557
622
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
558
623
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
@@ -561,7 +626,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
561
626
|
return Promise.resolve();
|
|
562
627
|
}
|
|
563
628
|
|
|
564
|
-
public async
|
|
629
|
+
public async loadCapsule(contractAddress: AztecAddress, slot: Fr): Promise<Fr[] | null> {
|
|
565
630
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
566
631
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
567
632
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
@@ -573,7 +638,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
573
638
|
);
|
|
574
639
|
}
|
|
575
640
|
|
|
576
|
-
public
|
|
641
|
+
public deleteCapsule(contractAddress: AztecAddress, slot: Fr): Promise<void> {
|
|
577
642
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
578
643
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
579
644
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
@@ -582,12 +647,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
582
647
|
return Promise.resolve();
|
|
583
648
|
}
|
|
584
649
|
|
|
585
|
-
public
|
|
586
|
-
contractAddress: AztecAddress,
|
|
587
|
-
srcSlot: Fr,
|
|
588
|
-
dstSlot: Fr,
|
|
589
|
-
numEntries: number,
|
|
590
|
-
): Promise<void> {
|
|
650
|
+
public copyCapsule(contractAddress: AztecAddress, srcSlot: Fr, dstSlot: Fr, numEntries: number): Promise<void> {
|
|
591
651
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
592
652
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
593
653
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
@@ -595,8 +655,19 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
595
655
|
return this.capsuleStore.copyCapsule(this.contractAddress, srcSlot, dstSlot, numEntries, this.jobId);
|
|
596
656
|
}
|
|
597
657
|
|
|
658
|
+
/**
|
|
659
|
+
* Clears cached sync state for a contract for a set of scopes, forcing re-sync on the next query so that newly
|
|
660
|
+
* stored notes or events are discovered.
|
|
661
|
+
*/
|
|
662
|
+
public invalidateContractSyncCache(contractAddress: AztecAddress, scopes: AztecAddress[]): void {
|
|
663
|
+
if (!contractAddress.equals(this.contractAddress)) {
|
|
664
|
+
throw new Error(`Contract ${this.contractAddress} cannot invalidate sync cache of ${contractAddress}`);
|
|
665
|
+
}
|
|
666
|
+
this.contractSyncService.invalidateContractForScopes(contractAddress, scopes);
|
|
667
|
+
}
|
|
668
|
+
|
|
598
669
|
// TODO(#11849): consider replacing this oracle with a pure Noir implementation of aes decryption.
|
|
599
|
-
public
|
|
670
|
+
public aes128Decrypt(ciphertext: Buffer, iv: Buffer, symKey: Buffer): Promise<Buffer> {
|
|
600
671
|
const aes128 = new Aes128();
|
|
601
672
|
return aes128.decryptBufferCBC(ciphertext, iv, symKey);
|
|
602
673
|
}
|
|
@@ -607,11 +678,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
607
678
|
* @param ephPk - The ephemeral public key to get the secret for.
|
|
608
679
|
* @returns The secret for the given address.
|
|
609
680
|
*/
|
|
610
|
-
public
|
|
611
|
-
return this.getSharedSecret(address, ephPk);
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
protected async getSharedSecret(address: AztecAddress, ephPk: Point): Promise<Point> {
|
|
681
|
+
public async getSharedSecret(address: AztecAddress, ephPk: Point): Promise<Point> {
|
|
615
682
|
// TODO(#12656): return an app-siloed secret
|
|
616
683
|
const recipientCompleteAddress = await this.getCompleteAddressOrFail(address);
|
|
617
684
|
const ivskM = await this.keyStore.getMasterSecretKey(
|
|
@@ -620,4 +687,14 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
620
687
|
const addressSecret = await computeAddressSecret(await recipientCompleteAddress.getPreaddress(), ivskM);
|
|
621
688
|
return deriveEcdhSharedSecret(addressSecret, ephPk);
|
|
622
689
|
}
|
|
690
|
+
|
|
691
|
+
public emitOffchainEffect(data: Fr[]): Promise<void> {
|
|
692
|
+
this.offchainEffects.push({ data, contractAddress: this.contractAddress });
|
|
693
|
+
return Promise.resolve();
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/** Returns offchain effects collected during execution. */
|
|
697
|
+
public getOffchainEffects(): OffchainEffect[] {
|
|
698
|
+
return this.offchainEffects;
|
|
699
|
+
}
|
|
623
700
|
}
|
|
@@ -20,12 +20,12 @@ export class ContractSyncService implements StagedStore {
|
|
|
20
20
|
readonly storeName = 'contract_sync';
|
|
21
21
|
|
|
22
22
|
// Tracks contracts synced since last wipe. The cache is keyed per individual scope address
|
|
23
|
-
// (`contractAddress:scopeAddress`), or `contractAddress:*` for
|
|
23
|
+
// (`contractAddress:scopeAddress`), or `contractAddress:*` for all scopes (all accounts).
|
|
24
24
|
// The value is a promise that resolves when the contract is synced.
|
|
25
25
|
private syncedContracts: Map<string, Promise<void>> = new Map();
|
|
26
26
|
|
|
27
|
-
// Per-job
|
|
28
|
-
private
|
|
27
|
+
// Per-job excluded contract addresses - these contracts should not be synced.
|
|
28
|
+
private excludedFromSync: Map<string, Set<string>> = new Map();
|
|
29
29
|
|
|
30
30
|
constructor(
|
|
31
31
|
private aztecNode: AztecNode,
|
|
@@ -35,8 +35,8 @@ export class ContractSyncService implements StagedStore {
|
|
|
35
35
|
) {}
|
|
36
36
|
|
|
37
37
|
/** Sets contracts that should be skipped during sync for a specific job. */
|
|
38
|
-
|
|
39
|
-
this.
|
|
38
|
+
setExcludedFromSync(jobId: string, addresses: Set<string>): void {
|
|
39
|
+
this.excludedFromSync.set(jobId, addresses);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
/**
|
|
@@ -56,47 +56,34 @@ export class ContractSyncService implements StagedStore {
|
|
|
56
56
|
jobId: string,
|
|
57
57
|
scopes: AccessScopes,
|
|
58
58
|
): Promise<void> {
|
|
59
|
-
|
|
60
|
-
const overrides = this.overriddenContracts.get(jobId);
|
|
61
|
-
if (overrides?.has(contractAddress.toString())) {
|
|
59
|
+
if (this.#shouldSkipSync(jobId, contractAddress)) {
|
|
62
60
|
return;
|
|
63
61
|
}
|
|
64
62
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const allScopesExisting = this.syncedContracts.get(allScopesKey);
|
|
68
|
-
if (allScopesExisting || (scopes !== 'ALL_SCOPES' && scopes.length == 0)) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const unsyncedScopes =
|
|
73
|
-
scopes === 'ALL_SCOPES'
|
|
74
|
-
? scopes
|
|
75
|
-
: scopes.filter(scope => !this.syncedContracts.has(toKey(contractAddress, scope)));
|
|
76
|
-
const unsyncedScopesKeys = toKeys(contractAddress, unsyncedScopes);
|
|
77
|
-
|
|
78
|
-
if (unsyncedScopesKeys.length > 0) {
|
|
79
|
-
// Start sync and store the promise for all unsynced scopes
|
|
80
|
-
const promise = this.#doSync(
|
|
63
|
+
this.#startSyncIfNeeded(contractAddress, scopes, scopesToSync =>
|
|
64
|
+
this.#syncContract(
|
|
81
65
|
contractAddress,
|
|
82
66
|
functionToInvokeAfterSync,
|
|
83
67
|
utilityExecutor,
|
|
84
68
|
anchorBlockHeader,
|
|
85
69
|
jobId,
|
|
86
|
-
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
unsyncedScopesKeys.forEach(key => this.syncedContracts.delete(key));
|
|
90
|
-
throw err;
|
|
91
|
-
});
|
|
92
|
-
unsyncedScopesKeys.forEach(key => this.syncedContracts.set(key, promise));
|
|
93
|
-
}
|
|
70
|
+
scopesToSync,
|
|
71
|
+
),
|
|
72
|
+
);
|
|
94
73
|
|
|
95
|
-
|
|
96
|
-
await Promise.all(promises);
|
|
74
|
+
await this.#awaitSync(contractAddress, scopes);
|
|
97
75
|
}
|
|
98
76
|
|
|
99
|
-
|
|
77
|
+
/** Clears sync cache entries for the given scopes of a contract. Also clears the ALL_SCOPES entry. */
|
|
78
|
+
invalidateContractForScopes(contractAddress: AztecAddress, scopes: AztecAddress[]): void {
|
|
79
|
+
if (scopes.length === 0) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
scopes.forEach(scope => this.syncedContracts.delete(toKey(contractAddress, scope)));
|
|
83
|
+
this.syncedContracts.delete(toKey(contractAddress, 'ALL_SCOPES'));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async #syncContract(
|
|
100
87
|
contractAddress: AztecAddress,
|
|
101
88
|
functionToInvokeAfterSync: FunctionSelector | null,
|
|
102
89
|
utilityExecutor: (call: FunctionCall, scopes: AccessScopes) => Promise<any>,
|
|
@@ -129,8 +116,8 @@ export class ContractSyncService implements StagedStore {
|
|
|
129
116
|
}
|
|
130
117
|
|
|
131
118
|
commit(jobId: string): Promise<void> {
|
|
132
|
-
// Clear
|
|
133
|
-
this.
|
|
119
|
+
// Clear excluded contracts for this job
|
|
120
|
+
this.excludedFromSync.delete(jobId);
|
|
134
121
|
return Promise.resolve();
|
|
135
122
|
}
|
|
136
123
|
|
|
@@ -138,9 +125,51 @@ export class ContractSyncService implements StagedStore {
|
|
|
138
125
|
// We clear the synced contracts cache here because, when the job is discarded, any associated database writes from
|
|
139
126
|
// the sync are also undone.
|
|
140
127
|
this.syncedContracts.clear();
|
|
141
|
-
this.
|
|
128
|
+
this.excludedFromSync.delete(jobId);
|
|
142
129
|
return Promise.resolve();
|
|
143
130
|
}
|
|
131
|
+
/** Returns true if sync should be skipped for this contract */
|
|
132
|
+
#shouldSkipSync(jobId: string, contractAddress: AztecAddress): boolean {
|
|
133
|
+
return !!this.excludedFromSync.get(jobId)?.has(contractAddress.toString());
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** If there are unsynced scopes, starts sync and stores the promise in cache with error cleanup. */
|
|
137
|
+
#startSyncIfNeeded(
|
|
138
|
+
contractAddress: AztecAddress,
|
|
139
|
+
scopes: AccessScopes,
|
|
140
|
+
syncFn: (scopesToSync: AccessScopes) => Promise<void>,
|
|
141
|
+
): void {
|
|
142
|
+
const scopesToSync = this.#getScopesToSync(contractAddress, scopes);
|
|
143
|
+
const keys = toKeys(contractAddress, scopesToSync);
|
|
144
|
+
if (keys.length === 0) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const promise = syncFn(scopesToSync).catch(err => {
|
|
148
|
+
keys.forEach(key => this.syncedContracts.delete(key));
|
|
149
|
+
throw err;
|
|
150
|
+
});
|
|
151
|
+
keys.forEach(key => this.syncedContracts.set(key, promise));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Filters out scopes that are already cached, returning only those that still need syncing. */
|
|
155
|
+
#getScopesToSync(contractAddress: AztecAddress, scopes: AccessScopes): AccessScopes {
|
|
156
|
+
if (this.syncedContracts.has(toKey(contractAddress, 'ALL_SCOPES'))) {
|
|
157
|
+
// If we are already syncing all scopes, then return an empty list
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
if (scopes === 'ALL_SCOPES') {
|
|
161
|
+
return 'ALL_SCOPES';
|
|
162
|
+
}
|
|
163
|
+
return scopes.filter(scope => !this.syncedContracts.has(toKey(contractAddress, scope)));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Collects all relevant scope promises (including in-flight ones from concurrent calls) and awaits them. */
|
|
167
|
+
async #awaitSync(contractAddress: AztecAddress, scopes: AccessScopes): Promise<void> {
|
|
168
|
+
const promises = toKeys(contractAddress, scopes)
|
|
169
|
+
.map(key => this.syncedContracts.get(key))
|
|
170
|
+
.filter(p => p !== undefined);
|
|
171
|
+
await Promise.all(promises);
|
|
172
|
+
}
|
|
144
173
|
}
|
|
145
174
|
|
|
146
175
|
function toKeys(contract: AztecAddress, scopes: AccessScopes) {
|
|
@@ -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
|
+
}
|
package/src/oracle_version.ts
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
/// to version the oracle interface to ensure that developers get a reasonable error message if they use incompatible
|
|
3
3
|
/// versions of Aztec.nr and PXE. The Noir counterpart is in `noir-projects/aztec-nr/aztec/src/oracle/version.nr`.
|
|
4
4
|
///
|
|
5
|
-
/// @dev Whenever a contract function or Noir test is run, the `
|
|
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 =
|
|
7
|
+
export const ORACLE_VERSION = 18;
|
|
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 = '
|
|
12
|
+
export const ORACLE_INTERFACE_HASH = '57e5b07c6d55fb167ef90f8d0f410f9bdb5b154a31159c624a061be40b02a2c2';
|