@aztec/prover-node 0.0.0-test.0 → 0.0.1-commit.21caa21
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 +18 -0
- package/dest/actions/download-epoch-proving-job.d.ts.map +1 -0
- package/dest/actions/download-epoch-proving-job.js +37 -0
- package/dest/actions/index.d.ts +3 -0
- package/dest/actions/index.d.ts.map +1 -0
- package/dest/actions/index.js +2 -0
- package/dest/actions/rerun-epoch-proving-job.d.ts +11 -0
- package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -0
- package/dest/actions/rerun-epoch-proving-job.js +40 -0
- package/dest/actions/upload-epoch-proof-failure.d.ts +15 -0
- package/dest/actions/upload-epoch-proof-failure.d.ts.map +1 -0
- package/dest/actions/upload-epoch-proof-failure.js +78 -0
- package/dest/bin/run-failed-epoch.d.ts +2 -0
- package/dest/bin/run-failed-epoch.d.ts.map +1 -0
- package/dest/bin/run-failed-epoch.js +67 -0
- package/dest/config.d.ts +13 -10
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +81 -14
- package/dest/factory.d.ts +13 -9
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +95 -31
- package/dest/index.d.ts +2 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -1
- package/dest/job/epoch-proving-job-data.d.ts +17 -0
- package/dest/job/epoch-proving-job-data.d.ts.map +1 -0
- package/dest/job/epoch-proving-job-data.js +53 -0
- package/dest/job/epoch-proving-job.d.ts +25 -17
- package/dest/job/epoch-proving-job.d.ts.map +1 -1
- package/dest/job/epoch-proving-job.js +155 -51
- package/dest/metrics.d.ts +29 -5
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +141 -35
- package/dest/monitors/epoch-monitor.d.ts +5 -2
- package/dest/monitors/epoch-monitor.d.ts.map +1 -1
- package/dest/monitors/epoch-monitor.js +15 -2
- package/dest/monitors/index.d.ts +1 -1
- package/dest/prover-node-publisher.d.ts +10 -12
- package/dest/prover-node-publisher.d.ts.map +1 -1
- package/dest/prover-node-publisher.js +62 -62
- package/dest/prover-node.d.ts +48 -43
- package/dest/prover-node.d.ts.map +1 -1
- package/dest/prover-node.js +175 -105
- package/dest/prover-publisher-factory.d.ts +21 -0
- package/dest/prover-publisher-factory.d.ts.map +1 -0
- package/dest/prover-publisher-factory.js +26 -0
- package/dest/test/index.d.ts +5 -3
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +1 -3
- package/package.json +39 -33
- package/src/actions/download-epoch-proving-job.ts +44 -0
- package/src/actions/index.ts +2 -0
- package/src/actions/rerun-epoch-proving-job.ts +61 -0
- package/src/actions/upload-epoch-proof-failure.ts +88 -0
- package/src/bin/run-failed-epoch.ts +77 -0
- package/src/config.ts +108 -24
- package/src/factory.ts +163 -43
- package/src/index.ts +1 -1
- package/src/job/epoch-proving-job-data.ts +77 -0
- package/src/job/epoch-proving-job.ts +222 -52
- package/src/metrics.ts +135 -37
- package/src/monitors/epoch-monitor.ts +18 -6
- package/src/prover-node-publisher.ts +96 -88
- package/src/prover-node.ts +213 -136
- package/src/prover-publisher-factory.ts +37 -0
- package/src/test/index.ts +7 -4
- package/dest/http.d.ts +0 -8
- package/dest/http.d.ts.map +0 -1
- package/dest/http.js +0 -9
- package/dest/prover-coordination/config.d.ts +0 -7
- package/dest/prover-coordination/config.d.ts.map +0 -1
- package/dest/prover-coordination/config.js +0 -11
- package/dest/prover-coordination/factory.d.ts +0 -22
- package/dest/prover-coordination/factory.d.ts.map +0 -1
- package/dest/prover-coordination/factory.js +0 -42
- package/dest/prover-coordination/index.d.ts +0 -3
- package/dest/prover-coordination/index.d.ts.map +0 -1
- package/dest/prover-coordination/index.js +0 -2
- package/src/http.ts +0 -13
- package/src/prover-coordination/config.ts +0 -17
- package/src/prover-coordination/factory.ts +0 -72
- package/src/prover-coordination/index.ts +0 -2
package/dest/metrics.js
CHANGED
|
@@ -1,83 +1,187 @@
|
|
|
1
1
|
import { createLogger } from '@aztec/foundation/log';
|
|
2
2
|
import { Attributes, Metrics, ValueType } from '@aztec/telemetry-client';
|
|
3
|
-
import { formatEther } from 'viem';
|
|
4
|
-
export class
|
|
5
|
-
|
|
3
|
+
import { formatEther, formatUnits } from 'viem';
|
|
4
|
+
export class ProverNodeJobMetrics {
|
|
5
|
+
meter;
|
|
6
|
+
tracer;
|
|
6
7
|
logger;
|
|
7
8
|
proverEpochExecutionDuration;
|
|
8
9
|
provingJobDuration;
|
|
9
10
|
provingJobBlocks;
|
|
10
11
|
provingJobTransactions;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
txGas;
|
|
15
|
-
txCalldataSize;
|
|
16
|
-
txCalldataGas;
|
|
17
|
-
txBlobDataGasUsed;
|
|
18
|
-
txBlobDataGasCost;
|
|
19
|
-
senderBalance;
|
|
20
|
-
constructor(client, name = 'ProverNode', logger = createLogger('prover-node:publisher:metrics')){
|
|
21
|
-
this.client = client;
|
|
12
|
+
constructor(meter, tracer, logger = createLogger('prover-node:publisher:metrics')){
|
|
13
|
+
this.meter = meter;
|
|
14
|
+
this.tracer = tracer;
|
|
22
15
|
this.logger = logger;
|
|
23
|
-
|
|
24
|
-
this.proverEpochExecutionDuration = meter.createHistogram(Metrics.PROVER_NODE_EXECUTION_DURATION, {
|
|
16
|
+
this.proverEpochExecutionDuration = this.meter.createHistogram(Metrics.PROVER_NODE_EXECUTION_DURATION, {
|
|
25
17
|
description: 'Duration of execution of an epoch by the prover',
|
|
26
18
|
unit: 'ms',
|
|
27
19
|
valueType: ValueType.INT
|
|
28
20
|
});
|
|
29
|
-
this.provingJobDuration = meter.createHistogram(Metrics.PROVER_NODE_JOB_DURATION, {
|
|
21
|
+
this.provingJobDuration = this.meter.createHistogram(Metrics.PROVER_NODE_JOB_DURATION, {
|
|
30
22
|
description: 'Duration of proving job',
|
|
31
23
|
unit: 's',
|
|
32
24
|
valueType: ValueType.DOUBLE
|
|
33
25
|
});
|
|
34
|
-
this.provingJobBlocks = meter.createGauge(Metrics.PROVER_NODE_JOB_BLOCKS, {
|
|
26
|
+
this.provingJobBlocks = this.meter.createGauge(Metrics.PROVER_NODE_JOB_BLOCKS, {
|
|
35
27
|
description: 'Number of blocks in a proven epoch',
|
|
36
28
|
valueType: ValueType.INT
|
|
37
29
|
});
|
|
38
|
-
this.provingJobTransactions = meter.createGauge(Metrics.PROVER_NODE_JOB_TRANSACTIONS, {
|
|
30
|
+
this.provingJobTransactions = this.meter.createGauge(Metrics.PROVER_NODE_JOB_TRANSACTIONS, {
|
|
39
31
|
description: 'Number of transactions in a proven epoch',
|
|
40
32
|
valueType: ValueType.INT
|
|
41
33
|
});
|
|
42
|
-
|
|
34
|
+
}
|
|
35
|
+
recordProvingJob(executionTimeMs, totalTimeMs, numBlocks, numTxs) {
|
|
36
|
+
this.proverEpochExecutionDuration.record(Math.ceil(executionTimeMs));
|
|
37
|
+
this.provingJobDuration.record(totalTimeMs / 1000);
|
|
38
|
+
this.provingJobBlocks.record(Math.floor(numBlocks));
|
|
39
|
+
this.provingJobTransactions.record(Math.floor(numTxs));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export class ProverNodeRewardsMetrics {
|
|
43
|
+
meter;
|
|
44
|
+
coinbase;
|
|
45
|
+
rollup;
|
|
46
|
+
logger;
|
|
47
|
+
rewards;
|
|
48
|
+
accumulatedRewards;
|
|
49
|
+
prevEpoch;
|
|
50
|
+
proofSubmissionEpochs;
|
|
51
|
+
constructor(meter, coinbase, rollup, logger = createLogger('prover-node:publisher:metrics')){
|
|
52
|
+
this.meter = meter;
|
|
53
|
+
this.coinbase = coinbase;
|
|
54
|
+
this.rollup = rollup;
|
|
55
|
+
this.logger = logger;
|
|
56
|
+
this.prevEpoch = -1n;
|
|
57
|
+
this.proofSubmissionEpochs = 0;
|
|
58
|
+
this.observe = async (observer)=>{
|
|
59
|
+
const epoch = await this.rollup.getCurrentEpochNumber();
|
|
60
|
+
if (epoch > this.proofSubmissionEpochs) {
|
|
61
|
+
// look at the prev epoch so that we get an accurate value, after proof submission window has closed
|
|
62
|
+
// For example, if proof submission window is 1 epoch, and we are in epoch 2, we should be looking at epoch 0.
|
|
63
|
+
// Similarly, if the proof submission window is 0, and we are in epoch 1, we should be looking at epoch 0.
|
|
64
|
+
const closedEpoch = BigInt(epoch) - BigInt(this.proofSubmissionEpochs) - 1n;
|
|
65
|
+
const rewards = await this.rollup.getSpecificProverRewardsForEpoch(closedEpoch, this.coinbase);
|
|
66
|
+
const fmt = parseFloat(formatUnits(rewards, 18));
|
|
67
|
+
observer.observe(this.rewards, fmt, {
|
|
68
|
+
[Attributes.COINBASE]: this.coinbase.toString()
|
|
69
|
+
});
|
|
70
|
+
// only accumulate once per epoch
|
|
71
|
+
if (closedEpoch > this.prevEpoch) {
|
|
72
|
+
this.prevEpoch = closedEpoch;
|
|
73
|
+
this.accumulatedRewards.add(fmt, {
|
|
74
|
+
[Attributes.COINBASE]: this.coinbase.toString()
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
this.rewards = this.meter.createObservableGauge(Metrics.PROVER_NODE_REWARDS_PER_EPOCH, {
|
|
80
|
+
valueType: ValueType.DOUBLE,
|
|
81
|
+
description: 'The rewards earned'
|
|
82
|
+
});
|
|
83
|
+
this.accumulatedRewards = this.meter.createUpDownCounter(Metrics.PROVER_NODE_REWARDS_TOTAL, {
|
|
84
|
+
valueType: ValueType.DOUBLE,
|
|
85
|
+
description: 'The rewards earned (total)'
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
async start() {
|
|
89
|
+
const proofSubmissionEpochs = await this.rollup.getProofSubmissionEpochs();
|
|
90
|
+
this.proofSubmissionEpochs = Number(proofSubmissionEpochs);
|
|
91
|
+
this.meter.addBatchObservableCallback(this.observe, [
|
|
92
|
+
this.rewards
|
|
93
|
+
]);
|
|
94
|
+
}
|
|
95
|
+
stop() {
|
|
96
|
+
this.meter.removeBatchObservableCallback(this.observe, [
|
|
97
|
+
this.rewards
|
|
98
|
+
]);
|
|
99
|
+
}
|
|
100
|
+
observe;
|
|
101
|
+
}
|
|
102
|
+
export class ProverNodePublisherMetrics {
|
|
103
|
+
client;
|
|
104
|
+
logger;
|
|
105
|
+
gasPrice;
|
|
106
|
+
txCount;
|
|
107
|
+
txDuration;
|
|
108
|
+
txGas;
|
|
109
|
+
txCalldataSize;
|
|
110
|
+
txCalldataGas;
|
|
111
|
+
txBlobDataGasUsed;
|
|
112
|
+
txBlobDataGasCost;
|
|
113
|
+
txTotalFee;
|
|
114
|
+
senderBalance;
|
|
115
|
+
meter;
|
|
116
|
+
constructor(client, name = 'ProverNode', logger = createLogger('prover-node:publisher:metrics')){
|
|
117
|
+
this.client = client;
|
|
118
|
+
this.logger = logger;
|
|
119
|
+
this.meter = client.getMeter(name);
|
|
120
|
+
this.gasPrice = this.meter.createHistogram(Metrics.L1_PUBLISHER_GAS_PRICE, {
|
|
43
121
|
description: 'The gas price used for transactions',
|
|
44
122
|
unit: 'gwei',
|
|
45
123
|
valueType: ValueType.DOUBLE
|
|
46
124
|
});
|
|
47
|
-
this.txCount = meter.createUpDownCounter(Metrics.L1_PUBLISHER_TX_COUNT, {
|
|
125
|
+
this.txCount = this.meter.createUpDownCounter(Metrics.L1_PUBLISHER_TX_COUNT, {
|
|
48
126
|
description: 'The number of transactions processed'
|
|
49
127
|
});
|
|
50
|
-
this.txDuration = meter.createHistogram(Metrics.L1_PUBLISHER_TX_DURATION, {
|
|
128
|
+
this.txDuration = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_DURATION, {
|
|
51
129
|
description: 'The duration of transaction processing',
|
|
52
130
|
unit: 'ms',
|
|
53
131
|
valueType: ValueType.INT
|
|
54
132
|
});
|
|
55
|
-
this.txGas = meter.createHistogram(Metrics.L1_PUBLISHER_TX_GAS, {
|
|
133
|
+
this.txGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_GAS, {
|
|
56
134
|
description: 'The gas consumed by transactions',
|
|
57
135
|
unit: 'gas',
|
|
58
136
|
valueType: ValueType.INT
|
|
59
137
|
});
|
|
60
|
-
this.txCalldataSize = meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_SIZE, {
|
|
138
|
+
this.txCalldataSize = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_SIZE, {
|
|
61
139
|
description: 'The size of the calldata in transactions',
|
|
62
140
|
unit: 'By',
|
|
63
141
|
valueType: ValueType.INT
|
|
64
142
|
});
|
|
65
|
-
this.txCalldataGas = meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_GAS, {
|
|
143
|
+
this.txCalldataGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_GAS, {
|
|
66
144
|
description: 'The gas consumed by the calldata in transactions',
|
|
67
145
|
unit: 'gas',
|
|
68
146
|
valueType: ValueType.INT
|
|
69
147
|
});
|
|
70
|
-
this.txBlobDataGasUsed = meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_USED, {
|
|
148
|
+
this.txBlobDataGasUsed = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_USED, {
|
|
71
149
|
description: 'The amount of blob gas used in transactions',
|
|
72
150
|
unit: 'gas',
|
|
73
151
|
valueType: ValueType.INT
|
|
74
152
|
});
|
|
75
|
-
this.txBlobDataGasCost = meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_COST, {
|
|
153
|
+
this.txBlobDataGasCost = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_COST, {
|
|
76
154
|
description: 'The gas cost of blobs in transactions',
|
|
77
155
|
unit: 'gwei',
|
|
78
156
|
valueType: ValueType.INT
|
|
79
157
|
});
|
|
80
|
-
this.
|
|
158
|
+
this.txTotalFee = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_TOTAL_FEE, {
|
|
159
|
+
description: 'How much L1 tx costs',
|
|
160
|
+
unit: 'gwei',
|
|
161
|
+
valueType: ValueType.DOUBLE,
|
|
162
|
+
advice: {
|
|
163
|
+
explicitBucketBoundaries: [
|
|
164
|
+
0.001,
|
|
165
|
+
0.002,
|
|
166
|
+
0.004,
|
|
167
|
+
0.008,
|
|
168
|
+
0.01,
|
|
169
|
+
0.02,
|
|
170
|
+
0.04,
|
|
171
|
+
0.08,
|
|
172
|
+
0.1,
|
|
173
|
+
0.2,
|
|
174
|
+
0.4,
|
|
175
|
+
0.8,
|
|
176
|
+
1,
|
|
177
|
+
1.2,
|
|
178
|
+
1.4,
|
|
179
|
+
1.8,
|
|
180
|
+
2
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
this.senderBalance = this.meter.createGauge(Metrics.L1_PUBLISHER_BALANCE, {
|
|
81
185
|
unit: 'eth',
|
|
82
186
|
description: 'The balance of the sender address',
|
|
83
187
|
valueType: ValueType.DOUBLE
|
|
@@ -92,12 +196,6 @@ export class ProverNodeMetrics {
|
|
|
92
196
|
recordSubmitProof(durationMs, stats) {
|
|
93
197
|
this.recordTx(durationMs, stats);
|
|
94
198
|
}
|
|
95
|
-
recordProvingJob(executionTimeMs, totalTimeMs, numBlocks, numTxs) {
|
|
96
|
-
this.proverEpochExecutionDuration.record(Math.ceil(executionTimeMs));
|
|
97
|
-
this.provingJobDuration.record(totalTimeMs / 1000);
|
|
98
|
-
this.provingJobBlocks.record(Math.floor(numBlocks));
|
|
99
|
-
this.provingJobTransactions.record(Math.floor(numTxs));
|
|
100
|
-
}
|
|
101
199
|
recordSenderBalance(wei, senderAddress) {
|
|
102
200
|
const eth = parseFloat(formatEther(wei, 'wei'));
|
|
103
201
|
this.senderBalance.record(eth, {
|
|
@@ -122,7 +220,15 @@ export class ProverNodeMetrics {
|
|
|
122
220
|
this.txBlobDataGasUsed.record(Number(stats.blobGasUsed), attributes);
|
|
123
221
|
try {
|
|
124
222
|
this.gasPrice.record(parseInt(formatEther(stats.gasPrice, 'gwei'), 10));
|
|
125
|
-
} catch
|
|
223
|
+
} catch {
|
|
224
|
+
// ignore
|
|
225
|
+
}
|
|
226
|
+
const executionFee = stats.gasUsed * stats.gasPrice;
|
|
227
|
+
const blobFee = stats.blobGasUsed * stats.blobDataGas;
|
|
228
|
+
const totalFee = executionFee + blobFee;
|
|
229
|
+
try {
|
|
230
|
+
this.txTotalFee.record(parseFloat(formatEther(totalFee)));
|
|
231
|
+
} catch {
|
|
126
232
|
// ignore
|
|
127
233
|
}
|
|
128
234
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { EpochNumber } from '@aztec/foundation/branded-types';
|
|
1
2
|
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
2
3
|
import { type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
3
4
|
import { type TelemetryClient, type Traceable, type Tracer } from '@aztec/telemetry-client';
|
|
4
5
|
export interface EpochMonitorHandler {
|
|
5
|
-
handleEpochReadyToProve(epochNumber:
|
|
6
|
+
handleEpochReadyToProve(epochNumber: EpochNumber): Promise<boolean>;
|
|
6
7
|
}
|
|
7
8
|
/**
|
|
8
9
|
* Fires an event when a new epoch ready to prove is detected.
|
|
@@ -26,9 +27,11 @@ export declare class EpochMonitor implements Traceable {
|
|
|
26
27
|
private latestEpochNumber;
|
|
27
28
|
constructor(l2BlockSource: L2BlockSource, l1Constants: Pick<L1RollupConstants, 'epochDuration'>, options: {
|
|
28
29
|
pollingIntervalMs: number;
|
|
30
|
+
provingDelayMs?: number;
|
|
29
31
|
}, telemetry?: TelemetryClient);
|
|
30
32
|
static create(l2BlockSource: L2BlockSource, options: {
|
|
31
33
|
pollingIntervalMs: number;
|
|
34
|
+
provingDelayMs?: number;
|
|
32
35
|
}, telemetry?: TelemetryClient): Promise<EpochMonitor>;
|
|
33
36
|
start(handler: EpochMonitorHandler): void;
|
|
34
37
|
/** Exposed for testing */
|
|
@@ -37,4 +40,4 @@ export declare class EpochMonitor implements Traceable {
|
|
|
37
40
|
work(): Promise<void>;
|
|
38
41
|
private getEpochNumberToProve;
|
|
39
42
|
}
|
|
40
|
-
//# sourceMappingURL=
|
|
43
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXBvY2gtbW9uaXRvci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21vbml0b3JzL2Vwb2NoLW1vbml0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBSTlELE9BQU8sS0FBSyxFQUFFLGFBQWEsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUFrQixNQUFNLDZCQUE2QixDQUFDO0FBQ3JGLE9BQU8sRUFDTCxLQUFLLGVBQWUsRUFDcEIsS0FBSyxTQUFTLEVBQ2QsS0FBSyxNQUFNLEVBR1osTUFBTSx5QkFBeUIsQ0FBQztBQUVqQyxNQUFNLFdBQVcsbUJBQW1CO0lBQ2xDLHVCQUF1QixDQUFDLFdBQVcsRUFBRSxXQUFXLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0NBQ3JFO0FBRUQ7Ozs7Ozs7Ozs7R0FVRztBQUNILHFCQUFhLFlBQWEsWUFBVyxTQUFTO0lBUzFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsYUFBYTtJQUM5QixPQUFPLENBQUMsUUFBUSxDQUFDLFdBQVc7SUFDNUIsT0FBTyxDQUFDLE9BQU87SUFWakIsT0FBTyxDQUFDLGNBQWMsQ0FBaUI7SUFDdkMsT0FBTyxDQUFDLEdBQUcsQ0FBNkM7SUFDeEQsU0FBZ0IsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUUvQixPQUFPLENBQUMsT0FBTyxDQUFrQztJQUNqRCxPQUFPLENBQUMsaUJBQWlCLENBQTBCO0lBRW5ELFlBQ21CLGFBQWEsRUFBRSxhQUFhLEVBQzVCLFdBQVcsRUFBRSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsZUFBZSxDQUFDLEVBQzlELE9BQU8sRUFBRTtRQUFFLGlCQUFpQixFQUFFLE1BQU0sQ0FBQztRQUFDLGNBQWMsQ0FBQyxFQUFFLE1BQU0sQ0FBQTtLQUFFLEVBQ3ZFLFNBQVMsR0FBRSxlQUFzQyxFQU9sRDtJQUVELE9BQW9CLE1BQU0sQ0FDeEIsYUFBYSxFQUFFLGFBQWEsRUFDNUIsT0FBTyxFQUFFO1FBQUUsaUJBQWlCLEVBQUUsTUFBTSxDQUFDO1FBQUMsY0FBYyxDQUFDLEVBQUUsTUFBTSxDQUFBO0tBQUUsRUFDL0QsU0FBUyxHQUFFLGVBQXNDLEdBQ2hELE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FHdkI7SUFFTSxLQUFLLENBQUMsT0FBTyxFQUFFLG1CQUFtQixRQUl4QztJQUVELDBCQUEwQjtJQUNuQixVQUFVLENBQUMsT0FBTyxFQUFFLG1CQUFtQixRQUU3QztJQUVZLElBQUksa0JBR2hCO0lBR1ksSUFBSSxrQkEyQmhCO1lBRWEscUJBQXFCO0NBWXBDIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"epoch-monitor.d.ts","sourceRoot":"","sources":["../../src/monitors/epoch-monitor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"epoch-monitor.d.ts","sourceRoot":"","sources":["../../src/monitors/epoch-monitor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAI9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,KAAK,iBAAiB,EAAkB,MAAM,6BAA6B,CAAC;AACrF,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,MAAM,EAGZ,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,mBAAmB;IAClC,uBAAuB,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACrE;AAED;;;;;;;;;;GAUG;AACH,qBAAa,YAAa,YAAW,SAAS;IAS1C,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,OAAO;IAVjB,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,GAAG,CAA6C;IACxD,SAAgB,MAAM,EAAE,MAAM,CAAC;IAE/B,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,iBAAiB,CAA0B;IAEnD,YACmB,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,EAC9D,OAAO,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,EACvE,SAAS,GAAE,eAAsC,EAOlD;IAED,OAAoB,MAAM,CACxB,aAAa,EAAE,aAAa,EAC5B,OAAO,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,EAC/D,SAAS,GAAE,eAAsC,GAChD,OAAO,CAAC,YAAY,CAAC,CAGvB;IAEM,KAAK,CAAC,OAAO,EAAE,mBAAmB,QAIxC;IAED,0BAA0B;IACnB,UAAU,CAAC,OAAO,EAAE,mBAAmB,QAE7C;IAEY,IAAI,kBAGhB;IAGY,IAAI,kBA2BhB;YAEa,qBAAqB;CAYpC"}
|
|
@@ -6,6 +6,7 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
6
6
|
}
|
|
7
7
|
import { createLogger } from '@aztec/foundation/log';
|
|
8
8
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
9
|
+
import { sleep } from '@aztec/foundation/sleep';
|
|
9
10
|
import { getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
|
|
10
11
|
import { getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
11
12
|
/**
|
|
@@ -34,6 +35,9 @@ import { getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
|
34
35
|
this.log = createLogger('prover-node:epoch-monitor');
|
|
35
36
|
this.tracer = telemetry.getTracer('EpochMonitor');
|
|
36
37
|
this.runningPromise = new RunningPromise(this.work.bind(this), this.log, this.options.pollingIntervalMs);
|
|
38
|
+
if (this.options.provingDelayMs) {
|
|
39
|
+
this.log.warn(`Prover node epoch monitor running with delay of ${this.options.provingDelayMs}ms`);
|
|
40
|
+
}
|
|
37
41
|
}
|
|
38
42
|
static async create(l2BlockSource, options, telemetry = getTelemetryClient()) {
|
|
39
43
|
const l1Constants = await l2BlockSource.getL1Constants();
|
|
@@ -53,6 +57,10 @@ import { getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
|
53
57
|
}
|
|
54
58
|
async work() {
|
|
55
59
|
const { epochToProve, blockNumber, slotNumber } = await this.getEpochNumberToProve();
|
|
60
|
+
this.log.debug(`Epoch to prove: ${epochToProve}`, {
|
|
61
|
+
blockNumber,
|
|
62
|
+
slotNumber
|
|
63
|
+
});
|
|
56
64
|
if (epochToProve === undefined) {
|
|
57
65
|
this.log.trace(`Next block to prove ${blockNumber} not yet mined`, {
|
|
58
66
|
blockNumber
|
|
@@ -76,9 +84,14 @@ import { getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
|
76
84
|
});
|
|
77
85
|
return;
|
|
78
86
|
}
|
|
87
|
+
if (this.options.provingDelayMs) {
|
|
88
|
+
this.log.debug(`Waiting ${this.options.provingDelayMs}ms before proving epoch ${epochToProve}`);
|
|
89
|
+
await sleep(this.options.provingDelayMs);
|
|
90
|
+
}
|
|
79
91
|
this.log.debug(`Epoch ${epochToProve} is ready to be proven`);
|
|
80
|
-
await this.handler?.handleEpochReadyToProve(epochToProve)
|
|
81
|
-
|
|
92
|
+
if (await this.handler?.handleEpochReadyToProve(epochToProve)) {
|
|
93
|
+
this.latestEpochNumber = epochToProve;
|
|
94
|
+
}
|
|
82
95
|
}
|
|
83
96
|
async getEpochNumberToProve() {
|
|
84
97
|
const lastBlockProven = await this.l2BlockSource.getProvenBlockNumber();
|
package/dest/monitors/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from './epoch-monitor.js';
|
|
2
|
-
//# sourceMappingURL=
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tb25pdG9ycy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLG9CQUFvQixDQUFDIn0=
|
|
@@ -1,22 +1,19 @@
|
|
|
1
|
+
import { BatchedBlob } from '@aztec/blob-lib';
|
|
1
2
|
import { AZTEC_MAX_EPOCH_DURATION } from '@aztec/constants';
|
|
2
|
-
import type { L1TxUtils, RollupContract } from '@aztec/ethereum';
|
|
3
|
+
import type { L1TxUtils, RollupContract, ViemCommitteeAttestation } from '@aztec/ethereum';
|
|
4
|
+
import { EpochNumber } from '@aztec/foundation/branded-types';
|
|
3
5
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
6
|
import { Fr } from '@aztec/foundation/fields';
|
|
5
|
-
import {
|
|
7
|
+
import type { Tuple } from '@aztec/foundation/serialize';
|
|
6
8
|
import type { PublisherConfig, TxSenderConfig } from '@aztec/sequencer-client';
|
|
7
9
|
import type { Proof } from '@aztec/stdlib/proofs';
|
|
8
10
|
import type { FeeRecipient, RootRollupPublicInputs } from '@aztec/stdlib/rollup';
|
|
9
11
|
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
10
|
-
/**
|
|
11
|
-
* Stats for a sent transaction.
|
|
12
|
-
*/
|
|
13
12
|
/** Arguments to the submitEpochProof method of the rollup contract */
|
|
14
13
|
export type L1SubmitEpochProofArgs = {
|
|
15
14
|
epochSize: number;
|
|
16
15
|
previousArchive: Fr;
|
|
17
16
|
endArchive: Fr;
|
|
18
|
-
previousBlockHash: Fr;
|
|
19
|
-
endBlockHash: Fr;
|
|
20
17
|
endTimestamp: Fr;
|
|
21
18
|
outHash: Fr;
|
|
22
19
|
proverId: Fr;
|
|
@@ -24,8 +21,6 @@ export type L1SubmitEpochProofArgs = {
|
|
|
24
21
|
proof: Proof;
|
|
25
22
|
};
|
|
26
23
|
export declare class ProverNodePublisher {
|
|
27
|
-
private interruptibleSleep;
|
|
28
|
-
private sleepTimeMs;
|
|
29
24
|
private interrupted;
|
|
30
25
|
private metrics;
|
|
31
26
|
protected log: import("@aztec/foundation/log").Logger;
|
|
@@ -36,6 +31,7 @@ export declare class ProverNodePublisher {
|
|
|
36
31
|
l1TxUtils: L1TxUtils;
|
|
37
32
|
telemetry?: TelemetryClient;
|
|
38
33
|
});
|
|
34
|
+
getRollupContract(): RollupContract;
|
|
39
35
|
/**
|
|
40
36
|
* Calling `interrupt` will cause any in progress call to `publishRollup` to return `false` asap.
|
|
41
37
|
* Be warned, the call may return false even if the tx subsequently gets successfully mined.
|
|
@@ -47,15 +43,17 @@ export declare class ProverNodePublisher {
|
|
|
47
43
|
restart(): void;
|
|
48
44
|
getSenderAddress(): EthAddress;
|
|
49
45
|
submitEpochProof(args: {
|
|
50
|
-
epochNumber:
|
|
46
|
+
epochNumber: EpochNumber;
|
|
51
47
|
fromBlock: number;
|
|
52
48
|
toBlock: number;
|
|
53
49
|
publicInputs: RootRollupPublicInputs;
|
|
54
50
|
proof: Proof;
|
|
51
|
+
batchedBlobInputs: BatchedBlob;
|
|
52
|
+
attestations: ViemCommitteeAttestation[];
|
|
55
53
|
}): Promise<boolean>;
|
|
56
54
|
private validateEpochProofSubmission;
|
|
57
55
|
private sendSubmitEpochProofTx;
|
|
56
|
+
private getEpochProofPublicInputsArgs;
|
|
58
57
|
private getSubmitEpochProofArgs;
|
|
59
|
-
protected sleepOrInterrupted(): Promise<void>;
|
|
60
58
|
}
|
|
61
|
-
//# sourceMappingURL=
|
|
59
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmVyLW5vZGUtcHVibGlzaGVyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvcHJvdmVyLW5vZGUtcHVibGlzaGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxXQUFXLEVBQThCLE1BQU0saUJBQWlCLENBQUM7QUFDMUUsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDNUQsT0FBTyxLQUFLLEVBQUUsU0FBUyxFQUFFLGNBQWMsRUFBRSx3QkFBd0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRTNGLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUU5RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDM0QsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRTlDLE9BQU8sS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBR3pELE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxjQUFjLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUUvRSxPQUFPLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNsRCxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUVqRixPQUFPLEVBQUUsS0FBSyxlQUFlLEVBQXNCLE1BQU0seUJBQXlCLENBQUM7QUFPbkYsc0VBQXNFO0FBQ3RFLE1BQU0sTUFBTSxzQkFBc0IsR0FBRztJQUNuQyxTQUFTLEVBQUUsTUFBTSxDQUFDO0lBQ2xCLGVBQWUsRUFBRSxFQUFFLENBQUM7SUFDcEIsVUFBVSxFQUFFLEVBQUUsQ0FBQztJQUNmLFlBQVksRUFBRSxFQUFFLENBQUM7SUFDakIsT0FBTyxFQUFFLEVBQUUsQ0FBQztJQUNaLFFBQVEsRUFBRSxFQUFFLENBQUM7SUFDYixJQUFJLEVBQUUsS0FBSyxDQUFDLFlBQVksRUFBRSxPQUFPLHdCQUF3QixDQUFDLENBQUM7SUFDM0QsS0FBSyxFQUFFLEtBQUssQ0FBQztDQUNkLENBQUM7QUFFRixxQkFBYSxtQkFBbUI7SUFDOUIsT0FBTyxDQUFDLFdBQVcsQ0FBUztJQUM1QixPQUFPLENBQUMsT0FBTyxDQUE2QjtJQUU1QyxTQUFTLENBQUMsR0FBRyx5Q0FBK0M7SUFFNUQsU0FBUyxDQUFDLGNBQWMsRUFBRSxjQUFjLENBQUM7SUFFekMsU0FBZ0IsU0FBUyxFQUFFLFNBQVMsQ0FBQztJQUVyQyxZQUNFLE1BQU0sRUFBRSxjQUFjLEdBQUcsZUFBZSxFQUN4QyxJQUFJLEVBQUU7UUFDSixjQUFjLEVBQUUsY0FBYyxDQUFDO1FBQy9CLFNBQVMsRUFBRSxTQUFTLENBQUM7UUFDckIsU0FBUyxDQUFDLEVBQUUsZUFBZSxDQUFDO0tBQzdCLEVBUUY7SUFFTSxpQkFBaUIsbUJBRXZCO0lBRUQ7Ozs7O09BS0c7SUFDSSxTQUFTLFNBR2Y7SUFFRCx3REFBd0Q7SUFDakQsT0FBTyxTQUdiO0lBRU0sZ0JBQWdCLGVBRXRCO0lBRVksZ0JBQWdCLENBQUMsSUFBSSxFQUFFO1FBQ2xDLFdBQVcsRUFBRSxXQUFXLENBQUM7UUFDekIsU0FBUyxFQUFFLE1BQU0sQ0FBQztRQUNsQixPQUFPLEVBQUUsTUFBTSxDQUFDO1FBQ2hCLFlBQVksRUFBRSxzQkFBc0IsQ0FBQztRQUNyQyxLQUFLLEVBQUUsS0FBSyxDQUFDO1FBQ2IsaUJBQWlCLEVBQUUsV0FBVyxDQUFDO1FBQy9CLFlBQVksRUFBRSx3QkFBd0IsRUFBRSxDQUFDO0tBQzFDLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQWdEbkI7WUFFYSw0QkFBNEI7WUEyRDVCLHNCQUFzQjtJQXlDcEMsT0FBTyxDQUFDLDZCQUE2QjtJQXlCckMsT0FBTyxDQUFDLHVCQUF1QjtDQXVCaEMifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prover-node-publisher.d.ts","sourceRoot":"","sources":["../src/prover-node-publisher.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"prover-node-publisher.d.ts","sourceRoot":"","sources":["../src/prover-node-publisher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA8B,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAE3F,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE9D,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAE9C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAGzD,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAE/E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEjF,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AAOnF,sEAAsE;AACtE,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,EAAE,CAAC;IACpB,UAAU,EAAE,EAAE,CAAC;IACf,YAAY,EAAE,EAAE,CAAC;IACjB,OAAO,EAAE,EAAE,CAAC;IACZ,QAAQ,EAAE,EAAE,CAAC;IACb,IAAI,EAAE,KAAK,CAAC,YAAY,EAAE,OAAO,wBAAwB,CAAC,CAAC;IAC3D,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAA6B;IAE5C,SAAS,CAAC,GAAG,yCAA+C;IAE5D,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC;IAEzC,SAAgB,SAAS,EAAE,SAAS,CAAC;IAErC,YACE,MAAM,EAAE,cAAc,GAAG,eAAe,EACxC,IAAI,EAAE;QACJ,cAAc,EAAE,cAAc,CAAC;QAC/B,SAAS,EAAE,SAAS,CAAC;QACrB,SAAS,CAAC,EAAE,eAAe,CAAC;KAC7B,EAQF;IAEM,iBAAiB,mBAEvB;IAED;;;;;OAKG;IACI,SAAS,SAGf;IAED,wDAAwD;IACjD,OAAO,SAGb;IAEM,gBAAgB,eAEtB;IAEY,gBAAgB,CAAC,IAAI,EAAE;QAClC,WAAW,EAAE,WAAW,CAAC;QACzB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,sBAAsB,CAAC;QACrC,KAAK,EAAE,KAAK,CAAC;QACb,iBAAiB,EAAE,WAAW,CAAC;QAC/B,YAAY,EAAE,wBAAwB,EAAE,CAAC;KAC1C,GAAG,OAAO,CAAC,OAAO,CAAC,CAgDnB;YAEa,4BAA4B;YA2D5B,sBAAsB;IAyCpC,OAAO,CAAC,6BAA6B;IAyBrC,OAAO,CAAC,uBAAuB;CAuBhC"}
|
|
@@ -1,31 +1,32 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getEthBlobEvaluationInputs } from '@aztec/blob-lib';
|
|
2
|
+
import { AZTEC_MAX_EPOCH_DURATION } from '@aztec/constants';
|
|
2
3
|
import { makeTuple } from '@aztec/foundation/array';
|
|
3
|
-
import { areArraysEqual
|
|
4
|
+
import { areArraysEqual } from '@aztec/foundation/collection';
|
|
4
5
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
6
|
import { Fr } from '@aztec/foundation/fields';
|
|
6
7
|
import { createLogger } from '@aztec/foundation/log';
|
|
7
|
-
import { serializeToBuffer } from '@aztec/foundation/serialize';
|
|
8
|
-
import { InterruptibleSleep } from '@aztec/foundation/sleep';
|
|
9
8
|
import { Timer } from '@aztec/foundation/timer';
|
|
10
9
|
import { RollupAbi } from '@aztec/l1-artifacts';
|
|
10
|
+
import { CommitteeAttestation, CommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
|
|
11
11
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
12
|
+
import { inspect } from 'util';
|
|
12
13
|
import { encodeFunctionData } from 'viem';
|
|
13
|
-
import {
|
|
14
|
+
import { ProverNodePublisherMetrics } from './metrics.js';
|
|
14
15
|
export class ProverNodePublisher {
|
|
15
|
-
interruptibleSleep = new InterruptibleSleep();
|
|
16
|
-
sleepTimeMs;
|
|
17
16
|
interrupted = false;
|
|
18
17
|
metrics;
|
|
19
18
|
log = createLogger('prover-node:l1-tx-publisher');
|
|
20
19
|
rollupContract;
|
|
21
20
|
l1TxUtils;
|
|
22
21
|
constructor(config, deps){
|
|
23
|
-
this.sleepTimeMs = config?.l1PublishRetryIntervalMS ?? 60_000;
|
|
24
22
|
const telemetry = deps.telemetry ?? getTelemetryClient();
|
|
25
|
-
this.metrics = new
|
|
23
|
+
this.metrics = new ProverNodePublisherMetrics(telemetry, 'ProverNode');
|
|
26
24
|
this.rollupContract = deps.rollupContract;
|
|
27
25
|
this.l1TxUtils = deps.l1TxUtils;
|
|
28
26
|
}
|
|
27
|
+
getRollupContract() {
|
|
28
|
+
return this.rollupContract;
|
|
29
|
+
}
|
|
29
30
|
/**
|
|
30
31
|
* Calling `interrupt` will cause any in progress call to `publishRollup` to return `false` asap.
|
|
31
32
|
* Be warned, the call may return false even if the tx subsequently gets successfully mined.
|
|
@@ -33,13 +34,14 @@ export class ProverNodePublisher {
|
|
|
33
34
|
* A call to `restart` is required before you can continue publishing.
|
|
34
35
|
*/ interrupt() {
|
|
35
36
|
this.interrupted = true;
|
|
36
|
-
this.
|
|
37
|
+
this.l1TxUtils.interrupt();
|
|
37
38
|
}
|
|
38
39
|
/** Restarts the publisher after calling `interrupt`. */ restart() {
|
|
39
40
|
this.interrupted = false;
|
|
41
|
+
this.l1TxUtils.restart();
|
|
40
42
|
}
|
|
41
43
|
getSenderAddress() {
|
|
42
|
-
return
|
|
44
|
+
return this.l1TxUtils.getSenderAddress();
|
|
43
45
|
}
|
|
44
46
|
async submitEpochProof(args) {
|
|
45
47
|
const { epochNumber, fromBlock, toBlock } = args;
|
|
@@ -57,12 +59,12 @@ export class ProverNodePublisher {
|
|
|
57
59
|
return false;
|
|
58
60
|
}
|
|
59
61
|
try {
|
|
60
|
-
this.metrics.recordSenderBalance(await this.l1TxUtils.getSenderBalance(), this.l1TxUtils.getSenderAddress());
|
|
62
|
+
this.metrics.recordSenderBalance(await this.l1TxUtils.getSenderBalance(), this.l1TxUtils.getSenderAddress().toString());
|
|
61
63
|
} catch (err) {
|
|
62
64
|
this.log.warn(`Failed to record the ETH balance of the prover node: ${err}`);
|
|
63
65
|
}
|
|
64
66
|
// Tx was mined successfully
|
|
65
|
-
if (txReceipt.status) {
|
|
67
|
+
if (txReceipt.status === 'success') {
|
|
66
68
|
const tx = await this.l1TxUtils.getTransactionStats(txReceipt.transactionHash);
|
|
67
69
|
const stats = {
|
|
68
70
|
gasPrice: txReceipt.effectiveGasPrice,
|
|
@@ -83,45 +85,42 @@ export class ProverNodePublisher {
|
|
|
83
85
|
return true;
|
|
84
86
|
}
|
|
85
87
|
this.metrics.recordFailedTx();
|
|
86
|
-
this.log.error(`Rollup.submitEpochProof tx status failed
|
|
87
|
-
await this.sleepOrInterrupted();
|
|
88
|
+
this.log.error(`Rollup.submitEpochProof tx status failed ${txReceipt.transactionHash}`, undefined, ctx);
|
|
88
89
|
}
|
|
89
|
-
this.log.verbose('L2 block data syncing interrupted
|
|
90
|
+
this.log.verbose('L2 block data syncing interrupted', ctx);
|
|
90
91
|
return false;
|
|
91
92
|
}
|
|
92
93
|
async validateEpochProofSubmission(args) {
|
|
93
|
-
const { fromBlock, toBlock, publicInputs,
|
|
94
|
+
const { fromBlock, toBlock, publicInputs, batchedBlobInputs } = args;
|
|
94
95
|
// Check that the block numbers match the expected epoch to be proven
|
|
95
|
-
const {
|
|
96
|
-
if
|
|
96
|
+
const { pending, proven } = await this.rollupContract.getTips();
|
|
97
|
+
// Don't publish if proven is beyond our toBlock, pointless to do so
|
|
98
|
+
if (proven > BigInt(toBlock)) {
|
|
97
99
|
throw new Error(`Cannot submit epoch proof for ${fromBlock}-${toBlock} as proven block is ${proven}`);
|
|
98
100
|
}
|
|
101
|
+
// toBlock can't be greater than pending
|
|
99
102
|
if (toBlock > pending) {
|
|
100
103
|
throw new Error(`Cannot submit epoch proof for ${fromBlock}-${toBlock} as pending block is ${pending}`);
|
|
101
104
|
}
|
|
102
|
-
// Check the
|
|
103
|
-
const blockLog = await this.rollupContract.
|
|
104
|
-
if (publicInputs.
|
|
105
|
-
throw new Error(`Previous archive root mismatch: ${publicInputs.
|
|
106
|
-
}
|
|
107
|
-
// TODO: Remove zero check once we inject the proper zero blockhash
|
|
108
|
-
if (blockLog.blockHash !== Fr.ZERO.toString() && publicInputs.previousBlockHash.toString() !== blockLog.blockHash) {
|
|
109
|
-
throw new Error(`Previous block hash mismatch: ${publicInputs.previousBlockHash.toString()} !== ${blockLog.blockHash}`);
|
|
105
|
+
// Check the archive for the immediate block before the epoch
|
|
106
|
+
const blockLog = await this.rollupContract.getCheckpoint(BigInt(fromBlock - 1));
|
|
107
|
+
if (publicInputs.previousArchiveRoot.toString() !== blockLog.archive) {
|
|
108
|
+
throw new Error(`Previous archive root mismatch: ${publicInputs.previousArchiveRoot.toString()} !== ${blockLog.archive}`);
|
|
110
109
|
}
|
|
111
|
-
// Check the
|
|
112
|
-
const endBlockLog = await this.rollupContract.
|
|
113
|
-
if (publicInputs.
|
|
114
|
-
throw new Error(`End archive root mismatch: ${publicInputs.
|
|
110
|
+
// Check the archive for the last block in the epoch
|
|
111
|
+
const endBlockLog = await this.rollupContract.getCheckpoint(BigInt(toBlock));
|
|
112
|
+
if (publicInputs.endArchiveRoot.toString() !== endBlockLog.archive) {
|
|
113
|
+
throw new Error(`End archive root mismatch: ${publicInputs.endArchiveRoot.toString()} !== ${endBlockLog.archive}`);
|
|
115
114
|
}
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
// Check the batched blob inputs from the root rollup against the batched blob computed in ts
|
|
116
|
+
const finalBlobAccumulator = batchedBlobInputs.toFinalBlobAccumulator();
|
|
117
|
+
if (!publicInputs.blobPublicInputs.equals(finalBlobAccumulator)) {
|
|
118
|
+
throw new Error(`Batched blob mismatch: ${inspect(publicInputs.blobPublicInputs)} !== ${inspect(finalBlobAccumulator)}`);
|
|
118
119
|
}
|
|
119
120
|
// Compare the public inputs computed by the contract with the ones injected
|
|
120
|
-
const rollupPublicInputs = await this.rollupContract.getEpochProofPublicInputs(this.
|
|
121
|
-
const aggregationObject = proof.isEmpty() ? times(AGGREGATION_OBJECT_LENGTH, Fr.zero) : proof.extractAggregationObject();
|
|
121
|
+
const rollupPublicInputs = await this.rollupContract.getEpochProofPublicInputs(this.getEpochProofPublicInputsArgs(args));
|
|
122
122
|
const argsPublicInputs = [
|
|
123
|
-
...publicInputs.toFields()
|
|
124
|
-
...aggregationObject
|
|
123
|
+
...publicInputs.toFields()
|
|
125
124
|
];
|
|
126
125
|
if (!areArraysEqual(rollupPublicInputs.map(Fr.fromHexString), argsPublicInputs, (a, b)=>a.equals(b))) {
|
|
127
126
|
const fmt = (inputs)=>inputs.map((x)=>x.toString()).join(', ');
|
|
@@ -129,20 +128,14 @@ export class ProverNodePublisher {
|
|
|
129
128
|
}
|
|
130
129
|
}
|
|
131
130
|
async sendSubmitEpochProofTx(args) {
|
|
132
|
-
const proofHex = `0x${args.proof.withoutPublicInputs().toString('hex')}`;
|
|
133
|
-
const argsArray = this.getSubmitEpochProofArgs(args);
|
|
134
131
|
const txArgs = [
|
|
135
|
-
|
|
136
|
-
start: argsArray[0],
|
|
137
|
-
end: argsArray[1],
|
|
138
|
-
args: argsArray[2],
|
|
139
|
-
fees: argsArray[3],
|
|
140
|
-
blobPublicInputs: argsArray[4],
|
|
141
|
-
aggregationObject: argsArray[5],
|
|
142
|
-
proof: proofHex
|
|
143
|
-
}
|
|
132
|
+
this.getSubmitEpochProofArgs(args)
|
|
144
133
|
];
|
|
145
|
-
this.log.info(`
|
|
134
|
+
this.log.info(`Submitting epoch proof to L1 rollup contract`, {
|
|
135
|
+
proofSize: args.proof.withoutPublicInputs().length,
|
|
136
|
+
fromBlock: args.fromBlock,
|
|
137
|
+
toBlock: args.toBlock
|
|
138
|
+
});
|
|
146
139
|
const data = encodeFunctionData({
|
|
147
140
|
abi: RollupAbi,
|
|
148
141
|
functionName: 'submitEpochRootProof',
|
|
@@ -168,25 +161,32 @@ export class ProverNodePublisher {
|
|
|
168
161
|
return undefined;
|
|
169
162
|
}
|
|
170
163
|
}
|
|
171
|
-
|
|
164
|
+
getEpochProofPublicInputsArgs(args) {
|
|
165
|
+
// Returns arguments for EpochProofLib.sol -> getEpochProofPublicInputs()
|
|
172
166
|
return [
|
|
173
167
|
BigInt(args.fromBlock),
|
|
174
168
|
BigInt(args.toBlock),
|
|
175
169
|
{
|
|
176
|
-
previousArchive: args.publicInputs.
|
|
177
|
-
endArchive: args.publicInputs.
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
endTimestamp: args.publicInputs.endTimestamp.toBigInt(),
|
|
181
|
-
outHash: args.publicInputs.outHash.toString(),
|
|
182
|
-
proverId: EthAddress.fromField(args.publicInputs.proverId).toString()
|
|
183
|
-
},
|
|
170
|
+
previousArchive: args.publicInputs.previousArchiveRoot.toString(),
|
|
171
|
+
endArchive: args.publicInputs.endArchiveRoot.toString(),
|
|
172
|
+
proverId: EthAddress.fromField(args.publicInputs.constants.proverId).toString()
|
|
173
|
+
} /*_args*/ ,
|
|
184
174
|
makeTuple(AZTEC_MAX_EPOCH_DURATION * 2, (i)=>i % 2 === 0 ? args.publicInputs.fees[i / 2].recipient.toField().toString() : args.publicInputs.fees[(i - 1) / 2].value.toString()),
|
|
185
|
-
|
|
186
|
-
`0x${serializeToBuffer(args.proof.extractAggregationObject()).toString('hex')}`
|
|
175
|
+
getEthBlobEvaluationInputs(args.batchedBlobInputs)
|
|
187
176
|
];
|
|
188
177
|
}
|
|
189
|
-
|
|
190
|
-
|
|
178
|
+
getSubmitEpochProofArgs(args) {
|
|
179
|
+
// Returns arguments for EpochProofLib.sol -> submitEpochRootProof()
|
|
180
|
+
const proofHex = `0x${args.proof.withoutPublicInputs().toString('hex')}`;
|
|
181
|
+
const argsArray = this.getEpochProofPublicInputsArgs(args);
|
|
182
|
+
return {
|
|
183
|
+
start: argsArray[0],
|
|
184
|
+
end: argsArray[1],
|
|
185
|
+
args: argsArray[2],
|
|
186
|
+
fees: argsArray[3],
|
|
187
|
+
attestations: new CommitteeAttestationsAndSigners(args.attestations.map((a)=>CommitteeAttestation.fromViem(a))).getPackedAttestations(),
|
|
188
|
+
blobInputs: argsArray[4],
|
|
189
|
+
proof: proofHex
|
|
190
|
+
};
|
|
191
191
|
}
|
|
192
192
|
}
|