@aztec/pxe 0.0.1-commit.9ee6fcc6 → 0.0.1-commit.9ef841308
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/block_synchronizer/block_synchronizer.d.ts +1 -1
- package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
- package/dest/block_synchronizer/block_synchronizer.js +6 -0
- package/dest/contract_function_simulator/contract_function_simulator.d.ts +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.js +4 -3
- 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 +2 -5
- package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +2 -3
- 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 +2 -5
- package/dest/contract_function_simulator/oracle/interfaces.d.ts +19 -19
- package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts +1 -1
- package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.js +18 -22
- package/dest/contract_function_simulator/oracle/oracle.d.ts +38 -19
- package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/oracle.js +60 -39
- package/dest/contract_function_simulator/oracle/private_execution.js +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +6 -6
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.js +7 -7
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +28 -26
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +108 -69
- package/dest/contract_logging.d.ts +9 -4
- package/dest/contract_logging.d.ts.map +1 -1
- package/dest/contract_logging.js +21 -6
- package/dest/contract_sync/contract_sync_service.d.ts +3 -2
- package/dest/contract_sync/contract_sync_service.d.ts.map +1 -1
- package/dest/contract_sync/contract_sync_service.js +12 -2
- package/dest/contract_sync/helpers.d.ts +2 -2
- package/dest/contract_sync/helpers.d.ts.map +1 -1
- package/dest/contract_sync/helpers.js +7 -2
- package/dest/events/event_service.d.ts +3 -2
- package/dest/events/event_service.d.ts.map +1 -1
- package/dest/events/event_service.js +16 -4
- package/dest/logs/log_service.d.ts +6 -7
- package/dest/logs/log_service.d.ts.map +1 -1
- package/dest/logs/log_service.js +24 -28
- package/dest/messages/message_context_service.d.ts +3 -3
- package/dest/messages/message_context_service.d.ts.map +1 -1
- package/dest/messages/message_context_service.js +3 -3
- package/dest/notes/note_service.d.ts +2 -2
- package/dest/notes/note_service.d.ts.map +1 -1
- package/dest/notes/note_service.js +14 -5
- package/dest/oracle_version.d.ts +2 -2
- package/dest/oracle_version.js +2 -2
- package/dest/pxe.d.ts +1 -1
- package/dest/pxe.d.ts.map +1 -1
- package/dest/pxe.js +4 -2
- package/dest/storage/capsule_store/capsule_service.d.ts +22 -0
- package/dest/storage/capsule_store/capsule_service.d.ts.map +1 -0
- package/dest/storage/capsule_store/capsule_service.js +50 -0
- package/dest/storage/capsule_store/capsule_store.d.ts +9 -9
- package/dest/storage/capsule_store/capsule_store.d.ts.map +1 -1
- package/dest/storage/capsule_store/capsule_store.js +33 -28
- package/dest/storage/capsule_store/index.d.ts +2 -1
- package/dest/storage/capsule_store/index.d.ts.map +1 -1
- package/dest/storage/capsule_store/index.js +1 -0
- package/dest/storage/metadata.d.ts +1 -1
- package/dest/storage/metadata.js +1 -1
- package/package.json +16 -16
- package/src/block_synchronizer/block_synchronizer.ts +6 -0
- package/src/contract_function_simulator/contract_function_simulator.ts +4 -3
- package/src/contract_function_simulator/noir-structs/event_validation_request.ts +0 -3
- package/src/contract_function_simulator/noir-structs/note_validation_request.ts +0 -3
- package/src/contract_function_simulator/oracle/interfaces.ts +26 -17
- package/src/contract_function_simulator/oracle/legacy_oracle_mappings.ts +13 -50
- package/src/contract_function_simulator/oracle/oracle.ts +79 -33
- package/src/contract_function_simulator/oracle/private_execution.ts +1 -1
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +7 -7
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +195 -78
- package/src/contract_logging.ts +18 -5
- package/src/contract_sync/contract_sync_service.ts +22 -11
- package/src/contract_sync/helpers.ts +3 -2
- package/src/events/event_service.ts +17 -4
- package/src/logs/log_service.ts +51 -46
- package/src/messages/message_context_service.ts +3 -4
- package/src/notes/note_service.ts +16 -5
- package/src/oracle_version.ts +2 -2
- package/src/pxe.ts +4 -1
- package/src/storage/capsule_store/capsule_service.ts +91 -0
- package/src/storage/capsule_store/capsule_store.ts +34 -26
- package/src/storage/capsule_store/index.ts +1 -0
- package/src/storage/metadata.ts +1 -1
- package/dest/contract_function_simulator/noir-structs/message_tx_context.d.ts +0 -16
- package/dest/contract_function_simulator/noir-structs/message_tx_context.d.ts.map +0 -1
- package/dest/contract_function_simulator/noir-structs/message_tx_context.js +0 -57
- package/src/contract_function_simulator/noir-structs/message_tx_context.ts +0 -55
|
@@ -15,14 +15,14 @@ import { siloNullifier } from '@aztec/stdlib/hash';
|
|
|
15
15
|
import type { AztecNode } from '@aztec/stdlib/interfaces/server';
|
|
16
16
|
import type { KeyValidationRequest } from '@aztec/stdlib/kernel';
|
|
17
17
|
import { type PublicKeys, computeAddressSecret } from '@aztec/stdlib/keys';
|
|
18
|
-
import {
|
|
18
|
+
import { MessageContext, deriveAppSiloedSharedSecret } from '@aztec/stdlib/logs';
|
|
19
19
|
import { getNonNullifiedL1ToL2MessageWitness } from '@aztec/stdlib/messaging';
|
|
20
20
|
import type { NoteStatus } from '@aztec/stdlib/note';
|
|
21
21
|
import { MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
|
|
22
22
|
import type { BlockHeader, Capsule, OffchainEffect } from '@aztec/stdlib/tx';
|
|
23
23
|
|
|
24
24
|
import type { AccessScopes } from '../../access_scopes.js';
|
|
25
|
-
import { createContractLogger, logContractMessage } from '../../contract_logging.js';
|
|
25
|
+
import { createContractLogger, logContractMessage, stripAztecnrLogPrefix } from '../../contract_logging.js';
|
|
26
26
|
import type { ContractSyncService } from '../../contract_sync/contract_sync_service.js';
|
|
27
27
|
import { EventService } from '../../events/event_service.js';
|
|
28
28
|
import { LogService } from '../../logs/log_service.js';
|
|
@@ -30,7 +30,7 @@ import { MessageContextService } from '../../messages/message_context_service.js
|
|
|
30
30
|
import { NoteService } from '../../notes/note_service.js';
|
|
31
31
|
import { ORACLE_VERSION } from '../../oracle_version.js';
|
|
32
32
|
import type { AddressStore } from '../../storage/address_store/address_store.js';
|
|
33
|
-
import type {
|
|
33
|
+
import type { CapsuleService } from '../../storage/capsule_store/capsule_service.js';
|
|
34
34
|
import type { ContractStore } from '../../storage/contract_store/contract_store.js';
|
|
35
35
|
import type { NoteStore } from '../../storage/note_store/note_store.js';
|
|
36
36
|
import type { PrivateEventStore } from '../../storage/private_event_store/private_event_store.js';
|
|
@@ -39,7 +39,6 @@ import type { SenderAddressBookStore } from '../../storage/tagging_store/sender_
|
|
|
39
39
|
import { EventValidationRequest } from '../noir-structs/event_validation_request.js';
|
|
40
40
|
import { LogRetrievalRequest } from '../noir-structs/log_retrieval_request.js';
|
|
41
41
|
import { LogRetrievalResponse } from '../noir-structs/log_retrieval_response.js';
|
|
42
|
-
import { MessageTxContext } from '../noir-structs/message_tx_context.js';
|
|
43
42
|
import { NoteValidationRequest } from '../noir-structs/note_validation_request.js';
|
|
44
43
|
import { UtilityContext } from '../noir-structs/utility_context.js';
|
|
45
44
|
import { pickNotes } from '../pick_notes.js';
|
|
@@ -60,7 +59,7 @@ export type UtilityExecutionOracleArgs = {
|
|
|
60
59
|
aztecNode: AztecNode;
|
|
61
60
|
recipientTaggingStore: RecipientTaggingStore;
|
|
62
61
|
senderAddressBookStore: SenderAddressBookStore;
|
|
63
|
-
|
|
62
|
+
capsuleService: CapsuleService;
|
|
64
63
|
privateEventStore: PrivateEventStore;
|
|
65
64
|
messageContextService: MessageContextService;
|
|
66
65
|
contractSyncService: ContractSyncService;
|
|
@@ -77,6 +76,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
77
76
|
isUtility = true as const;
|
|
78
77
|
|
|
79
78
|
private contractLogger: Logger | undefined;
|
|
79
|
+
private aztecnrLogger: Logger | undefined;
|
|
80
80
|
private offchainEffects: OffchainEffect[] = [];
|
|
81
81
|
|
|
82
82
|
protected readonly contractAddress: AztecAddress;
|
|
@@ -90,7 +90,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
90
90
|
protected readonly aztecNode: AztecNode;
|
|
91
91
|
protected readonly recipientTaggingStore: RecipientTaggingStore;
|
|
92
92
|
protected readonly senderAddressBookStore: SenderAddressBookStore;
|
|
93
|
-
protected readonly
|
|
93
|
+
protected readonly capsuleService: CapsuleService;
|
|
94
94
|
protected readonly privateEventStore: PrivateEventStore;
|
|
95
95
|
protected readonly messageContextService: MessageContextService;
|
|
96
96
|
protected readonly contractSyncService: ContractSyncService;
|
|
@@ -110,7 +110,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
110
110
|
this.aztecNode = args.aztecNode;
|
|
111
111
|
this.recipientTaggingStore = args.recipientTaggingStore;
|
|
112
112
|
this.senderAddressBookStore = args.senderAddressBookStore;
|
|
113
|
-
this.
|
|
113
|
+
this.capsuleService = args.capsuleService;
|
|
114
114
|
this.privateEventStore = args.privateEventStore;
|
|
115
115
|
this.messageContextService = args.messageContextService;
|
|
116
116
|
this.contractSyncService = args.contractSyncService;
|
|
@@ -128,15 +128,25 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
128
128
|
const LEGACY_ORACLE_VERSION = 12;
|
|
129
129
|
if (isProtocolContract(this.contractAddress)) {
|
|
130
130
|
if (version !== LEGACY_ORACLE_VERSION && version !== ORACLE_VERSION) {
|
|
131
|
+
const hint =
|
|
132
|
+
version > ORACLE_VERSION
|
|
133
|
+
? 'The contract was compiled with a newer version of Aztec.nr than your private environment supports. Upgrade your private environment to a compatible version.'
|
|
134
|
+
: 'The contract was compiled with an older version of Aztec.nr than your private environment supports. Recompile the contract with a compatible version of Aztec.nr.';
|
|
131
135
|
throw new Error(
|
|
132
|
-
`
|
|
136
|
+
`Incompatible private environment version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle version ${LEGACY_ORACLE_VERSION} or ${ORACLE_VERSION}, got ${version})`,
|
|
133
137
|
);
|
|
134
138
|
}
|
|
135
139
|
return;
|
|
136
140
|
}
|
|
137
141
|
|
|
138
142
|
if (version !== ORACLE_VERSION) {
|
|
139
|
-
|
|
143
|
+
const hint =
|
|
144
|
+
version > ORACLE_VERSION
|
|
145
|
+
? 'The contract was compiled with a newer version of Aztec.nr than your private environment supports. Upgrade your private environment to a compatible version.'
|
|
146
|
+
: 'The contract was compiled with an older version of Aztec.nr than your private environment supports. Recompile the contract with a compatible version of Aztec.nr.';
|
|
147
|
+
throw new Error(
|
|
148
|
+
`Incompatible private environment version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle version ${ORACLE_VERSION}, got ${version})`,
|
|
149
|
+
);
|
|
140
150
|
}
|
|
141
151
|
}
|
|
142
152
|
|
|
@@ -173,16 +183,18 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
173
183
|
|
|
174
184
|
/**
|
|
175
185
|
* Fetches the index and sibling path of a leaf at a given block from the note hash tree.
|
|
176
|
-
* @param
|
|
177
|
-
* witness.
|
|
186
|
+
* @param blockHash - The hash of a block that contains the note hash tree root in which to find the
|
|
187
|
+
* membership witness.
|
|
178
188
|
* @param noteHash - The note hash to find in the note hash tree.
|
|
179
189
|
* @returns The membership witness containing the leaf index and sibling path
|
|
180
190
|
*/
|
|
181
191
|
public getNoteHashMembershipWitness(
|
|
182
|
-
|
|
192
|
+
blockHash: BlockHash,
|
|
183
193
|
noteHash: Fr,
|
|
184
194
|
): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT> | undefined> {
|
|
185
|
-
return this
|
|
195
|
+
return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
|
|
196
|
+
this.aztecNode.getNoteHashMembershipWitness(blockHash, noteHash),
|
|
197
|
+
);
|
|
186
198
|
}
|
|
187
199
|
|
|
188
200
|
/**
|
|
@@ -191,16 +203,21 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
191
203
|
* Block hashes are the leaves of the archive tree. Each time a new block is added to the chain,
|
|
192
204
|
* its block hash is appended as a new leaf to the archive tree.
|
|
193
205
|
*
|
|
194
|
-
* @param
|
|
206
|
+
* @param referenceBlockHash - The hash of a block that contains the archive tree root in which to find the membership
|
|
195
207
|
* witness.
|
|
196
208
|
* @param blockHash - The block hash to find in the archive tree.
|
|
197
209
|
* @returns The membership witness containing the leaf index and sibling path
|
|
198
210
|
*/
|
|
199
211
|
public getBlockHashMembershipWitness(
|
|
200
|
-
|
|
212
|
+
referenceBlockHash: BlockHash,
|
|
201
213
|
blockHash: BlockHash,
|
|
202
214
|
): Promise<MembershipWitness<typeof ARCHIVE_HEIGHT> | undefined> {
|
|
203
|
-
|
|
215
|
+
// Note that we validate that the reference block hash is at or before the anchor block - we don't test the block
|
|
216
|
+
// hash at all. If the block hash did not exist by the reference block hash, then the node will not return the
|
|
217
|
+
// membership witness as there is none.
|
|
218
|
+
return this.#queryWithBlockHashNotAfterAnchor(referenceBlockHash, () =>
|
|
219
|
+
this.aztecNode.getBlockHashMembershipWitness(referenceBlockHash, blockHash),
|
|
220
|
+
);
|
|
204
221
|
}
|
|
205
222
|
|
|
206
223
|
/**
|
|
@@ -213,7 +230,9 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
213
230
|
blockHash: BlockHash,
|
|
214
231
|
nullifier: Fr,
|
|
215
232
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
216
|
-
return this
|
|
233
|
+
return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
|
|
234
|
+
this.aztecNode.getNullifierMembershipWitness(blockHash, nullifier),
|
|
235
|
+
);
|
|
217
236
|
}
|
|
218
237
|
|
|
219
238
|
/**
|
|
@@ -229,7 +248,9 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
229
248
|
blockHash: BlockHash,
|
|
230
249
|
nullifier: Fr,
|
|
231
250
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
232
|
-
return this
|
|
251
|
+
return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
|
|
252
|
+
this.aztecNode.getLowNullifierMembershipWitness(blockHash, nullifier),
|
|
253
|
+
);
|
|
233
254
|
}
|
|
234
255
|
|
|
235
256
|
/**
|
|
@@ -239,7 +260,9 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
239
260
|
* @returns - The witness
|
|
240
261
|
*/
|
|
241
262
|
public getPublicDataWitness(blockHash: BlockHash, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
|
|
242
|
-
return this
|
|
263
|
+
return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
|
|
264
|
+
this.aztecNode.getPublicDataWitness(blockHash, leafSlot),
|
|
265
|
+
);
|
|
243
266
|
}
|
|
244
267
|
|
|
245
268
|
/**
|
|
@@ -262,7 +285,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
262
285
|
* @param account - The account address.
|
|
263
286
|
* @returns The public keys and partial address, or `undefined` if the account is not registered.
|
|
264
287
|
*/
|
|
265
|
-
public async
|
|
288
|
+
public async getPublicKeysAndPartialAddress(
|
|
266
289
|
account: AztecAddress,
|
|
267
290
|
): Promise<{ publicKeys: PublicKeys; partialAddress: PartialAddress } | undefined> {
|
|
268
291
|
const completeAddress = await this.addressStore.getCompleteAddress(account);
|
|
@@ -368,7 +391,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
368
391
|
* @param innerNullifier - The inner nullifier.
|
|
369
392
|
* @returns A boolean indicating whether the nullifier exists in the tree or not.
|
|
370
393
|
*/
|
|
371
|
-
public async
|
|
394
|
+
public async doesNullifierExist(innerNullifier: Fr) {
|
|
372
395
|
const [nullifier, anchorBlockHash] = await Promise.all([
|
|
373
396
|
siloNullifier(this.contractAddress, innerNullifier!),
|
|
374
397
|
this.anchorBlockHeader.hash(),
|
|
@@ -380,7 +403,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
380
403
|
}
|
|
381
404
|
|
|
382
405
|
/**
|
|
383
|
-
*
|
|
406
|
+
* Returns the membership witness of an un-nullified L1 to L2 message.
|
|
384
407
|
* @param contractAddress - Address of a contract by which the message was emitted.
|
|
385
408
|
* @param messageHash - Hash of the message.
|
|
386
409
|
* @param secret - Secret used to compute a nullifier.
|
|
@@ -393,6 +416,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
393
416
|
contractAddress,
|
|
394
417
|
messageHash,
|
|
395
418
|
secret,
|
|
419
|
+
await this.anchorBlockHeader.hash(),
|
|
396
420
|
);
|
|
397
421
|
|
|
398
422
|
return new MessageLoadOracleInputs(messageIndex, siblingPath);
|
|
@@ -405,29 +429,31 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
405
429
|
* @param startStorageSlot - The starting storage slot.
|
|
406
430
|
* @param numberOfElements - Number of elements to read from the starting storage slot.
|
|
407
431
|
*/
|
|
408
|
-
public
|
|
432
|
+
public getFromPublicStorage(
|
|
409
433
|
blockHash: BlockHash,
|
|
410
434
|
contractAddress: AztecAddress,
|
|
411
435
|
startStorageSlot: Fr,
|
|
412
436
|
numberOfElements: number,
|
|
413
437
|
) {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
438
|
+
return this.#queryWithBlockHashNotAfterAnchor(blockHash, async () => {
|
|
439
|
+
const slots = Array(numberOfElements)
|
|
440
|
+
.fill(0)
|
|
441
|
+
.map((_, i) => new Fr(startStorageSlot.value + BigInt(i)));
|
|
417
442
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
443
|
+
const values = await Promise.all(
|
|
444
|
+
slots.map(storageSlot => this.aztecNode.getPublicStorageAt(blockHash, contractAddress, storageSlot)),
|
|
445
|
+
);
|
|
421
446
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
447
|
+
this.logger.debug(
|
|
448
|
+
`Oracle storage read: slots=[${slots.map(slot => slot.toString()).join(', ')}] address=${contractAddress.toString()} values=[${values.join(', ')}]`,
|
|
449
|
+
);
|
|
425
450
|
|
|
426
|
-
|
|
451
|
+
return values;
|
|
452
|
+
});
|
|
427
453
|
}
|
|
428
454
|
|
|
429
455
|
/**
|
|
430
|
-
* Returns a per-contract logger whose output is prefixed with `
|
|
456
|
+
* Returns a per-contract logger whose output is prefixed with `contract:<name>(<addrAbbrev>)`.
|
|
431
457
|
*/
|
|
432
458
|
async #getContractLogger(): Promise<Logger> {
|
|
433
459
|
if (!this.contractLogger) {
|
|
@@ -436,26 +462,47 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
436
462
|
this.contractLogger = await createContractLogger(
|
|
437
463
|
this.contractAddress,
|
|
438
464
|
addr => this.contractStore.getDebugContractName(addr),
|
|
465
|
+
'user',
|
|
439
466
|
{ instanceId: this.jobId },
|
|
440
467
|
);
|
|
441
468
|
}
|
|
442
469
|
return this.contractLogger;
|
|
443
470
|
}
|
|
444
471
|
|
|
472
|
+
/**
|
|
473
|
+
* Returns a per-contract logger whose output is prefixed with `aztecnr:<name>(<addrAbbrev>)`.
|
|
474
|
+
*/
|
|
475
|
+
async #getAztecnrLogger(): Promise<Logger> {
|
|
476
|
+
if (!this.aztecnrLogger) {
|
|
477
|
+
// Purpose of instanceId is to distinguish logs from different instances of the same component. It makes sense
|
|
478
|
+
// to re-use jobId as instanceId here as executions of different PXE jobs are isolated.
|
|
479
|
+
this.aztecnrLogger = await createContractLogger(
|
|
480
|
+
this.contractAddress,
|
|
481
|
+
addr => this.contractStore.getDebugContractName(addr),
|
|
482
|
+
'aztecnr',
|
|
483
|
+
{ instanceId: this.jobId },
|
|
484
|
+
);
|
|
485
|
+
}
|
|
486
|
+
return this.aztecnrLogger;
|
|
487
|
+
}
|
|
488
|
+
|
|
445
489
|
public async log(level: number, message: string, fields: Fr[]): Promise<void> {
|
|
446
490
|
if (!LogLevels[level]) {
|
|
447
491
|
throw new Error(`Invalid log level: ${level}`);
|
|
448
492
|
}
|
|
449
|
-
|
|
450
|
-
|
|
493
|
+
|
|
494
|
+
const { kind, message: strippedMessage } = stripAztecnrLogPrefix(message);
|
|
495
|
+
|
|
496
|
+
const logger = kind == 'aztecnr' ? await this.#getAztecnrLogger() : await this.#getContractLogger();
|
|
497
|
+
logContractMessage(logger, LogLevels[level], strippedMessage, fields);
|
|
451
498
|
}
|
|
452
499
|
|
|
453
|
-
public async
|
|
500
|
+
public async getPendingTaggedLogs(pendingTaggedLogArrayBaseSlot: Fr, scope: AztecAddress) {
|
|
454
501
|
const logService = new LogService(
|
|
455
502
|
this.aztecNode,
|
|
456
503
|
this.anchorBlockHeader,
|
|
457
504
|
this.keyStore,
|
|
458
|
-
this.
|
|
505
|
+
this.capsuleService,
|
|
459
506
|
this.recipientTaggingStore,
|
|
460
507
|
this.senderAddressBookStore,
|
|
461
508
|
this.addressStore,
|
|
@@ -463,7 +510,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
463
510
|
this.logger.getBindings(),
|
|
464
511
|
);
|
|
465
512
|
|
|
466
|
-
await logService.fetchTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot,
|
|
513
|
+
await logService.fetchTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot, scope);
|
|
467
514
|
}
|
|
468
515
|
|
|
469
516
|
/**
|
|
@@ -482,6 +529,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
482
529
|
eventValidationRequestsArrayBaseSlot: Fr,
|
|
483
530
|
maxNotePackedLen: number,
|
|
484
531
|
maxEventSerializedLen: number,
|
|
532
|
+
scope: AztecAddress,
|
|
485
533
|
) {
|
|
486
534
|
// TODO(#10727): allow other contracts to store notes
|
|
487
535
|
if (!this.contractAddress.equals(contractAddress)) {
|
|
@@ -491,11 +539,21 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
491
539
|
// We read all note and event validation requests and process them all concurrently. This makes the process much
|
|
492
540
|
// faster as we don't need to wait for the network round-trip.
|
|
493
541
|
const noteValidationRequests = (
|
|
494
|
-
await this.
|
|
542
|
+
await this.capsuleService.readCapsuleArray(
|
|
543
|
+
contractAddress,
|
|
544
|
+
noteValidationRequestsArrayBaseSlot,
|
|
545
|
+
this.jobId,
|
|
546
|
+
scope,
|
|
547
|
+
)
|
|
495
548
|
).map(fields => NoteValidationRequest.fromFields(fields, maxNotePackedLen));
|
|
496
549
|
|
|
497
550
|
const eventValidationRequests = (
|
|
498
|
-
await this.
|
|
551
|
+
await this.capsuleService.readCapsuleArray(
|
|
552
|
+
contractAddress,
|
|
553
|
+
eventValidationRequestsArrayBaseSlot,
|
|
554
|
+
this.jobId,
|
|
555
|
+
scope,
|
|
556
|
+
)
|
|
499
557
|
).map(fields => EventValidationRequest.fromFields(fields, maxEventSerializedLen));
|
|
500
558
|
|
|
501
559
|
const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockHeader, this.jobId);
|
|
@@ -510,7 +568,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
510
568
|
request.noteHash,
|
|
511
569
|
request.nullifier,
|
|
512
570
|
request.txHash,
|
|
513
|
-
|
|
571
|
+
scope,
|
|
514
572
|
),
|
|
515
573
|
);
|
|
516
574
|
|
|
@@ -523,21 +581,34 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
523
581
|
request.serializedEvent,
|
|
524
582
|
request.eventCommitment,
|
|
525
583
|
request.txHash,
|
|
526
|
-
|
|
584
|
+
scope,
|
|
527
585
|
),
|
|
528
586
|
);
|
|
529
587
|
|
|
530
588
|
await Promise.all([...noteStorePromises, ...eventStorePromises]);
|
|
531
589
|
|
|
532
590
|
// Requests are cleared once we're done.
|
|
533
|
-
await this.
|
|
534
|
-
|
|
591
|
+
await this.capsuleService.setCapsuleArray(
|
|
592
|
+
contractAddress,
|
|
593
|
+
noteValidationRequestsArrayBaseSlot,
|
|
594
|
+
[],
|
|
595
|
+
this.jobId,
|
|
596
|
+
scope,
|
|
597
|
+
);
|
|
598
|
+
await this.capsuleService.setCapsuleArray(
|
|
599
|
+
contractAddress,
|
|
600
|
+
eventValidationRequestsArrayBaseSlot,
|
|
601
|
+
[],
|
|
602
|
+
this.jobId,
|
|
603
|
+
scope,
|
|
604
|
+
);
|
|
535
605
|
}
|
|
536
606
|
|
|
537
|
-
public async
|
|
607
|
+
public async getLogsByTag(
|
|
538
608
|
contractAddress: AztecAddress,
|
|
539
609
|
logRetrievalRequestsArrayBaseSlot: Fr,
|
|
540
610
|
logRetrievalResponsesArrayBaseSlot: Fr,
|
|
611
|
+
scope: AztecAddress,
|
|
541
612
|
) {
|
|
542
613
|
// TODO(#10727): allow other contracts to process partial notes
|
|
543
614
|
if (!this.contractAddress.equals(contractAddress)) {
|
|
@@ -547,14 +618,14 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
547
618
|
// We read all log retrieval requests and process them all concurrently. This makes the process much faster as we
|
|
548
619
|
// don't need to wait for the network round-trip.
|
|
549
620
|
const logRetrievalRequests = (
|
|
550
|
-
await this.
|
|
621
|
+
await this.capsuleService.readCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, this.jobId, scope)
|
|
551
622
|
).map(LogRetrievalRequest.fromFields);
|
|
552
623
|
|
|
553
624
|
const logService = new LogService(
|
|
554
625
|
this.aztecNode,
|
|
555
626
|
this.anchorBlockHeader,
|
|
556
627
|
this.keyStore,
|
|
557
|
-
this.
|
|
628
|
+
this.capsuleService,
|
|
558
629
|
this.recipientTaggingStore,
|
|
559
630
|
this.senderAddressBookStore,
|
|
560
631
|
this.addressStore,
|
|
@@ -562,33 +633,47 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
562
633
|
this.logger.getBindings(),
|
|
563
634
|
);
|
|
564
635
|
|
|
565
|
-
const maybeLogRetrievalResponses = await logService.
|
|
636
|
+
const maybeLogRetrievalResponses = await logService.fetchLogsByTag(contractAddress, logRetrievalRequests);
|
|
566
637
|
|
|
567
638
|
// Requests are cleared once we're done.
|
|
568
|
-
await this.
|
|
639
|
+
await this.capsuleService.setCapsuleArray(
|
|
640
|
+
contractAddress,
|
|
641
|
+
logRetrievalRequestsArrayBaseSlot,
|
|
642
|
+
[],
|
|
643
|
+
this.jobId,
|
|
644
|
+
scope,
|
|
645
|
+
);
|
|
569
646
|
|
|
570
647
|
// The responses are stored as Option<LogRetrievalResponse> in a second CapsuleArray.
|
|
571
|
-
await this.
|
|
648
|
+
await this.capsuleService.setCapsuleArray(
|
|
572
649
|
contractAddress,
|
|
573
650
|
logRetrievalResponsesArrayBaseSlot,
|
|
574
651
|
maybeLogRetrievalResponses.map(LogRetrievalResponse.toSerializedOption),
|
|
575
652
|
this.jobId,
|
|
653
|
+
scope,
|
|
576
654
|
);
|
|
577
655
|
}
|
|
578
656
|
|
|
579
|
-
public async
|
|
657
|
+
public async getMessageContextsByTxHash(
|
|
580
658
|
contractAddress: AztecAddress,
|
|
581
659
|
messageContextRequestsArrayBaseSlot: Fr,
|
|
582
660
|
messageContextResponsesArrayBaseSlot: Fr,
|
|
661
|
+
scope: AztecAddress,
|
|
583
662
|
) {
|
|
584
663
|
try {
|
|
585
664
|
if (!this.contractAddress.equals(contractAddress)) {
|
|
586
665
|
throw new Error(`Got a message context request from ${contractAddress}, expected ${this.contractAddress}`);
|
|
587
666
|
}
|
|
588
|
-
|
|
667
|
+
|
|
668
|
+
// TODO(@mverzilli): this is a prime example of where using a volatile array would make much more sense, we don't
|
|
669
|
+
// need scopes here, we just need a bit of shared memory to cross boundaries between Noir and TS.
|
|
670
|
+
// At the same time, we don't want to allow any global scope access other than where backwards compatibility
|
|
671
|
+
// forces us to. Hence we need the scope here to be artificial.
|
|
672
|
+
const requestCapsules = await this.capsuleService.readCapsuleArray(
|
|
589
673
|
contractAddress,
|
|
590
674
|
messageContextRequestsArrayBaseSlot,
|
|
591
675
|
this.jobId,
|
|
676
|
+
scope,
|
|
592
677
|
);
|
|
593
678
|
|
|
594
679
|
const txHashes = requestCapsules.map((fields, i) => {
|
|
@@ -600,66 +685,73 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
600
685
|
return fields[0];
|
|
601
686
|
});
|
|
602
687
|
|
|
603
|
-
const maybeMessageContexts = await this.messageContextService.
|
|
688
|
+
const maybeMessageContexts = await this.messageContextService.getMessageContextsByTxHash(
|
|
604
689
|
txHashes,
|
|
605
690
|
this.anchorBlockHeader.getBlockNumber(),
|
|
606
691
|
);
|
|
607
692
|
|
|
608
693
|
// Leave response in response capsule array.
|
|
609
|
-
await this.
|
|
694
|
+
await this.capsuleService.setCapsuleArray(
|
|
610
695
|
contractAddress,
|
|
611
696
|
messageContextResponsesArrayBaseSlot,
|
|
612
|
-
maybeMessageContexts.map(
|
|
697
|
+
maybeMessageContexts.map(MessageContext.toSerializedOption),
|
|
613
698
|
this.jobId,
|
|
699
|
+
scope,
|
|
614
700
|
);
|
|
615
701
|
} finally {
|
|
616
|
-
await this.
|
|
702
|
+
await this.capsuleService.setCapsuleArray(
|
|
703
|
+
contractAddress,
|
|
704
|
+
messageContextRequestsArrayBaseSlot,
|
|
705
|
+
[],
|
|
706
|
+
this.jobId,
|
|
707
|
+
scope,
|
|
708
|
+
);
|
|
617
709
|
}
|
|
618
710
|
}
|
|
619
711
|
|
|
620
|
-
public
|
|
712
|
+
public setCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[], scope: AztecAddress): void {
|
|
621
713
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
622
714
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
623
715
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
624
716
|
}
|
|
625
|
-
this.
|
|
626
|
-
return Promise.resolve();
|
|
717
|
+
this.capsuleService.setCapsule(contractAddress, slot, capsule, this.jobId, scope);
|
|
627
718
|
}
|
|
628
719
|
|
|
629
|
-
public
|
|
720
|
+
public getCapsule(contractAddress: AztecAddress, slot: Fr, scope: AztecAddress): Promise<Fr[] | null> {
|
|
630
721
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
631
722
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
632
723
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
633
724
|
}
|
|
634
|
-
return (
|
|
635
|
-
// TODO(#12425): On the following line, the pertinent capsule gets overshadowed by the transient one. Tackle this.
|
|
636
|
-
this.capsules.find(c => c.contractAddress.equals(contractAddress) && c.storageSlot.equals(slot))?.data ??
|
|
637
|
-
(await this.capsuleStore.loadCapsule(this.contractAddress, slot, this.jobId))
|
|
638
|
-
);
|
|
725
|
+
return this.capsuleService.getCapsule(contractAddress, slot, this.jobId, scope, this.capsules);
|
|
639
726
|
}
|
|
640
727
|
|
|
641
|
-
public deleteCapsule(contractAddress: AztecAddress, slot: Fr):
|
|
728
|
+
public deleteCapsule(contractAddress: AztecAddress, slot: Fr, scope: AztecAddress): void {
|
|
642
729
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
643
730
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
644
731
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
645
732
|
}
|
|
646
|
-
this.
|
|
647
|
-
return Promise.resolve();
|
|
733
|
+
this.capsuleService.deleteCapsule(contractAddress, slot, this.jobId, scope);
|
|
648
734
|
}
|
|
649
735
|
|
|
650
|
-
public copyCapsule(
|
|
736
|
+
public copyCapsule(
|
|
737
|
+
contractAddress: AztecAddress,
|
|
738
|
+
srcSlot: Fr,
|
|
739
|
+
dstSlot: Fr,
|
|
740
|
+
numEntries: number,
|
|
741
|
+
scope: AztecAddress,
|
|
742
|
+
): Promise<void> {
|
|
651
743
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
652
744
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
653
745
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
654
746
|
}
|
|
655
|
-
return this.
|
|
747
|
+
return this.capsuleService.copyCapsule(contractAddress, srcSlot, dstSlot, numEntries, this.jobId, scope);
|
|
656
748
|
}
|
|
657
749
|
|
|
658
750
|
/**
|
|
659
751
|
* Clears cached sync state for a contract for a set of scopes, forcing re-sync on the next query so that newly
|
|
660
752
|
* stored notes or events are discovered.
|
|
661
753
|
*/
|
|
662
|
-
public
|
|
754
|
+
public setContractSyncCacheInvalid(contractAddress: AztecAddress, scopes: AztecAddress[]): void {
|
|
663
755
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
664
756
|
throw new Error(`Contract ${this.contractAddress} cannot invalidate sync cache of ${contractAddress}`);
|
|
665
757
|
}
|
|
@@ -667,25 +759,30 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
667
759
|
}
|
|
668
760
|
|
|
669
761
|
// TODO(#11849): consider replacing this oracle with a pure Noir implementation of aes decryption.
|
|
670
|
-
public
|
|
762
|
+
public decryptAes128(ciphertext: Buffer, iv: Buffer, symKey: Buffer): Promise<Buffer> {
|
|
671
763
|
const aes128 = new Aes128();
|
|
672
764
|
return aes128.decryptBufferCBC(ciphertext, iv, symKey);
|
|
673
765
|
}
|
|
674
766
|
|
|
675
767
|
/**
|
|
676
|
-
* Retrieves the shared secret for a given address and ephemeral public key.
|
|
768
|
+
* Retrieves the app-siloed shared secret for a given address and ephemeral public key.
|
|
677
769
|
* @param address - The address to get the secret for.
|
|
678
770
|
* @param ephPk - The ephemeral public key to get the secret for.
|
|
679
|
-
* @
|
|
771
|
+
* @param contractAddress - The contract address for app-siloing (validated against execution context).
|
|
772
|
+
* @returns The app-siloed shared secret as a Field.
|
|
680
773
|
*/
|
|
681
|
-
public async getSharedSecret(address: AztecAddress, ephPk: Point): Promise<
|
|
682
|
-
|
|
774
|
+
public async getSharedSecret(address: AztecAddress, ephPk: Point, contractAddress: AztecAddress): Promise<Fr> {
|
|
775
|
+
if (!contractAddress.equals(this.contractAddress)) {
|
|
776
|
+
throw new Error(
|
|
777
|
+
`getSharedSecret called with contract address ${contractAddress}, expected ${this.contractAddress}`,
|
|
778
|
+
);
|
|
779
|
+
}
|
|
683
780
|
const recipientCompleteAddress = await this.getCompleteAddressOrFail(address);
|
|
684
781
|
const ivskM = await this.keyStore.getMasterSecretKey(
|
|
685
782
|
recipientCompleteAddress.publicKeys.masterIncomingViewingPublicKey,
|
|
686
783
|
);
|
|
687
784
|
const addressSecret = await computeAddressSecret(await recipientCompleteAddress.getPreaddress(), ivskM);
|
|
688
|
-
return
|
|
785
|
+
return deriveAppSiloedSharedSecret(addressSecret, ephPk, this.contractAddress);
|
|
689
786
|
}
|
|
690
787
|
|
|
691
788
|
public emitOffchainEffect(data: Fr[]): Promise<void> {
|
|
@@ -697,4 +794,24 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
697
794
|
public getOffchainEffects(): OffchainEffect[] {
|
|
698
795
|
return this.offchainEffects;
|
|
699
796
|
}
|
|
797
|
+
|
|
798
|
+
/** Runs a query concurrently with a validation that the block hash is not ahead of the anchor block. */
|
|
799
|
+
async #queryWithBlockHashNotAfterAnchor<T>(blockHash: BlockHash, query: () => Promise<T>): Promise<T> {
|
|
800
|
+
const [response] = await Promise.all([
|
|
801
|
+
query(),
|
|
802
|
+
(async () => {
|
|
803
|
+
const header = await this.aztecNode.getBlockHeader(blockHash);
|
|
804
|
+
if (!header) {
|
|
805
|
+
throw new Error(`Could not find block header for block hash ${blockHash}`);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
if (header.getBlockNumber() > this.anchorBlockHeader.getBlockNumber()) {
|
|
809
|
+
throw new Error(
|
|
810
|
+
`Made a node query with a reference block hash ${blockHash} with block number ${header.getBlockNumber()}, which is ahead of the anchor block number ${this.anchorBlockHeader.getBlockNumber()} (from anchor block hash ${await this.anchorBlockHeader.hash()}).`,
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
})(),
|
|
814
|
+
]);
|
|
815
|
+
return response;
|
|
816
|
+
}
|
|
700
817
|
}
|
package/src/contract_logging.ts
CHANGED
|
@@ -5,18 +5,22 @@ import type { DebugLog } from '@aztec/stdlib/logs';
|
|
|
5
5
|
|
|
6
6
|
/** Resolves a contract address to a human-readable name, if available. */
|
|
7
7
|
export type ContractNameResolver = (address: AztecAddress) => Promise<string | undefined>;
|
|
8
|
+
export type CONTRACT_LOG_KIND = 'aztecnr' | 'user';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
|
-
* Creates a logger whose output is prefixed with `
|
|
11
|
+
* Creates a logger whose output is prefixed with `contract:<name>(<addrAbbrev>)`.
|
|
11
12
|
*/
|
|
12
13
|
export async function createContractLogger(
|
|
13
14
|
contractAddress: AztecAddress,
|
|
14
15
|
getContractName: ContractNameResolver,
|
|
16
|
+
kind: CONTRACT_LOG_KIND,
|
|
15
17
|
options?: { instanceId?: string },
|
|
16
18
|
): Promise<Logger> {
|
|
17
19
|
const addrAbbrev = contractAddress.toString().slice(0, 10);
|
|
18
20
|
const name = await getContractName(contractAddress);
|
|
19
|
-
|
|
21
|
+
|
|
22
|
+
const prefix = kind == 'aztecnr' ? 'aztecnr' : 'contract';
|
|
23
|
+
const module = name ? `${prefix}:${name}(${addrAbbrev})` : `${prefix}:Unknown(${addrAbbrev})`;
|
|
20
24
|
return createLogger(module, options);
|
|
21
25
|
}
|
|
22
26
|
|
|
@@ -29,11 +33,20 @@ export function logContractMessage(logger: Logger, level: LogLevel, message: str
|
|
|
29
33
|
|
|
30
34
|
/**
|
|
31
35
|
* Displays debug logs collected during public function simulation,
|
|
32
|
-
* using the `
|
|
36
|
+
* using the `contract:` prefixed logger format.
|
|
33
37
|
*/
|
|
34
38
|
export async function displayDebugLogs(debugLogs: DebugLog[], getContractName: ContractNameResolver): Promise<void> {
|
|
35
39
|
for (const log of debugLogs) {
|
|
36
|
-
const
|
|
37
|
-
|
|
40
|
+
const { kind, message } = stripAztecnrLogPrefix(log.message);
|
|
41
|
+
const logger = await createContractLogger(log.contractAddress, getContractName, kind);
|
|
42
|
+
logContractMessage(logger, log.level, message, log.fields);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function stripAztecnrLogPrefix(message: string): { kind: CONTRACT_LOG_KIND; message: string } {
|
|
47
|
+
if (message.startsWith('[aztec-nr] ')) {
|
|
48
|
+
return { kind: 'aztecnr', message: message.slice('[aztec-nr] '.length) };
|
|
49
|
+
} else {
|
|
50
|
+
return { kind: 'user', message };
|
|
38
51
|
}
|
|
39
52
|
}
|