@aztec/prover-node 0.0.1-commit.b9865e97 → 0.0.1-commit.be03c316
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/README.md +518 -0
- package/dest/actions/rerun-epoch-proving-job.d.ts +3 -3
- package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -1
- package/dest/actions/rerun-epoch-proving-job.js +102 -19
- package/dest/checkpoint-store.d.ts +87 -0
- package/dest/checkpoint-store.d.ts.map +1 -0
- package/dest/checkpoint-store.js +186 -0
- package/dest/config.d.ts +3 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +8 -1
- package/dest/factory.d.ts +4 -1
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +2 -6
- package/dest/index.d.ts +2 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/job/checkpoint-prover.d.ts +134 -0
- package/dest/job/checkpoint-prover.d.ts.map +1 -0
- package/dest/job/checkpoint-prover.js +353 -0
- package/dest/job/epoch-session.d.ts +146 -0
- package/dest/job/epoch-session.d.ts.map +1 -0
- package/dest/job/epoch-session.js +720 -0
- package/dest/job/top-tree-job.d.ts +82 -0
- package/dest/job/top-tree-job.d.ts.map +1 -0
- package/dest/job/top-tree-job.js +152 -0
- package/dest/metrics.d.ts +25 -8
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +64 -14
- package/dest/proof-publishing-service.d.ts +161 -0
- package/dest/proof-publishing-service.d.ts.map +1 -0
- package/dest/proof-publishing-service.js +335 -0
- package/dest/prover-node-publisher.d.ts +10 -19
- package/dest/prover-node-publisher.d.ts.map +1 -1
- package/dest/prover-node-publisher.js +43 -99
- package/dest/prover-node.d.ts +107 -67
- package/dest/prover-node.d.ts.map +1 -1
- package/dest/prover-node.js +476 -261
- package/dest/prover-publisher-factory.d.ts +3 -1
- package/dest/prover-publisher-factory.d.ts.map +1 -1
- package/dest/prover-publisher-factory.js +1 -0
- package/dest/session-manager.d.ts +158 -0
- package/dest/session-manager.d.ts.map +1 -0
- package/dest/session-manager.js +452 -0
- package/dest/test/index.d.ts +7 -6
- package/dest/test/index.d.ts.map +1 -1
- package/package.json +24 -23
- package/src/actions/rerun-epoch-proving-job.ts +104 -27
- package/src/checkpoint-store.ts +218 -0
- package/src/config.ts +12 -1
- package/src/factory.ts +5 -8
- package/src/index.ts +1 -0
- package/src/job/checkpoint-prover.ts +468 -0
- package/src/job/epoch-session.ts +436 -0
- package/src/job/top-tree-job.ts +227 -0
- package/src/metrics.ts +65 -23
- package/src/proof-publishing-service.ts +427 -0
- package/src/prover-node-publisher.ts +58 -123
- package/src/prover-node.ts +549 -283
- package/src/prover-publisher-factory.ts +3 -0
- package/src/session-manager.ts +552 -0
- package/src/test/index.ts +6 -6
- package/dest/job/epoch-proving-job.d.ts +0 -67
- package/dest/job/epoch-proving-job.d.ts.map +0 -1
- package/dest/job/epoch-proving-job.js +0 -912
- package/src/job/epoch-proving-job.ts +0 -531
|
@@ -2,21 +2,17 @@ import { BatchedBlob, getEthBlobEvaluationInputs } from '@aztec/blob-lib';
|
|
|
2
2
|
import { MAX_CHECKPOINTS_PER_EPOCH } from '@aztec/constants';
|
|
3
3
|
import type { RollupContract, ViemCommitteeAttestation } from '@aztec/ethereum/contracts';
|
|
4
4
|
import type { L1TxUtils } from '@aztec/ethereum/l1-tx-utils';
|
|
5
|
-
import { makeTuple } from '@aztec/foundation/array';
|
|
6
5
|
import { CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
|
|
7
6
|
import { areArraysEqual } from '@aztec/foundation/collection';
|
|
8
7
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
9
8
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
10
9
|
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
11
|
-
import { retryUntil } from '@aztec/foundation/retry';
|
|
12
|
-
import type { Tuple } from '@aztec/foundation/serialize';
|
|
13
10
|
import { Timer } from '@aztec/foundation/timer';
|
|
14
11
|
import { RollupAbi } from '@aztec/l1-artifacts';
|
|
15
12
|
import type { PublisherConfig, TxSenderConfig } from '@aztec/sequencer-client';
|
|
16
13
|
import { CommitteeAttestation, CommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
|
|
17
|
-
import { getProofSubmissionDeadlineTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
18
14
|
import type { Proof } from '@aztec/stdlib/proofs';
|
|
19
|
-
import type {
|
|
15
|
+
import type { CheckpointHeader, RootRollupPublicInputs } from '@aztec/stdlib/rollup';
|
|
20
16
|
import type { L1PublishProofStats } from '@aztec/stdlib/stats';
|
|
21
17
|
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
22
18
|
|
|
@@ -33,18 +29,19 @@ export type L1SubmitEpochProofArgs = {
|
|
|
33
29
|
endTimestamp: Fr;
|
|
34
30
|
outHash: Fr;
|
|
35
31
|
proverId: Fr;
|
|
36
|
-
|
|
32
|
+
headers: CheckpointHeader[];
|
|
37
33
|
proof: Proof;
|
|
38
34
|
};
|
|
39
35
|
|
|
40
36
|
export class ProverNodePublisher {
|
|
41
|
-
private interrupted = false;
|
|
42
37
|
private metrics: ProverNodePublisherMetrics;
|
|
43
38
|
|
|
44
39
|
protected log: Logger;
|
|
45
40
|
|
|
46
41
|
protected rollupContract: RollupContract;
|
|
47
42
|
|
|
43
|
+
protected proofSubmissionTarget: Hex;
|
|
44
|
+
|
|
48
45
|
public readonly l1TxUtils: L1TxUtils;
|
|
49
46
|
|
|
50
47
|
constructor(
|
|
@@ -52,6 +49,7 @@ export class ProverNodePublisher {
|
|
|
52
49
|
deps: {
|
|
53
50
|
rollupContract: RollupContract;
|
|
54
51
|
l1TxUtils: L1TxUtils;
|
|
52
|
+
proofSubmissionTarget?: EthAddress;
|
|
55
53
|
telemetry?: TelemetryClient;
|
|
56
54
|
},
|
|
57
55
|
bindings?: LoggerBindings,
|
|
@@ -62,6 +60,7 @@ export class ProverNodePublisher {
|
|
|
62
60
|
this.log = createLogger('prover-node:l1-tx-publisher', bindings);
|
|
63
61
|
|
|
64
62
|
this.rollupContract = deps.rollupContract;
|
|
63
|
+
this.proofSubmissionTarget = deps.proofSubmissionTarget?.toString() ?? deps.rollupContract.address;
|
|
65
64
|
this.l1TxUtils = deps.l1TxUtils;
|
|
66
65
|
}
|
|
67
66
|
|
|
@@ -69,23 +68,6 @@ export class ProverNodePublisher {
|
|
|
69
68
|
return this.rollupContract;
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
/**
|
|
73
|
-
* Calling `interrupt` will cause any in progress call to `publishRollup` to return `false` asap.
|
|
74
|
-
* Be warned, the call may return false even if the tx subsequently gets successfully mined.
|
|
75
|
-
* In practice this shouldn't matter, as we'll only ever be calling `interrupt` when we know it's going to fail.
|
|
76
|
-
* A call to `restart` is required before you can continue publishing.
|
|
77
|
-
*/
|
|
78
|
-
public interrupt() {
|
|
79
|
-
this.interrupted = true;
|
|
80
|
-
this.l1TxUtils.interrupt();
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/** Restarts the publisher after calling `interrupt`. */
|
|
84
|
-
public restart() {
|
|
85
|
-
this.interrupted = false;
|
|
86
|
-
this.l1TxUtils.restart();
|
|
87
|
-
}
|
|
88
|
-
|
|
89
71
|
public getSenderAddress() {
|
|
90
72
|
return this.l1TxUtils.getSenderAddress();
|
|
91
73
|
}
|
|
@@ -98,107 +80,54 @@ export class ProverNodePublisher {
|
|
|
98
80
|
proof: Proof;
|
|
99
81
|
batchedBlobInputs: BatchedBlob;
|
|
100
82
|
attestations: ViemCommitteeAttestation[];
|
|
83
|
+
headers: CheckpointHeader[];
|
|
84
|
+
/** Wall-clock deadline (proof-submission window end) past which the L1 tx should stop retrying. */
|
|
85
|
+
deadline?: Date;
|
|
101
86
|
}): Promise<boolean> {
|
|
102
87
|
const { epochNumber, fromCheckpoint, toCheckpoint } = args;
|
|
103
88
|
const ctx = { epochNumber, fromCheckpoint, toCheckpoint };
|
|
104
89
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return false;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const timer = new Timer();
|
|
112
|
-
// Validate epoch proof range and hashes are correct before submitting
|
|
113
|
-
await this.validateEpochProofSubmission(args);
|
|
114
|
-
|
|
115
|
-
const txReceipt = await this.sendSubmitEpochProofTx(args);
|
|
116
|
-
if (!txReceipt) {
|
|
117
|
-
this.log.error(`Failed to mine submitEpochProof tx`, undefined, ctx);
|
|
118
|
-
return false;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
try {
|
|
122
|
-
this.metrics.recordSenderBalance(
|
|
123
|
-
await this.l1TxUtils.getSenderBalance(),
|
|
124
|
-
this.l1TxUtils.getSenderAddress().toString(),
|
|
125
|
-
);
|
|
126
|
-
} catch (err) {
|
|
127
|
-
this.log.warn(`Failed to record the ETH balance of the prover node: ${err}`);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Tx was mined successfully
|
|
131
|
-
if (txReceipt.status === 'success') {
|
|
132
|
-
const tx = await this.l1TxUtils.getTransactionStats(txReceipt.transactionHash);
|
|
133
|
-
const stats: L1PublishProofStats = {
|
|
134
|
-
gasPrice: txReceipt.effectiveGasPrice,
|
|
135
|
-
gasUsed: txReceipt.gasUsed,
|
|
136
|
-
transactionHash: txReceipt.transactionHash,
|
|
137
|
-
calldataGas: tx!.calldataGas,
|
|
138
|
-
calldataSize: tx!.calldataSize,
|
|
139
|
-
sender: tx!.sender,
|
|
140
|
-
blobDataGas: 0n,
|
|
141
|
-
blobGasUsed: 0n,
|
|
142
|
-
eventName: 'proof-published-to-l1',
|
|
143
|
-
};
|
|
144
|
-
this.log.info(`Published epoch proof to L1 rollup contract`, { ...stats, ...ctx });
|
|
145
|
-
this.metrics.recordSubmitProof(timer.ms(), stats);
|
|
146
|
-
return true;
|
|
147
|
-
}
|
|
90
|
+
const timer = new Timer();
|
|
91
|
+
// Validate epoch proof range and hashes are correct before submitting
|
|
92
|
+
await this.validateEpochProofSubmission(args);
|
|
148
93
|
|
|
149
|
-
|
|
150
|
-
|
|
94
|
+
const txReceipt = await this.sendSubmitEpochProofTx(args);
|
|
95
|
+
if (!txReceipt) {
|
|
96
|
+
this.log.error(`Failed to mine submitEpochProof tx`, undefined, ctx);
|
|
97
|
+
return false;
|
|
151
98
|
}
|
|
152
99
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
100
|
+
try {
|
|
101
|
+
this.metrics.recordSenderBalance(
|
|
102
|
+
await this.l1TxUtils.getSenderBalance(),
|
|
103
|
+
this.l1TxUtils.getSenderAddress().toString(),
|
|
104
|
+
);
|
|
105
|
+
} catch (err) {
|
|
106
|
+
this.log.warn(`Failed to record the ETH balance of the prover node: ${err}`);
|
|
107
|
+
}
|
|
156
108
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
109
|
+
// Tx was mined successfully
|
|
110
|
+
if (txReceipt.status === 'success') {
|
|
111
|
+
const tx = await this.l1TxUtils.getTransactionStats(txReceipt.transactionHash);
|
|
112
|
+
const stats: L1PublishProofStats = {
|
|
113
|
+
gasPrice: txReceipt.effectiveGasPrice,
|
|
114
|
+
gasUsed: txReceipt.gasUsed,
|
|
115
|
+
transactionHash: txReceipt.transactionHash,
|
|
116
|
+
calldataGas: tx!.calldataGas,
|
|
117
|
+
calldataSize: tx!.calldataSize,
|
|
118
|
+
sender: tx!.sender,
|
|
119
|
+
blobDataGas: 0n,
|
|
120
|
+
blobGasUsed: 0n,
|
|
121
|
+
eventName: 'proof-published-to-l1',
|
|
122
|
+
};
|
|
123
|
+
this.log.info(`Published epoch proof to L1 rollup contract`, { ...stats, ...ctx });
|
|
124
|
+
this.metrics.recordSubmitProof(timer.ms(), stats);
|
|
161
125
|
return true;
|
|
162
126
|
}
|
|
163
127
|
|
|
164
|
-
|
|
165
|
-
this.log.
|
|
166
|
-
|
|
167
|
-
fromCheckpoint,
|
|
168
|
-
provenCheckpoint,
|
|
169
|
-
timeout,
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
await retryUntil(
|
|
173
|
-
async () => {
|
|
174
|
-
if (this.interrupted) {
|
|
175
|
-
return true;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const proven = await this.getProvenCheckpoint();
|
|
179
|
-
this.log.verbose(`Proven checkpoint is at ${proven} (waiting for ${fromCheckpoint - 1})`, { epochNumber });
|
|
180
|
-
return this.isStartBuildingOnProven(fromCheckpoint, proven) ? true : undefined;
|
|
181
|
-
},
|
|
182
|
-
`proven checkpoint to reach ${fromCheckpoint - 1}`,
|
|
183
|
-
timeout,
|
|
184
|
-
4,
|
|
185
|
-
);
|
|
186
|
-
|
|
187
|
-
return !this.interrupted;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
private async getProvenCheckpoint() {
|
|
191
|
-
return (await this.rollupContract.getTips()).proven;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
private isStartBuildingOnProven(fromCheckpoint: CheckpointNumber, provenCheckpoint: CheckpointNumber) {
|
|
195
|
-
return fromCheckpoint - 1 <= provenCheckpoint;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
private async getSecondsUntilProofSubmissionWindowEnd(epochNumber: EpochNumber) {
|
|
199
|
-
const deadline = getProofSubmissionDeadlineTimestamp(epochNumber, await this.rollupContract.getRollupConstants());
|
|
200
|
-
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
201
|
-
return Math.max(Number(deadline - now), 0.001);
|
|
128
|
+
this.metrics.recordFailedTx();
|
|
129
|
+
this.log.error(`Rollup submitEpochProof tx reverted ${txReceipt.transactionHash}`, undefined, ctx);
|
|
130
|
+
return false;
|
|
202
131
|
}
|
|
203
132
|
|
|
204
133
|
private async validateEpochProofSubmission(args: {
|
|
@@ -208,6 +137,7 @@ export class ProverNodePublisher {
|
|
|
208
137
|
proof: Proof;
|
|
209
138
|
batchedBlobInputs: BatchedBlob;
|
|
210
139
|
attestations: ViemCommitteeAttestation[];
|
|
140
|
+
headers: CheckpointHeader[];
|
|
211
141
|
}) {
|
|
212
142
|
const { fromCheckpoint, toCheckpoint, publicInputs, batchedBlobInputs } = args;
|
|
213
143
|
|
|
@@ -281,6 +211,7 @@ export class ProverNodePublisher {
|
|
|
281
211
|
proof: Proof;
|
|
282
212
|
batchedBlobInputs: BatchedBlob;
|
|
283
213
|
attestations: ViemCommitteeAttestation[];
|
|
214
|
+
headers: CheckpointHeader[];
|
|
284
215
|
}): Promise<void> {
|
|
285
216
|
const { epochNumber, fromCheckpoint, toCheckpoint } = args;
|
|
286
217
|
|
|
@@ -290,7 +221,7 @@ export class ProverNodePublisher {
|
|
|
290
221
|
const senderAddress = this.l1TxUtils.getSenderAddress();
|
|
291
222
|
|
|
292
223
|
const [gasLimit, gasPrice, latestBlock] = await Promise.all([
|
|
293
|
-
this.l1TxUtils.estimateGas(senderAddress.toString() as `0x${string}`, { to: this.
|
|
224
|
+
this.l1TxUtils.estimateGas(senderAddress.toString() as `0x${string}`, { to: this.proofSubmissionTarget, data }),
|
|
294
225
|
this.l1TxUtils.getGasPrice(),
|
|
295
226
|
this.l1TxUtils.client.getBlock({ blockTag: 'latest' }),
|
|
296
227
|
]);
|
|
@@ -328,6 +259,7 @@ export class ProverNodePublisher {
|
|
|
328
259
|
proof: Proof;
|
|
329
260
|
batchedBlobInputs: BatchedBlob;
|
|
330
261
|
attestations: ViemCommitteeAttestation[];
|
|
262
|
+
headers: CheckpointHeader[];
|
|
331
263
|
}): Hex {
|
|
332
264
|
return encodeFunctionData({
|
|
333
265
|
abi: RollupAbi,
|
|
@@ -339,10 +271,12 @@ export class ProverNodePublisher {
|
|
|
339
271
|
private async sendSubmitEpochProofTx(args: {
|
|
340
272
|
fromCheckpoint: CheckpointNumber;
|
|
341
273
|
toCheckpoint: CheckpointNumber;
|
|
274
|
+
deadline?: Date;
|
|
342
275
|
publicInputs: RootRollupPublicInputs;
|
|
343
276
|
proof: Proof;
|
|
344
277
|
batchedBlobInputs: BatchedBlob;
|
|
345
278
|
attestations: ViemCommitteeAttestation[];
|
|
279
|
+
headers: CheckpointHeader[];
|
|
346
280
|
}): Promise<TransactionReceipt | undefined> {
|
|
347
281
|
const txArgs = [this.getSubmitEpochProofArgs(args)] as const;
|
|
348
282
|
|
|
@@ -357,7 +291,10 @@ export class ProverNodePublisher {
|
|
|
357
291
|
args: txArgs,
|
|
358
292
|
});
|
|
359
293
|
try {
|
|
360
|
-
const { receipt } = await this.l1TxUtils.sendAndMonitorTransaction(
|
|
294
|
+
const { receipt } = await this.l1TxUtils.sendAndMonitorTransaction(
|
|
295
|
+
{ to: this.proofSubmissionTarget, data },
|
|
296
|
+
{ txTimeoutAt: args.deadline },
|
|
297
|
+
);
|
|
361
298
|
if (receipt.status !== 'success') {
|
|
362
299
|
const errorMsg = await this.l1TxUtils.tryGetErrorFromRevertedTx(
|
|
363
300
|
data,
|
|
@@ -365,7 +302,7 @@ export class ProverNodePublisher {
|
|
|
365
302
|
args: [...txArgs],
|
|
366
303
|
functionName: 'submitEpochRootProof',
|
|
367
304
|
abi: RollupAbi,
|
|
368
|
-
address: this.
|
|
305
|
+
address: this.proofSubmissionTarget,
|
|
369
306
|
},
|
|
370
307
|
/*blobInputs*/ undefined,
|
|
371
308
|
/*stateOverride*/ [],
|
|
@@ -386,6 +323,7 @@ export class ProverNodePublisher {
|
|
|
386
323
|
publicInputs: RootRollupPublicInputs;
|
|
387
324
|
batchedBlobInputs: BatchedBlob;
|
|
388
325
|
attestations: ViemCommitteeAttestation[];
|
|
326
|
+
headers: CheckpointHeader[];
|
|
389
327
|
}) {
|
|
390
328
|
// Returns arguments for EpochProofLib.sol -> getEpochProofPublicInputs()
|
|
391
329
|
return [
|
|
@@ -397,11 +335,7 @@ export class ProverNodePublisher {
|
|
|
397
335
|
outHash: args.publicInputs.outHash.toString(),
|
|
398
336
|
proverId: EthAddress.fromField(args.publicInputs.constants.proverId).toString(),
|
|
399
337
|
} /*_args*/,
|
|
400
|
-
|
|
401
|
-
i % 2 === 0
|
|
402
|
-
? args.publicInputs.fees[i / 2].recipient.toField().toString()
|
|
403
|
-
: args.publicInputs.fees[(i - 1) / 2].value.toString(),
|
|
404
|
-
) /*_fees*/,
|
|
338
|
+
args.headers.map(header => header.toViem()) /*_headers*/,
|
|
405
339
|
getEthBlobEvaluationInputs(args.batchedBlobInputs) /*_blobPublicInputs*/,
|
|
406
340
|
] as const;
|
|
407
341
|
}
|
|
@@ -413,6 +347,7 @@ export class ProverNodePublisher {
|
|
|
413
347
|
proof: Proof;
|
|
414
348
|
batchedBlobInputs: BatchedBlob;
|
|
415
349
|
attestations: ViemCommitteeAttestation[];
|
|
350
|
+
headers: CheckpointHeader[];
|
|
416
351
|
}) {
|
|
417
352
|
// Returns arguments for EpochProofLib.sol -> submitEpochRootProof()
|
|
418
353
|
const proofHex: Hex = `0x${args.proof.withoutPublicInputs().toString('hex')}`;
|
|
@@ -421,7 +356,7 @@ export class ProverNodePublisher {
|
|
|
421
356
|
start: argsArray[0],
|
|
422
357
|
end: argsArray[1],
|
|
423
358
|
args: argsArray[2],
|
|
424
|
-
|
|
359
|
+
headers: argsArray[3],
|
|
425
360
|
attestations: CommitteeAttestationsAndSigners.packAttestations(
|
|
426
361
|
args.attestations.map(a => CommitteeAttestation.fromViem(a)),
|
|
427
362
|
),
|