@aztec/prover-node 0.0.1-commit.fce3e4f → 0.0.1-commit.fffb133c
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/actions/download-epoch-proving-job.d.ts +1 -1
- package/dest/actions/rerun-epoch-proving-job.d.ts +3 -2
- package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -1
- package/dest/actions/rerun-epoch-proving-job.js +3 -1
- package/dest/config.d.ts +5 -4
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +4 -3
- package/dest/factory.d.ts +2 -4
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +20 -15
- package/dest/index.d.ts +2 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/job/epoch-proving-job-data.d.ts +7 -6
- package/dest/job/epoch-proving-job-data.d.ts.map +1 -1
- package/dest/job/epoch-proving-job-data.js +24 -18
- package/dest/job/epoch-proving-job.d.ts +3 -3
- package/dest/job/epoch-proving-job.d.ts.map +1 -1
- package/dest/job/epoch-proving-job.js +478 -99
- package/dest/metrics.d.ts +4 -3
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +21 -97
- package/dest/monitors/epoch-monitor.d.ts +1 -1
- package/dest/monitors/epoch-monitor.d.ts.map +1 -1
- package/dest/monitors/epoch-monitor.js +3 -11
- package/dest/prover-node-publisher.d.ts +7 -6
- package/dest/prover-node-publisher.d.ts.map +1 -1
- package/dest/prover-node-publisher.js +41 -36
- package/dest/prover-node.d.ts +4 -4
- package/dest/prover-node.d.ts.map +1 -1
- package/dest/prover-node.js +427 -45
- package/dest/prover-publisher-factory.d.ts +4 -2
- package/dest/prover-publisher-factory.d.ts.map +1 -1
- package/package.json +25 -25
- package/src/actions/rerun-epoch-proving-job.ts +3 -2
- package/src/bin/run-failed-epoch.ts +1 -1
- package/src/config.ts +6 -4
- package/src/factory.ts +28 -17
- package/src/index.ts +1 -0
- package/src/job/epoch-proving-job-data.ts +28 -23
- package/src/job/epoch-proving-job.ts +102 -97
- package/src/metrics.ts +27 -82
- package/src/monitors/epoch-monitor.ts +3 -10
- package/src/prover-node-publisher.ts +60 -50
- package/src/prover-node.ts +36 -32
- package/src/prover-publisher-factory.ts +3 -1
package/src/metrics.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RollupContract } from '@aztec/ethereum';
|
|
1
|
+
import type { RollupContract } from '@aztec/ethereum/contracts';
|
|
2
2
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import type { L1PublishProofStats, L1PublishStats } from '@aztec/stdlib/stats';
|
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
type TelemetryClient,
|
|
14
14
|
type Tracer,
|
|
15
15
|
type UpDownCounter,
|
|
16
|
-
ValueType,
|
|
17
16
|
} from '@aztec/telemetry-client';
|
|
18
17
|
|
|
19
18
|
import { formatEther, formatUnits } from 'viem';
|
|
@@ -21,6 +20,7 @@ import { formatEther, formatUnits } from 'viem';
|
|
|
21
20
|
export class ProverNodeJobMetrics {
|
|
22
21
|
proverEpochExecutionDuration: Histogram;
|
|
23
22
|
provingJobDuration: Histogram;
|
|
23
|
+
provingJobCheckpoints: Gauge;
|
|
24
24
|
provingJobBlocks: Gauge;
|
|
25
25
|
provingJobTransactions: Gauge;
|
|
26
26
|
|
|
@@ -29,29 +29,23 @@ export class ProverNodeJobMetrics {
|
|
|
29
29
|
public readonly tracer: Tracer,
|
|
30
30
|
private logger = createLogger('prover-node:publisher:metrics'),
|
|
31
31
|
) {
|
|
32
|
-
this.proverEpochExecutionDuration = this.meter.createHistogram(Metrics.PROVER_NODE_EXECUTION_DURATION
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
this.provingJobDuration = this.meter.createHistogram(Metrics.PROVER_NODE_JOB_DURATION, {
|
|
38
|
-
description: 'Duration of proving job',
|
|
39
|
-
unit: 's',
|
|
40
|
-
valueType: ValueType.DOUBLE,
|
|
41
|
-
});
|
|
42
|
-
this.provingJobBlocks = this.meter.createGauge(Metrics.PROVER_NODE_JOB_BLOCKS, {
|
|
43
|
-
description: 'Number of blocks in a proven epoch',
|
|
44
|
-
valueType: ValueType.INT,
|
|
45
|
-
});
|
|
46
|
-
this.provingJobTransactions = this.meter.createGauge(Metrics.PROVER_NODE_JOB_TRANSACTIONS, {
|
|
47
|
-
description: 'Number of transactions in a proven epoch',
|
|
48
|
-
valueType: ValueType.INT,
|
|
49
|
-
});
|
|
32
|
+
this.proverEpochExecutionDuration = this.meter.createHistogram(Metrics.PROVER_NODE_EXECUTION_DURATION);
|
|
33
|
+
this.provingJobDuration = this.meter.createHistogram(Metrics.PROVER_NODE_JOB_DURATION);
|
|
34
|
+
this.provingJobCheckpoints = this.meter.createGauge(Metrics.PROVER_NODE_JOB_CHECKPOINTS);
|
|
35
|
+
this.provingJobBlocks = this.meter.createGauge(Metrics.PROVER_NODE_JOB_BLOCKS);
|
|
36
|
+
this.provingJobTransactions = this.meter.createGauge(Metrics.PROVER_NODE_JOB_TRANSACTIONS);
|
|
50
37
|
}
|
|
51
38
|
|
|
52
|
-
public recordProvingJob(
|
|
39
|
+
public recordProvingJob(
|
|
40
|
+
executionTimeMs: number,
|
|
41
|
+
totalTimeMs: number,
|
|
42
|
+
numCheckpoints: number,
|
|
43
|
+
numBlocks: number,
|
|
44
|
+
numTxs: number,
|
|
45
|
+
) {
|
|
53
46
|
this.proverEpochExecutionDuration.record(Math.ceil(executionTimeMs));
|
|
54
47
|
this.provingJobDuration.record(totalTimeMs / 1000);
|
|
48
|
+
this.provingJobCheckpoints.record(Math.floor(numCheckpoints));
|
|
55
49
|
this.provingJobBlocks.record(Math.floor(numBlocks));
|
|
56
50
|
this.provingJobTransactions.record(Math.floor(numTxs));
|
|
57
51
|
}
|
|
@@ -69,15 +63,9 @@ export class ProverNodeRewardsMetrics {
|
|
|
69
63
|
private rollup: RollupContract,
|
|
70
64
|
private logger = createLogger('prover-node:publisher:metrics'),
|
|
71
65
|
) {
|
|
72
|
-
this.rewards = this.meter.createObservableGauge(Metrics.PROVER_NODE_REWARDS_PER_EPOCH
|
|
73
|
-
valueType: ValueType.DOUBLE,
|
|
74
|
-
description: 'The rewards earned',
|
|
75
|
-
});
|
|
66
|
+
this.rewards = this.meter.createObservableGauge(Metrics.PROVER_NODE_REWARDS_PER_EPOCH);
|
|
76
67
|
|
|
77
|
-
this.accumulatedRewards = this.meter.createUpDownCounter(Metrics.PROVER_NODE_REWARDS_TOTAL
|
|
78
|
-
valueType: ValueType.DOUBLE,
|
|
79
|
-
description: 'The rewards earned (total)',
|
|
80
|
-
});
|
|
68
|
+
this.accumulatedRewards = this.meter.createUpDownCounter(Metrics.PROVER_NODE_REWARDS_TOTAL);
|
|
81
69
|
}
|
|
82
70
|
|
|
83
71
|
public async start() {
|
|
@@ -138,68 +126,25 @@ export class ProverNodePublisherMetrics {
|
|
|
138
126
|
) {
|
|
139
127
|
this.meter = client.getMeter(name);
|
|
140
128
|
|
|
141
|
-
this.gasPrice = this.meter.createHistogram(Metrics.L1_PUBLISHER_GAS_PRICE
|
|
142
|
-
description: 'The gas price used for transactions',
|
|
143
|
-
unit: 'gwei',
|
|
144
|
-
valueType: ValueType.DOUBLE,
|
|
145
|
-
});
|
|
129
|
+
this.gasPrice = this.meter.createHistogram(Metrics.L1_PUBLISHER_GAS_PRICE);
|
|
146
130
|
|
|
147
|
-
this.txCount = this.meter.createUpDownCounter(Metrics.L1_PUBLISHER_TX_COUNT
|
|
148
|
-
description: 'The number of transactions processed',
|
|
149
|
-
});
|
|
131
|
+
this.txCount = this.meter.createUpDownCounter(Metrics.L1_PUBLISHER_TX_COUNT);
|
|
150
132
|
|
|
151
|
-
this.txDuration = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_DURATION
|
|
152
|
-
description: 'The duration of transaction processing',
|
|
153
|
-
unit: 'ms',
|
|
154
|
-
valueType: ValueType.INT,
|
|
155
|
-
});
|
|
133
|
+
this.txDuration = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_DURATION);
|
|
156
134
|
|
|
157
|
-
this.txGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_GAS
|
|
158
|
-
description: 'The gas consumed by transactions',
|
|
159
|
-
unit: 'gas',
|
|
160
|
-
valueType: ValueType.INT,
|
|
161
|
-
});
|
|
135
|
+
this.txGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_GAS);
|
|
162
136
|
|
|
163
|
-
this.txCalldataSize = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_SIZE
|
|
164
|
-
description: 'The size of the calldata in transactions',
|
|
165
|
-
unit: 'By',
|
|
166
|
-
valueType: ValueType.INT,
|
|
167
|
-
});
|
|
137
|
+
this.txCalldataSize = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_SIZE);
|
|
168
138
|
|
|
169
|
-
this.txCalldataGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_GAS
|
|
170
|
-
description: 'The gas consumed by the calldata in transactions',
|
|
171
|
-
unit: 'gas',
|
|
172
|
-
valueType: ValueType.INT,
|
|
173
|
-
});
|
|
139
|
+
this.txCalldataGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_GAS);
|
|
174
140
|
|
|
175
|
-
this.txBlobDataGasUsed = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_USED
|
|
176
|
-
description: 'The amount of blob gas used in transactions',
|
|
177
|
-
unit: 'gas',
|
|
178
|
-
valueType: ValueType.INT,
|
|
179
|
-
});
|
|
141
|
+
this.txBlobDataGasUsed = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_USED);
|
|
180
142
|
|
|
181
|
-
this.txBlobDataGasCost = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_COST
|
|
182
|
-
description: 'The gas cost of blobs in transactions',
|
|
183
|
-
unit: 'gwei',
|
|
184
|
-
valueType: ValueType.INT,
|
|
185
|
-
});
|
|
143
|
+
this.txBlobDataGasCost = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_COST);
|
|
186
144
|
|
|
187
|
-
this.txTotalFee = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_TOTAL_FEE
|
|
188
|
-
description: 'How much L1 tx costs',
|
|
189
|
-
unit: 'gwei',
|
|
190
|
-
valueType: ValueType.DOUBLE,
|
|
191
|
-
advice: {
|
|
192
|
-
explicitBucketBoundaries: [
|
|
193
|
-
0.001, 0.002, 0.004, 0.008, 0.01, 0.02, 0.04, 0.08, 0.1, 0.2, 0.4, 0.8, 1, 1.2, 1.4, 1.8, 2,
|
|
194
|
-
],
|
|
195
|
-
},
|
|
196
|
-
});
|
|
145
|
+
this.txTotalFee = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_TOTAL_FEE);
|
|
197
146
|
|
|
198
|
-
this.senderBalance = this.meter.createGauge(Metrics.L1_PUBLISHER_BALANCE
|
|
199
|
-
unit: 'eth',
|
|
200
|
-
description: 'The balance of the sender address',
|
|
201
|
-
valueType: ValueType.DOUBLE,
|
|
202
|
-
});
|
|
147
|
+
this.senderBalance = this.meter.createGauge(Metrics.L1_PUBLISHER_BALANCE);
|
|
203
148
|
}
|
|
204
149
|
|
|
205
150
|
recordFailedTx() {
|
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
import { EpochNumber } from '@aztec/foundation/branded-types';
|
|
1
|
+
import { BlockNumber, EpochNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
3
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
4
4
|
import { sleep } from '@aztec/foundation/sleep';
|
|
5
5
|
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
6
6
|
import { type L1RollupConstants, getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
|
|
7
|
-
import {
|
|
8
|
-
type TelemetryClient,
|
|
9
|
-
type Traceable,
|
|
10
|
-
type Tracer,
|
|
11
|
-
getTelemetryClient,
|
|
12
|
-
trackSpan,
|
|
13
|
-
} from '@aztec/telemetry-client';
|
|
7
|
+
import { type TelemetryClient, type Traceable, type Tracer, getTelemetryClient } from '@aztec/telemetry-client';
|
|
14
8
|
|
|
15
9
|
export interface EpochMonitorHandler {
|
|
16
10
|
handleEpochReadyToProve(epochNumber: EpochNumber): Promise<boolean>;
|
|
@@ -73,7 +67,6 @@ export class EpochMonitor implements Traceable {
|
|
|
73
67
|
this.log.info('Stopped EpochMonitor');
|
|
74
68
|
}
|
|
75
69
|
|
|
76
|
-
@trackSpan('EpochMonitor.work')
|
|
77
70
|
public async work() {
|
|
78
71
|
const { epochToProve, blockNumber, slotNumber } = await this.getEpochNumberToProve();
|
|
79
72
|
this.log.debug(`Epoch to prove: ${epochToProve}`, { blockNumber, slotNumber });
|
|
@@ -105,7 +98,7 @@ export class EpochMonitor implements Traceable {
|
|
|
105
98
|
|
|
106
99
|
private async getEpochNumberToProve() {
|
|
107
100
|
const lastBlockProven = await this.l2BlockSource.getProvenBlockNumber();
|
|
108
|
-
const firstBlockToProve = lastBlockProven + 1;
|
|
101
|
+
const firstBlockToProve = BlockNumber(lastBlockProven + 1);
|
|
109
102
|
const firstBlockHeaderToProve = await this.l2BlockSource.getBlockHeader(firstBlockToProve);
|
|
110
103
|
if (!firstBlockHeaderToProve) {
|
|
111
104
|
return { epochToProve: undefined, blockNumber: firstBlockToProve };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { BatchedBlob, getEthBlobEvaluationInputs } from '@aztec/blob-lib';
|
|
2
2
|
import { AZTEC_MAX_EPOCH_DURATION } from '@aztec/constants';
|
|
3
|
-
import type {
|
|
3
|
+
import type { RollupContract, ViemCommitteeAttestation } from '@aztec/ethereum/contracts';
|
|
4
|
+
import type { L1TxUtils } from '@aztec/ethereum/l1-tx-utils';
|
|
4
5
|
import { makeTuple } from '@aztec/foundation/array';
|
|
5
|
-
import { EpochNumber } from '@aztec/foundation/branded-types';
|
|
6
|
+
import { CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
|
|
6
7
|
import { areArraysEqual } from '@aztec/foundation/collection';
|
|
8
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
7
9
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
8
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
9
10
|
import { createLogger } from '@aztec/foundation/log';
|
|
10
11
|
import type { Tuple } from '@aztec/foundation/serialize';
|
|
11
12
|
import { Timer } from '@aztec/foundation/timer';
|
|
@@ -87,15 +88,15 @@ export class ProverNodePublisher {
|
|
|
87
88
|
|
|
88
89
|
public async submitEpochProof(args: {
|
|
89
90
|
epochNumber: EpochNumber;
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
fromCheckpoint: CheckpointNumber;
|
|
92
|
+
toCheckpoint: CheckpointNumber;
|
|
92
93
|
publicInputs: RootRollupPublicInputs;
|
|
93
94
|
proof: Proof;
|
|
94
95
|
batchedBlobInputs: BatchedBlob;
|
|
95
96
|
attestations: ViemCommitteeAttestation[];
|
|
96
97
|
}): Promise<boolean> {
|
|
97
|
-
const { epochNumber,
|
|
98
|
-
const ctx = { epochNumber,
|
|
98
|
+
const { epochNumber, fromCheckpoint, toCheckpoint } = args;
|
|
99
|
+
const ctx = { epochNumber, fromCheckpoint, toCheckpoint };
|
|
99
100
|
|
|
100
101
|
if (!this.interrupted) {
|
|
101
102
|
const timer = new Timer();
|
|
@@ -104,6 +105,7 @@ export class ProverNodePublisher {
|
|
|
104
105
|
|
|
105
106
|
const txReceipt = await this.sendSubmitEpochProofTx(args);
|
|
106
107
|
if (!txReceipt) {
|
|
108
|
+
this.log.error(`Failed to mine submitEpochProof tx`, undefined, ctx);
|
|
107
109
|
return false;
|
|
108
110
|
}
|
|
109
111
|
|
|
@@ -136,47 +138,51 @@ export class ProverNodePublisher {
|
|
|
136
138
|
}
|
|
137
139
|
|
|
138
140
|
this.metrics.recordFailedTx();
|
|
139
|
-
this.log.error(`Rollup
|
|
141
|
+
this.log.error(`Rollup submitEpochProof tx reverted ${txReceipt.transactionHash}`, undefined, ctx);
|
|
140
142
|
}
|
|
141
143
|
|
|
142
|
-
this.log.verbose('
|
|
144
|
+
this.log.verbose('Checkpoint data syncing interrupted', ctx);
|
|
143
145
|
return false;
|
|
144
146
|
}
|
|
145
147
|
|
|
146
148
|
private async validateEpochProofSubmission(args: {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
+
fromCheckpoint: CheckpointNumber;
|
|
150
|
+
toCheckpoint: CheckpointNumber;
|
|
149
151
|
publicInputs: RootRollupPublicInputs;
|
|
150
152
|
proof: Proof;
|
|
151
153
|
batchedBlobInputs: BatchedBlob;
|
|
152
154
|
attestations: ViemCommitteeAttestation[];
|
|
153
155
|
}) {
|
|
154
|
-
const {
|
|
156
|
+
const { fromCheckpoint, toCheckpoint, publicInputs, batchedBlobInputs } = args;
|
|
155
157
|
|
|
156
|
-
// Check that the
|
|
158
|
+
// Check that the checkpoint numbers match the expected epoch to be proven
|
|
157
159
|
const { pending, proven } = await this.rollupContract.getTips();
|
|
158
|
-
// Don't publish if proven is beyond our
|
|
159
|
-
if (proven >
|
|
160
|
-
throw new Error(
|
|
160
|
+
// Don't publish if proven is beyond our toCheckpoint, pointless to do so
|
|
161
|
+
if (proven > toCheckpoint) {
|
|
162
|
+
throw new Error(
|
|
163
|
+
`Cannot submit epoch proof for ${fromCheckpoint}-${toCheckpoint} as proven checkpoint is ${proven}`,
|
|
164
|
+
);
|
|
161
165
|
}
|
|
162
|
-
//
|
|
163
|
-
if (
|
|
164
|
-
throw new Error(
|
|
166
|
+
// toCheckpoint can't be greater than pending
|
|
167
|
+
if (toCheckpoint > pending) {
|
|
168
|
+
throw new Error(
|
|
169
|
+
`Cannot submit epoch proof for ${fromCheckpoint}-${toCheckpoint} as pending checkpoint is ${pending}`,
|
|
170
|
+
);
|
|
165
171
|
}
|
|
166
172
|
|
|
167
|
-
// Check the archive for the immediate
|
|
168
|
-
const
|
|
169
|
-
if (publicInputs.previousArchiveRoot.
|
|
173
|
+
// Check the archive for the immediate checkpoint before the epoch
|
|
174
|
+
const checkpointLog = await this.rollupContract.getCheckpoint(CheckpointNumber(fromCheckpoint - 1));
|
|
175
|
+
if (!publicInputs.previousArchiveRoot.equals(checkpointLog.archive)) {
|
|
170
176
|
throw new Error(
|
|
171
|
-
`Previous archive root mismatch: ${publicInputs.previousArchiveRoot.toString()} !== ${
|
|
177
|
+
`Previous archive root mismatch: ${publicInputs.previousArchiveRoot.toString()} !== ${checkpointLog.archive.toString()}`,
|
|
172
178
|
);
|
|
173
179
|
}
|
|
174
180
|
|
|
175
|
-
// Check the archive for the last
|
|
176
|
-
const
|
|
177
|
-
if (publicInputs.endArchiveRoot.
|
|
181
|
+
// Check the archive for the last checkpoint in the epoch
|
|
182
|
+
const endCheckpointLog = await this.rollupContract.getCheckpoint(toCheckpoint);
|
|
183
|
+
if (!publicInputs.endArchiveRoot.equals(endCheckpointLog.archive)) {
|
|
178
184
|
throw new Error(
|
|
179
|
-
`End archive root mismatch: ${publicInputs.endArchiveRoot.toString()} !== ${
|
|
185
|
+
`End archive root mismatch: ${publicInputs.endArchiveRoot.toString()} !== ${endCheckpointLog.archive.toString()}`,
|
|
180
186
|
);
|
|
181
187
|
}
|
|
182
188
|
|
|
@@ -194,7 +200,7 @@ export class ProverNodePublisher {
|
|
|
194
200
|
);
|
|
195
201
|
const argsPublicInputs = [...publicInputs.toFields()];
|
|
196
202
|
|
|
197
|
-
if (!areArraysEqual(rollupPublicInputs
|
|
203
|
+
if (!areArraysEqual(rollupPublicInputs, argsPublicInputs, (a, b) => a.equals(b))) {
|
|
198
204
|
const fmt = (inputs: Fr[] | readonly string[]) => inputs.map(x => x.toString()).join(', ');
|
|
199
205
|
throw new Error(
|
|
200
206
|
`Root rollup public inputs mismatch:\nRollup: ${fmt(rollupPublicInputs)}\nComputed:${fmt(argsPublicInputs)}`,
|
|
@@ -203,8 +209,8 @@ export class ProverNodePublisher {
|
|
|
203
209
|
}
|
|
204
210
|
|
|
205
211
|
private async sendSubmitEpochProofTx(args: {
|
|
206
|
-
|
|
207
|
-
|
|
212
|
+
fromCheckpoint: CheckpointNumber;
|
|
213
|
+
toCheckpoint: CheckpointNumber;
|
|
208
214
|
publicInputs: RootRollupPublicInputs;
|
|
209
215
|
proof: Proof;
|
|
210
216
|
batchedBlobInputs: BatchedBlob;
|
|
@@ -214,8 +220,8 @@ export class ProverNodePublisher {
|
|
|
214
220
|
|
|
215
221
|
this.log.info(`Submitting epoch proof to L1 rollup contract`, {
|
|
216
222
|
proofSize: args.proof.withoutPublicInputs().length,
|
|
217
|
-
|
|
218
|
-
|
|
223
|
+
fromCheckpoint: args.fromCheckpoint,
|
|
224
|
+
toCheckpoint: args.toCheckpoint,
|
|
219
225
|
});
|
|
220
226
|
const data = encodeFunctionData({
|
|
221
227
|
abi: RollupAbi,
|
|
@@ -224,39 +230,43 @@ export class ProverNodePublisher {
|
|
|
224
230
|
});
|
|
225
231
|
try {
|
|
226
232
|
const { receipt } = await this.l1TxUtils.sendAndMonitorTransaction({ to: this.rollupContract.address, data });
|
|
233
|
+
if (receipt.status !== 'success') {
|
|
234
|
+
const errorMsg = await this.l1TxUtils.tryGetErrorFromRevertedTx(
|
|
235
|
+
data,
|
|
236
|
+
{
|
|
237
|
+
args: [...txArgs],
|
|
238
|
+
functionName: 'submitEpochRootProof',
|
|
239
|
+
abi: RollupAbi,
|
|
240
|
+
address: this.rollupContract.address,
|
|
241
|
+
},
|
|
242
|
+
/*blobInputs*/ undefined,
|
|
243
|
+
/*stateOverride*/ [],
|
|
244
|
+
);
|
|
245
|
+
this.log.error(`Rollup submit epoch proof tx reverted with ${errorMsg ?? 'unknown error'}`);
|
|
246
|
+
return undefined;
|
|
247
|
+
}
|
|
227
248
|
return receipt;
|
|
228
249
|
} catch (err) {
|
|
229
250
|
this.log.error(`Rollup submit epoch proof failed`, err);
|
|
230
|
-
const errorMsg = await this.l1TxUtils.tryGetErrorFromRevertedTx(
|
|
231
|
-
data,
|
|
232
|
-
{
|
|
233
|
-
args: [...txArgs],
|
|
234
|
-
functionName: 'submitEpochRootProof',
|
|
235
|
-
abi: RollupAbi,
|
|
236
|
-
address: this.rollupContract.address,
|
|
237
|
-
},
|
|
238
|
-
/*blobInputs*/ undefined,
|
|
239
|
-
/*stateOverride*/ [],
|
|
240
|
-
);
|
|
241
|
-
this.log.error(`Rollup submit epoch proof tx reverted. ${errorMsg}`);
|
|
242
251
|
return undefined;
|
|
243
252
|
}
|
|
244
253
|
}
|
|
245
254
|
|
|
246
255
|
private getEpochProofPublicInputsArgs(args: {
|
|
247
|
-
|
|
248
|
-
|
|
256
|
+
fromCheckpoint: CheckpointNumber;
|
|
257
|
+
toCheckpoint: CheckpointNumber;
|
|
249
258
|
publicInputs: RootRollupPublicInputs;
|
|
250
259
|
batchedBlobInputs: BatchedBlob;
|
|
251
260
|
attestations: ViemCommitteeAttestation[];
|
|
252
261
|
}) {
|
|
253
262
|
// Returns arguments for EpochProofLib.sol -> getEpochProofPublicInputs()
|
|
254
263
|
return [
|
|
255
|
-
BigInt(args.
|
|
256
|
-
BigInt(args.
|
|
264
|
+
BigInt(args.fromCheckpoint) /*_start*/,
|
|
265
|
+
BigInt(args.toCheckpoint) /*_end*/,
|
|
257
266
|
{
|
|
258
267
|
previousArchive: args.publicInputs.previousArchiveRoot.toString(),
|
|
259
268
|
endArchive: args.publicInputs.endArchiveRoot.toString(),
|
|
269
|
+
outHash: args.publicInputs.outHash.toString(),
|
|
260
270
|
proverId: EthAddress.fromField(args.publicInputs.constants.proverId).toString(),
|
|
261
271
|
} /*_args*/,
|
|
262
272
|
makeTuple(AZTEC_MAX_EPOCH_DURATION * 2, i =>
|
|
@@ -269,8 +279,8 @@ export class ProverNodePublisher {
|
|
|
269
279
|
}
|
|
270
280
|
|
|
271
281
|
private getSubmitEpochProofArgs(args: {
|
|
272
|
-
|
|
273
|
-
|
|
282
|
+
fromCheckpoint: CheckpointNumber;
|
|
283
|
+
toCheckpoint: CheckpointNumber;
|
|
274
284
|
publicInputs: RootRollupPublicInputs;
|
|
275
285
|
proof: Proof;
|
|
276
286
|
batchedBlobInputs: BatchedBlob;
|
package/src/prover-node.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import type { Archiver } from '@aztec/archiver';
|
|
2
|
-
import type { RollupContract } from '@aztec/ethereum';
|
|
3
|
-
import { EpochNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import type { RollupContract } from '@aztec/ethereum/contracts';
|
|
3
|
+
import { BlockNumber, CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
|
|
4
4
|
import { assertRequired, compact, pick, sum } from '@aztec/foundation/collection';
|
|
5
|
+
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
6
|
import { memoize } from '@aztec/foundation/decorators';
|
|
6
|
-
import type { Fr } from '@aztec/foundation/fields';
|
|
7
7
|
import { createLogger } from '@aztec/foundation/log';
|
|
8
8
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
9
9
|
import type { DataStoreConfig } from '@aztec/kv-store/config';
|
|
10
10
|
import type { P2PClient } from '@aztec/p2p';
|
|
11
11
|
import { PublicProcessorFactory } from '@aztec/simulator/server';
|
|
12
|
-
import type {
|
|
12
|
+
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
13
|
+
import type { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
13
14
|
import type { ChainConfig } from '@aztec/stdlib/config';
|
|
14
15
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
15
16
|
import { getProofSubmissionDeadlineTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
@@ -271,10 +272,13 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
271
272
|
|
|
272
273
|
// Gather all data for this epoch
|
|
273
274
|
const epochData = await this.gatherEpochData(epochNumber);
|
|
274
|
-
|
|
275
|
-
const
|
|
276
|
-
const
|
|
277
|
-
|
|
275
|
+
const fromCheckpoint = epochData.checkpoints[0].number;
|
|
276
|
+
const toCheckpoint = epochData.checkpoints.at(-1)!.number;
|
|
277
|
+
const fromBlock = epochData.checkpoints[0].blocks[0].number;
|
|
278
|
+
const toBlock = epochData.checkpoints.at(-1)!.blocks.at(-1)!.number;
|
|
279
|
+
this.log.verbose(
|
|
280
|
+
`Creating proving job for epoch ${epochNumber} for checkpoint range ${fromCheckpoint} to ${toCheckpoint} and block range ${fromBlock} to ${toBlock}`,
|
|
281
|
+
);
|
|
278
282
|
|
|
279
283
|
// Fast forward world state to right before the target block and get a fork
|
|
280
284
|
await this.worldState.syncImmediate(toBlock);
|
|
@@ -289,7 +293,6 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
289
293
|
// Set deadline for this job to run. It will abort if it takes too long.
|
|
290
294
|
const deadlineTs = getProofSubmissionDeadlineTimestamp(epochNumber, await this.getL1Constants());
|
|
291
295
|
const deadline = new Date(Number(deadlineTs) * 1000);
|
|
292
|
-
|
|
293
296
|
const job = this.doCreateEpochProvingJob(epochData, deadline, publicProcessorFactory, this.publisher, opts);
|
|
294
297
|
this.jobs.set(job.getId(), job);
|
|
295
298
|
return job;
|
|
@@ -302,28 +305,30 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
302
305
|
|
|
303
306
|
@trackSpan('ProverNode.gatherEpochData', epochNumber => ({ [Attributes.EPOCH_NUMBER]: epochNumber }))
|
|
304
307
|
private async gatherEpochData(epochNumber: EpochNumber): Promise<EpochProvingJobData> {
|
|
305
|
-
const
|
|
306
|
-
const txArray = await this.gatherTxs(epochNumber,
|
|
308
|
+
const checkpoints = await this.gatherCheckpoints(epochNumber);
|
|
309
|
+
const txArray = await this.gatherTxs(epochNumber, checkpoints);
|
|
307
310
|
const txs = new Map<string, Tx>(txArray.map(tx => [tx.getTxHash().toString(), tx]));
|
|
308
|
-
const l1ToL2Messages = await this.gatherMessages(epochNumber,
|
|
309
|
-
const
|
|
310
|
-
const
|
|
311
|
-
const
|
|
311
|
+
const l1ToL2Messages = await this.gatherMessages(epochNumber, checkpoints);
|
|
312
|
+
const [firstBlock] = checkpoints[0].blocks;
|
|
313
|
+
const previousBlockHeader = await this.gatherPreviousBlockHeader(epochNumber, firstBlock.number - 1);
|
|
314
|
+
const [lastPublishedCheckpoint] = await this.l2BlockSource.getCheckpoints(checkpoints.at(-1)!.number, 1);
|
|
315
|
+
const attestations = lastPublishedCheckpoint?.attestations ?? [];
|
|
312
316
|
|
|
313
|
-
return {
|
|
317
|
+
return { checkpoints, txs, l1ToL2Messages, epochNumber, previousBlockHeader, attestations };
|
|
314
318
|
}
|
|
315
319
|
|
|
316
|
-
private async
|
|
317
|
-
const
|
|
318
|
-
if (
|
|
320
|
+
private async gatherCheckpoints(epochNumber: EpochNumber) {
|
|
321
|
+
const checkpoints = await this.l2BlockSource.getCheckpointsForEpoch(epochNumber);
|
|
322
|
+
if (checkpoints.length === 0) {
|
|
319
323
|
throw new EmptyEpochError(epochNumber);
|
|
320
324
|
}
|
|
321
|
-
return
|
|
325
|
+
return checkpoints;
|
|
322
326
|
}
|
|
323
327
|
|
|
324
|
-
private async gatherTxs(epochNumber: EpochNumber,
|
|
328
|
+
private async gatherTxs(epochNumber: EpochNumber, checkpoints: Checkpoint[]) {
|
|
325
329
|
const deadline = new Date(this.dateProvider.now() + this.config.txGatheringTimeoutMs);
|
|
326
330
|
const txProvider = this.p2pClient.getTxProvider();
|
|
331
|
+
const blocks = checkpoints.flatMap(checkpoint => checkpoint.blocks);
|
|
327
332
|
const txsByBlock = await Promise.all(blocks.map(block => txProvider.getTxsForBlock(block, { deadline })));
|
|
328
333
|
const txs = txsByBlock.map(({ txs }) => txs).flat();
|
|
329
334
|
const missingTxs = txsByBlock.map(({ missingTxs }) => missingTxs).flat();
|
|
@@ -336,25 +341,24 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
336
341
|
throw new Error(`Txs not found for epoch ${epochNumber}: ${missingTxs.map(hash => hash.toString()).join(', ')}`);
|
|
337
342
|
}
|
|
338
343
|
|
|
339
|
-
private async gatherMessages(epochNumber: EpochNumber,
|
|
340
|
-
const messages = await Promise.all(
|
|
344
|
+
private async gatherMessages(epochNumber: EpochNumber, checkpoints: Checkpoint[]) {
|
|
345
|
+
const messages = await Promise.all(checkpoints.map(c => this.l1ToL2MessageSource.getL1ToL2Messages(c.number)));
|
|
341
346
|
const messageCount = sum(messages.map(m => m.length));
|
|
342
347
|
this.log.verbose(`Gathered all ${messageCount} messages for epoch ${epochNumber}`, { epochNumber });
|
|
343
|
-
const
|
|
344
|
-
for (let i = 0; i <
|
|
345
|
-
|
|
348
|
+
const messagesByCheckpoint: Record<CheckpointNumber, Fr[]> = {};
|
|
349
|
+
for (let i = 0; i < checkpoints.length; i++) {
|
|
350
|
+
messagesByCheckpoint[checkpoints[i].number] = messages[i];
|
|
346
351
|
}
|
|
347
|
-
return
|
|
352
|
+
return messagesByCheckpoint;
|
|
348
353
|
}
|
|
349
354
|
|
|
350
|
-
private async gatherPreviousBlockHeader(epochNumber: EpochNumber,
|
|
351
|
-
const previousBlockNumber = initialBlock.number - 1;
|
|
355
|
+
private async gatherPreviousBlockHeader(epochNumber: EpochNumber, previousBlockNumber: number) {
|
|
352
356
|
const header = await (previousBlockNumber === 0
|
|
353
357
|
? this.worldState.getCommitted().getInitialHeader()
|
|
354
|
-
: this.l2BlockSource.getBlockHeader(previousBlockNumber));
|
|
358
|
+
: this.l2BlockSource.getBlockHeader(BlockNumber(previousBlockNumber)));
|
|
355
359
|
|
|
356
360
|
if (!header) {
|
|
357
|
-
throw new Error(`Previous block header ${
|
|
361
|
+
throw new Error(`Previous block header ${previousBlockNumber} not found for proving epoch ${epochNumber}`);
|
|
358
362
|
}
|
|
359
363
|
|
|
360
364
|
this.log.verbose(`Gathered previous block header ${header.getBlockNumber()} for epoch ${epochNumber}`);
|
|
@@ -391,7 +395,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
|
|
|
391
395
|
private validateConfig() {
|
|
392
396
|
if (
|
|
393
397
|
this.config.proverNodeFailedEpochStore &&
|
|
394
|
-
(!this.config.dataDirectory || !this.config.l1ChainId ||
|
|
398
|
+
(!this.config.dataDirectory || !this.config.l1ChainId || this.config.rollupVersion === undefined)
|
|
395
399
|
) {
|
|
396
400
|
this.log.warn(
|
|
397
401
|
`Invalid prover-node config (missing dataDirectory, l1ChainId, or rollupVersion)`,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RollupContract } from '@aztec/ethereum/contracts';
|
|
2
|
+
import type { L1TxUtils } from '@aztec/ethereum/l1-tx-utils';
|
|
3
|
+
import type { PublisherManager } from '@aztec/ethereum/publisher-manager';
|
|
2
4
|
import type { PublisherConfig, TxSenderConfig } from '@aztec/sequencer-client';
|
|
3
5
|
import type { TelemetryClient } from '@aztec/telemetry-client';
|
|
4
6
|
|