@aztec/sequencer-client 0.26.3 → 0.26.6
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_builder/solo_block_builder.d.ts +5 -4
- package/dest/block_builder/solo_block_builder.d.ts.map +1 -1
- package/dest/block_builder/solo_block_builder.js +82 -34
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +29 -3
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +4 -2
- package/dest/index.d.ts +9 -7
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +9 -8
- package/dest/publisher/l1-publisher.js +5 -5
- package/dest/publisher/viem-tx-sender.js +2 -2
- package/dest/sequencer/abstract_phase_manager.d.ts +12 -15
- package/dest/sequencer/abstract_phase_manager.d.ts.map +1 -1
- package/dest/sequencer/abstract_phase_manager.js +32 -24
- package/dest/sequencer/app_logic_phase_manager.d.ts +1 -6
- package/dest/sequencer/app_logic_phase_manager.d.ts.map +1 -1
- package/dest/sequencer/app_logic_phase_manager.js +11 -8
- package/dest/sequencer/hints_builder.d.ts +13 -0
- package/dest/sequencer/hints_builder.d.ts.map +1 -0
- package/dest/sequencer/hints_builder.js +21 -0
- package/dest/sequencer/index.d.ts +1 -1
- package/dest/sequencer/index.d.ts.map +1 -1
- package/dest/sequencer/index.js +2 -2
- package/dest/sequencer/phase_manager_factory.d.ts.map +1 -1
- package/dest/sequencer/phase_manager_factory.js +5 -1
- package/dest/sequencer/processed_tx.d.ts +37 -2
- package/dest/sequencer/processed_tx.d.ts.map +1 -1
- package/dest/sequencer/processed_tx.js +67 -9
- package/dest/sequencer/public_processor.d.ts +3 -1
- package/dest/sequencer/public_processor.d.ts.map +1 -1
- package/dest/sequencer/public_processor.js +18 -11
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +3 -4
- package/dest/sequencer/setup_phase_manager.d.ts +1 -6
- package/dest/sequencer/setup_phase_manager.d.ts.map +1 -1
- package/dest/sequencer/setup_phase_manager.js +3 -5
- package/dest/sequencer/tail_phase_manager.d.ts +28 -0
- package/dest/sequencer/tail_phase_manager.d.ts.map +1 -0
- package/dest/sequencer/tail_phase_manager.js +32 -0
- package/dest/sequencer/teardown_phase_manager.d.ts +1 -6
- package/dest/sequencer/teardown_phase_manager.d.ts.map +1 -1
- package/dest/sequencer/teardown_phase_manager.js +3 -4
- package/dest/simulator/acvm_native.d.ts +20 -0
- package/dest/simulator/acvm_native.d.ts.map +1 -0
- package/dest/simulator/acvm_native.js +96 -0
- package/dest/simulator/acvm_wasm.d.ts +7 -0
- package/dest/simulator/acvm_wasm.d.ts.map +1 -0
- package/dest/simulator/acvm_wasm.js +23 -0
- package/dest/simulator/index.d.ts +8 -1
- package/dest/simulator/index.d.ts.map +1 -1
- package/dest/simulator/index.js +2 -2
- package/dest/simulator/public_kernel.d.ts +11 -1
- package/dest/simulator/public_kernel.d.ts.map +1 -1
- package/dest/simulator/public_kernel.js +34 -6
- package/dest/simulator/rollup.d.ts +4 -0
- package/dest/simulator/rollup.d.ts.map +1 -1
- package/dest/simulator/rollup.js +16 -20
- package/dest/simulator/simulation_provider.d.ts +9 -0
- package/dest/simulator/simulation_provider.d.ts.map +1 -0
- package/dest/simulator/simulation_provider.js +2 -0
- package/package.json +15 -13
- package/src/block_builder/solo_block_builder.ts +115 -82
- package/src/client/sequencer-client.ts +37 -2
- package/src/config.ts +4 -0
- package/src/index.ts +9 -7
- package/src/publisher/l1-publisher.ts +4 -4
- package/src/publisher/viem-tx-sender.ts +1 -1
- package/src/sequencer/abstract_phase_manager.ts +58 -48
- package/src/sequencer/app_logic_phase_manager.ts +12 -22
- package/src/sequencer/hints_builder.ts +56 -0
- package/src/sequencer/index.ts +1 -1
- package/src/sequencer/phase_manager_factory.ts +12 -0
- package/src/sequencer/processed_tx.ts +147 -17
- package/src/sequencer/public_processor.ts +28 -14
- package/src/sequencer/sequencer.ts +2 -3
- package/src/sequencer/setup_phase_manager.ts +5 -19
- package/src/sequencer/tail_phase_manager.ts +49 -0
- package/src/sequencer/teardown_phase_manager.ts +5 -18
- package/src/simulator/acvm_native.ts +112 -0
- package/src/simulator/acvm_wasm.ts +31 -0
- package/src/simulator/index.ts +8 -0
- package/src/simulator/public_kernel.ts +62 -8
- package/src/simulator/rollup.ts +31 -19
- package/src/simulator/simulation_provider.ts +10 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FunctionL2Logs, MerkleTreeId, Tx } from '@aztec/circuit-types';
|
|
1
|
+
import { FunctionL2Logs, MerkleTreeId, SimulationError, Tx } from '@aztec/circuit-types';
|
|
2
2
|
import {
|
|
3
3
|
AztecAddress,
|
|
4
4
|
CallRequest,
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
MAX_NEW_NULLIFIERS_PER_CALL,
|
|
14
14
|
MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX,
|
|
15
15
|
MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
16
|
+
MAX_NULLIFIER_READ_REQUESTS_PER_CALL,
|
|
16
17
|
MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
|
|
17
18
|
MAX_PUBLIC_DATA_READS_PER_CALL,
|
|
18
19
|
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL,
|
|
@@ -21,8 +22,6 @@ import {
|
|
|
21
22
|
MembershipWitness,
|
|
22
23
|
PrivateKernelTailCircuitPublicInputs,
|
|
23
24
|
Proof,
|
|
24
|
-
PublicAccumulatedNonRevertibleData,
|
|
25
|
-
PublicAccumulatedRevertibleData,
|
|
26
25
|
PublicCallData,
|
|
27
26
|
PublicCallRequest,
|
|
28
27
|
PublicCallStackItem,
|
|
@@ -32,7 +31,9 @@ import {
|
|
|
32
31
|
PublicKernelCircuitPrivateInputs,
|
|
33
32
|
PublicKernelCircuitPublicInputs,
|
|
34
33
|
PublicKernelData,
|
|
34
|
+
PublicKernelTailCircuitPrivateInputs,
|
|
35
35
|
RETURN_VALUES_LENGTH,
|
|
36
|
+
ReadRequest,
|
|
36
37
|
SideEffect,
|
|
37
38
|
SideEffectLinkedToNoteHash,
|
|
38
39
|
VK_TREE_HEIGHT,
|
|
@@ -56,21 +57,25 @@ import { env } from 'process';
|
|
|
56
57
|
import { getVerificationKeys } from '../mocks/verification_keys.js';
|
|
57
58
|
import { PublicProver } from '../prover/index.js';
|
|
58
59
|
import { PublicKernelCircuitSimulator } from '../simulator/index.js';
|
|
60
|
+
import { HintsBuilder } from './hints_builder.js';
|
|
59
61
|
import { FailedTx } from './processed_tx.js';
|
|
60
62
|
|
|
61
63
|
export enum PublicKernelPhase {
|
|
62
64
|
SETUP = 'setup',
|
|
63
65
|
APP_LOGIC = 'app-logic',
|
|
64
66
|
TEARDOWN = 'teardown',
|
|
67
|
+
TAIL = 'tail',
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
export const PhaseIsRevertible: Record<PublicKernelPhase, boolean> = {
|
|
68
71
|
[PublicKernelPhase.SETUP]: false,
|
|
69
72
|
[PublicKernelPhase.APP_LOGIC]: true,
|
|
70
73
|
[PublicKernelPhase.TEARDOWN]: false,
|
|
74
|
+
[PublicKernelPhase.TAIL]: false,
|
|
71
75
|
};
|
|
72
76
|
|
|
73
77
|
export abstract class AbstractPhaseManager {
|
|
78
|
+
protected hintsBuilder: HintsBuilder;
|
|
74
79
|
protected log: DebugLogger;
|
|
75
80
|
constructor(
|
|
76
81
|
protected db: MerkleTreeOperations,
|
|
@@ -81,6 +86,7 @@ export abstract class AbstractPhaseManager {
|
|
|
81
86
|
protected historicalHeader: Header,
|
|
82
87
|
public phase: PublicKernelPhase,
|
|
83
88
|
) {
|
|
89
|
+
this.hintsBuilder = new HintsBuilder(db);
|
|
84
90
|
this.log = createDebugLogger(`aztec:sequencer:${phase}`);
|
|
85
91
|
}
|
|
86
92
|
/**
|
|
@@ -102,6 +108,10 @@ export abstract class AbstractPhaseManager {
|
|
|
102
108
|
* the proof of the public kernel circuit for this phase
|
|
103
109
|
*/
|
|
104
110
|
publicKernelProof: Proof;
|
|
111
|
+
/**
|
|
112
|
+
* revert reason, if any
|
|
113
|
+
*/
|
|
114
|
+
revertReason: SimulationError | undefined;
|
|
105
115
|
}>;
|
|
106
116
|
abstract rollback(tx: Tx, err: unknown): Promise<FailedTx>;
|
|
107
117
|
|
|
@@ -127,6 +137,7 @@ export abstract class AbstractPhaseManager {
|
|
|
127
137
|
[PublicKernelPhase.SETUP]: [],
|
|
128
138
|
[PublicKernelPhase.APP_LOGIC]: [],
|
|
129
139
|
[PublicKernelPhase.TEARDOWN]: [],
|
|
140
|
+
[PublicKernelPhase.TAIL]: [],
|
|
130
141
|
};
|
|
131
142
|
}
|
|
132
143
|
|
|
@@ -140,12 +151,14 @@ export abstract class AbstractPhaseManager {
|
|
|
140
151
|
[PublicKernelPhase.SETUP]: [],
|
|
141
152
|
[PublicKernelPhase.APP_LOGIC]: publicCallsStack,
|
|
142
153
|
[PublicKernelPhase.TEARDOWN]: [],
|
|
154
|
+
[PublicKernelPhase.TAIL]: [],
|
|
143
155
|
};
|
|
144
156
|
} else {
|
|
145
157
|
return {
|
|
146
158
|
[PublicKernelPhase.SETUP]: publicCallsStack.slice(0, firstRevertibleCallIndex - 1),
|
|
147
159
|
[PublicKernelPhase.APP_LOGIC]: publicCallsStack.slice(firstRevertibleCallIndex),
|
|
148
160
|
[PublicKernelPhase.TEARDOWN]: [publicCallsStack[firstRevertibleCallIndex - 1]],
|
|
161
|
+
[PublicKernelPhase.TAIL]: [],
|
|
149
162
|
};
|
|
150
163
|
}
|
|
151
164
|
}
|
|
@@ -158,55 +171,18 @@ export abstract class AbstractPhaseManager {
|
|
|
158
171
|
return calls;
|
|
159
172
|
}
|
|
160
173
|
|
|
161
|
-
public static getKernelOutputAndProof(
|
|
162
|
-
tx: Tx,
|
|
163
|
-
publicKernelPublicInput?: PublicKernelCircuitPublicInputs,
|
|
164
|
-
previousPublicKernelProof?: Proof,
|
|
165
|
-
): {
|
|
166
|
-
/**
|
|
167
|
-
* the output of the public kernel circuit for this phase
|
|
168
|
-
*/
|
|
169
|
-
publicKernelPublicInput: PublicKernelCircuitPublicInputs;
|
|
170
|
-
/**
|
|
171
|
-
* the proof of the public kernel circuit for this phase
|
|
172
|
-
*/
|
|
173
|
-
publicKernelProof: Proof;
|
|
174
|
-
} {
|
|
175
|
-
if (publicKernelPublicInput && previousPublicKernelProof) {
|
|
176
|
-
return {
|
|
177
|
-
publicKernelPublicInput: publicKernelPublicInput,
|
|
178
|
-
publicKernelProof: previousPublicKernelProof,
|
|
179
|
-
};
|
|
180
|
-
} else {
|
|
181
|
-
const publicKernelPublicInput = new PublicKernelCircuitPublicInputs(
|
|
182
|
-
tx.data.aggregationObject,
|
|
183
|
-
PublicAccumulatedNonRevertibleData.fromPrivateAccumulatedNonRevertibleData(tx.data.endNonRevertibleData),
|
|
184
|
-
PublicAccumulatedRevertibleData.fromPrivateAccumulatedRevertibleData(tx.data.end),
|
|
185
|
-
tx.data.constants,
|
|
186
|
-
tx.data.needsSetup,
|
|
187
|
-
tx.data.needsAppLogic,
|
|
188
|
-
tx.data.needsTeardown,
|
|
189
|
-
);
|
|
190
|
-
const publicKernelProof = previousPublicKernelProof || tx.proof;
|
|
191
|
-
return {
|
|
192
|
-
publicKernelPublicInput,
|
|
193
|
-
publicKernelProof,
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
174
|
protected async processEnqueuedPublicCalls(
|
|
199
175
|
tx: Tx,
|
|
200
176
|
previousPublicKernelOutput: PublicKernelCircuitPublicInputs,
|
|
201
177
|
previousPublicKernelProof: Proof,
|
|
202
|
-
): Promise<[PublicKernelCircuitPublicInputs, Proof, FunctionL2Logs[]]> {
|
|
178
|
+
): Promise<[PublicKernelCircuitPublicInputs, Proof, FunctionL2Logs[], SimulationError | undefined]> {
|
|
203
179
|
let kernelOutput = previousPublicKernelOutput;
|
|
204
180
|
let kernelProof = previousPublicKernelProof;
|
|
205
181
|
|
|
206
182
|
const enqueuedCalls = this.extractEnqueuedPublicCalls(tx);
|
|
207
183
|
|
|
208
184
|
if (!enqueuedCalls || !enqueuedCalls.length) {
|
|
209
|
-
return [kernelOutput, kernelProof, []];
|
|
185
|
+
return [kernelOutput, kernelProof, [], undefined];
|
|
210
186
|
}
|
|
211
187
|
|
|
212
188
|
const newUnencryptedFunctionLogs: FunctionL2Logs[] = [];
|
|
@@ -241,7 +217,18 @@ export abstract class AbstractPhaseManager {
|
|
|
241
217
|
executionStack.push(...result.nestedExecutions);
|
|
242
218
|
const callData = await this.getPublicCallData(result, isExecutionRequest);
|
|
243
219
|
|
|
244
|
-
[kernelOutput, kernelProof] = await this.runKernelCircuit(
|
|
220
|
+
[kernelOutput, kernelProof] = await this.runKernelCircuit(kernelOutput, kernelProof, callData);
|
|
221
|
+
|
|
222
|
+
if (kernelOutput.reverted && this.phase === PublicKernelPhase.APP_LOGIC) {
|
|
223
|
+
this.log.debug(
|
|
224
|
+
`Reverting on ${result.execution.contractAddress.toString()}:${functionSelector} with reason: ${
|
|
225
|
+
result.revertReason
|
|
226
|
+
}`,
|
|
227
|
+
);
|
|
228
|
+
// halt immediately if the public kernel circuit has reverted.
|
|
229
|
+
// return no logs, as they should not go on-chain.
|
|
230
|
+
return [kernelOutput, kernelProof, [], result.revertReason];
|
|
231
|
+
}
|
|
245
232
|
|
|
246
233
|
if (!enqueuedExecutionResult) {
|
|
247
234
|
enqueuedExecutionResult = result;
|
|
@@ -255,25 +242,42 @@ export abstract class AbstractPhaseManager {
|
|
|
255
242
|
// TODO(#3675): This should be done in a public kernel circuit
|
|
256
243
|
removeRedundantPublicDataWrites(kernelOutput);
|
|
257
244
|
|
|
258
|
-
return [kernelOutput, kernelProof, newUnencryptedFunctionLogs];
|
|
245
|
+
return [kernelOutput, kernelProof, newUnencryptedFunctionLogs, undefined];
|
|
259
246
|
}
|
|
260
247
|
|
|
261
248
|
protected async runKernelCircuit(
|
|
262
|
-
callData: PublicCallData,
|
|
263
249
|
previousOutput: PublicKernelCircuitPublicInputs,
|
|
264
250
|
previousProof: Proof,
|
|
251
|
+
callData?: PublicCallData,
|
|
265
252
|
): Promise<[PublicKernelCircuitPublicInputs, Proof]> {
|
|
266
|
-
const output = await this.getKernelCircuitOutput(
|
|
253
|
+
const output = await this.getKernelCircuitOutput(previousOutput, previousProof, callData);
|
|
267
254
|
const proof = await this.publicProver.getPublicKernelCircuitProof(output);
|
|
268
255
|
return [output, proof];
|
|
269
256
|
}
|
|
270
257
|
|
|
271
|
-
protected getKernelCircuitOutput(
|
|
272
|
-
callData: PublicCallData,
|
|
258
|
+
protected async getKernelCircuitOutput(
|
|
273
259
|
previousOutput: PublicKernelCircuitPublicInputs,
|
|
274
260
|
previousProof: Proof,
|
|
261
|
+
callData?: PublicCallData,
|
|
275
262
|
): Promise<PublicKernelCircuitPublicInputs> {
|
|
276
263
|
const previousKernel = this.getPreviousKernelData(previousOutput, previousProof);
|
|
264
|
+
|
|
265
|
+
if (this.phase === PublicKernelPhase.TAIL) {
|
|
266
|
+
const { endNonRevertibleData, end } = previousOutput;
|
|
267
|
+
const nullifierReadRequestResetHints = await this.hintsBuilder.getNullifierReadRequestResetHints(
|
|
268
|
+
endNonRevertibleData.nullifierReadRequests,
|
|
269
|
+
end.nullifierReadRequests,
|
|
270
|
+
endNonRevertibleData.newNullifiers,
|
|
271
|
+
end.newNullifiers,
|
|
272
|
+
);
|
|
273
|
+
const inputs = new PublicKernelTailCircuitPrivateInputs(previousKernel, nullifierReadRequestResetHints);
|
|
274
|
+
return this.publicKernel.publicKernelCircuitTail(inputs);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (!callData) {
|
|
278
|
+
throw new Error(`Cannot run public kernel circuit without call data for phase '${this.phase}'.`);
|
|
279
|
+
}
|
|
280
|
+
|
|
277
281
|
const inputs = new PublicKernelCircuitPrivateInputs(previousKernel, callData);
|
|
278
282
|
switch (this.phase) {
|
|
279
283
|
case PublicKernelPhase.SETUP:
|
|
@@ -320,6 +324,11 @@ export abstract class AbstractPhaseManager {
|
|
|
320
324
|
newNullifiers: padArrayEnd(result.newNullifiers, SideEffectLinkedToNoteHash.empty(), MAX_NEW_NULLIFIERS_PER_CALL),
|
|
321
325
|
newL2ToL1Msgs: padArrayEnd(result.newL2ToL1Messages, L2ToL1Message.empty(), MAX_NEW_L2_TO_L1_MSGS_PER_CALL),
|
|
322
326
|
returnValues: padArrayEnd(result.returnValues, Fr.ZERO, RETURN_VALUES_LENGTH),
|
|
327
|
+
nullifierReadRequests: padArrayEnd(
|
|
328
|
+
result.nullifierReadRequests,
|
|
329
|
+
ReadRequest.empty(),
|
|
330
|
+
MAX_NULLIFIER_READ_REQUESTS_PER_CALL,
|
|
331
|
+
),
|
|
323
332
|
contractStorageReads: padArrayEnd(
|
|
324
333
|
result.contractStorageReads,
|
|
325
334
|
ContractStorageRead.empty(),
|
|
@@ -334,6 +343,7 @@ export abstract class AbstractPhaseManager {
|
|
|
334
343
|
unencryptedLogsHash,
|
|
335
344
|
unencryptedLogPreimagesLength,
|
|
336
345
|
historicalHeader: this.historicalHeader,
|
|
346
|
+
reverted: result.reverted,
|
|
337
347
|
});
|
|
338
348
|
}
|
|
339
349
|
|
|
@@ -27,42 +27,32 @@ export class AppLogicPhaseManager extends AbstractPhaseManager {
|
|
|
27
27
|
super(db, publicExecutor, publicKernel, publicProver, globalVariables, historicalHeader, phase);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
async handle(
|
|
30
|
+
override async handle(
|
|
31
31
|
tx: Tx,
|
|
32
32
|
previousPublicKernelOutput: PublicKernelCircuitPublicInputs,
|
|
33
33
|
previousPublicKernelProof: Proof,
|
|
34
|
-
)
|
|
35
|
-
/**
|
|
36
|
-
* the output of the public kernel circuit for this phase
|
|
37
|
-
*/
|
|
38
|
-
publicKernelOutput: PublicKernelCircuitPublicInputs;
|
|
39
|
-
/**
|
|
40
|
-
* the proof of the public kernel circuit for this phase
|
|
41
|
-
*/
|
|
42
|
-
publicKernelProof: Proof;
|
|
43
|
-
}> {
|
|
34
|
+
) {
|
|
44
35
|
// add new contracts to the contracts db so that their functions may be found and called
|
|
45
36
|
// TODO(#4073): This is catching only private deployments, when we add public ones, we'll
|
|
46
37
|
// have to capture contracts emitted in that phase as well.
|
|
47
38
|
// TODO(@spalladino): Should we allow emitting contracts in the fee preparation phase?
|
|
48
39
|
this.log(`Processing tx ${tx.getTxHash()}`);
|
|
49
40
|
await this.publicContractsDB.addNewContracts(tx);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
tx,
|
|
53
|
-
previousPublicKernelOutput,
|
|
54
|
-
previousPublicKernelProof,
|
|
55
|
-
);
|
|
56
|
-
tx.unencryptedLogs.addFunctionLogs(newUnencryptedFunctionLogs);
|
|
41
|
+
const [publicKernelOutput, publicKernelProof, newUnencryptedFunctionLogs, revertReason] =
|
|
42
|
+
await this.processEnqueuedPublicCalls(tx, previousPublicKernelOutput, previousPublicKernelProof);
|
|
57
43
|
|
|
58
|
-
|
|
59
|
-
|
|
44
|
+
if (revertReason) {
|
|
45
|
+
await this.rollback(tx, revertReason);
|
|
46
|
+
} else {
|
|
47
|
+
tx.unencryptedLogs.addFunctionLogs(newUnencryptedFunctionLogs);
|
|
48
|
+
await this.publicStateDB.commit();
|
|
49
|
+
}
|
|
60
50
|
|
|
61
|
-
return { publicKernelOutput, publicKernelProof };
|
|
51
|
+
return { publicKernelOutput, publicKernelProof, revertReason };
|
|
62
52
|
}
|
|
63
53
|
|
|
64
54
|
async rollback(tx: Tx, err: unknown): Promise<FailedTx> {
|
|
65
|
-
this.log.warn(`
|
|
55
|
+
this.log.warn(`Rolling back changes from ${tx.getTxHash()}`);
|
|
66
56
|
// remove contracts on failure
|
|
67
57
|
await this.publicContractsDB.removeNewContracts(tx);
|
|
68
58
|
// rollback any state updates from this failed transaction
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { MerkleTreeId } from '@aztec/circuit-types';
|
|
2
|
+
import {
|
|
3
|
+
Fr,
|
|
4
|
+
MAX_NEW_NULLIFIERS_PER_TX,
|
|
5
|
+
MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX,
|
|
6
|
+
MAX_NULLIFIER_READ_REQUESTS_PER_TX,
|
|
7
|
+
MAX_REVERTIBLE_NULLIFIERS_PER_TX,
|
|
8
|
+
MembershipWitness,
|
|
9
|
+
NULLIFIER_TREE_HEIGHT,
|
|
10
|
+
NullifierLeafPreimage,
|
|
11
|
+
ReadRequestContext,
|
|
12
|
+
SideEffectLinkedToNoteHash,
|
|
13
|
+
buildNullifierReadRequestResetHints,
|
|
14
|
+
concatAccumulatedData,
|
|
15
|
+
mergeAccumulatedData,
|
|
16
|
+
} from '@aztec/circuits.js';
|
|
17
|
+
import { Tuple } from '@aztec/foundation/serialize';
|
|
18
|
+
import { MerkleTreeOperations } from '@aztec/world-state';
|
|
19
|
+
|
|
20
|
+
export class HintsBuilder {
|
|
21
|
+
constructor(private db: MerkleTreeOperations) {}
|
|
22
|
+
|
|
23
|
+
getNullifierReadRequestResetHints(
|
|
24
|
+
nullifierReadRequestsNonRevertible: Tuple<ReadRequestContext, typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX>,
|
|
25
|
+
nullifierReadRequestsRevertible: Tuple<ReadRequestContext, typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX>,
|
|
26
|
+
nullifiersNonRevertible: Tuple<SideEffectLinkedToNoteHash, typeof MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX>,
|
|
27
|
+
nullifiersRevertible: Tuple<SideEffectLinkedToNoteHash, typeof MAX_REVERTIBLE_NULLIFIERS_PER_TX>,
|
|
28
|
+
) {
|
|
29
|
+
return buildNullifierReadRequestResetHints(
|
|
30
|
+
this,
|
|
31
|
+
mergeAccumulatedData(
|
|
32
|
+
MAX_NULLIFIER_READ_REQUESTS_PER_TX,
|
|
33
|
+
nullifierReadRequestsNonRevertible,
|
|
34
|
+
nullifierReadRequestsRevertible,
|
|
35
|
+
),
|
|
36
|
+
concatAccumulatedData(MAX_NEW_NULLIFIERS_PER_TX, nullifiersNonRevertible, nullifiersRevertible),
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async getNullifierMembershipWitness(nullifier: Fr) {
|
|
41
|
+
const index = await this.db.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer());
|
|
42
|
+
if (index === undefined) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const siblingPath = await this.db.getSiblingPath(MerkleTreeId.NULLIFIER_TREE, index);
|
|
47
|
+
const membershipWitness = new MembershipWitness(
|
|
48
|
+
NULLIFIER_TREE_HEIGHT,
|
|
49
|
+
index,
|
|
50
|
+
siblingPath.toTuple<typeof NULLIFIER_TREE_HEIGHT>(),
|
|
51
|
+
);
|
|
52
|
+
const leafPreimage = (await this.db.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index))! as NullifierLeafPreimage;
|
|
53
|
+
|
|
54
|
+
return { membershipWitness, leafPreimage };
|
|
55
|
+
}
|
|
56
|
+
}
|
package/src/sequencer/index.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { ContractsDataSourcePublicDB } from '../simulator/public_executor.js';
|
|
|
9
9
|
import { AbstractPhaseManager, PublicKernelPhase } from './abstract_phase_manager.js';
|
|
10
10
|
import { AppLogicPhaseManager } from './app_logic_phase_manager.js';
|
|
11
11
|
import { SetupPhaseManager } from './setup_phase_manager.js';
|
|
12
|
+
import { TailPhaseManager } from './tail_phase_manager.js';
|
|
12
13
|
import { TeardownPhaseManager } from './teardown_phase_manager.js';
|
|
13
14
|
|
|
14
15
|
export class PhaseDidNotChangeError extends Error {
|
|
@@ -115,6 +116,17 @@ export class PhaseManagerFactory {
|
|
|
115
116
|
publicContractsDB,
|
|
116
117
|
publicStateDB,
|
|
117
118
|
);
|
|
119
|
+
} else if (currentPhaseManager.phase !== PublicKernelPhase.TAIL) {
|
|
120
|
+
return new TailPhaseManager(
|
|
121
|
+
db,
|
|
122
|
+
publicExecutor,
|
|
123
|
+
publicKernel,
|
|
124
|
+
publicProver,
|
|
125
|
+
globalVariables,
|
|
126
|
+
historicalHeader,
|
|
127
|
+
publicContractsDB,
|
|
128
|
+
publicStateDB,
|
|
129
|
+
);
|
|
118
130
|
} else {
|
|
119
131
|
return undefined;
|
|
120
132
|
}
|
|
@@ -1,13 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ContractData,
|
|
3
|
+
ExtendedContractData,
|
|
4
|
+
PublicDataWrite,
|
|
5
|
+
SimulationError,
|
|
6
|
+
Tx,
|
|
7
|
+
TxEffect,
|
|
8
|
+
TxHash,
|
|
9
|
+
TxL2Logs,
|
|
10
|
+
} from '@aztec/circuit-types';
|
|
2
11
|
import {
|
|
3
12
|
Fr,
|
|
4
13
|
Header,
|
|
14
|
+
MAX_NEW_CONTRACTS_PER_TX,
|
|
15
|
+
MAX_NEW_NOTE_HASHES_PER_TX,
|
|
16
|
+
MAX_NEW_NULLIFIERS_PER_TX,
|
|
17
|
+
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
5
18
|
Proof,
|
|
6
19
|
PublicAccumulatedNonRevertibleData,
|
|
7
20
|
PublicAccumulatedRevertibleData,
|
|
8
21
|
PublicKernelCircuitPublicInputs,
|
|
22
|
+
SideEffect,
|
|
23
|
+
SideEffectLinkedToNoteHash,
|
|
9
24
|
makeEmptyProof,
|
|
10
25
|
} from '@aztec/circuits.js';
|
|
26
|
+
import { Tuple, fromFieldsTuple } from '@aztec/foundation/serialize';
|
|
11
27
|
|
|
12
28
|
/**
|
|
13
29
|
* Represents a tx that has been processed by the sequencer public processor,
|
|
@@ -26,8 +42,39 @@ export type ProcessedTx = Pick<Tx, 'proof' | 'encryptedLogs' | 'unencryptedLogs'
|
|
|
26
42
|
* Flag indicating the tx is 'empty' meaning it's a padding tx to take us to a power of 2.
|
|
27
43
|
*/
|
|
28
44
|
isEmpty: boolean;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Reason the tx was reverted.
|
|
48
|
+
*/
|
|
49
|
+
revertReason: SimulationError | undefined;
|
|
29
50
|
};
|
|
30
51
|
|
|
52
|
+
export type RevertedTx = ProcessedTx & {
|
|
53
|
+
data: PublicKernelCircuitPublicInputs & {
|
|
54
|
+
reverted: true;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
revertReason: SimulationError;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export function isRevertedTx(tx: ProcessedTx): tx is RevertedTx {
|
|
61
|
+
return tx.data.reverted;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function partitionReverts(txs: ProcessedTx[]): { reverted: RevertedTx[]; nonReverted: ProcessedTx[] } {
|
|
65
|
+
return txs.reduce(
|
|
66
|
+
({ reverted, nonReverted }, tx) => {
|
|
67
|
+
if (isRevertedTx(tx)) {
|
|
68
|
+
reverted.push(tx);
|
|
69
|
+
} else {
|
|
70
|
+
nonReverted.push(tx);
|
|
71
|
+
}
|
|
72
|
+
return { reverted, nonReverted };
|
|
73
|
+
},
|
|
74
|
+
{ reverted: [], nonReverted: [] } as ReturnType<typeof partitionReverts>,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
31
78
|
/**
|
|
32
79
|
* Represents a tx that failed to be processed by the sequencer public processor.
|
|
33
80
|
*/
|
|
@@ -42,31 +89,73 @@ export type FailedTx = {
|
|
|
42
89
|
error: Error;
|
|
43
90
|
};
|
|
44
91
|
|
|
92
|
+
/**
|
|
93
|
+
*
|
|
94
|
+
* @param tx - the TX being procesed
|
|
95
|
+
* @param publicKernelPublicInput - the output of the public kernel circuit, unless we just came from private
|
|
96
|
+
* @param publicKernelProof - the proof of the public kernel circuit, unless we just came from private
|
|
97
|
+
* @returns PublicKernelCircuitPublicInputs, either passed through from the input or converted from the output of the TX,
|
|
98
|
+
* and Proof, either passed through from the input or the proof of the TX
|
|
99
|
+
*/
|
|
100
|
+
export function getPreviousOutputAndProof(
|
|
101
|
+
tx: Tx,
|
|
102
|
+
publicKernelPublicInput?: PublicKernelCircuitPublicInputs,
|
|
103
|
+
publicKernelProof?: 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
|
+
previousProof: Proof;
|
|
113
|
+
} {
|
|
114
|
+
if (publicKernelPublicInput && publicKernelProof) {
|
|
115
|
+
return {
|
|
116
|
+
publicKernelPublicInput,
|
|
117
|
+
previousProof: publicKernelProof,
|
|
118
|
+
};
|
|
119
|
+
} else {
|
|
120
|
+
const publicKernelPublicInput = new PublicKernelCircuitPublicInputs(
|
|
121
|
+
tx.data.aggregationObject,
|
|
122
|
+
PublicAccumulatedNonRevertibleData.fromPrivateAccumulatedNonRevertibleData(tx.data.endNonRevertibleData),
|
|
123
|
+
PublicAccumulatedRevertibleData.fromPrivateAccumulatedRevertibleData(tx.data.end),
|
|
124
|
+
tx.data.constants,
|
|
125
|
+
tx.data.needsSetup,
|
|
126
|
+
tx.data.needsAppLogic,
|
|
127
|
+
tx.data.needsTeardown,
|
|
128
|
+
false, // reverted
|
|
129
|
+
);
|
|
130
|
+
return {
|
|
131
|
+
publicKernelPublicInput,
|
|
132
|
+
previousProof: publicKernelProof || tx.proof,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
45
137
|
/**
|
|
46
138
|
* Makes a processed tx out of source tx.
|
|
47
139
|
* @param tx - Source tx.
|
|
48
140
|
* @param kernelOutput - Output of the kernel circuit simulation for this tx.
|
|
49
141
|
* @param proof - Proof of the kernel circuit for this tx.
|
|
50
142
|
*/
|
|
51
|
-
export function makeProcessedTx(
|
|
143
|
+
export function makeProcessedTx(
|
|
144
|
+
tx: Tx,
|
|
145
|
+
kernelOutput?: PublicKernelCircuitPublicInputs,
|
|
146
|
+
proof?: Proof,
|
|
147
|
+
revertReason?: SimulationError,
|
|
148
|
+
): ProcessedTx {
|
|
149
|
+
const { publicKernelPublicInput, previousProof } = getPreviousOutputAndProof(tx, kernelOutput, proof);
|
|
52
150
|
return {
|
|
53
151
|
hash: tx.getTxHash(),
|
|
54
|
-
data:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
PublicAccumulatedRevertibleData.fromPrivateAccumulatedRevertibleData(tx.data.end),
|
|
60
|
-
tx.data.constants,
|
|
61
|
-
tx.data.needsSetup,
|
|
62
|
-
tx.data.needsAppLogic,
|
|
63
|
-
tx.data.needsTeardown,
|
|
64
|
-
),
|
|
65
|
-
proof: proof ?? tx.proof,
|
|
66
|
-
encryptedLogs: tx.encryptedLogs,
|
|
67
|
-
unencryptedLogs: tx.unencryptedLogs,
|
|
68
|
-
newContracts: tx.newContracts,
|
|
152
|
+
data: publicKernelPublicInput,
|
|
153
|
+
proof: previousProof,
|
|
154
|
+
encryptedLogs: revertReason ? new TxL2Logs([]) : tx.encryptedLogs,
|
|
155
|
+
unencryptedLogs: revertReason ? new TxL2Logs([]) : tx.unencryptedLogs,
|
|
156
|
+
newContracts: revertReason ? [ExtendedContractData.empty()] : tx.newContracts,
|
|
69
157
|
isEmpty: false,
|
|
158
|
+
revertReason,
|
|
70
159
|
};
|
|
71
160
|
}
|
|
72
161
|
|
|
@@ -90,5 +179,46 @@ export function makeEmptyProcessedTx(header: Header, chainId: Fr, version: Fr):
|
|
|
90
179
|
proof: emptyProof,
|
|
91
180
|
newContracts: [ExtendedContractData.empty()],
|
|
92
181
|
isEmpty: true,
|
|
182
|
+
revertReason: undefined,
|
|
93
183
|
};
|
|
94
184
|
}
|
|
185
|
+
|
|
186
|
+
export function toTxEffect(tx: ProcessedTx): TxEffect {
|
|
187
|
+
return new TxEffect(
|
|
188
|
+
tx.data.combinedData.newNoteHashes.map((c: SideEffect) => c.value) as Tuple<Fr, typeof MAX_NEW_NOTE_HASHES_PER_TX>,
|
|
189
|
+
tx.data.combinedData.newNullifiers.map((n: SideEffectLinkedToNoteHash) => n.value) as Tuple<
|
|
190
|
+
Fr,
|
|
191
|
+
typeof MAX_NEW_NULLIFIERS_PER_TX
|
|
192
|
+
>,
|
|
193
|
+
tx.data.combinedData.newL2ToL1Msgs,
|
|
194
|
+
tx.data.combinedData.publicDataUpdateRequests.map(t => new PublicDataWrite(t.leafSlot, t.newValue)) as Tuple<
|
|
195
|
+
PublicDataWrite,
|
|
196
|
+
typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX
|
|
197
|
+
>,
|
|
198
|
+
tx.data.combinedData.newContracts.map(cd => cd.hash()) as Tuple<Fr, typeof MAX_NEW_CONTRACTS_PER_TX>,
|
|
199
|
+
tx.data.combinedData.newContracts.map(
|
|
200
|
+
cd => new ContractData(cd.contractAddress, cd.portalContractAddress),
|
|
201
|
+
) as Tuple<ContractData, typeof MAX_NEW_CONTRACTS_PER_TX>,
|
|
202
|
+
tx.encryptedLogs || new TxL2Logs([]),
|
|
203
|
+
tx.unencryptedLogs || new TxL2Logs([]),
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function validateProcessedTxLogs(tx: ProcessedTx): void {
|
|
208
|
+
const unencryptedLogs = tx.unencryptedLogs || new TxL2Logs([]);
|
|
209
|
+
const kernelUnencryptedLogsHash = fromFieldsTuple(tx.data.combinedData.unencryptedLogsHash);
|
|
210
|
+
if (!unencryptedLogs.hash().equals(kernelUnencryptedLogsHash)) {
|
|
211
|
+
throw new Error(
|
|
212
|
+
`Unencrypted logs hash mismatch. Expected ${unencryptedLogs
|
|
213
|
+
.hash()
|
|
214
|
+
.toString('hex')}, got ${kernelUnencryptedLogsHash.toString('hex')}.
|
|
215
|
+
Processed: ${JSON.stringify(unencryptedLogs.toJSON())}
|
|
216
|
+
Kernel Length: ${tx.data.combinedData.unencryptedLogPreimagesLength}`,
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export function validateProcessedTx(tx: ProcessedTx): void {
|
|
222
|
+
validateProcessedTxLogs(tx);
|
|
223
|
+
// TODO: validate other fields
|
|
224
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ContractDataSource, L1ToL2MessageSource, Tx } from '@aztec/circuit-types';
|
|
1
|
+
import { ContractDataSource, L1ToL2MessageSource, SimulationError, Tx } from '@aztec/circuit-types';
|
|
2
2
|
import { TxSequencerProcessingStats } from '@aztec/circuit-types/stats';
|
|
3
3
|
import { GlobalVariables, Header } from '@aztec/circuits.js';
|
|
4
4
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
@@ -11,9 +11,17 @@ import { PublicProver } from '../prover/index.js';
|
|
|
11
11
|
import { PublicKernelCircuitSimulator } from '../simulator/index.js';
|
|
12
12
|
import { ContractsDataSourcePublicDB, WorldStateDB, WorldStatePublicDB } from '../simulator/public_executor.js';
|
|
13
13
|
import { RealPublicKernelCircuitSimulator } from '../simulator/public_kernel.js';
|
|
14
|
+
import { SimulationProvider } from '../simulator/simulation_provider.js';
|
|
14
15
|
import { AbstractPhaseManager } from './abstract_phase_manager.js';
|
|
15
16
|
import { PhaseManagerFactory } from './phase_manager_factory.js';
|
|
16
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
FailedTx,
|
|
19
|
+
ProcessedTx,
|
|
20
|
+
getPreviousOutputAndProof,
|
|
21
|
+
makeEmptyProcessedTx,
|
|
22
|
+
makeProcessedTx,
|
|
23
|
+
validateProcessedTx,
|
|
24
|
+
} from './processed_tx.js';
|
|
17
25
|
|
|
18
26
|
/**
|
|
19
27
|
* Creates new instances of PublicProcessor given the provided merkle tree db and contract data source.
|
|
@@ -23,6 +31,7 @@ export class PublicProcessorFactory {
|
|
|
23
31
|
private merkleTree: MerkleTreeOperations,
|
|
24
32
|
private contractDataSource: ContractDataSource,
|
|
25
33
|
private l1Tol2MessagesDataSource: L1ToL2MessageSource,
|
|
34
|
+
private simulator: SimulationProvider,
|
|
26
35
|
) {}
|
|
27
36
|
|
|
28
37
|
/**
|
|
@@ -45,7 +54,7 @@ export class PublicProcessorFactory {
|
|
|
45
54
|
return new PublicProcessor(
|
|
46
55
|
this.merkleTree,
|
|
47
56
|
publicExecutor,
|
|
48
|
-
new RealPublicKernelCircuitSimulator(),
|
|
57
|
+
new RealPublicKernelCircuitSimulator(this.simulator),
|
|
49
58
|
new EmptyPublicProver(),
|
|
50
59
|
globalVariables,
|
|
51
60
|
historicalHeader,
|
|
@@ -97,17 +106,15 @@ export class PublicProcessor {
|
|
|
97
106
|
this.publicStateDB,
|
|
98
107
|
);
|
|
99
108
|
this.log(`Beginning processing in phase ${phase?.phase} for tx ${tx.getTxHash()}`);
|
|
100
|
-
let { publicKernelPublicInput,
|
|
101
|
-
|
|
102
|
-
undefined,
|
|
103
|
-
undefined,
|
|
104
|
-
);
|
|
109
|
+
let { publicKernelPublicInput, previousProof: proof } = getPreviousOutputAndProof(tx, undefined, undefined);
|
|
110
|
+
let revertReason: SimulationError | undefined;
|
|
105
111
|
const timer = new Timer();
|
|
106
112
|
try {
|
|
107
113
|
while (phase) {
|
|
108
|
-
const output = await phase.handle(tx, publicKernelPublicInput,
|
|
114
|
+
const output = await phase.handle(tx, publicKernelPublicInput, proof);
|
|
109
115
|
publicKernelPublicInput = output.publicKernelOutput;
|
|
110
|
-
|
|
116
|
+
proof = output.publicKernelProof;
|
|
117
|
+
revertReason ??= output.revertReason;
|
|
111
118
|
phase = PhaseManagerFactory.phaseFromOutput(
|
|
112
119
|
publicKernelPublicInput,
|
|
113
120
|
phase,
|
|
@@ -122,7 +129,9 @@ export class PublicProcessor {
|
|
|
122
129
|
);
|
|
123
130
|
}
|
|
124
131
|
|
|
125
|
-
const processedTransaction = makeProcessedTx(tx, publicKernelPublicInput,
|
|
132
|
+
const processedTransaction = makeProcessedTx(tx, publicKernelPublicInput, proof, revertReason);
|
|
133
|
+
validateProcessedTx(processedTransaction);
|
|
134
|
+
|
|
126
135
|
result.push(processedTransaction);
|
|
127
136
|
|
|
128
137
|
this.log(`Processed public part of ${tx.data.endNonRevertibleData.newNullifiers[0].value}`, {
|
|
@@ -133,9 +142,14 @@ export class PublicProcessor {
|
|
|
133
142
|
0,
|
|
134
143
|
...tx.getStats(),
|
|
135
144
|
} satisfies TxSequencerProcessingStats);
|
|
136
|
-
} catch (err) {
|
|
137
|
-
const
|
|
138
|
-
|
|
145
|
+
} catch (err: any) {
|
|
146
|
+
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
|
|
147
|
+
this.log.warn(`Failed to process tx ${tx.getTxHash()}: ${errorMessage}`);
|
|
148
|
+
|
|
149
|
+
failed.push({
|
|
150
|
+
tx,
|
|
151
|
+
error: err instanceof Error ? err : new Error(errorMessage),
|
|
152
|
+
});
|
|
139
153
|
}
|
|
140
154
|
}
|
|
141
155
|
|