@aztec/pxe 4.0.0-nightly.20260112 → 4.0.0-nightly.20260114
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 +4 -2
- package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
- package/dest/block_synchronizer/block_synchronizer.js +19 -13
- package/dest/contract_function_simulator/oracle/interfaces.d.ts +3 -3
- package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/note_packing_utils.d.ts +4 -4
- package/dest/contract_function_simulator/oracle/note_packing_utils.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/note_packing_utils.js +5 -5
- package/dest/contract_function_simulator/oracle/oracle.js +1 -1
- package/dest/contract_function_simulator/oracle/private_execution.d.ts +1 -1
- package/dest/contract_function_simulator/oracle/private_execution.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution.js +1 -2
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +1 -16
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.js +4 -31
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +15 -13
- package/dest/events/event_service.d.ts +1 -1
- package/dest/events/event_service.d.ts.map +1 -1
- package/dest/events/event_service.js +8 -12
- package/dest/logs/log_service.d.ts +3 -2
- package/dest/logs/log_service.d.ts.map +1 -1
- package/dest/logs/log_service.js +4 -2
- 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 -22
- package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts +2 -2
- package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts.map +1 -1
- package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.js +2 -2
- package/dest/private_kernel/private_kernel_execution_prover.d.ts +1 -1
- package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_execution_prover.js +3 -4
- package/dest/private_kernel/private_kernel_oracle.d.ts +24 -28
- package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_oracle.js +92 -2
- package/dest/pxe.d.ts +7 -36
- package/dest/pxe.d.ts.map +1 -1
- package/dest/pxe.js +12 -59
- package/dest/storage/capsule_store/capsule_store.d.ts +24 -9
- package/dest/storage/capsule_store/capsule_store.d.ts.map +1 -1
- package/dest/storage/capsule_store/capsule_store.js +132 -23
- package/dest/storage/note_store/note_store.d.ts +6 -5
- package/dest/storage/note_store/note_store.d.ts.map +1 -1
- package/dest/storage/note_store/note_store.js +89 -94
- package/dest/storage/private_event_store/private_event_store.d.ts +13 -6
- package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
- package/dest/storage/private_event_store/private_event_store.js +70 -56
- package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts +1 -1
- package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts.map +1 -1
- package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.js +1 -1
- package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts +1 -1
- 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 +2 -2
- package/package.json +16 -16
- package/src/block_synchronizer/block_synchronizer.ts +23 -12
- package/src/contract_function_simulator/oracle/interfaces.ts +2 -2
- package/src/contract_function_simulator/oracle/note_packing_utils.ts +6 -6
- package/src/contract_function_simulator/oracle/oracle.ts +1 -1
- package/src/contract_function_simulator/oracle/private_execution.ts +0 -2
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +2 -36
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +15 -10
- package/src/events/event_service.ts +12 -26
- package/src/logs/log_service.ts +2 -1
- package/src/notes/note_service.ts +14 -23
- package/src/private_kernel/hints/build_private_kernel_reset_private_inputs.ts +1 -2
- package/src/private_kernel/private_kernel_execution_prover.ts +2 -4
- package/src/private_kernel/private_kernel_oracle.ts +119 -36
- package/src/pxe.ts +10 -81
- package/src/storage/capsule_store/capsule_store.ts +159 -23
- package/src/storage/note_store/note_store.ts +98 -95
- package/src/storage/private_event_store/private_event_store.ts +92 -65
- package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +4 -1
- package/src/tagging/sender_sync/utils/get_status_change_of_pending.ts +6 -2
- package/dest/private_kernel/private_kernel_oracle_impl.d.ts +0 -46
- package/dest/private_kernel/private_kernel_oracle_impl.d.ts.map +0 -1
- package/dest/private_kernel/private_kernel_oracle_impl.js +0 -86
- package/src/private_kernel/private_kernel_oracle_impl.ts +0 -133
|
@@ -354,6 +354,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
354
354
|
this.recipientTaggingStore,
|
|
355
355
|
this.senderAddressBookStore,
|
|
356
356
|
this.addressStore,
|
|
357
|
+
this.jobId,
|
|
357
358
|
);
|
|
358
359
|
|
|
359
360
|
await logService.syncTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot, this.scopes);
|
|
@@ -385,11 +386,11 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
385
386
|
// We read all note and event validation requests and process them all concurrently. This makes the process much
|
|
386
387
|
// faster as we don't need to wait for the network round-trip.
|
|
387
388
|
const noteValidationRequests = (
|
|
388
|
-
await this.capsuleStore.readCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot)
|
|
389
|
+
await this.capsuleStore.readCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot, this.jobId)
|
|
389
390
|
).map(NoteValidationRequest.fromFields);
|
|
390
391
|
|
|
391
392
|
const eventValidationRequests = (
|
|
392
|
-
await this.capsuleStore.readCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot)
|
|
393
|
+
await this.capsuleStore.readCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, this.jobId)
|
|
393
394
|
).map(EventValidationRequest.fromFields);
|
|
394
395
|
|
|
395
396
|
const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockStore);
|
|
@@ -424,8 +425,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
424
425
|
await Promise.all([...noteDeliveries, ...eventDeliveries]);
|
|
425
426
|
|
|
426
427
|
// Requests are cleared once we're done.
|
|
427
|
-
await this.capsuleStore.setCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot, []);
|
|
428
|
-
await this.capsuleStore.setCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, []);
|
|
428
|
+
await this.capsuleStore.setCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot, [], this.jobId);
|
|
429
|
+
await this.capsuleStore.setCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, [], this.jobId);
|
|
429
430
|
}
|
|
430
431
|
|
|
431
432
|
public async utilityBulkRetrieveLogs(
|
|
@@ -441,7 +442,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
441
442
|
// We read all log retrieval requests and process them all concurrently. This makes the process much faster as we
|
|
442
443
|
// don't need to wait for the network round-trip.
|
|
443
444
|
const logRetrievalRequests = (
|
|
444
|
-
await this.capsuleStore.readCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot)
|
|
445
|
+
await this.capsuleStore.readCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, this.jobId)
|
|
445
446
|
).map(LogRetrievalRequest.fromFields);
|
|
446
447
|
|
|
447
448
|
const logService = new LogService(
|
|
@@ -452,18 +453,20 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
452
453
|
this.recipientTaggingStore,
|
|
453
454
|
this.senderAddressBookStore,
|
|
454
455
|
this.addressStore,
|
|
456
|
+
this.jobId,
|
|
455
457
|
);
|
|
456
458
|
|
|
457
459
|
const maybeLogRetrievalResponses = await logService.bulkRetrieveLogs(logRetrievalRequests);
|
|
458
460
|
|
|
459
461
|
// Requests are cleared once we're done.
|
|
460
|
-
await this.capsuleStore.setCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, []);
|
|
462
|
+
await this.capsuleStore.setCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, [], this.jobId);
|
|
461
463
|
|
|
462
464
|
// The responses are stored as Option<LogRetrievalResponse> in a second CapsuleArray.
|
|
463
465
|
await this.capsuleStore.setCapsuleArray(
|
|
464
466
|
contractAddress,
|
|
465
467
|
logRetrievalResponsesArrayBaseSlot,
|
|
466
468
|
maybeLogRetrievalResponses.map(LogRetrievalResponse.toSerializedOption),
|
|
469
|
+
this.jobId,
|
|
467
470
|
);
|
|
468
471
|
}
|
|
469
472
|
|
|
@@ -472,7 +475,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
472
475
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
473
476
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
474
477
|
}
|
|
475
|
-
|
|
478
|
+
this.capsuleStore.storeCapsule(this.contractAddress, slot, capsule, this.jobId);
|
|
479
|
+
return Promise.resolve();
|
|
476
480
|
}
|
|
477
481
|
|
|
478
482
|
public async utilityLoadCapsule(contractAddress: AztecAddress, slot: Fr): Promise<Fr[] | null> {
|
|
@@ -483,7 +487,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
483
487
|
return (
|
|
484
488
|
// TODO(#12425): On the following line, the pertinent capsule gets overshadowed by the transient one. Tackle this.
|
|
485
489
|
this.capsules.find(c => c.contractAddress.equals(contractAddress) && c.storageSlot.equals(slot))?.data ??
|
|
486
|
-
(await this.capsuleStore.loadCapsule(this.contractAddress, slot))
|
|
490
|
+
(await this.capsuleStore.loadCapsule(this.contractAddress, slot, this.jobId))
|
|
487
491
|
);
|
|
488
492
|
}
|
|
489
493
|
|
|
@@ -492,7 +496,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
492
496
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
493
497
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
494
498
|
}
|
|
495
|
-
|
|
499
|
+
this.capsuleStore.deleteCapsule(this.contractAddress, slot, this.jobId);
|
|
500
|
+
return Promise.resolve();
|
|
496
501
|
}
|
|
497
502
|
|
|
498
503
|
public utilityCopyCapsule(
|
|
@@ -505,7 +510,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
505
510
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
506
511
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
507
512
|
}
|
|
508
|
-
return this.capsuleStore.copyCapsule(this.contractAddress, srcSlot, dstSlot, numEntries);
|
|
513
|
+
return this.capsuleStore.copyCapsule(this.contractAddress, srcSlot, dstSlot, numEntries, this.jobId);
|
|
509
514
|
}
|
|
510
515
|
|
|
511
516
|
// TODO(#11849): consider replacing this oracle with a pure Noir implementation of aes decryption.
|
|
@@ -3,7 +3,6 @@ import type { EventSelector } from '@aztec/stdlib/abi';
|
|
|
3
3
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
4
4
|
import { siloNullifier } from '@aztec/stdlib/hash';
|
|
5
5
|
import type { AztecNode } from '@aztec/stdlib/interfaces/server';
|
|
6
|
-
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
7
6
|
import type { TxHash } from '@aztec/stdlib/tx';
|
|
8
7
|
|
|
9
8
|
import { AnchorBlockStore } from '../storage/anchor_block_store/anchor_block_store.js';
|
|
@@ -45,35 +44,22 @@ export class EventService {
|
|
|
45
44
|
throw new Error(`Could not find tx effect for tx hash ${txHash} as of block number ${syncedBlockNumber}`);
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
// Find the index of the event commitment in the nullifiers array to determine event ordering within the tx
|
|
48
|
+
const eventIndexInTx = txEffect.data.nullifiers.findIndex(n => n.equals(siloedEventCommitment));
|
|
49
|
+
if (eventIndexInTx === -1) {
|
|
50
50
|
throw new Error(
|
|
51
51
|
`Event commitment ${eventCommitment} (siloed as ${siloedEventCommitment}) is not present in tx ${txHash}`,
|
|
52
52
|
);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return this.privateEventStore.storePrivateEventLog(
|
|
66
|
-
selector,
|
|
67
|
-
randomness,
|
|
68
|
-
content,
|
|
69
|
-
Number(nullifierIndex.data), // Index of the event commitment in the nullifier tree
|
|
70
|
-
{
|
|
71
|
-
contractAddress,
|
|
72
|
-
scope,
|
|
73
|
-
txHash,
|
|
74
|
-
l2BlockNumber: nullifierIndex.l2BlockNumber, // Block number in which the event was emitted
|
|
75
|
-
l2BlockHash: nullifierIndex.l2BlockHash, // Block hash in which the event was emitted
|
|
76
|
-
},
|
|
77
|
-
);
|
|
55
|
+
return this.privateEventStore.storePrivateEventLog(selector, randomness, content, siloedEventCommitment, {
|
|
56
|
+
contractAddress,
|
|
57
|
+
scope,
|
|
58
|
+
txHash,
|
|
59
|
+
l2BlockNumber: txEffect.l2BlockNumber,
|
|
60
|
+
l2BlockHash: txEffect.l2BlockHash,
|
|
61
|
+
txIndexInBlock: txEffect.txIndexInBlock,
|
|
62
|
+
eventIndexInTx,
|
|
63
|
+
});
|
|
78
64
|
}
|
|
79
65
|
}
|
package/src/logs/log_service.ts
CHANGED
|
@@ -26,6 +26,7 @@ export class LogService {
|
|
|
26
26
|
private readonly recipientTaggingStore: RecipientTaggingStore,
|
|
27
27
|
private readonly senderAddressBookStore: SenderAddressBookStore,
|
|
28
28
|
private readonly addressStore: AddressStore,
|
|
29
|
+
private readonly jobId: string,
|
|
29
30
|
) {}
|
|
30
31
|
|
|
31
32
|
public async bulkRetrieveLogs(logRetrievalRequests: LogRetrievalRequest[]): Promise<(LogRetrievalResponse | null)[]> {
|
|
@@ -186,7 +187,7 @@ export class LogService {
|
|
|
186
187
|
});
|
|
187
188
|
|
|
188
189
|
// TODO: This looks like it could belong more at the oracle interface level
|
|
189
|
-
return this.capsuleStore.appendToCapsuleArray(contractAddress, capsuleArrayBaseSlot, pendingTaggedLogs);
|
|
190
|
+
return this.capsuleStore.appendToCapsuleArray(contractAddress, capsuleArrayBaseSlot, pendingTaggedLogs, this.jobId);
|
|
190
191
|
}
|
|
191
192
|
|
|
192
193
|
async #getCompleteAddress(account: AztecAddress): Promise<CompleteAddress> {
|
|
@@ -41,7 +41,7 @@ export class NoteService {
|
|
|
41
41
|
scopes,
|
|
42
42
|
});
|
|
43
43
|
return noteDaos.map(
|
|
44
|
-
({ contractAddress, owner, storageSlot, randomness, noteNonce, note, noteHash, siloedNullifier
|
|
44
|
+
({ contractAddress, owner, storageSlot, randomness, noteNonce, note, noteHash, siloedNullifier }) => ({
|
|
45
45
|
contractAddress,
|
|
46
46
|
owner,
|
|
47
47
|
storageSlot,
|
|
@@ -49,9 +49,8 @@ export class NoteService {
|
|
|
49
49
|
noteNonce,
|
|
50
50
|
note,
|
|
51
51
|
noteHash,
|
|
52
|
+
isPending: false, // Note service deals only with settled notes
|
|
52
53
|
siloedNullifier,
|
|
53
|
-
// PXE can use this index to get full MembershipWitness
|
|
54
|
-
index,
|
|
55
54
|
}),
|
|
56
55
|
);
|
|
57
56
|
}
|
|
@@ -146,7 +145,10 @@ export class NoteService {
|
|
|
146
145
|
const uniqueNoteHash = await computeUniqueNoteHash(noteNonce, await siloNoteHash(contractAddress, noteHash));
|
|
147
146
|
const siloedNullifier = await siloNullifier(contractAddress, nullifier);
|
|
148
147
|
|
|
149
|
-
const txEffect = await
|
|
148
|
+
const [txEffect, [nullifierIndex]] = await Promise.all([
|
|
149
|
+
this.aztecNode.getTxEffect(txHash),
|
|
150
|
+
this.aztecNode.findLeavesIndexes(syncedBlockNumber, MerkleTreeId.NULLIFIER_TREE, [siloedNullifier]),
|
|
151
|
+
]);
|
|
150
152
|
if (!txEffect) {
|
|
151
153
|
throw new Error(`Could not find tx effect for tx hash ${txHash}`);
|
|
152
154
|
}
|
|
@@ -155,25 +157,12 @@ export class NoteService {
|
|
|
155
157
|
throw new Error(`Could not find tx effect for tx hash ${txHash} as of block number ${syncedBlockNumber}`);
|
|
156
158
|
}
|
|
157
159
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
+
// Find the index of the note hash in the noteHashes array to determine note ordering within the tx
|
|
161
|
+
const noteIndexInTx = txEffect.data.noteHashes.findIndex(nh => nh.equals(uniqueNoteHash));
|
|
162
|
+
if (noteIndexInTx === -1) {
|
|
160
163
|
throw new Error(`Note hash ${noteHash} (uniqued as ${uniqueNoteHash}) is not present in tx ${txHash}`);
|
|
161
164
|
}
|
|
162
165
|
|
|
163
|
-
// We store notes by their index in the global note hash tree, which has the convenient side effect of validating
|
|
164
|
-
// note existence in said tree. We concurrently also check if the note's nullifier exists, performing all node
|
|
165
|
-
// queries in a single round-trip.
|
|
166
|
-
const [[uniqueNoteHashTreeIndexInBlock], [nullifierIndex]] = await Promise.all([
|
|
167
|
-
this.aztecNode.findLeavesIndexes(syncedBlockNumber, MerkleTreeId.NOTE_HASH_TREE, [uniqueNoteHash]),
|
|
168
|
-
this.aztecNode.findLeavesIndexes(syncedBlockNumber, MerkleTreeId.NULLIFIER_TREE, [siloedNullifier]),
|
|
169
|
-
]);
|
|
170
|
-
|
|
171
|
-
if (uniqueNoteHashTreeIndexInBlock === undefined) {
|
|
172
|
-
throw new Error(
|
|
173
|
-
`Note hash ${noteHash} (uniqued as ${uniqueNoteHash}) is not present on the tree at block ${syncedBlockNumber} (from tx ${txHash})`,
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
166
|
const noteDao = new NoteDao(
|
|
178
167
|
new Note(content),
|
|
179
168
|
contractAddress,
|
|
@@ -184,15 +173,17 @@ export class NoteService {
|
|
|
184
173
|
noteHash,
|
|
185
174
|
siloedNullifier,
|
|
186
175
|
txHash,
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
176
|
+
txEffect.l2BlockNumber,
|
|
177
|
+
txEffect.l2BlockHash.toString(),
|
|
178
|
+
txEffect.txIndexInBlock,
|
|
179
|
+
noteIndexInTx,
|
|
190
180
|
);
|
|
191
181
|
|
|
192
182
|
// The note was found by `recipient`, so we use that as the scope when storing the note.
|
|
193
183
|
await this.noteStore.addNotes([noteDao], recipient);
|
|
194
184
|
|
|
195
185
|
if (nullifierIndex !== undefined) {
|
|
186
|
+
// We found nullifier index which implies that the note has already been nullified.
|
|
196
187
|
const { data: _, ...blockHashAndNum } = nullifierIndex;
|
|
197
188
|
await this.noteStore.applyNullifiers([{ data: siloedNullifier, ...blockHashAndNum }]);
|
|
198
189
|
}
|
|
@@ -138,7 +138,7 @@ export class PrivateKernelResetPrivateInputsBuilder {
|
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
async build(oracle: PrivateKernelOracle
|
|
141
|
+
async build(oracle: PrivateKernelOracle) {
|
|
142
142
|
if (privateKernelResetDimensionNames.every(name => !this.requestedDimensions[name])) {
|
|
143
143
|
throw new Error('Reset is not required.');
|
|
144
144
|
}
|
|
@@ -190,7 +190,6 @@ export class PrivateKernelResetPrivateInputsBuilder {
|
|
|
190
190
|
this.previousKernel.validationRequests.noteHashReadRequests,
|
|
191
191
|
this.previousKernel.end.noteHashes,
|
|
192
192
|
this.noteHashResetActions,
|
|
193
|
-
noteHashLeafIndexMap,
|
|
194
193
|
),
|
|
195
194
|
await buildNullifierReadRequestHintsFromResetActions(
|
|
196
195
|
{ getNullifierMembershipWitness: getNullifierMembershipWitnessResolver(oracle) },
|
|
@@ -28,7 +28,6 @@ import {
|
|
|
28
28
|
type PrivateCallExecutionResult,
|
|
29
29
|
type PrivateExecutionResult,
|
|
30
30
|
TxRequest,
|
|
31
|
-
collectNoteHashLeafIndexMap,
|
|
32
31
|
collectNoteHashNullifierCounterMap,
|
|
33
32
|
getFinalMinRevertibleSideEffectCounter,
|
|
34
33
|
} from '@aztec/stdlib/tx';
|
|
@@ -101,7 +100,6 @@ export class PrivateKernelExecutionProver {
|
|
|
101
100
|
|
|
102
101
|
const executionSteps: PrivateExecutionStep[] = [];
|
|
103
102
|
|
|
104
|
-
const noteHashLeafIndexMap = collectNoteHashLeafIndexMap(executionResult);
|
|
105
103
|
const noteHashNullifierCounterMap = collectNoteHashNullifierCounterMap(executionResult);
|
|
106
104
|
const minRevertibleSideEffectCounter = getFinalMinRevertibleSideEffectCounter(executionResult);
|
|
107
105
|
const splitCounter = isPrivateOnlyTx ? 0 : minRevertibleSideEffectCounter;
|
|
@@ -116,7 +114,7 @@ export class PrivateKernelExecutionProver {
|
|
|
116
114
|
);
|
|
117
115
|
while (resetBuilder.needsReset()) {
|
|
118
116
|
const witgenTimer = new Timer();
|
|
119
|
-
const privateInputs = await resetBuilder.build(this.oracle
|
|
117
|
+
const privateInputs = await resetBuilder.build(this.oracle);
|
|
120
118
|
output = generateWitnesses
|
|
121
119
|
? await this.proofCreator.generateResetOutput(privateInputs)
|
|
122
120
|
: await this.proofCreator.simulateReset(privateInputs);
|
|
@@ -224,7 +222,7 @@ export class PrivateKernelExecutionProver {
|
|
|
224
222
|
);
|
|
225
223
|
while (resetBuilder.needsReset()) {
|
|
226
224
|
const witgenTimer = new Timer();
|
|
227
|
-
const privateInputs = await resetBuilder.build(this.oracle
|
|
225
|
+
const privateInputs = await resetBuilder.build(this.oracle);
|
|
228
226
|
output = generateWitnesses
|
|
229
227
|
? await this.proofCreator.generateResetOutput(privateInputs)
|
|
230
228
|
: await this.proofCreator.simulateReset(privateInputs);
|
|
@@ -1,72 +1,155 @@
|
|
|
1
|
-
import { FUNCTION_TREE_HEIGHT, NOTE_HASH_TREE_HEIGHT, VK_TREE_HEIGHT } from '@aztec/constants';
|
|
1
|
+
import { FUNCTION_TREE_HEIGHT, NOTE_HASH_TREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT, VK_TREE_HEIGHT } from '@aztec/constants';
|
|
2
2
|
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
3
|
import type { GrumpkinScalar, Point } from '@aztec/foundation/curves/grumpkin';
|
|
4
4
|
import { MembershipWitness } from '@aztec/foundation/trees';
|
|
5
|
+
import type { KeyStore } from '@aztec/key-store';
|
|
6
|
+
import { getVKIndex, getVKSiblingPath } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
7
|
+
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
5
8
|
import type { FunctionSelector } from '@aztec/stdlib/abi';
|
|
6
9
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
10
|
+
import type { BlockParameter } from '@aztec/stdlib/block';
|
|
11
|
+
import {
|
|
12
|
+
type ContractInstanceWithAddress,
|
|
13
|
+
computeContractClassIdPreimage,
|
|
14
|
+
computeSaltedInitializationHash,
|
|
15
|
+
} from '@aztec/stdlib/contract';
|
|
16
|
+
import { DelayedPublicMutableValues, DelayedPublicMutableValuesWithHash } from '@aztec/stdlib/delayed-public-mutable';
|
|
17
|
+
import { computePublicDataTreeLeafSlot } from '@aztec/stdlib/hash';
|
|
18
|
+
import type { AztecNode } from '@aztec/stdlib/interfaces/client';
|
|
7
19
|
import { UpdatedClassIdHints } from '@aztec/stdlib/kernel';
|
|
8
|
-
import type { PublicKeys } from '@aztec/stdlib/keys';
|
|
9
20
|
import type { NullifierMembershipWitness } from '@aztec/stdlib/trees';
|
|
10
21
|
import type { VerificationKeyAsFields } from '@aztec/stdlib/vks';
|
|
11
22
|
|
|
23
|
+
import type { ContractStore } from '../storage/contract_store/contract_store.js';
|
|
24
|
+
|
|
25
|
+
// TODO: Block number should not be "latest".
|
|
26
|
+
// It should be fixed at the time the proof is being simulated. I.e., it should be the same as the value defined in the constant data.
|
|
27
|
+
|
|
12
28
|
/**
|
|
13
29
|
* Provides functionality needed by the private kernel for interacting with our state trees.
|
|
14
|
-
* This is either PrivateKernelOracleImpl, or a mocked test implementation.
|
|
15
30
|
*/
|
|
16
|
-
export
|
|
31
|
+
export class PrivateKernelOracle {
|
|
32
|
+
constructor(
|
|
33
|
+
private contractStore: ContractStore,
|
|
34
|
+
private keyStore: KeyStore,
|
|
35
|
+
private node: AztecNode,
|
|
36
|
+
private blockNumber: BlockParameter = 'latest',
|
|
37
|
+
) {}
|
|
38
|
+
|
|
17
39
|
/** Retrieves the preimage of a contract address from the registered contract instances db. */
|
|
18
|
-
getContractAddressPreimage(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
40
|
+
public async getContractAddressPreimage(
|
|
41
|
+
address: AztecAddress,
|
|
42
|
+
): Promise<ContractInstanceWithAddress & { saltedInitializationHash: Fr }> {
|
|
43
|
+
const instance = await this.contractStore.getContractInstance(address);
|
|
44
|
+
if (!instance) {
|
|
45
|
+
throw new Error(`Contract instance not found when getting address preimage. Contract address: ${address}.`);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
saltedInitializationHash: await computeSaltedInitializationHash(instance),
|
|
49
|
+
...instance,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
24
52
|
|
|
25
53
|
/** Retrieves the preimage of a contract class id from the contract classes db. */
|
|
26
|
-
getContractClassIdPreimage(
|
|
27
|
-
contractClassId
|
|
28
|
-
|
|
54
|
+
public async getContractClassIdPreimage(contractClassId: Fr) {
|
|
55
|
+
const contractClass = await this.contractStore.getContractClass(contractClassId);
|
|
56
|
+
if (!contractClass) {
|
|
57
|
+
throw new Error(`Contract class not found when getting class id preimage. Class id: ${contractClassId}.`);
|
|
58
|
+
}
|
|
59
|
+
return computeContractClassIdPreimage(contractClass);
|
|
60
|
+
}
|
|
29
61
|
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
*/
|
|
33
|
-
getFunctionMembershipWitness(
|
|
62
|
+
/** Returns a membership witness with the sibling path and leaf index in our private functions tree. */
|
|
63
|
+
public async getFunctionMembershipWitness(
|
|
34
64
|
contractClassId: Fr,
|
|
35
65
|
selector: FunctionSelector,
|
|
36
|
-
): Promise<MembershipWitness<typeof FUNCTION_TREE_HEIGHT
|
|
66
|
+
): Promise<MembershipWitness<typeof FUNCTION_TREE_HEIGHT>> {
|
|
67
|
+
const membershipWitness = await this.contractStore.getFunctionMembershipWitness(contractClassId, selector);
|
|
68
|
+
if (!membershipWitness) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Membership witness not found for contract class id ${contractClassId} and selector ${selector}.`,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
return membershipWitness;
|
|
74
|
+
}
|
|
37
75
|
|
|
38
76
|
/**
|
|
39
77
|
* Returns a membership witness with the sibling path and leaf index in our protocol VK indexed merkle tree.
|
|
40
78
|
* Used to validate the previous kernel's verification key.
|
|
41
79
|
*/
|
|
42
|
-
getVkMembershipWitness(vk: VerificationKeyAsFields): Promise<MembershipWitness<typeof VK_TREE_HEIGHT
|
|
80
|
+
public getVkMembershipWitness(vk: VerificationKeyAsFields): Promise<MembershipWitness<typeof VK_TREE_HEIGHT>> {
|
|
81
|
+
const leafIndex = getVKIndex(vk);
|
|
82
|
+
return Promise.resolve(new MembershipWitness(VK_TREE_HEIGHT, BigInt(leafIndex), getVKSiblingPath(leafIndex)));
|
|
83
|
+
}
|
|
43
84
|
|
|
44
|
-
/**
|
|
45
|
-
|
|
46
|
-
|
|
85
|
+
/** Returns a membership witness with the sibling path and leaf index in our note hash tree. */
|
|
86
|
+
getNoteHashMembershipWitness(noteHash: Fr): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT> | undefined> {
|
|
87
|
+
return this.node.getNoteHashMembershipWitness(this.blockNumber, noteHash);
|
|
88
|
+
}
|
|
47
89
|
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
90
|
+
/** Returns a membership witness with the sibling path and leaf index in our nullifier indexed merkle tree. */
|
|
91
|
+
getNullifierMembershipWitness(nullifier: Fr): Promise<NullifierMembershipWitness | undefined> {
|
|
92
|
+
return this.node.getNullifierMembershipWitness(this.blockNumber, nullifier);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Returns the root of our note hash merkle tree. */
|
|
96
|
+
async getNoteHashTreeRoot(): Promise<Fr> {
|
|
97
|
+
const header = await this.node.getBlockHeader(this.blockNumber);
|
|
98
|
+
if (!header) {
|
|
99
|
+
throw new Error(`No block header found for block number ${this.blockNumber}`);
|
|
100
|
+
}
|
|
101
|
+
return header.state.partial.noteHashTree.root;
|
|
102
|
+
}
|
|
56
103
|
|
|
57
104
|
/**
|
|
58
105
|
* Retrieves the sk_m corresponding to the pk_m.
|
|
59
106
|
* @throws If the provided public key is not associated with any of the registered accounts.
|
|
60
|
-
* @param
|
|
107
|
+
* @param masterPublicKey - The master public key to get secret key for.
|
|
61
108
|
* @returns A Promise that resolves to sk_m.
|
|
62
109
|
* @dev Used when feeding the sk_m to the kernel circuit for keys verification.
|
|
63
110
|
*/
|
|
64
|
-
getMasterSecretKey(masterPublicKey: Point): Promise<GrumpkinScalar
|
|
111
|
+
public getMasterSecretKey(masterPublicKey: Point): Promise<GrumpkinScalar> {
|
|
112
|
+
return this.keyStore.getMasterSecretKey(masterPublicKey);
|
|
113
|
+
}
|
|
65
114
|
|
|
66
115
|
/** Use debug data to get the function name corresponding to a selector. */
|
|
67
|
-
getDebugFunctionName(contractAddress: AztecAddress, selector: FunctionSelector): Promise<string | undefined
|
|
116
|
+
public getDebugFunctionName(contractAddress: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
|
|
117
|
+
return this.contractStore.getDebugFunctionName(contractAddress, selector);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Returns a membership witness and leaf index to our public data indexed merkle tree,
|
|
122
|
+
* along with an associated DelayedPublicMutable containing the class ID to update.
|
|
123
|
+
*/
|
|
124
|
+
public async getUpdatedClassIdHints(contractAddress: AztecAddress): Promise<UpdatedClassIdHints> {
|
|
125
|
+
const { delayedPublicMutableSlot, delayedPublicMutableHashSlot } =
|
|
126
|
+
await DelayedPublicMutableValuesWithHash.getContractUpdateSlots(contractAddress);
|
|
127
|
+
|
|
128
|
+
const hashLeafSlot = await computePublicDataTreeLeafSlot(
|
|
129
|
+
ProtocolContractAddress.ContractInstanceRegistry,
|
|
130
|
+
delayedPublicMutableHashSlot,
|
|
131
|
+
);
|
|
132
|
+
const updatedClassIdWitness = await this.node.getPublicDataWitness(this.blockNumber, hashLeafSlot);
|
|
133
|
+
|
|
134
|
+
if (!updatedClassIdWitness) {
|
|
135
|
+
throw new Error(`No public data tree witness found for ${hashLeafSlot}`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const readStorage = (storageSlot: Fr) =>
|
|
139
|
+
this.node.getPublicStorageAt(this.blockNumber, ProtocolContractAddress.ContractInstanceRegistry, storageSlot);
|
|
140
|
+
const delayedPublicMutableValues = await DelayedPublicMutableValues.readFromTree(
|
|
141
|
+
delayedPublicMutableSlot,
|
|
142
|
+
readStorage,
|
|
143
|
+
);
|
|
68
144
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
145
|
+
return new UpdatedClassIdHints(
|
|
146
|
+
new MembershipWitness(
|
|
147
|
+
PUBLIC_DATA_TREE_HEIGHT,
|
|
148
|
+
updatedClassIdWitness.index,
|
|
149
|
+
updatedClassIdWitness.siblingPath.toTuple(),
|
|
150
|
+
),
|
|
151
|
+
updatedClassIdWitness.leafPreimage,
|
|
152
|
+
delayedPublicMutableValues,
|
|
153
|
+
);
|
|
154
|
+
}
|
|
72
155
|
}
|
package/src/pxe.ts
CHANGED
|
@@ -19,14 +19,13 @@ import type { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
|
19
19
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
20
20
|
import {
|
|
21
21
|
CompleteAddress,
|
|
22
|
-
type ContractClassWithId,
|
|
23
22
|
type ContractInstanceWithAddress,
|
|
24
23
|
type PartialAddress,
|
|
25
24
|
computeContractAddressFromInstance,
|
|
26
25
|
getContractClassFromArtifact,
|
|
27
26
|
} from '@aztec/stdlib/contract';
|
|
28
27
|
import { SimulationError } from '@aztec/stdlib/errors';
|
|
29
|
-
import { computeProtocolNullifier
|
|
28
|
+
import { computeProtocolNullifier } from '@aztec/stdlib/hash';
|
|
30
29
|
import type { AztecNode, PrivateKernelProver } from '@aztec/stdlib/interfaces/client';
|
|
31
30
|
import type {
|
|
32
31
|
PrivateExecutionStep,
|
|
@@ -69,7 +68,7 @@ import {
|
|
|
69
68
|
PrivateKernelExecutionProver,
|
|
70
69
|
type PrivateKernelExecutionProverConfig,
|
|
71
70
|
} from './private_kernel/private_kernel_execution_prover.js';
|
|
72
|
-
import {
|
|
71
|
+
import { PrivateKernelOracle } from './private_kernel/private_kernel_oracle.js';
|
|
73
72
|
import { AddressStore } from './storage/address_store/address_store.js';
|
|
74
73
|
import { AnchorBlockStore } from './storage/anchor_block_store/anchor_block_store.js';
|
|
75
74
|
import { CapsuleStore } from './storage/capsule_store/capsule_store.js';
|
|
@@ -148,6 +147,7 @@ export class PXE {
|
|
|
148
147
|
const tipsStore = new L2TipsKVStore(store, 'pxe');
|
|
149
148
|
const synchronizer = new BlockSynchronizer(
|
|
150
149
|
node,
|
|
150
|
+
store,
|
|
151
151
|
anchorBlockStore,
|
|
152
152
|
noteStore,
|
|
153
153
|
privateEventStore,
|
|
@@ -157,6 +157,7 @@ export class PXE {
|
|
|
157
157
|
);
|
|
158
158
|
|
|
159
159
|
const jobCoordinator = new JobCoordinator(store);
|
|
160
|
+
jobCoordinator.registerStores([capsuleStore]);
|
|
160
161
|
|
|
161
162
|
const debugUtils = new PXEDebugUtils(contractStore, noteStore);
|
|
162
163
|
|
|
@@ -274,19 +275,6 @@ export class PXE {
|
|
|
274
275
|
this.log.verbose(`Registered protocol contracts in pxe`, registered);
|
|
275
276
|
}
|
|
276
277
|
|
|
277
|
-
async #isContractClassPubliclyRegistered(id: Fr): Promise<boolean> {
|
|
278
|
-
return !!(await this.node.getContractClass(id));
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
async #isContractPublished(address: AztecAddress): Promise<boolean> {
|
|
282
|
-
return !!(await this.node.getContract(address));
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
async #isContractInitialized(address: AztecAddress): Promise<boolean> {
|
|
286
|
-
const initNullifier = await siloNullifier(address, address.toField());
|
|
287
|
-
return !!(await this.node.getNullifierMembershipWitness('latest', initNullifier));
|
|
288
|
-
}
|
|
289
|
-
|
|
290
278
|
// Executes the entrypoint private function, as well as all nested private
|
|
291
279
|
// functions that might arise.
|
|
292
280
|
async #executePrivate(
|
|
@@ -395,12 +383,7 @@ export class PXE {
|
|
|
395
383
|
config: PrivateKernelExecutionProverConfig,
|
|
396
384
|
): Promise<PrivateKernelExecutionProofOutput<PrivateKernelTailCircuitPublicInputs>> {
|
|
397
385
|
const simulationAnchorBlock = privateExecutionResult.getSimulationAnchorBlockNumber();
|
|
398
|
-
const kernelOracle = new
|
|
399
|
-
this.contractStore,
|
|
400
|
-
this.keyStore,
|
|
401
|
-
this.node,
|
|
402
|
-
simulationAnchorBlock,
|
|
403
|
-
);
|
|
386
|
+
const kernelOracle = new PrivateKernelOracle(this.contractStore, this.keyStore, this.node, simulationAnchorBlock);
|
|
404
387
|
const kernelTraceProver = new PrivateKernelExecutionProver(kernelOracle, proofCreator, !this.proverEnabled);
|
|
405
388
|
this.log.debug(`Executing kernel trace prover (${JSON.stringify(config)})...`);
|
|
406
389
|
return await kernelTraceProver.proveWithKernels(txExecutionRequest.toTxRequest(), privateExecutionResult, config);
|
|
@@ -413,66 +396,12 @@ export class PXE {
|
|
|
413
396
|
}
|
|
414
397
|
|
|
415
398
|
/**
|
|
416
|
-
* Returns the contract
|
|
417
|
-
*
|
|
418
|
-
* @
|
|
419
|
-
* @param id - Identifier of the class.
|
|
420
|
-
* @param includeArtifact - Identifier of the class.
|
|
421
|
-
* @returns - It returns the contract class metadata, with the artifact field being optional, and will only be returned if true is passed in
|
|
422
|
-
* for `includeArtifact`
|
|
423
|
-
* TODO(@spalladino): The PXE actually holds artifacts and not classes, what should we return? Also,
|
|
424
|
-
* should the pxe query the node for contract public info, and merge it with its own definitions?
|
|
425
|
-
* TODO(@spalladino): This method is strictly needed to decide whether to publicly register a class or not
|
|
426
|
-
* during a public deployment. We probably want a nicer and more general API for this, but it'll have to
|
|
427
|
-
* do for the time being.
|
|
399
|
+
* Returns the contract artifact for a given contract class id, if it's registered in the PXE.
|
|
400
|
+
* @param id - Identifier of the contract class.
|
|
401
|
+
* @returns The contract artifact if found, undefined otherwise.
|
|
428
402
|
*/
|
|
429
|
-
public async
|
|
430
|
-
id
|
|
431
|
-
includeArtifact: boolean = false,
|
|
432
|
-
): Promise<{
|
|
433
|
-
contractClass: ContractClassWithId | undefined;
|
|
434
|
-
isContractClassPubliclyRegistered: boolean;
|
|
435
|
-
artifact: ContractArtifact | undefined;
|
|
436
|
-
}> {
|
|
437
|
-
const artifact = await this.contractStore.getContractArtifact(id);
|
|
438
|
-
if (!artifact) {
|
|
439
|
-
this.log.warn(`No artifact found for contract class ${id.toString()} when looking for its metadata`);
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
return {
|
|
443
|
-
contractClass: artifact && (await getContractClassFromArtifact(artifact)),
|
|
444
|
-
isContractClassPubliclyRegistered: await this.#isContractClassPubliclyRegistered(id),
|
|
445
|
-
artifact: includeArtifact ? artifact : undefined,
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Returns the contract metadata given an address.
|
|
451
|
-
* The metadata consists of its contract instance, which includes the contract class identifier,
|
|
452
|
-
* initialization hash, deployment salt, and public keys hash; whether the contract instance has been initialized;
|
|
453
|
-
* and whether the contract instance with the given address has been publicly deployed.
|
|
454
|
-
* @remark - it queries the node to check whether the contract instance has been initialized / publicly deployed through a node.
|
|
455
|
-
* This query is not dependent on the PXE.
|
|
456
|
-
* @param address - The address that the contract instance resides at.
|
|
457
|
-
* @returns - It returns the contract metadata
|
|
458
|
-
* TODO(@spalladino): Should we return the public keys in plain as well here?
|
|
459
|
-
*/
|
|
460
|
-
public async getContractMetadata(address: AztecAddress): Promise<{
|
|
461
|
-
contractInstance: ContractInstanceWithAddress | undefined;
|
|
462
|
-
isContractInitialized: boolean;
|
|
463
|
-
isContractPublished: boolean;
|
|
464
|
-
}> {
|
|
465
|
-
let instance;
|
|
466
|
-
try {
|
|
467
|
-
instance = await this.contractStore.getContractInstance(address);
|
|
468
|
-
} catch {
|
|
469
|
-
this.log.warn(`No instance found for contract ${address.toString()} when looking for its metadata`);
|
|
470
|
-
}
|
|
471
|
-
return {
|
|
472
|
-
contractInstance: instance,
|
|
473
|
-
isContractInitialized: await this.#isContractInitialized(address),
|
|
474
|
-
isContractPublished: await this.#isContractPublished(address),
|
|
475
|
-
};
|
|
403
|
+
public async getContractArtifact(id: Fr): Promise<ContractArtifact | undefined> {
|
|
404
|
+
return await this.contractStore.getContractArtifact(id);
|
|
476
405
|
}
|
|
477
406
|
|
|
478
407
|
/**
|