@aztec/prover-node 0.0.1-commit.2f68f620 → 0.0.1-commit.3100065
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 +511 -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 +106 -104
- package/dest/checkpoint-store.d.ts +88 -0
- package/dest/checkpoint-store.d.ts.map +1 -0
- package/dest/checkpoint-store.js +169 -0
- package/dest/config.d.ts +1 -3
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +1 -8
- package/dest/factory.d.ts +1 -1
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +1 -7
- 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 +124 -0
- package/dest/job/checkpoint-prover.d.ts.map +1 -0
- package/dest/job/checkpoint-prover.js +330 -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 +7 -22
- package/dest/prover-node-publisher.d.ts.map +1 -1
- package/dest/prover-node-publisher.js +41 -101
- package/dest/prover-node.d.ts +105 -67
- package/dest/prover-node.d.ts.map +1 -1
- package/dest/prover-node.js +472 -261
- package/dest/prover-publisher-factory.d.ts +1 -3
- package/dest/prover-publisher-factory.d.ts.map +1 -1
- package/dest/prover-publisher-factory.js +0 -1
- package/dest/session-manager.d.ts +158 -0
- package/dest/session-manager.d.ts.map +1 -0
- package/dest/session-manager.js +482 -0
- package/dest/test/index.d.ts +7 -6
- package/dest/test/index.d.ts.map +1 -1
- package/package.json +23 -23
- package/src/actions/rerun-epoch-proving-job.ts +102 -27
- package/src/checkpoint-store.ts +194 -0
- package/src/config.ts +2 -11
- package/src/factory.ts +0 -9
- package/src/index.ts +1 -0
- package/src/job/checkpoint-prover.ts +442 -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 +54 -127
- package/src/prover-node.ts +545 -282
- package/src/prover-publisher-factory.ts +0 -3
- package/src/session-manager.ts +583 -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,20 +29,17 @@ 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
|
|
|
48
|
-
protected proofSubmissionTarget: Hex;
|
|
49
|
-
|
|
50
43
|
public readonly l1TxUtils: L1TxUtils;
|
|
51
44
|
|
|
52
45
|
constructor(
|
|
@@ -54,7 +47,6 @@ export class ProverNodePublisher {
|
|
|
54
47
|
deps: {
|
|
55
48
|
rollupContract: RollupContract;
|
|
56
49
|
l1TxUtils: L1TxUtils;
|
|
57
|
-
proofSubmissionTarget?: EthAddress;
|
|
58
50
|
telemetry?: TelemetryClient;
|
|
59
51
|
},
|
|
60
52
|
bindings?: LoggerBindings,
|
|
@@ -65,7 +57,6 @@ export class ProverNodePublisher {
|
|
|
65
57
|
this.log = createLogger('prover-node:l1-tx-publisher', bindings);
|
|
66
58
|
|
|
67
59
|
this.rollupContract = deps.rollupContract;
|
|
68
|
-
this.proofSubmissionTarget = deps.proofSubmissionTarget?.toString() ?? deps.rollupContract.address;
|
|
69
60
|
this.l1TxUtils = deps.l1TxUtils;
|
|
70
61
|
}
|
|
71
62
|
|
|
@@ -73,23 +64,6 @@ export class ProverNodePublisher {
|
|
|
73
64
|
return this.rollupContract;
|
|
74
65
|
}
|
|
75
66
|
|
|
76
|
-
/**
|
|
77
|
-
* Calling `interrupt` will cause any in progress call to `publishRollup` to return `false` asap.
|
|
78
|
-
* Be warned, the call may return false even if the tx subsequently gets successfully mined.
|
|
79
|
-
* In practice this shouldn't matter, as we'll only ever be calling `interrupt` when we know it's going to fail.
|
|
80
|
-
* A call to `restart` is required before you can continue publishing.
|
|
81
|
-
*/
|
|
82
|
-
public interrupt() {
|
|
83
|
-
this.interrupted = true;
|
|
84
|
-
this.l1TxUtils.interrupt();
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/** Restarts the publisher after calling `interrupt`. */
|
|
88
|
-
public restart() {
|
|
89
|
-
this.interrupted = false;
|
|
90
|
-
this.l1TxUtils.restart();
|
|
91
|
-
}
|
|
92
|
-
|
|
93
67
|
public getSenderAddress() {
|
|
94
68
|
return this.l1TxUtils.getSenderAddress();
|
|
95
69
|
}
|
|
@@ -102,107 +76,54 @@ export class ProverNodePublisher {
|
|
|
102
76
|
proof: Proof;
|
|
103
77
|
batchedBlobInputs: BatchedBlob;
|
|
104
78
|
attestations: ViemCommitteeAttestation[];
|
|
79
|
+
headers: CheckpointHeader[];
|
|
80
|
+
/** Wall-clock deadline (proof-submission window end) past which the L1 tx should stop retrying. */
|
|
81
|
+
deadline?: Date;
|
|
105
82
|
}): Promise<boolean> {
|
|
106
83
|
const { epochNumber, fromCheckpoint, toCheckpoint } = args;
|
|
107
84
|
const ctx = { epochNumber, fromCheckpoint, toCheckpoint };
|
|
108
85
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const timer = new Timer();
|
|
116
|
-
// Validate epoch proof range and hashes are correct before submitting
|
|
117
|
-
await this.validateEpochProofSubmission(args);
|
|
118
|
-
|
|
119
|
-
const txReceipt = await this.sendSubmitEpochProofTx(args);
|
|
120
|
-
if (!txReceipt) {
|
|
121
|
-
this.log.error(`Failed to mine submitEpochProof tx`, undefined, ctx);
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
try {
|
|
126
|
-
this.metrics.recordSenderBalance(
|
|
127
|
-
await this.l1TxUtils.getSenderBalance(),
|
|
128
|
-
this.l1TxUtils.getSenderAddress().toString(),
|
|
129
|
-
);
|
|
130
|
-
} catch (err) {
|
|
131
|
-
this.log.warn(`Failed to record the ETH balance of the prover node: ${err}`);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Tx was mined successfully
|
|
135
|
-
if (txReceipt.status === 'success') {
|
|
136
|
-
const tx = await this.l1TxUtils.getTransactionStats(txReceipt.transactionHash);
|
|
137
|
-
const stats: L1PublishProofStats = {
|
|
138
|
-
gasPrice: txReceipt.effectiveGasPrice,
|
|
139
|
-
gasUsed: txReceipt.gasUsed,
|
|
140
|
-
transactionHash: txReceipt.transactionHash,
|
|
141
|
-
calldataGas: tx!.calldataGas,
|
|
142
|
-
calldataSize: tx!.calldataSize,
|
|
143
|
-
sender: tx!.sender,
|
|
144
|
-
blobDataGas: 0n,
|
|
145
|
-
blobGasUsed: 0n,
|
|
146
|
-
eventName: 'proof-published-to-l1',
|
|
147
|
-
};
|
|
148
|
-
this.log.info(`Published epoch proof to L1 rollup contract`, { ...stats, ...ctx });
|
|
149
|
-
this.metrics.recordSubmitProof(timer.ms(), stats);
|
|
150
|
-
return true;
|
|
151
|
-
}
|
|
86
|
+
const timer = new Timer();
|
|
87
|
+
// Validate epoch proof range and hashes are correct before submitting
|
|
88
|
+
await this.validateEpochProofSubmission(args);
|
|
152
89
|
|
|
153
|
-
|
|
154
|
-
|
|
90
|
+
const txReceipt = await this.sendSubmitEpochProofTx(args);
|
|
91
|
+
if (!txReceipt) {
|
|
92
|
+
this.log.error(`Failed to mine submitEpochProof tx`, undefined, ctx);
|
|
93
|
+
return false;
|
|
155
94
|
}
|
|
156
95
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
96
|
+
try {
|
|
97
|
+
this.metrics.recordSenderBalance(
|
|
98
|
+
await this.l1TxUtils.getSenderBalance(),
|
|
99
|
+
this.l1TxUtils.getSenderAddress().toString(),
|
|
100
|
+
);
|
|
101
|
+
} catch (err) {
|
|
102
|
+
this.log.warn(`Failed to record the ETH balance of the prover node: ${err}`);
|
|
103
|
+
}
|
|
160
104
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
105
|
+
// Tx was mined successfully
|
|
106
|
+
if (txReceipt.status === 'success') {
|
|
107
|
+
const tx = await this.l1TxUtils.getTransactionStats(txReceipt.transactionHash);
|
|
108
|
+
const stats: L1PublishProofStats = {
|
|
109
|
+
gasPrice: txReceipt.effectiveGasPrice,
|
|
110
|
+
gasUsed: txReceipt.gasUsed,
|
|
111
|
+
transactionHash: txReceipt.transactionHash,
|
|
112
|
+
calldataGas: tx!.calldataGas,
|
|
113
|
+
calldataSize: tx!.calldataSize,
|
|
114
|
+
sender: tx!.sender,
|
|
115
|
+
blobDataGas: 0n,
|
|
116
|
+
blobGasUsed: 0n,
|
|
117
|
+
eventName: 'proof-published-to-l1',
|
|
118
|
+
};
|
|
119
|
+
this.log.info(`Published epoch proof to L1 rollup contract`, { ...stats, ...ctx });
|
|
120
|
+
this.metrics.recordSubmitProof(timer.ms(), stats);
|
|
165
121
|
return true;
|
|
166
122
|
}
|
|
167
123
|
|
|
168
|
-
|
|
169
|
-
this.log.
|
|
170
|
-
|
|
171
|
-
fromCheckpoint,
|
|
172
|
-
provenCheckpoint,
|
|
173
|
-
timeout,
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
await retryUntil(
|
|
177
|
-
async () => {
|
|
178
|
-
if (this.interrupted) {
|
|
179
|
-
return true;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const proven = await this.getProvenCheckpoint();
|
|
183
|
-
this.log.verbose(`Proven checkpoint is at ${proven} (waiting for ${fromCheckpoint - 1})`, { epochNumber });
|
|
184
|
-
return this.isStartBuildingOnProven(fromCheckpoint, proven) ? true : undefined;
|
|
185
|
-
},
|
|
186
|
-
`proven checkpoint to reach ${fromCheckpoint - 1}`,
|
|
187
|
-
timeout,
|
|
188
|
-
4,
|
|
189
|
-
);
|
|
190
|
-
|
|
191
|
-
return !this.interrupted;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
private async getProvenCheckpoint() {
|
|
195
|
-
return (await this.rollupContract.getTips()).proven;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
private isStartBuildingOnProven(fromCheckpoint: CheckpointNumber, provenCheckpoint: CheckpointNumber) {
|
|
199
|
-
return fromCheckpoint - 1 <= provenCheckpoint;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
private async getSecondsUntilProofSubmissionWindowEnd(epochNumber: EpochNumber) {
|
|
203
|
-
const deadline = getProofSubmissionDeadlineTimestamp(epochNumber, await this.rollupContract.getRollupConstants());
|
|
204
|
-
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
205
|
-
return Math.max(Number(deadline - now), 0.001);
|
|
124
|
+
this.metrics.recordFailedTx();
|
|
125
|
+
this.log.error(`Rollup submitEpochProof tx reverted ${txReceipt.transactionHash}`, undefined, ctx);
|
|
126
|
+
return false;
|
|
206
127
|
}
|
|
207
128
|
|
|
208
129
|
private async validateEpochProofSubmission(args: {
|
|
@@ -212,6 +133,7 @@ export class ProverNodePublisher {
|
|
|
212
133
|
proof: Proof;
|
|
213
134
|
batchedBlobInputs: BatchedBlob;
|
|
214
135
|
attestations: ViemCommitteeAttestation[];
|
|
136
|
+
headers: CheckpointHeader[];
|
|
215
137
|
}) {
|
|
216
138
|
const { fromCheckpoint, toCheckpoint, publicInputs, batchedBlobInputs } = args;
|
|
217
139
|
|
|
@@ -285,6 +207,7 @@ export class ProverNodePublisher {
|
|
|
285
207
|
proof: Proof;
|
|
286
208
|
batchedBlobInputs: BatchedBlob;
|
|
287
209
|
attestations: ViemCommitteeAttestation[];
|
|
210
|
+
headers: CheckpointHeader[];
|
|
288
211
|
}): Promise<void> {
|
|
289
212
|
const { epochNumber, fromCheckpoint, toCheckpoint } = args;
|
|
290
213
|
|
|
@@ -294,7 +217,7 @@ export class ProverNodePublisher {
|
|
|
294
217
|
const senderAddress = this.l1TxUtils.getSenderAddress();
|
|
295
218
|
|
|
296
219
|
const [gasLimit, gasPrice, latestBlock] = await Promise.all([
|
|
297
|
-
this.l1TxUtils.estimateGas(senderAddress.toString() as `0x${string}`, { to: this.
|
|
220
|
+
this.l1TxUtils.estimateGas(senderAddress.toString() as `0x${string}`, { to: this.rollupContract.address, data }),
|
|
298
221
|
this.l1TxUtils.getGasPrice(),
|
|
299
222
|
this.l1TxUtils.client.getBlock({ blockTag: 'latest' }),
|
|
300
223
|
]);
|
|
@@ -332,6 +255,7 @@ export class ProverNodePublisher {
|
|
|
332
255
|
proof: Proof;
|
|
333
256
|
batchedBlobInputs: BatchedBlob;
|
|
334
257
|
attestations: ViemCommitteeAttestation[];
|
|
258
|
+
headers: CheckpointHeader[];
|
|
335
259
|
}): Hex {
|
|
336
260
|
return encodeFunctionData({
|
|
337
261
|
abi: RollupAbi,
|
|
@@ -343,10 +267,12 @@ export class ProverNodePublisher {
|
|
|
343
267
|
private async sendSubmitEpochProofTx(args: {
|
|
344
268
|
fromCheckpoint: CheckpointNumber;
|
|
345
269
|
toCheckpoint: CheckpointNumber;
|
|
270
|
+
deadline?: Date;
|
|
346
271
|
publicInputs: RootRollupPublicInputs;
|
|
347
272
|
proof: Proof;
|
|
348
273
|
batchedBlobInputs: BatchedBlob;
|
|
349
274
|
attestations: ViemCommitteeAttestation[];
|
|
275
|
+
headers: CheckpointHeader[];
|
|
350
276
|
}): Promise<TransactionReceipt | undefined> {
|
|
351
277
|
const txArgs = [this.getSubmitEpochProofArgs(args)] as const;
|
|
352
278
|
|
|
@@ -361,7 +287,10 @@ export class ProverNodePublisher {
|
|
|
361
287
|
args: txArgs,
|
|
362
288
|
});
|
|
363
289
|
try {
|
|
364
|
-
const { receipt } = await this.l1TxUtils.sendAndMonitorTransaction(
|
|
290
|
+
const { receipt } = await this.l1TxUtils.sendAndMonitorTransaction(
|
|
291
|
+
{ to: this.rollupContract.address, data },
|
|
292
|
+
{ txTimeoutAt: args.deadline },
|
|
293
|
+
);
|
|
365
294
|
if (receipt.status !== 'success') {
|
|
366
295
|
const errorMsg = await this.l1TxUtils.tryGetErrorFromRevertedTx(
|
|
367
296
|
data,
|
|
@@ -369,7 +298,7 @@ export class ProverNodePublisher {
|
|
|
369
298
|
args: [...txArgs],
|
|
370
299
|
functionName: 'submitEpochRootProof',
|
|
371
300
|
abi: RollupAbi,
|
|
372
|
-
address: this.
|
|
301
|
+
address: this.rollupContract.address,
|
|
373
302
|
},
|
|
374
303
|
/*blobInputs*/ undefined,
|
|
375
304
|
/*stateOverride*/ [],
|
|
@@ -390,6 +319,7 @@ export class ProverNodePublisher {
|
|
|
390
319
|
publicInputs: RootRollupPublicInputs;
|
|
391
320
|
batchedBlobInputs: BatchedBlob;
|
|
392
321
|
attestations: ViemCommitteeAttestation[];
|
|
322
|
+
headers: CheckpointHeader[];
|
|
393
323
|
}) {
|
|
394
324
|
// Returns arguments for EpochProofLib.sol -> getEpochProofPublicInputs()
|
|
395
325
|
return [
|
|
@@ -401,11 +331,7 @@ export class ProverNodePublisher {
|
|
|
401
331
|
outHash: args.publicInputs.outHash.toString(),
|
|
402
332
|
proverId: EthAddress.fromField(args.publicInputs.constants.proverId).toString(),
|
|
403
333
|
} /*_args*/,
|
|
404
|
-
|
|
405
|
-
i % 2 === 0
|
|
406
|
-
? args.publicInputs.fees[i / 2].recipient.toField().toString()
|
|
407
|
-
: args.publicInputs.fees[(i - 1) / 2].value.toString(),
|
|
408
|
-
) /*_fees*/,
|
|
334
|
+
args.headers.map(header => header.toViem()) /*_headers*/,
|
|
409
335
|
getEthBlobEvaluationInputs(args.batchedBlobInputs) /*_blobPublicInputs*/,
|
|
410
336
|
] as const;
|
|
411
337
|
}
|
|
@@ -417,6 +343,7 @@ export class ProverNodePublisher {
|
|
|
417
343
|
proof: Proof;
|
|
418
344
|
batchedBlobInputs: BatchedBlob;
|
|
419
345
|
attestations: ViemCommitteeAttestation[];
|
|
346
|
+
headers: CheckpointHeader[];
|
|
420
347
|
}) {
|
|
421
348
|
// Returns arguments for EpochProofLib.sol -> submitEpochRootProof()
|
|
422
349
|
const proofHex: Hex = `0x${args.proof.withoutPublicInputs().toString('hex')}`;
|
|
@@ -425,7 +352,7 @@ export class ProverNodePublisher {
|
|
|
425
352
|
start: argsArray[0],
|
|
426
353
|
end: argsArray[1],
|
|
427
354
|
args: argsArray[2],
|
|
428
|
-
|
|
355
|
+
headers: argsArray[3],
|
|
429
356
|
attestations: CommitteeAttestationsAndSigners.packAttestations(
|
|
430
357
|
args.attestations.map(a => CommitteeAttestation.fromViem(a)),
|
|
431
358
|
),
|