@aztec/sequencer-client 0.22.0 → 0.24.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.
Files changed (76) hide show
  1. package/dest/block_builder/solo_block_builder.d.ts +2 -2
  2. package/dest/block_builder/solo_block_builder.d.ts.map +1 -1
  3. package/dest/block_builder/solo_block_builder.js +3 -3
  4. package/dest/client/sequencer-client.d.ts +2 -0
  5. package/dest/client/sequencer-client.d.ts.map +1 -1
  6. package/dest/client/sequencer-client.js +7 -1
  7. package/dest/config.d.ts.map +1 -1
  8. package/dest/config.js +6 -2
  9. package/dest/global_variable_builder/global_builder.d.ts +7 -3
  10. package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
  11. package/dest/global_variable_builder/global_builder.js +6 -4
  12. package/dest/prover/empty.d.ts +2 -2
  13. package/dest/prover/empty.d.ts.map +1 -1
  14. package/dest/prover/empty.js +1 -1
  15. package/dest/prover/index.d.ts +2 -2
  16. package/dest/prover/index.d.ts.map +1 -1
  17. package/dest/sequencer/abstract_phase_manager.d.ts +11 -11
  18. package/dest/sequencer/abstract_phase_manager.d.ts.map +1 -1
  19. package/dest/sequencer/abstract_phase_manager.js +18 -15
  20. package/dest/sequencer/application_logic_phase_manager.d.ts +3 -3
  21. package/dest/sequencer/application_logic_phase_manager.d.ts.map +1 -1
  22. package/dest/sequencer/application_logic_phase_manager.js +2 -2
  23. package/dest/sequencer/fee_distribution_phase_manager.d.ts +4 -4
  24. package/dest/sequencer/fee_distribution_phase_manager.d.ts.map +1 -1
  25. package/dest/sequencer/fee_distribution_phase_manager.js +2 -2
  26. package/dest/sequencer/fee_preparation_phase_manager.d.ts +3 -3
  27. package/dest/sequencer/fee_preparation_phase_manager.d.ts.map +1 -1
  28. package/dest/sequencer/fee_preparation_phase_manager.js +1 -2
  29. package/dest/sequencer/processed_tx.d.ts +3 -3
  30. package/dest/sequencer/processed_tx.d.ts.map +1 -1
  31. package/dest/sequencer/processed_tx.js +4 -4
  32. package/dest/sequencer/public_processor.d.ts.map +1 -1
  33. package/dest/sequencer/public_processor.js +1 -1
  34. package/dest/sequencer/sequencer.d.ts +5 -1
  35. package/dest/sequencer/sequencer.d.ts.map +1 -1
  36. package/dest/sequencer/sequencer.js +18 -2
  37. package/dest/simulator/index.d.ts +3 -3
  38. package/dest/simulator/index.d.ts.map +1 -1
  39. package/dest/simulator/public_kernel.d.ts +3 -3
  40. package/dest/simulator/public_kernel.d.ts.map +1 -1
  41. package/dest/simulator/public_kernel.js +4 -4
  42. package/dest/simulator/rollup.js +2 -2
  43. package/package.json +12 -23
  44. package/src/block_builder/index.ts +24 -0
  45. package/src/block_builder/solo_block_builder.ts +715 -0
  46. package/src/block_builder/types.ts +8 -0
  47. package/src/client/index.ts +1 -0
  48. package/src/client/sequencer-client.ts +97 -0
  49. package/src/config.ts +86 -0
  50. package/src/global_variable_builder/config.ts +20 -0
  51. package/src/global_variable_builder/global_builder.ts +95 -0
  52. package/src/global_variable_builder/index.ts +16 -0
  53. package/src/global_variable_builder/viem-reader.ts +61 -0
  54. package/src/index.ts +15 -0
  55. package/src/mocks/verification_keys.ts +36 -0
  56. package/src/prover/empty.ts +74 -0
  57. package/src/prover/index.ts +53 -0
  58. package/src/publisher/config.ts +41 -0
  59. package/src/publisher/index.ts +14 -0
  60. package/src/publisher/l1-publisher.ts +365 -0
  61. package/src/publisher/viem-tx-sender.ts +241 -0
  62. package/src/receiver.ts +13 -0
  63. package/src/sequencer/abstract_phase_manager.ts +427 -0
  64. package/src/sequencer/application_logic_phase_manager.ts +107 -0
  65. package/src/sequencer/config.ts +1 -0
  66. package/src/sequencer/fee_distribution_phase_manager.ts +70 -0
  67. package/src/sequencer/fee_preparation_phase_manager.ts +79 -0
  68. package/src/sequencer/index.ts +2 -0
  69. package/src/sequencer/processed_tx.ts +95 -0
  70. package/src/sequencer/public_processor.ts +136 -0
  71. package/src/sequencer/sequencer.ts +462 -0
  72. package/src/simulator/index.ts +53 -0
  73. package/src/simulator/public_executor.ts +169 -0
  74. package/src/simulator/public_kernel.ts +58 -0
  75. package/src/simulator/rollup.ts +76 -0
  76. package/src/utils.ts +16 -0
@@ -0,0 +1,427 @@
1
+ import { FunctionL2Logs, MerkleTreeId, Tx } from '@aztec/circuit-types';
2
+ import {
3
+ AztecAddress,
4
+ CallRequest,
5
+ CombinedAccumulatedData,
6
+ ContractStorageRead,
7
+ ContractStorageUpdateRequest,
8
+ Fr,
9
+ GlobalVariables,
10
+ Header,
11
+ MAX_NEW_COMMITMENTS_PER_CALL,
12
+ MAX_NEW_L2_TO_L1_MSGS_PER_CALL,
13
+ MAX_NEW_NULLIFIERS_PER_CALL,
14
+ MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
15
+ MAX_PUBLIC_DATA_READS_PER_CALL,
16
+ MAX_PUBLIC_DATA_READS_PER_TX,
17
+ MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL,
18
+ MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
19
+ MembershipWitness,
20
+ Proof,
21
+ PublicCallData,
22
+ PublicCallRequest,
23
+ PublicCallStackItem,
24
+ PublicCircuitPublicInputs,
25
+ PublicDataRead,
26
+ PublicDataUpdateRequest,
27
+ PublicKernelCircuitPrivateInputs,
28
+ PublicKernelCircuitPublicInputs,
29
+ PublicKernelData,
30
+ RETURN_VALUES_LENGTH,
31
+ SideEffect,
32
+ SideEffectLinkedToNoteHash,
33
+ VK_TREE_HEIGHT,
34
+ } from '@aztec/circuits.js';
35
+ import { computeVarArgsHash } from '@aztec/circuits.js/abis';
36
+ import { arrayNonEmptyLength, padArrayEnd } from '@aztec/foundation/collection';
37
+ import { createDebugLogger } from '@aztec/foundation/log';
38
+ import { to2Fields } from '@aztec/foundation/serialize';
39
+ import {
40
+ PublicExecution,
41
+ PublicExecutionResult,
42
+ PublicExecutor,
43
+ collectPublicDataReads,
44
+ collectPublicDataUpdateRequests,
45
+ isPublicExecutionResult,
46
+ } from '@aztec/simulator';
47
+ import { MerkleTreeOperations } from '@aztec/world-state';
48
+
49
+ import { env } from 'process';
50
+
51
+ import { getVerificationKeys } from '../mocks/verification_keys.js';
52
+ import { PublicProver } from '../prover/index.js';
53
+ import { PublicKernelCircuitSimulator } from '../simulator/index.js';
54
+ import { FailedTx } from './processed_tx.js';
55
+
56
+ /**
57
+ * A phase manager is responsible for performing/rolling back a phase of a transaction.
58
+ *
59
+ * The phases are as follows:
60
+ * 1. Fee Preparation
61
+ * 2. Application Logic
62
+ * 3. Fee Distribution
63
+ */
64
+ export abstract class AbstractPhaseManager {
65
+ constructor(
66
+ protected db: MerkleTreeOperations,
67
+ protected publicExecutor: PublicExecutor,
68
+ protected publicKernel: PublicKernelCircuitSimulator,
69
+ protected publicProver: PublicProver,
70
+ protected globalVariables: GlobalVariables,
71
+ protected historicalHeader: Header,
72
+ protected log = createDebugLogger('aztec:sequencer:phase-manager'),
73
+ ) {}
74
+ /**
75
+ *
76
+ * @param tx - the tx to be processed
77
+ * @param publicKernelPublicInputs - the output of the public kernel circuit for the previous phase
78
+ * @param previousPublicKernelProof - the proof of the public kernel circuit for the previous phase
79
+ */
80
+ abstract handle(
81
+ tx: Tx,
82
+ publicKernelPublicInputs?: PublicKernelCircuitPublicInputs,
83
+ previousPublicKernelProof?: Proof,
84
+ ): Promise<{
85
+ /**
86
+ * the output of the public kernel circuit for this phase
87
+ */
88
+ publicKernelOutput?: PublicKernelCircuitPublicInputs;
89
+ /**
90
+ * the proof of the public kernel circuit for this phase
91
+ */
92
+ publicKernelProof?: Proof;
93
+ }>;
94
+ abstract nextPhase(): AbstractPhaseManager | undefined;
95
+ abstract rollback(tx: Tx, err: unknown): Promise<FailedTx>;
96
+
97
+ // Extract the public calls from the tx for this phase
98
+ abstract extractEnqueuedPublicCalls(tx: Tx): PublicCallRequest[];
99
+
100
+ protected getKernelOutputAndProof(
101
+ tx: Tx,
102
+ publicKernelPublicInput?: PublicKernelCircuitPublicInputs,
103
+ previousPublicKernelProof?: Proof,
104
+ ): {
105
+ /**
106
+ * the output of the public kernel circuit for this phase
107
+ */
108
+ publicKernelPublicInput: PublicKernelCircuitPublicInputs;
109
+ /**
110
+ * the proof of the public kernel circuit for this phase
111
+ */
112
+ publicKernelProof: Proof;
113
+ } {
114
+ if (publicKernelPublicInput && previousPublicKernelProof) {
115
+ return {
116
+ publicKernelPublicInput: publicKernelPublicInput,
117
+ publicKernelProof: previousPublicKernelProof,
118
+ };
119
+ } else {
120
+ const publicKernelPublicInput = new PublicKernelCircuitPublicInputs(
121
+ tx.data.aggregationObject,
122
+ tx.data.endNonRevertibleData,
123
+ CombinedAccumulatedData.fromFinalAccumulatedData(tx.data.end),
124
+ tx.data.constants,
125
+ tx.data.isPrivate,
126
+ );
127
+ const publicKernelProof = previousPublicKernelProof || tx.proof;
128
+ return {
129
+ publicKernelPublicInput,
130
+ publicKernelProof,
131
+ };
132
+ }
133
+ }
134
+
135
+ protected async processEnqueuedPublicCalls(
136
+ enqueuedCalls: PublicCallRequest[],
137
+ previousPublicKernelOutput: PublicKernelCircuitPublicInputs,
138
+ previousPublicKernelProof: Proof,
139
+ ): Promise<[PublicKernelCircuitPublicInputs, Proof, FunctionL2Logs[]]> {
140
+ if (!enqueuedCalls || !enqueuedCalls.length) {
141
+ throw new Error(`Missing preimages for enqueued public calls`);
142
+ }
143
+ let kernelOutput = previousPublicKernelOutput;
144
+ let kernelProof = previousPublicKernelProof;
145
+
146
+ const newUnencryptedFunctionLogs: FunctionL2Logs[] = [];
147
+
148
+ // TODO(#1684): Should multiple separately enqueued public calls be treated as
149
+ // separate public callstacks to be proven by separate public kernel sequences
150
+ // and submitted separately to the base rollup?
151
+
152
+ for (const enqueuedCall of enqueuedCalls) {
153
+ const executionStack: (PublicExecution | PublicExecutionResult)[] = [enqueuedCall];
154
+
155
+ // Keep track of which result is for the top/enqueued call
156
+ let enqueuedExecutionResult: PublicExecutionResult | undefined;
157
+
158
+ while (executionStack.length) {
159
+ const current = executionStack.pop()!;
160
+ const isExecutionRequest = !isPublicExecutionResult(current);
161
+
162
+ // NOTE: temporary glue to incorporate avm execution calls
163
+ const simulator = (execution: PublicExecution, globalVariables: GlobalVariables) =>
164
+ env.AVM_ENABLED
165
+ ? this.publicExecutor.simulateAvm(execution, globalVariables)
166
+ : this.publicExecutor.simulate(execution, globalVariables);
167
+
168
+ const result = isExecutionRequest ? await simulator(current, this.globalVariables) : current;
169
+
170
+ newUnencryptedFunctionLogs.push(result.unencryptedLogs);
171
+ const functionSelector = result.execution.functionData.selector.toString();
172
+ this.log(
173
+ `Running public kernel circuit for ${functionSelector}@${result.execution.contractAddress.toString()}`,
174
+ );
175
+ executionStack.push(...result.nestedExecutions);
176
+ const callData = await this.getPublicCallData(result, isExecutionRequest);
177
+
178
+ [kernelOutput, kernelProof] = await this.runKernelCircuit(callData, kernelOutput, kernelProof);
179
+
180
+ if (!enqueuedExecutionResult) {
181
+ enqueuedExecutionResult = result;
182
+ }
183
+ }
184
+ // HACK(#1622): Manually patches the ordering of public state actions
185
+ // TODO(#757): Enforce proper ordering of public state actions
186
+ this.patchPublicStorageActionOrdering(kernelOutput, enqueuedExecutionResult!);
187
+ }
188
+
189
+ // TODO(#3675): This should be done in a public kernel circuit
190
+ this.removeRedundantPublicDataWrites(kernelOutput);
191
+
192
+ return [kernelOutput, kernelProof, newUnencryptedFunctionLogs];
193
+ }
194
+
195
+ protected async runKernelCircuit(
196
+ callData: PublicCallData,
197
+ previousOutput: PublicKernelCircuitPublicInputs,
198
+ previousProof: Proof,
199
+ ): Promise<[PublicKernelCircuitPublicInputs, Proof]> {
200
+ const output = await this.getKernelCircuitOutput(callData, previousOutput, previousProof);
201
+ const proof = await this.publicProver.getPublicKernelCircuitProof(output);
202
+ return [output, proof];
203
+ }
204
+
205
+ protected getKernelCircuitOutput(
206
+ callData: PublicCallData,
207
+ previousOutput: PublicKernelCircuitPublicInputs,
208
+ previousProof: Proof,
209
+ ): Promise<PublicKernelCircuitPublicInputs> {
210
+ if (previousOutput?.isPrivate && previousProof) {
211
+ // Run the public kernel circuit with previous private kernel
212
+ const previousKernel = this.getPreviousKernelData(previousOutput, previousProof);
213
+ const inputs = new PublicKernelCircuitPrivateInputs(previousKernel, callData);
214
+ return this.publicKernel.publicKernelCircuitPrivateInput(inputs);
215
+ } else if (previousOutput && previousProof) {
216
+ // Run the public kernel circuit with previous public kernel
217
+ const previousKernel = this.getPreviousKernelData(previousOutput, previousProof);
218
+ const inputs = new PublicKernelCircuitPrivateInputs(previousKernel, callData);
219
+ return this.publicKernel.publicKernelCircuitNonFirstIteration(inputs);
220
+ } else {
221
+ throw new Error(`No public kernel circuit for inputs`);
222
+ }
223
+ }
224
+
225
+ protected getPreviousKernelData(
226
+ previousOutput: PublicKernelCircuitPublicInputs,
227
+ previousProof: Proof,
228
+ ): PublicKernelData {
229
+ const vk = getVerificationKeys().publicKernelCircuit;
230
+ const vkIndex = 0;
231
+ const vkSiblingPath = MembershipWitness.random(VK_TREE_HEIGHT).siblingPath;
232
+ return new PublicKernelData(previousOutput, previousProof, vk, vkIndex, vkSiblingPath);
233
+ }
234
+
235
+ protected async getPublicCircuitPublicInputs(result: PublicExecutionResult) {
236
+ const publicDataTreeInfo = await this.db.getTreeInfo(MerkleTreeId.PUBLIC_DATA_TREE);
237
+ this.historicalHeader.state.partial.publicDataTree.root = Fr.fromBuffer(publicDataTreeInfo.root);
238
+
239
+ const callStackPreimages = await this.getPublicCallStackPreimages(result);
240
+ const publicCallStackHashes = padArrayEnd(
241
+ callStackPreimages.map(c => c.hash()),
242
+ Fr.ZERO,
243
+ MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
244
+ );
245
+
246
+ // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) --> set this in Noir
247
+ const unencryptedLogsHash = to2Fields(result.unencryptedLogs.hash());
248
+ const unencryptedLogPreimagesLength = new Fr(result.unencryptedLogs.getSerializedLength());
249
+
250
+ return PublicCircuitPublicInputs.from({
251
+ callContext: result.execution.callContext,
252
+ proverAddress: AztecAddress.ZERO,
253
+ argsHash: computeVarArgsHash(result.execution.args),
254
+ newCommitments: padArrayEnd(result.newCommitments, SideEffect.empty(), MAX_NEW_COMMITMENTS_PER_CALL),
255
+ newNullifiers: padArrayEnd(result.newNullifiers, SideEffectLinkedToNoteHash.empty(), MAX_NEW_NULLIFIERS_PER_CALL),
256
+ newL2ToL1Msgs: padArrayEnd(result.newL2ToL1Messages, Fr.ZERO, MAX_NEW_L2_TO_L1_MSGS_PER_CALL),
257
+ returnValues: padArrayEnd(result.returnValues, Fr.ZERO, RETURN_VALUES_LENGTH),
258
+ contractStorageReads: padArrayEnd(
259
+ result.contractStorageReads,
260
+ ContractStorageRead.empty(),
261
+ MAX_PUBLIC_DATA_READS_PER_CALL,
262
+ ),
263
+ contractStorageUpdateRequests: padArrayEnd(
264
+ result.contractStorageUpdateRequests,
265
+ ContractStorageUpdateRequest.empty(),
266
+ MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL,
267
+ ),
268
+ publicCallStackHashes,
269
+ unencryptedLogsHash,
270
+ unencryptedLogPreimagesLength,
271
+ historicalHeader: this.historicalHeader,
272
+ });
273
+ }
274
+
275
+ protected async getPublicCallStackItem(result: PublicExecutionResult, isExecutionRequest = false) {
276
+ return new PublicCallStackItem(
277
+ result.execution.contractAddress,
278
+ result.execution.functionData,
279
+ await this.getPublicCircuitPublicInputs(result),
280
+ isExecutionRequest,
281
+ );
282
+ }
283
+
284
+ protected async getPublicCallStackPreimages(result: PublicExecutionResult): Promise<PublicCallStackItem[]> {
285
+ const nested = result.nestedExecutions;
286
+ if (nested.length > MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL) {
287
+ throw new Error(
288
+ `Public call stack size exceeded (max ${MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL}, got ${nested.length})`,
289
+ );
290
+ }
291
+
292
+ return await Promise.all(nested.map(n => this.getPublicCallStackItem(n)));
293
+ }
294
+
295
+ protected getBytecodeHash(_result: PublicExecutionResult) {
296
+ // TODO: Determine how to calculate bytecode hash. Circuits just check it isn't zero for now.
297
+ // See https://github.com/AztecProtocol/aztec3-packages/issues/378
298
+ const bytecodeHash = new Fr(1n);
299
+ return Promise.resolve(bytecodeHash);
300
+ }
301
+
302
+ /**
303
+ * Calculates the PublicCircuitOutput for this execution result along with its proof,
304
+ * and assembles a PublicCallData object from it.
305
+ * @param result - The execution result.
306
+ * @param preimages - The preimages of the callstack items.
307
+ * @param isExecutionRequest - Whether the current callstack item should be considered a public fn execution request.
308
+ * @returns A corresponding PublicCallData object.
309
+ */
310
+ protected async getPublicCallData(result: PublicExecutionResult, isExecutionRequest = false) {
311
+ const bytecodeHash = await this.getBytecodeHash(result);
312
+ const callStackItem = await this.getPublicCallStackItem(result, isExecutionRequest);
313
+ const publicCallRequests = (await this.getPublicCallStackPreimages(result)).map(c => c.toCallRequest());
314
+ const publicCallStack = padArrayEnd(publicCallRequests, CallRequest.empty(), MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL);
315
+ const portalContractAddress = result.execution.callContext.portalContractAddress.toField();
316
+ const proof = await this.publicProver.getPublicCircuitProof(callStackItem.publicInputs);
317
+ return new PublicCallData(callStackItem, publicCallStack, proof, portalContractAddress, bytecodeHash);
318
+ }
319
+
320
+ // HACK(#1622): this is a hack to fix ordering of public state in the call stack. Since the private kernel
321
+ // cannot keep track of side effects that happen after or before a nested call, we override the public
322
+ // state actions it emits with whatever we got from the simulator. As a sanity check, we at least verify
323
+ // that the elements are the same, so we are only tweaking their ordering.
324
+ // See yarn-project/end-to-end/src/e2e_ordering.test.ts
325
+ // See https://github.com/AztecProtocol/aztec-packages/issues/1616
326
+ // TODO(#757): Enforce proper ordering of public state actions
327
+ /**
328
+ * Patch the ordering of storage actions output from the public kernel.
329
+ * @param publicInputs - to be patched here: public inputs to the kernel iteration up to this point
330
+ * @param execResult - result of the top/first execution for this enqueued public call
331
+ */
332
+ private patchPublicStorageActionOrdering(
333
+ publicInputs: PublicKernelCircuitPublicInputs,
334
+ execResult: PublicExecutionResult,
335
+ ) {
336
+ // Convert ContractStorage* objects to PublicData* objects and sort them in execution order
337
+ const simPublicDataReads = collectPublicDataReads(execResult);
338
+ const simPublicDataUpdateRequests = collectPublicDataUpdateRequests(execResult);
339
+
340
+ const { publicDataReads, publicDataUpdateRequests } = publicInputs.end; // from kernel
341
+
342
+ // Validate all items in enqueued public calls are in the kernel emitted stack
343
+ const readsAreEqual = simPublicDataReads.reduce(
344
+ (accum, read) =>
345
+ accum && !!publicDataReads.find(item => item.leafSlot.equals(read.leafSlot) && item.value.equals(read.value)),
346
+ true,
347
+ );
348
+ const updatesAreEqual = simPublicDataUpdateRequests.reduce(
349
+ (accum, update) =>
350
+ accum &&
351
+ !!publicDataUpdateRequests.find(
352
+ item => item.leafSlot.equals(update.leafSlot) && item.newValue.equals(update.newValue),
353
+ ),
354
+ true,
355
+ );
356
+
357
+ if (!readsAreEqual) {
358
+ throw new Error(
359
+ `Public data reads from simulator do not match those from public kernel.\nFrom simulator: ${simPublicDataReads
360
+ .map(p => p.toFriendlyJSON())
361
+ .join(', ')}\nFrom public kernel: ${publicDataReads.map(i => i.toFriendlyJSON()).join(', ')}`,
362
+ );
363
+ }
364
+ if (!updatesAreEqual) {
365
+ throw new Error(
366
+ `Public data update requests from simulator do not match those from public kernel.\nFrom simulator: ${simPublicDataUpdateRequests
367
+ .map(p => p.toFriendlyJSON())
368
+ .join(', ')}\nFrom public kernel: ${publicDataUpdateRequests.map(i => i.toFriendlyJSON()).join(', ')}`,
369
+ );
370
+ }
371
+
372
+ // Assume that kernel public inputs has the right number of items.
373
+ // We only want to reorder the items from the public inputs of the
374
+ // most recently processed top/enqueued call.
375
+ const numTotalReadsInKernel = arrayNonEmptyLength(
376
+ publicInputs.end.publicDataReads,
377
+ f => f.leafSlot.equals(Fr.ZERO) && f.value.equals(Fr.ZERO),
378
+ );
379
+ const numTotalUpdatesInKernel = arrayNonEmptyLength(
380
+ publicInputs.end.publicDataUpdateRequests,
381
+ f => f.leafSlot.equals(Fr.ZERO) && f.newValue.equals(Fr.ZERO),
382
+ );
383
+ const numReadsBeforeThisEnqueuedCall = numTotalReadsInKernel - simPublicDataReads.length;
384
+ const numUpdatesBeforeThisEnqueuedCall = numTotalUpdatesInKernel - simPublicDataUpdateRequests.length;
385
+
386
+ // Override kernel output
387
+ publicInputs.end.publicDataReads = padArrayEnd(
388
+ [
389
+ // do not mess with items from previous top/enqueued calls in kernel output
390
+ ...publicDataReads.slice(0, numReadsBeforeThisEnqueuedCall),
391
+ ...simPublicDataReads,
392
+ ],
393
+ PublicDataRead.empty(),
394
+ MAX_PUBLIC_DATA_READS_PER_TX,
395
+ );
396
+
397
+ // Override kernel output
398
+ publicInputs.end.publicDataUpdateRequests = padArrayEnd(
399
+ [
400
+ // do not mess with items from previous top/enqueued calls in kernel output
401
+ ...publicDataUpdateRequests.slice(0, numUpdatesBeforeThisEnqueuedCall),
402
+ ...simPublicDataUpdateRequests,
403
+ ],
404
+ PublicDataUpdateRequest.empty(),
405
+ MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
406
+ );
407
+ }
408
+
409
+ private removeRedundantPublicDataWrites(publicInputs: PublicKernelCircuitPublicInputs) {
410
+ const lastWritesMap = new Map();
411
+ for (const write of publicInputs.end.publicDataUpdateRequests) {
412
+ const key = write.leafSlot.toString();
413
+ lastWritesMap.set(key, write);
414
+ }
415
+
416
+ const lastWrites = publicInputs.end.publicDataUpdateRequests.filter(
417
+ write => lastWritesMap.get(write.leafSlot.toString()) === write,
418
+ );
419
+
420
+ publicInputs.end.publicDataUpdateRequests = padArrayEnd(
421
+ lastWrites,
422
+
423
+ PublicDataUpdateRequest.empty(),
424
+ MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
425
+ );
426
+ }
427
+ }
@@ -0,0 +1,107 @@
1
+ import { Tx } from '@aztec/circuit-types';
2
+ import { GlobalVariables, Header, Proof, PublicCallRequest, PublicKernelCircuitPublicInputs } from '@aztec/circuits.js';
3
+ import { isArrayEmpty } from '@aztec/foundation/collection';
4
+ import { createDebugLogger } from '@aztec/foundation/log';
5
+ import { PublicExecutor, PublicStateDB } from '@aztec/simulator';
6
+ import { MerkleTreeOperations } from '@aztec/world-state';
7
+
8
+ import { PublicProver } from '../prover/index.js';
9
+ import { PublicKernelCircuitSimulator } from '../simulator/index.js';
10
+ import { ContractsDataSourcePublicDB } from '../simulator/public_executor.js';
11
+ import { AbstractPhaseManager } from './abstract_phase_manager.js';
12
+ import { FeeDistributionPhaseManager } from './fee_distribution_phase_manager.js';
13
+ import { FailedTx } from './processed_tx.js';
14
+
15
+ /**
16
+ * The phase manager responsible for performing the fee preparation phase.
17
+ */
18
+ export class ApplicationLogicPhaseManager extends AbstractPhaseManager {
19
+ constructor(
20
+ protected db: MerkleTreeOperations,
21
+ protected publicExecutor: PublicExecutor,
22
+ protected publicKernel: PublicKernelCircuitSimulator,
23
+ protected publicProver: PublicProver,
24
+ protected globalVariables: GlobalVariables,
25
+ protected historicalHeader: Header,
26
+ protected publicContractsDB: ContractsDataSourcePublicDB,
27
+ protected publicStateDB: PublicStateDB,
28
+
29
+ protected log = createDebugLogger('aztec:sequencer:application-logic'),
30
+ ) {
31
+ super(db, publicExecutor, publicKernel, publicProver, globalVariables, historicalHeader);
32
+ }
33
+
34
+ extractEnqueuedPublicCalls(tx: Tx): PublicCallRequest[] {
35
+ if (!tx.enqueuedPublicFunctionCalls) {
36
+ throw new Error(`Missing preimages for enqueued public calls`);
37
+ }
38
+ // Note: the first enqueued public call is for fee payments
39
+ // TODO(dbanks12): why must these be reversed?
40
+ return tx.enqueuedPublicFunctionCalls.slice().reverse();
41
+ }
42
+
43
+ async handle(
44
+ tx: Tx,
45
+ previousPublicKernelOutput?: PublicKernelCircuitPublicInputs,
46
+ previousPublicKernelProof?: Proof,
47
+ ): Promise<{
48
+ /**
49
+ * the output of the public kernel circuit for this phase
50
+ */
51
+ publicKernelOutput?: PublicKernelCircuitPublicInputs;
52
+ /**
53
+ * the proof of the public kernel circuit for this phase
54
+ */
55
+ publicKernelProof?: Proof;
56
+ }> {
57
+ // add new contracts to the contracts db so that their functions may be found and called
58
+ this.log(`Processing tx ${await tx.getTxHash()}`);
59
+ await this.publicContractsDB.addNewContracts(tx);
60
+ if (!isArrayEmpty(tx.data.end.publicCallStack, item => item.isEmpty())) {
61
+ const outputAndProof = this.getKernelOutputAndProof(tx, previousPublicKernelOutput, previousPublicKernelProof);
62
+
63
+ this.log(`Executing enqueued public calls for tx ${await tx.getTxHash()}`);
64
+ const [publicKernelOutput, publicKernelProof, newUnencryptedFunctionLogs] = await this.processEnqueuedPublicCalls(
65
+ this.extractEnqueuedPublicCalls(tx),
66
+ outputAndProof.publicKernelPublicInput,
67
+ outputAndProof.publicKernelProof,
68
+ );
69
+ tx.unencryptedLogs.addFunctionLogs(newUnencryptedFunctionLogs);
70
+
71
+ // commit the state updates from this transaction
72
+ await this.publicStateDB.commit();
73
+
74
+ return { publicKernelOutput, publicKernelProof };
75
+ } else {
76
+ return {
77
+ publicKernelOutput: undefined,
78
+ publicKernelProof: undefined,
79
+ };
80
+ }
81
+ }
82
+
83
+ nextPhase() {
84
+ return new FeeDistributionPhaseManager(
85
+ this.db,
86
+ this.publicExecutor,
87
+ this.publicKernel,
88
+ this.publicProver,
89
+ this.globalVariables,
90
+ this.historicalHeader,
91
+ this.publicContractsDB,
92
+ this.publicStateDB,
93
+ );
94
+ }
95
+
96
+ async rollback(tx: Tx, err: unknown): Promise<FailedTx> {
97
+ this.log.warn(`Error processing tx ${await tx.getTxHash()}: ${err}`);
98
+ // remove contracts on failure
99
+ await this.publicContractsDB.removeNewContracts(tx);
100
+ // rollback any state updates from this failed transaction
101
+ await this.publicStateDB.rollback();
102
+ return {
103
+ tx,
104
+ error: err instanceof Error ? err : new Error('Unknown error'),
105
+ };
106
+ }
107
+ }
@@ -0,0 +1 @@
1
+ export { SequencerConfig } from '@aztec/circuit-types';
@@ -0,0 +1,70 @@
1
+ import { Tx } from '@aztec/circuit-types';
2
+ import { GlobalVariables, Header, Proof, PublicCallRequest, PublicKernelCircuitPublicInputs } from '@aztec/circuits.js';
3
+ import { createDebugLogger } from '@aztec/foundation/log';
4
+ import { PublicExecutor, PublicStateDB } from '@aztec/simulator';
5
+ import { MerkleTreeOperations } from '@aztec/world-state';
6
+
7
+ import { PublicProver } from '../prover/index.js';
8
+ import { PublicKernelCircuitSimulator } from '../simulator/index.js';
9
+ import { ContractsDataSourcePublicDB } from '../simulator/public_executor.js';
10
+ import { AbstractPhaseManager } from './abstract_phase_manager.js';
11
+ import { FailedTx } from './processed_tx.js';
12
+
13
+ /**
14
+ * The phase manager responsible for performing the fee preparation phase.
15
+ */
16
+ export class FeeDistributionPhaseManager extends AbstractPhaseManager {
17
+ constructor(
18
+ protected db: MerkleTreeOperations,
19
+ protected publicExecutor: PublicExecutor,
20
+ protected publicKernel: PublicKernelCircuitSimulator,
21
+ protected publicProver: PublicProver,
22
+ protected globalVariables: GlobalVariables,
23
+ protected historicalHeader: Header,
24
+ protected publicContractsDB: ContractsDataSourcePublicDB,
25
+ protected publicStateDB: PublicStateDB,
26
+
27
+ protected log = createDebugLogger('aztec:sequencer:fee-distribution'),
28
+ ) {
29
+ super(db, publicExecutor, publicKernel, publicProver, globalVariables, historicalHeader);
30
+ }
31
+
32
+ // this is a no-op for now
33
+ extractEnqueuedPublicCalls(_tx: Tx): PublicCallRequest[] {
34
+ return [];
35
+ }
36
+
37
+ // this is a no-op for now
38
+ async handle(
39
+ tx: Tx,
40
+ previousPublicKernelOutput?: PublicKernelCircuitPublicInputs,
41
+ previousPublicKernelProof?: Proof,
42
+ ): Promise<{
43
+ /**
44
+ * the output of the public kernel circuit for this phase
45
+ */
46
+ publicKernelOutput?: PublicKernelCircuitPublicInputs;
47
+ /**
48
+ * the proof of the public kernel circuit for this phase
49
+ */
50
+ publicKernelProof?: Proof;
51
+ }> {
52
+ this.log.debug(`Handle ${await tx.getTxHash()} with no-op`);
53
+ return {
54
+ publicKernelOutput: previousPublicKernelOutput,
55
+ publicKernelProof: previousPublicKernelProof,
56
+ };
57
+ }
58
+
59
+ nextPhase() {
60
+ return undefined;
61
+ }
62
+
63
+ async rollback(tx: Tx, err: unknown): Promise<FailedTx> {
64
+ this.log.warn(`Error processing tx ${await tx.getTxHash()}: ${err}`);
65
+ return {
66
+ tx,
67
+ error: err instanceof Error ? err : new Error('Unknown error'),
68
+ };
69
+ }
70
+ }
@@ -0,0 +1,79 @@
1
+ import { Tx } from '@aztec/circuit-types';
2
+ import { GlobalVariables, Header, Proof, PublicCallRequest, PublicKernelCircuitPublicInputs } from '@aztec/circuits.js';
3
+ import { createDebugLogger } from '@aztec/foundation/log';
4
+ import { PublicExecutor, PublicStateDB } from '@aztec/simulator';
5
+ import { MerkleTreeOperations } from '@aztec/world-state';
6
+
7
+ import { PublicProver } from '../prover/index.js';
8
+ import { PublicKernelCircuitSimulator } from '../simulator/index.js';
9
+ import { ContractsDataSourcePublicDB } from '../simulator/public_executor.js';
10
+ import { AbstractPhaseManager } from './abstract_phase_manager.js';
11
+ import { ApplicationLogicPhaseManager } from './application_logic_phase_manager.js';
12
+ import { FailedTx } from './processed_tx.js';
13
+
14
+ /**
15
+ * The phase manager responsible for performing the fee preparation phase.
16
+ */
17
+ export class FeePreparationPhaseManager extends AbstractPhaseManager {
18
+ constructor(
19
+ protected db: MerkleTreeOperations,
20
+ protected publicExecutor: PublicExecutor,
21
+ protected publicKernel: PublicKernelCircuitSimulator,
22
+ protected publicProver: PublicProver,
23
+ protected globalVariables: GlobalVariables,
24
+ protected historicalHeader: Header,
25
+ protected publicContractsDB: ContractsDataSourcePublicDB,
26
+ protected publicStateDB: PublicStateDB,
27
+
28
+ protected log = createDebugLogger('aztec:sequencer:fee-preparation'),
29
+ ) {
30
+ super(db, publicExecutor, publicKernel, publicProver, globalVariables, historicalHeader);
31
+ }
32
+
33
+ extractEnqueuedPublicCalls(_tx: Tx): PublicCallRequest[] {
34
+ return [];
35
+ }
36
+
37
+ // this is a no-op for now
38
+ async handle(
39
+ tx: Tx,
40
+ previousPublicKernelOutput?: PublicKernelCircuitPublicInputs,
41
+ previousPublicKernelProof?: Proof,
42
+ ): Promise<{
43
+ /**
44
+ * the output of the public kernel circuit for this phase
45
+ */
46
+ publicKernelOutput?: PublicKernelCircuitPublicInputs;
47
+ /**
48
+ * the proof of the public kernel circuit for this phase
49
+ */
50
+ publicKernelProof?: Proof;
51
+ }> {
52
+ this.log.debug(`Handle ${await tx.getTxHash()} with no-op`);
53
+ return {
54
+ publicKernelOutput: previousPublicKernelOutput,
55
+ publicKernelProof: previousPublicKernelProof,
56
+ };
57
+ }
58
+
59
+ nextPhase(): AbstractPhaseManager {
60
+ return new ApplicationLogicPhaseManager(
61
+ this.db,
62
+ this.publicExecutor,
63
+ this.publicKernel,
64
+ this.publicProver,
65
+ this.globalVariables,
66
+ this.historicalHeader,
67
+ this.publicContractsDB,
68
+ this.publicStateDB,
69
+ );
70
+ }
71
+
72
+ async rollback(tx: Tx, err: unknown): Promise<FailedTx> {
73
+ this.log.warn(`Error processing tx ${await tx.getTxHash()}: ${err}`);
74
+ return {
75
+ tx,
76
+ error: err instanceof Error ? err : new Error('Unknown error'),
77
+ };
78
+ }
79
+ }
@@ -0,0 +1,2 @@
1
+ export * from './sequencer.js';
2
+ export * from './config.js';