@aztec/pxe 0.32.1 → 0.34.0
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/database/kv_pxe_database.d.ts +1 -1
- package/dest/database/kv_pxe_database.d.ts.map +1 -1
- package/dest/database/pxe_database.d.ts +1 -1
- package/dest/database/pxe_database.d.ts.map +1 -1
- package/dest/kernel_prover/kernel_prover.d.ts +3 -42
- package/dest/kernel_prover/kernel_prover.d.ts.map +1 -1
- package/dest/kernel_prover/kernel_prover.js +9 -37
- package/dest/kernel_prover/proof_creator.d.ts +3 -3
- package/dest/kernel_prover/proof_creator.d.ts.map +1 -1
- package/dest/kernel_prover/proof_creator.js +7 -9
- package/dest/note_processor/note_processor.d.ts +8 -10
- package/dest/note_processor/note_processor.d.ts.map +1 -1
- package/dest/note_processor/note_processor.js +22 -24
- package/dest/pxe_http/pxe_http_server.d.ts.map +1 -1
- package/dest/pxe_http/pxe_http_server.js +3 -3
- package/dest/pxe_service/pxe_service.d.ts +3 -2
- package/dest/pxe_service/pxe_service.d.ts.map +1 -1
- package/dest/pxe_service/pxe_service.js +58 -40
- package/dest/pxe_service/test/pxe_test_suite.js +3 -3
- package/dest/simulator_oracle/index.d.ts +1 -1
- package/dest/simulator_oracle/index.d.ts.map +1 -1
- package/dest/synchronizer/synchronizer.d.ts.map +1 -1
- package/dest/synchronizer/synchronizer.js +16 -20
- package/package.json +22 -16
- package/src/database/kv_pxe_database.ts +1 -1
- package/src/database/pxe_database.ts +1 -1
- package/src/kernel_prover/kernel_prover.ts +22 -88
- package/src/kernel_prover/proof_creator.ts +10 -10
- package/src/note_processor/note_processor.ts +25 -30
- package/src/pxe_http/pxe_http_server.ts +2 -1
- package/src/pxe_service/pxe_service.ts +69 -46
- package/src/pxe_service/test/pxe_test_suite.ts +2 -2
- package/src/synchronizer/synchronizer.ts +18 -22
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
type EncryptedL2BlockL2Logs,
|
|
4
4
|
type KeyStore,
|
|
5
5
|
L1NotePayload,
|
|
6
|
-
type
|
|
6
|
+
type L2Block,
|
|
7
7
|
TaggedNote,
|
|
8
8
|
} from '@aztec/circuit-types';
|
|
9
9
|
import { type NoteProcessorStats } from '@aztec/circuit-types/stats';
|
|
@@ -25,9 +25,9 @@ import { produceNoteDao } from './produce_note_dao.js';
|
|
|
25
25
|
*/
|
|
26
26
|
interface ProcessedData {
|
|
27
27
|
/**
|
|
28
|
-
* Holds L2 block
|
|
28
|
+
* Holds L2 block.
|
|
29
29
|
*/
|
|
30
|
-
|
|
30
|
+
block: L2Block;
|
|
31
31
|
/**
|
|
32
32
|
* DAOs of processed notes.
|
|
33
33
|
*/
|
|
@@ -82,25 +82,20 @@ export class NoteProcessor {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
/**
|
|
85
|
-
*
|
|
86
|
-
* It synchronizes the user's account by decrypting the encrypted logs and processing
|
|
87
|
-
* the transactions and auxiliary data associated with them.
|
|
88
|
-
* Throws an error if the number of block contexts and encrypted logs do not match.
|
|
85
|
+
* Extracts new user-relevant notes from the information contained in the provided L2 blocks and encrypted logs.
|
|
89
86
|
*
|
|
90
|
-
* @
|
|
91
|
-
* @param
|
|
87
|
+
* @throws If the number of blocks and encrypted logs do not match.
|
|
88
|
+
* @param l2Blocks - L2 blocks to be processed.
|
|
89
|
+
* @param encryptedL2BlockLogs - Encrypted logs associated with the L2 blocks.
|
|
92
90
|
* @returns A promise that resolves once the processing is completed.
|
|
93
91
|
*/
|
|
94
|
-
public async process(
|
|
95
|
-
|
|
96
|
-
encryptedL2BlockLogs: EncryptedL2BlockL2Logs[],
|
|
97
|
-
): Promise<void> {
|
|
98
|
-
if (l2BlockContexts.length !== encryptedL2BlockLogs.length) {
|
|
92
|
+
public async process(l2Blocks: L2Block[], encryptedL2BlockLogs: EncryptedL2BlockL2Logs[]): Promise<void> {
|
|
93
|
+
if (l2Blocks.length !== encryptedL2BlockLogs.length) {
|
|
99
94
|
throw new Error(
|
|
100
|
-
`Number of blocks and EncryptedLogs is not equal. Received ${
|
|
95
|
+
`Number of blocks and EncryptedLogs is not equal. Received ${l2Blocks.length} blocks, ${encryptedL2BlockLogs.length} encrypted logs.`,
|
|
101
96
|
);
|
|
102
97
|
}
|
|
103
|
-
if (
|
|
98
|
+
if (l2Blocks.length === 0) {
|
|
104
99
|
return;
|
|
105
100
|
}
|
|
106
101
|
|
|
@@ -113,9 +108,10 @@ export class NoteProcessor {
|
|
|
113
108
|
for (let blockIndex = 0; blockIndex < encryptedL2BlockLogs.length; ++blockIndex) {
|
|
114
109
|
this.stats.blocks++;
|
|
115
110
|
const { txLogs } = encryptedL2BlockLogs[blockIndex];
|
|
116
|
-
const
|
|
117
|
-
const
|
|
118
|
-
|
|
111
|
+
const block = l2Blocks[blockIndex];
|
|
112
|
+
const dataStartIndexForBlock =
|
|
113
|
+
block.header.state.partial.noteHashTree.nextAvailableLeafIndex -
|
|
114
|
+
block.body.numberOfTxsIncludingPadded * MAX_NEW_NOTE_HASHES_PER_TX;
|
|
119
115
|
|
|
120
116
|
// We are using set for `userPertainingTxIndices` to avoid duplicates. This would happen in case there were
|
|
121
117
|
// multiple encrypted logs in a tx pertaining to a user.
|
|
@@ -125,8 +121,7 @@ export class NoteProcessor {
|
|
|
125
121
|
// Iterate over all the encrypted logs and try decrypting them. If successful, store the note.
|
|
126
122
|
for (let indexOfTxInABlock = 0; indexOfTxInABlock < txLogs.length; ++indexOfTxInABlock) {
|
|
127
123
|
this.stats.txs++;
|
|
128
|
-
const dataStartIndexForTx =
|
|
129
|
-
dataEndIndexForBlock - (txLogs.length - indexOfTxInABlock) * MAX_NEW_NOTE_HASHES_PER_TX;
|
|
124
|
+
const dataStartIndexForTx = dataStartIndexForBlock + indexOfTxInABlock * MAX_NEW_NOTE_HASHES_PER_TX;
|
|
130
125
|
const newNoteHashes = block.body.txEffects[indexOfTxInABlock].noteHashes;
|
|
131
126
|
// Note: Each tx generates a `TxL2Logs` object and for this reason we can rely on its index corresponding
|
|
132
127
|
// to the index of a tx in a block.
|
|
@@ -139,7 +134,7 @@ export class NoteProcessor {
|
|
|
139
134
|
if (taggedNote?.notePayload) {
|
|
140
135
|
const { notePayload: payload } = taggedNote;
|
|
141
136
|
// We have successfully decrypted the data.
|
|
142
|
-
const txHash =
|
|
137
|
+
const txHash = block.body.txEffects[indexOfTxInABlock].txHash;
|
|
143
138
|
try {
|
|
144
139
|
const noteDao = await produceNoteDao(
|
|
145
140
|
this.simulator,
|
|
@@ -178,7 +173,7 @@ export class NoteProcessor {
|
|
|
178
173
|
}
|
|
179
174
|
|
|
180
175
|
blocksAndNotes.push({
|
|
181
|
-
|
|
176
|
+
block: l2Blocks[blockIndex],
|
|
182
177
|
noteDaos,
|
|
183
178
|
});
|
|
184
179
|
}
|
|
@@ -186,10 +181,10 @@ export class NoteProcessor {
|
|
|
186
181
|
await this.processBlocksAndNotes(blocksAndNotes);
|
|
187
182
|
await this.processDeferredNotes(deferredNoteDaos);
|
|
188
183
|
|
|
189
|
-
const syncedToBlock =
|
|
184
|
+
const syncedToBlock = l2Blocks[l2Blocks.length - 1].number;
|
|
190
185
|
await this.db.setSynchedBlockNumberForPublicKey(this.publicKey, syncedToBlock);
|
|
191
186
|
|
|
192
|
-
this.log(`Synched block ${syncedToBlock}`);
|
|
187
|
+
this.log.debug(`Synched block ${syncedToBlock}`);
|
|
193
188
|
}
|
|
194
189
|
|
|
195
190
|
/**
|
|
@@ -199,14 +194,14 @@ export class NoteProcessor {
|
|
|
199
194
|
* transaction auxiliary data from the database. This function keeps track of new nullifiers
|
|
200
195
|
* and ensures all other transactions are updated with newly settled block information.
|
|
201
196
|
*
|
|
202
|
-
* @param blocksAndNotes - Array of objects containing
|
|
197
|
+
* @param blocksAndNotes - Array of objects containing L2 blocks, user-pertaining transaction indices, and NoteDaos.
|
|
203
198
|
*/
|
|
204
199
|
private async processBlocksAndNotes(blocksAndNotes: ProcessedData[]) {
|
|
205
200
|
const noteDaos = blocksAndNotes.flatMap(b => b.noteDaos);
|
|
206
201
|
if (noteDaos.length) {
|
|
207
202
|
await this.db.addNotes(noteDaos);
|
|
208
203
|
noteDaos.forEach(noteDao => {
|
|
209
|
-
this.log(
|
|
204
|
+
this.log.verbose(
|
|
210
205
|
`Added note for contract ${noteDao.contractAddress} at slot ${
|
|
211
206
|
noteDao.storageSlot
|
|
212
207
|
} with nullifier ${noteDao.siloedNullifier.toString()}`,
|
|
@@ -215,11 +210,11 @@ export class NoteProcessor {
|
|
|
215
210
|
}
|
|
216
211
|
|
|
217
212
|
const newNullifiers: Fr[] = blocksAndNotes.flatMap(b =>
|
|
218
|
-
b.
|
|
213
|
+
b.block.body.txEffects.flatMap(txEffect => txEffect.nullifiers),
|
|
219
214
|
);
|
|
220
215
|
const removedNotes = await this.db.removeNullifiedNotes(newNullifiers, this.publicKey);
|
|
221
216
|
removedNotes.forEach(noteDao => {
|
|
222
|
-
this.log(
|
|
217
|
+
this.log.verbose(
|
|
223
218
|
`Removed note for contract ${noteDao.contractAddress} at slot ${
|
|
224
219
|
noteDao.storageSlot
|
|
225
220
|
} with nullifier ${noteDao.siloedNullifier.toString()}`,
|
|
@@ -236,7 +231,7 @@ export class NoteProcessor {
|
|
|
236
231
|
if (deferredNoteDaos.length) {
|
|
237
232
|
await this.db.addDeferredNotes(deferredNoteDaos);
|
|
238
233
|
deferredNoteDaos.forEach(noteDao => {
|
|
239
|
-
this.log(
|
|
234
|
+
this.log.verbose(
|
|
240
235
|
`Deferred note for contract ${noteDao.contractAddress} at slot ${
|
|
241
236
|
noteDao.storageSlot
|
|
242
237
|
} in tx ${noteDao.txHash.toString()}`,
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
Note,
|
|
10
10
|
NullifierMembershipWitness,
|
|
11
11
|
type PXE,
|
|
12
|
+
SimulatedTx,
|
|
12
13
|
Tx,
|
|
13
14
|
TxEffect,
|
|
14
15
|
TxExecutionRequest,
|
|
@@ -49,7 +50,7 @@ export function createPXERpcServer(pxeService: PXE): JsonRpcServer {
|
|
|
49
50
|
TxEffect,
|
|
50
51
|
LogId,
|
|
51
52
|
},
|
|
52
|
-
{ Tx, TxReceipt, EncryptedL2BlockL2Logs, UnencryptedL2BlockL2Logs, NullifierMembershipWitness },
|
|
53
|
+
{ SimulatedTx, Tx, TxReceipt, EncryptedL2BlockL2Logs, UnencryptedL2BlockL2Logs, NullifierMembershipWitness },
|
|
53
54
|
['start', 'stop'],
|
|
54
55
|
);
|
|
55
56
|
}
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
MerkleTreeId,
|
|
12
12
|
type NoteFilter,
|
|
13
13
|
type PXE,
|
|
14
|
+
SimulatedTx,
|
|
14
15
|
SimulationError,
|
|
15
16
|
Tx,
|
|
16
17
|
type TxEffect,
|
|
@@ -27,8 +28,7 @@ import {
|
|
|
27
28
|
CompleteAddress,
|
|
28
29
|
FunctionData,
|
|
29
30
|
type GrumpkinPrivateKey,
|
|
30
|
-
|
|
31
|
-
MAX_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX,
|
|
31
|
+
MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX,
|
|
32
32
|
type PartialAddress,
|
|
33
33
|
type PrivateKernelTailCircuitPublicInputs,
|
|
34
34
|
type PublicCallRequest,
|
|
@@ -71,7 +71,7 @@ export class PXEService implements PXE {
|
|
|
71
71
|
private simulator: AcirSimulator;
|
|
72
72
|
private log: DebugLogger;
|
|
73
73
|
private nodeVersion: string;
|
|
74
|
-
// serialize synchronizer and calls to
|
|
74
|
+
// serialize synchronizer and calls to proveTx.
|
|
75
75
|
// ensures that state is not changed while simulating
|
|
76
76
|
private jobQueue = new SerialQueue();
|
|
77
77
|
|
|
@@ -121,7 +121,7 @@ export class PXEService implements PXE {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
if (count > 0) {
|
|
124
|
-
this.log(`Restored ${count} accounts`);
|
|
124
|
+
this.log.info(`Restored ${count} accounts`);
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
|
|
@@ -388,26 +388,43 @@ export class PXEService implements PXE {
|
|
|
388
388
|
return await this.node.getBlock(blockNumber);
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
-
public async
|
|
391
|
+
public async proveTx(txRequest: TxExecutionRequest, simulatePublic: boolean) {
|
|
392
|
+
return (await this.simulateTx(txRequest, simulatePublic)).tx;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
public async simulateTx(
|
|
396
|
+
txRequest: TxExecutionRequest,
|
|
397
|
+
simulatePublic: boolean,
|
|
398
|
+
msgSender: AztecAddress | undefined = undefined,
|
|
399
|
+
) {
|
|
392
400
|
if (!txRequest.functionData.isPrivate) {
|
|
393
401
|
throw new Error(`Public entrypoints are not allowed`);
|
|
394
402
|
}
|
|
395
|
-
|
|
396
|
-
// all simulations must be serialized w.r.t. the synchronizer
|
|
397
403
|
return await this.jobQueue.put(async () => {
|
|
398
404
|
const timer = new Timer();
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
+
const simulatedTx = await this.#simulateAndProve(txRequest, msgSender);
|
|
406
|
+
// We log only if the msgSender is undefined, as simulating with a different msgSender
|
|
407
|
+
// is unlikely to be a real transaction, and likely to be only used to read data.
|
|
408
|
+
// Meaning that it will not necessarily have produced a nullifier (and thus have no TxHash)
|
|
409
|
+
// If we log, the `getTxHash` function will throw.
|
|
410
|
+
|
|
411
|
+
if (!msgSender) {
|
|
412
|
+
this.log.debug(`Processed private part of ${simulatedTx.tx.getTxHash()}`, {
|
|
413
|
+
eventName: 'tx-pxe-processing',
|
|
414
|
+
duration: timer.ms(),
|
|
415
|
+
...simulatedTx.tx.getStats(),
|
|
416
|
+
} satisfies TxPXEProcessingStats);
|
|
417
|
+
}
|
|
418
|
+
|
|
405
419
|
if (simulatePublic) {
|
|
406
|
-
|
|
420
|
+
// Only one transaction, so we can take index 0.
|
|
421
|
+
simulatedTx.publicReturnValues = (await this.#simulatePublicCalls(simulatedTx.tx))[0];
|
|
407
422
|
}
|
|
408
|
-
this.log.info(`Executed local simulation for ${tx.getTxHash()}`);
|
|
409
423
|
|
|
410
|
-
|
|
424
|
+
if (!msgSender) {
|
|
425
|
+
this.log.info(`Executed local simulation for ${simulatedTx.tx.getTxHash()}`);
|
|
426
|
+
}
|
|
427
|
+
return simulatedTx;
|
|
411
428
|
});
|
|
412
429
|
}
|
|
413
430
|
|
|
@@ -524,15 +541,15 @@ export class PXEService implements PXE {
|
|
|
524
541
|
};
|
|
525
542
|
}
|
|
526
543
|
|
|
527
|
-
async #simulate(txRequest: TxExecutionRequest): Promise<ExecutionResult> {
|
|
544
|
+
async #simulate(txRequest: TxExecutionRequest, msgSender?: AztecAddress): Promise<ExecutionResult> {
|
|
528
545
|
// TODO - Pause syncing while simulating.
|
|
529
546
|
|
|
530
547
|
const { contractAddress, functionArtifact, portalContract } = await this.#getSimulationParameters(txRequest);
|
|
531
548
|
|
|
532
|
-
this.log('Executing simulator...');
|
|
549
|
+
this.log.debug('Executing simulator...');
|
|
533
550
|
try {
|
|
534
|
-
const result = await this.simulator.run(txRequest, functionArtifact, contractAddress, portalContract);
|
|
535
|
-
this.log(
|
|
551
|
+
const result = await this.simulator.run(txRequest, functionArtifact, contractAddress, portalContract, msgSender);
|
|
552
|
+
this.log.verbose(`Simulation completed for ${contractAddress.toString()}:${functionArtifact.name}`);
|
|
536
553
|
return result;
|
|
537
554
|
} catch (err) {
|
|
538
555
|
if (err instanceof SimulationError) {
|
|
@@ -553,10 +570,10 @@ export class PXEService implements PXE {
|
|
|
553
570
|
async #simulateUnconstrained(execRequest: FunctionCall) {
|
|
554
571
|
const { contractAddress, functionArtifact } = await this.#getSimulationParameters(execRequest);
|
|
555
572
|
|
|
556
|
-
this.log('Executing unconstrained simulator...');
|
|
573
|
+
this.log.debug('Executing unconstrained simulator...');
|
|
557
574
|
try {
|
|
558
575
|
const result = await this.simulator.runUnconstrained(execRequest, functionArtifact, contractAddress);
|
|
559
|
-
this.log(
|
|
576
|
+
this.log.verbose(`Unconstrained simulation for ${contractAddress}.${functionArtifact.name} completed`);
|
|
560
577
|
|
|
561
578
|
return result;
|
|
562
579
|
} catch (err) {
|
|
@@ -575,7 +592,7 @@ export class PXEService implements PXE {
|
|
|
575
592
|
*/
|
|
576
593
|
async #simulatePublicCalls(tx: Tx) {
|
|
577
594
|
try {
|
|
578
|
-
await this.node.simulatePublicCalls(tx);
|
|
595
|
+
return await this.node.simulatePublicCalls(tx);
|
|
579
596
|
} catch (err) {
|
|
580
597
|
// Try to fill in the noir call stack since the PXE may have access to the debug metadata
|
|
581
598
|
if (err instanceof SimulationError) {
|
|
@@ -599,28 +616,26 @@ export class PXEService implements PXE {
|
|
|
599
616
|
|
|
600
617
|
/**
|
|
601
618
|
* Simulate a transaction, generate a kernel proof, and create a private transaction object.
|
|
602
|
-
* The function takes in a transaction request
|
|
603
|
-
*
|
|
619
|
+
* The function takes in a transaction request, simulates it, and then generates a kernel proof
|
|
620
|
+
* using the simulation result. Finally, it creates a private
|
|
604
621
|
* transaction object with the generated proof and public inputs. If a new contract address is provided,
|
|
605
622
|
* the function will also include the new contract's public functions in the transaction object.
|
|
606
623
|
*
|
|
607
624
|
* @param txExecutionRequest - The transaction request to be simulated and proved.
|
|
608
625
|
* @param signature - The ECDSA signature for the transaction request.
|
|
609
|
-
* @
|
|
626
|
+
* @param msgSender - (Optional) The message sender to use for the simulation.
|
|
627
|
+
* @returns An object tract contains:
|
|
628
|
+
* A private transaction object containing the proof, public inputs, and encrypted logs.
|
|
629
|
+
* The return values of the private execution
|
|
610
630
|
*/
|
|
611
|
-
async #simulateAndProve(txExecutionRequest: TxExecutionRequest) {
|
|
612
|
-
// TODO - Pause syncing while simulating.
|
|
613
|
-
|
|
631
|
+
async #simulateAndProve(txExecutionRequest: TxExecutionRequest, msgSender?: AztecAddress) {
|
|
614
632
|
// Get values that allow us to reconstruct the block hash
|
|
615
|
-
const executionResult = await this.#simulate(txExecutionRequest);
|
|
633
|
+
const executionResult = await this.#simulate(txExecutionRequest, msgSender);
|
|
616
634
|
|
|
617
635
|
const kernelOracle = new KernelOracle(this.contractDataOracle, this.keyStore, this.node);
|
|
618
636
|
const kernelProver = new KernelProver(kernelOracle);
|
|
619
|
-
this.log(`Executing kernel prover...`);
|
|
637
|
+
this.log.debug(`Executing kernel prover...`);
|
|
620
638
|
const { proof, publicInputs } = await kernelProver.prove(txExecutionRequest.toTxRequest(), executionResult);
|
|
621
|
-
this.log(
|
|
622
|
-
`Needs setup: ${publicInputs.needsSetup}, needs app logic: ${publicInputs.needsAppLogic}, needs teardown: ${publicInputs.needsTeardown}`,
|
|
623
|
-
);
|
|
624
639
|
|
|
625
640
|
const encryptedLogs = new EncryptedTxL2Logs(collectEncryptedLogs(executionResult));
|
|
626
641
|
const unencryptedLogs = new UnencryptedTxL2Logs(collectUnencryptedLogs(executionResult));
|
|
@@ -630,7 +645,8 @@ export class PXEService implements PXE {
|
|
|
630
645
|
// TODO(#757): Enforce proper ordering of enqueued public calls
|
|
631
646
|
await this.patchPublicCallStackOrdering(publicInputs, enqueuedPublicFunctions);
|
|
632
647
|
|
|
633
|
-
|
|
648
|
+
const tx = new Tx(publicInputs, proof, encryptedLogs, unencryptedLogs, enqueuedPublicFunctions);
|
|
649
|
+
return new SimulatedTx(tx, [executionResult.returnValues]);
|
|
634
650
|
}
|
|
635
651
|
|
|
636
652
|
/**
|
|
@@ -681,55 +697,62 @@ export class PXEService implements PXE {
|
|
|
681
697
|
publicInputs: PrivateKernelTailCircuitPublicInputs,
|
|
682
698
|
enqueuedPublicCalls: PublicCallRequest[],
|
|
683
699
|
) {
|
|
700
|
+
if (!publicInputs.forPublic) {
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
|
|
684
704
|
const enqueuedPublicCallStackItems = await Promise.all(enqueuedPublicCalls.map(c => c.toCallRequest()));
|
|
685
705
|
|
|
686
706
|
// Validate all items in enqueued public calls are in the kernel emitted stack
|
|
687
707
|
const enqueuedRevertiblePublicCallStackItems = enqueuedPublicCallStackItems.filter(enqueued =>
|
|
688
|
-
publicInputs.end.publicCallStack.find(item => item.equals(enqueued)),
|
|
708
|
+
publicInputs.forPublic!.end.publicCallStack.find(item => item.equals(enqueued)),
|
|
689
709
|
);
|
|
690
710
|
|
|
691
|
-
const revertibleStackSize = arrayNonEmptyLength(publicInputs.end.publicCallStack, item => item.isEmpty());
|
|
711
|
+
const revertibleStackSize = arrayNonEmptyLength(publicInputs.forPublic.end.publicCallStack, item => item.isEmpty());
|
|
692
712
|
|
|
693
713
|
if (enqueuedRevertiblePublicCallStackItems.length !== revertibleStackSize) {
|
|
694
714
|
throw new Error(
|
|
695
715
|
`Enqueued revertible public function calls and revertible public call stack do not match.\nEnqueued calls: ${enqueuedRevertiblePublicCallStackItems
|
|
696
716
|
.map(h => h.hash.toString())
|
|
697
|
-
.join(', ')}\nPublic call stack: ${publicInputs.end.publicCallStack
|
|
717
|
+
.join(', ')}\nPublic call stack: ${publicInputs.forPublic.end.publicCallStack
|
|
718
|
+
.map(i => i.toString())
|
|
719
|
+
.join(', ')}`,
|
|
698
720
|
);
|
|
699
721
|
}
|
|
700
722
|
|
|
701
723
|
// Override kernel output
|
|
702
|
-
publicInputs.end.publicCallStack = padArrayEnd(
|
|
724
|
+
publicInputs.forPublic.end.publicCallStack = padArrayEnd(
|
|
703
725
|
enqueuedRevertiblePublicCallStackItems,
|
|
704
726
|
CallRequest.empty(),
|
|
705
|
-
|
|
727
|
+
MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX,
|
|
706
728
|
);
|
|
707
729
|
|
|
708
730
|
// Do the same for non-revertible
|
|
709
731
|
|
|
710
732
|
const enqueuedNonRevertiblePublicCallStackItems = enqueuedPublicCallStackItems.filter(enqueued =>
|
|
711
|
-
publicInputs.endNonRevertibleData.publicCallStack.find(item => item.equals(enqueued)),
|
|
733
|
+
publicInputs.forPublic!.endNonRevertibleData.publicCallStack.find(item => item.equals(enqueued)),
|
|
712
734
|
);
|
|
713
735
|
|
|
714
|
-
const nonRevertibleStackSize = arrayNonEmptyLength(
|
|
715
|
-
|
|
736
|
+
const nonRevertibleStackSize = arrayNonEmptyLength(
|
|
737
|
+
publicInputs.forPublic.endNonRevertibleData.publicCallStack,
|
|
738
|
+
item => item.isEmpty(),
|
|
716
739
|
);
|
|
717
740
|
|
|
718
741
|
if (enqueuedNonRevertiblePublicCallStackItems.length !== nonRevertibleStackSize) {
|
|
719
742
|
throw new Error(
|
|
720
743
|
`Enqueued non-revertible public function calls and non-revertible public call stack do not match.\nEnqueued calls: ${enqueuedNonRevertiblePublicCallStackItems
|
|
721
744
|
.map(h => h.hash.toString())
|
|
722
|
-
.join(', ')}\nPublic call stack: ${publicInputs.endNonRevertibleData.publicCallStack
|
|
745
|
+
.join(', ')}\nPublic call stack: ${publicInputs.forPublic.endNonRevertibleData.publicCallStack
|
|
723
746
|
.map(i => i.toString())
|
|
724
747
|
.join(', ')}`,
|
|
725
748
|
);
|
|
726
749
|
}
|
|
727
750
|
|
|
728
751
|
// Override kernel output
|
|
729
|
-
publicInputs.endNonRevertibleData.publicCallStack = padArrayEnd(
|
|
752
|
+
publicInputs.forPublic.endNonRevertibleData.publicCallStack = padArrayEnd(
|
|
730
753
|
enqueuedNonRevertiblePublicCallStackItems,
|
|
731
754
|
CallRequest.empty(),
|
|
732
|
-
|
|
755
|
+
MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX,
|
|
733
756
|
);
|
|
734
757
|
}
|
|
735
758
|
|
|
@@ -135,12 +135,12 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise<PXE>) =>
|
|
|
135
135
|
authWitnesses: [],
|
|
136
136
|
});
|
|
137
137
|
|
|
138
|
-
await expect(async () => await pxe.
|
|
138
|
+
await expect(async () => await pxe.proveTx(txExecutionRequest, false)).rejects.toThrow(
|
|
139
139
|
'Public entrypoints are not allowed',
|
|
140
140
|
);
|
|
141
141
|
});
|
|
142
142
|
|
|
143
|
-
// Note: Not testing a successful run of `
|
|
143
|
+
// Note: Not testing a successful run of `proveTx`, `sendTx`, `getTxReceipt` and `viewTx` here as it requires
|
|
144
144
|
// a larger setup and it's sufficiently tested in the e2e tests.
|
|
145
145
|
|
|
146
146
|
it('throws when getting public storage for non-existent contract', async () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type AztecNode,
|
|
3
3
|
type KeyStore,
|
|
4
|
-
|
|
4
|
+
type L2Block,
|
|
5
5
|
L2BlockL2Logs,
|
|
6
6
|
MerkleTreeId,
|
|
7
7
|
type TxHash,
|
|
@@ -51,10 +51,10 @@ export class Synchronizer {
|
|
|
51
51
|
this.running = true;
|
|
52
52
|
|
|
53
53
|
await this.jobQueue.put(() => this.initialSync());
|
|
54
|
-
this.log('Initial sync complete');
|
|
54
|
+
this.log.info('Initial sync complete');
|
|
55
55
|
this.runningPromise = new RunningPromise(() => this.sync(limit), retryInterval);
|
|
56
56
|
this.runningPromise.start();
|
|
57
|
-
this.log('Started loop');
|
|
57
|
+
this.log.debug('Started loop');
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
protected async initialSync() {
|
|
@@ -107,17 +107,16 @@ export class Synchronizer {
|
|
|
107
107
|
|
|
108
108
|
const encryptedLogs = blocks.flatMap(block => block.body.encryptedLogs);
|
|
109
109
|
|
|
110
|
-
// Wrap blocks in block contexts & only keep those that match our query
|
|
111
|
-
const blockContexts = blocks.filter(block => block.number >= from).map(block => new L2BlockContext(block));
|
|
112
|
-
|
|
113
110
|
// Update latest tree roots from the most recent block
|
|
114
|
-
const latestBlock =
|
|
111
|
+
const latestBlock = blocks[blocks.length - 1];
|
|
115
112
|
await this.setHeaderFromBlock(latestBlock);
|
|
116
113
|
|
|
117
114
|
const logCount = L2BlockL2Logs.getTotalLogCount(encryptedLogs);
|
|
118
|
-
this.log(
|
|
115
|
+
this.log.debug(
|
|
116
|
+
`Forwarding ${logCount} encrypted logs and blocks to ${this.noteProcessors.length} note processors`,
|
|
117
|
+
);
|
|
119
118
|
for (const noteProcessor of this.noteProcessors) {
|
|
120
|
-
await noteProcessor.process(
|
|
119
|
+
await noteProcessor.process(blocks, encryptedLogs);
|
|
121
120
|
}
|
|
122
121
|
return true;
|
|
123
122
|
} catch (err) {
|
|
@@ -185,14 +184,12 @@ export class Synchronizer {
|
|
|
185
184
|
|
|
186
185
|
const encryptedLogs = blocks.flatMap(block => block.body.encryptedLogs);
|
|
187
186
|
|
|
188
|
-
const blockContexts = blocks.map(block => new L2BlockContext(block));
|
|
189
|
-
|
|
190
187
|
const logCount = L2BlockL2Logs.getTotalLogCount(encryptedLogs);
|
|
191
|
-
this.log(`Forwarding ${logCount} encrypted logs and blocks to note processors in catch up mode`);
|
|
188
|
+
this.log.debug(`Forwarding ${logCount} encrypted logs and blocks to note processors in catch up mode`);
|
|
192
189
|
|
|
193
190
|
for (const noteProcessor of catchUpGroup) {
|
|
194
191
|
// find the index of the first block that the note processor is not yet synced to
|
|
195
|
-
const index =
|
|
192
|
+
const index = blocks.findIndex(block => block.number > noteProcessor.status.syncedToBlock);
|
|
196
193
|
if (index === -1) {
|
|
197
194
|
// Due to the limit, we might not have fetched a new enough block for the note processor.
|
|
198
195
|
// And since the group is sorted, we break as soon as we find a note processor
|
|
@@ -202,14 +199,14 @@ export class Synchronizer {
|
|
|
202
199
|
|
|
203
200
|
this.log.debug(
|
|
204
201
|
`Catching up note processor ${noteProcessor.publicKey.toString()} by processing ${
|
|
205
|
-
|
|
202
|
+
blocks.length - index
|
|
206
203
|
} blocks`,
|
|
207
204
|
);
|
|
208
|
-
await noteProcessor.process(
|
|
205
|
+
await noteProcessor.process(blocks.slice(index), encryptedLogs.slice(index));
|
|
209
206
|
|
|
210
207
|
if (noteProcessor.status.syncedToBlock === toBlockNumber) {
|
|
211
208
|
// Note processor caught up, move it to `noteProcessors` from `noteProcessorsToCatchUp`.
|
|
212
|
-
this.log(`Note processor for ${noteProcessor.publicKey.toString()} has caught up`, {
|
|
209
|
+
this.log.debug(`Note processor for ${noteProcessor.publicKey.toString()} has caught up`, {
|
|
213
210
|
eventName: 'note-processor-caught-up',
|
|
214
211
|
publicKey: noteProcessor.publicKey.toString(),
|
|
215
212
|
duration: noteProcessor.timer.ms(),
|
|
@@ -231,13 +228,12 @@ export class Synchronizer {
|
|
|
231
228
|
}
|
|
232
229
|
}
|
|
233
230
|
|
|
234
|
-
private async setHeaderFromBlock(latestBlock:
|
|
235
|
-
|
|
236
|
-
if (block.number < this.initialSyncBlockNumber) {
|
|
231
|
+
private async setHeaderFromBlock(latestBlock: L2Block) {
|
|
232
|
+
if (latestBlock.number < this.initialSyncBlockNumber) {
|
|
237
233
|
return;
|
|
238
234
|
}
|
|
239
235
|
|
|
240
|
-
await this.db.setHeader(
|
|
236
|
+
await this.db.setHeader(latestBlock.header);
|
|
241
237
|
}
|
|
242
238
|
|
|
243
239
|
/**
|
|
@@ -250,7 +246,7 @@ export class Synchronizer {
|
|
|
250
246
|
public async stop() {
|
|
251
247
|
this.running = false;
|
|
252
248
|
await this.runningPromise?.stop();
|
|
253
|
-
this.log('Stopped');
|
|
249
|
+
this.log.info('Stopped');
|
|
254
250
|
}
|
|
255
251
|
|
|
256
252
|
/**
|
|
@@ -360,7 +356,7 @@ export class Synchronizer {
|
|
|
360
356
|
await this.db.addNotes(newNotes);
|
|
361
357
|
|
|
362
358
|
newNotes.forEach(noteDao => {
|
|
363
|
-
this.log(
|
|
359
|
+
this.log.debug(
|
|
364
360
|
`Decoded deferred note for contract ${noteDao.contractAddress} at slot ${
|
|
365
361
|
noteDao.storageSlot
|
|
366
362
|
} with nullifier ${noteDao.siloedNullifier.toString()}`,
|