@aztec/prover-node 0.0.1-commit.993d52e → 0.0.1-commit.9a89641
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 +572 -0
- package/dest/actions/download-epoch-proving-job.js +1 -1
- package/dest/actions/rerun-epoch-proving-job.d.ts +14 -4
- package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -1
- package/dest/actions/rerun-epoch-proving-job.js +244 -24
- package/dest/actions/upload-epoch-proof-failure.d.ts +2 -2
- package/dest/actions/upload-epoch-proof-failure.d.ts.map +1 -1
- package/dest/bin/run-failed-epoch.js +1 -3
- package/dest/checkpoint-store.d.ts +95 -0
- package/dest/checkpoint-store.d.ts.map +1 -0
- package/dest/checkpoint-store.js +178 -0
- package/dest/config.d.ts +4 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +10 -3
- package/dest/factory.d.ts +4 -1
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +28 -12
- 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 +165 -0
- package/dest/job/checkpoint-prover.d.ts.map +1 -0
- package/dest/job/checkpoint-prover.js +405 -0
- package/dest/job/epoch-session.d.ts +160 -0
- package/dest/job/epoch-session.d.ts.map +1 -0
- package/dest/job/epoch-session.js +744 -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 +40 -3
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +101 -4
- 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 +11 -9
- 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 +25 -15
- package/dest/prover-node-publisher.d.ts.map +1 -1
- package/dest/prover-node-publisher.js +201 -62
- package/dest/prover-node.d.ts +134 -67
- package/dest/prover-node.d.ts.map +1 -1
- package/dest/prover-node.js +539 -218
- package/dest/prover-publisher-factory.d.ts +4 -2
- package/dest/prover-publisher-factory.d.ts.map +1 -1
- package/dest/prover-publisher-factory.js +4 -3
- package/dest/session-manager.d.ts +158 -0
- package/dest/session-manager.d.ts.map +1 -0
- package/dest/session-manager.js +492 -0
- package/dest/test/index.d.ts +7 -6
- package/dest/test/index.d.ts.map +1 -1
- package/package.json +24 -22
- package/src/actions/download-epoch-proving-job.ts +1 -1
- package/src/actions/rerun-epoch-proving-job.ts +190 -31
- package/src/actions/upload-epoch-proof-failure.ts +1 -1
- package/src/bin/run-failed-epoch.ts +1 -2
- package/src/checkpoint-store.ts +212 -0
- package/src/config.ts +14 -3
- package/src/factory.ts +26 -12
- package/src/index.ts +1 -0
- package/src/job/checkpoint-prover.ts +538 -0
- package/src/job/epoch-session.ts +462 -0
- package/src/job/top-tree-job.ts +227 -0
- package/src/metrics.ts +123 -10
- package/src/monitors/epoch-monitor.ts +5 -6
- package/src/proof-publishing-service.ts +427 -0
- package/src/prover-node-publisher.ts +236 -78
- package/src/prover-node.ts +622 -243
- package/src/prover-publisher-factory.ts +6 -3
- package/src/session-manager.ts +592 -0
- package/src/test/index.ts +6 -6
- package/dest/job/epoch-proving-job.d.ts +0 -63
- package/dest/job/epoch-proving-job.d.ts.map +0 -1
- package/dest/job/epoch-proving-job.js +0 -752
- package/src/job/epoch-proving-job.ts +0 -449
package/README.md
CHANGED
|
@@ -1 +1,573 @@
|
|
|
1
1
|
# Prover Node
|
|
2
|
+
|
|
3
|
+
The prover node turns sequenced checkpoints into epoch proofs that get submitted to the L1
|
|
4
|
+
rollup contract. It runs alongside an Aztec validator/full-node and consumes the
|
|
5
|
+
canonical chain view those nodes emit, proving epochs **optimistically** — sub-tree
|
|
6
|
+
work begins the moment a checkpoint lands on L1, not when the epoch closes.
|
|
7
|
+
|
|
8
|
+
This document describes the internal architecture: the state held by the prover-node,
|
|
9
|
+
the events that drive it, and the data flow from a fresh `chain-checkpointed` event
|
|
10
|
+
through to a `submitEpochRootProof` on L1.
|
|
11
|
+
|
|
12
|
+
## Contents
|
|
13
|
+
|
|
14
|
+
1. [Architecture](#architecture)
|
|
15
|
+
2. [CheckpointProver lifecycle](#checkpointprover-lifecycle)
|
|
16
|
+
3. [EpochSession lifecycle](#epochsession-lifecycle)
|
|
17
|
+
4. [Event flow](#event-flow)
|
|
18
|
+
5. [Walkthroughs](#walkthroughs)
|
|
19
|
+
6. [Design rationale](#design-rationale)
|
|
20
|
+
7. [Configuration](#configuration)
|
|
21
|
+
8. [Failure handling and observability](#failure-handling-and-observability)
|
|
22
|
+
|
|
23
|
+
## Architecture
|
|
24
|
+
|
|
25
|
+
```mermaid
|
|
26
|
+
flowchart TB
|
|
27
|
+
L2BlockStream -->|chain-checkpointed| ProverNode
|
|
28
|
+
L2BlockStream -->|chain-pruned| ProverNode
|
|
29
|
+
L2BlockStream -->|chain-proven| ProverNode
|
|
30
|
+
L2BlockStream -->|any event| ProverNode
|
|
31
|
+
ProverNode --> CheckpointStore
|
|
32
|
+
ProverNode --> ChonkCache
|
|
33
|
+
ProverNode --> SessionManager
|
|
34
|
+
ProverNode --> ProofPublishingService
|
|
35
|
+
SessionManager --> EpochTicker[(periodic tick)]
|
|
36
|
+
SessionManager --> FullSessions[(fullSessions)]
|
|
37
|
+
SessionManager --> PartialSessions[(partialSessions)]
|
|
38
|
+
FullSessions -.referenced checkpoints.-> CheckpointStore
|
|
39
|
+
PartialSessions -.referenced checkpoints.-> CheckpointStore
|
|
40
|
+
FullSessions --> TopTreeJob
|
|
41
|
+
PartialSessions --> TopTreeJob
|
|
42
|
+
TopTreeJob -->|PublishCandidate| ProofPublishingService
|
|
43
|
+
ProofPublishingService -->|fresh per publish| ProverNodePublisher
|
|
44
|
+
ProverNodePublisher --> L1[L1 Rollup]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The prover-node splits responsibility between four classes:
|
|
48
|
+
|
|
49
|
+
- **`ProverNode`** — owns the long-lived collections, wires the L2BlockStream, and
|
|
50
|
+
translates each chain event into a single method call on the `SessionManager` or
|
|
51
|
+
`ProofPublishingService`. It also performs side effects that don't belong on an
|
|
52
|
+
`EpochSession`: registering new checkpoints with the store per event, and sweeping expired
|
|
53
|
+
epochs out of the cache and the store on a periodic ticker (see below). It uploads post-mortem
|
|
54
|
+
snapshots on failure at two levels: per checkpoint when a `CheckpointProver` fails (its `onFailed`
|
|
55
|
+
callback), and per session when a full session fails on its own account (`onSessionFailed` /
|
|
56
|
+
`EpochSession.hasFailed()`).
|
|
57
|
+
- **`CheckpointStore`** — a registry of `CheckpointProver` instances keyed by
|
|
58
|
+
`(checkpointNumber, slot, archiveRoot)`. Each `CheckpointProver` runs its own sub-tree pipeline
|
|
59
|
+
(tx gather → block processing → block-rollup proofs), starting eagerly the moment a
|
|
60
|
+
checkpoint is registered. The store holds the canonical checkpoint content that
|
|
61
|
+
`EpochSession`s query when assembling their subsets; a prune cancels and removes the affected
|
|
62
|
+
provers, so every prover in the store is canonical.
|
|
63
|
+
- **`SessionManager`** — owns every live `EpochSession`, the serial reconcile queue,
|
|
64
|
+
the periodic tick, and all `EpochSession` lifecycle decisions. `ProverNode` calls into it
|
|
65
|
+
via `onCheckpointAdded`, `onPrune`, and `startProof`. Every trigger it receives is
|
|
66
|
+
translated into a `reconcile(trigger)` call, a single idempotent function that walks
|
|
67
|
+
all `EpochSession`s, cancels any whose canonical content has shifted, re-creates them with
|
|
68
|
+
the new content, and opens fresh full `EpochSession`s for any epoch that has become provable.
|
|
69
|
+
It never builds a session over a **failed** `CheckpointProver` (one whose block proofs rejected —
|
|
70
|
+
a sub-tree fault or a prune-induced fork fault): a session over it could only fail, so the epoch is
|
|
71
|
+
cheaply skipped until a prune/re-add installs a fresh prover in its place, at which point a rebuilt
|
|
72
|
+
session reuses every already-completed sub-proof from the content-addressed broker. Reconcile runs on
|
|
73
|
+
a `SerialQueue` (from `@aztec/foundation/queue`), so two concurrent triggers can never interleave on an
|
|
74
|
+
`await` and race on the `EpochSession` maps.
|
|
75
|
+
- **`ProofPublishingService`** — central owner of L1 proof submission. `EpochSession`s hand
|
|
76
|
+
their top-tree proofs to the service as `PublishCandidate`s; the service serialises
|
|
77
|
+
one publish at a time against a freshly-created `ProverNodePublisher`, gates eligibility
|
|
78
|
+
on the proven block tip, picks the longest candidate per epoch as the winner
|
|
79
|
+
(others resolve `'superseded'`), and enforces a per-candidate `deadline`. It runs its
|
|
80
|
+
own `drain()` on a separate `SerialQueue`: submits, withdrawals, chain-proven advances,
|
|
81
|
+
and per-candidate deadline expiries all enqueue a drain pass, so the eligibility
|
|
82
|
+
re-check and the L1 publish never interleave with each other.
|
|
83
|
+
|
|
84
|
+
## CheckpointProver lifecycle
|
|
85
|
+
|
|
86
|
+
A `CheckpointProver` is content-addressed by `(checkpoint.number, slot, archiveRoot)`,
|
|
87
|
+
where `archiveRoot` is the checkpoint's own archive root (its post-state). Keying on the
|
|
88
|
+
post-state makes the identity precise: two checkpoints are "the same" iff they produce
|
|
89
|
+
the same archive — so a reorg branch, or a replacement built on the same predecessor but
|
|
90
|
+
with different content, yields a different archive root and a distinct `CheckpointProver`. A prune
|
|
91
|
+
cancels and removes a prover — its sub-tree work forks world-state per block and cannot survive the
|
|
92
|
+
prune — so a re-add, even of identical content, constructs a fresh `CheckpointProver` (block-rollup
|
|
93
|
+
jobs already completed in the proving broker are still reused, as they are content-addressed).
|
|
94
|
+
|
|
95
|
+
```mermaid
|
|
96
|
+
stateDiagram-v2
|
|
97
|
+
[*] --> Created
|
|
98
|
+
Created --> Proving: gather + execute
|
|
99
|
+
Proving --> Proven: sub-tree resolves blockProofs
|
|
100
|
+
Proving --> Cancelled: cancel() (prune / shutdown / epoch-session error)
|
|
101
|
+
Proven --> Cancelled: cancel() (prune / reap)
|
|
102
|
+
Proven --> Reaped: reapExpired(epoch)
|
|
103
|
+
Cancelled --> [*]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
A prune **cancels and removes** the affected `CheckpointProver`s from the store: a prover's
|
|
107
|
+
sub-tree work forks world-state per block, and an L1 prune of a base block faults those reads,
|
|
108
|
+
so there is nothing to preserve across a reorg. A re-add — even of identical content — therefore
|
|
109
|
+
constructs a fresh `CheckpointProver`. `EpochSession`s ask the store for the checkpoints in a slot
|
|
110
|
+
range; every prover in the store is canonical.
|
|
111
|
+
|
|
112
|
+
### Removal rules
|
|
113
|
+
|
|
114
|
+
- **Pruned**: `CheckpointStore.cancelAndRemoveAboveBlock(target)` cancels and removes every
|
|
115
|
+
`CheckpointProver` whose last block is above the prune target, the moment a `chain-pruned`
|
|
116
|
+
event arrives.
|
|
117
|
+
- **Expired**: `CheckpointStore.reapExpired(expiredEpoch)` drops any `CheckpointProver` whose
|
|
118
|
+
epoch is at or below the supplied expired epoch. Once an epoch's proof-submission window has
|
|
119
|
+
closed, its proof can no longer be accepted on L1, so the `CheckpointProver` is no longer needed.
|
|
120
|
+
- **Shutdown**: `CheckpointStore.stop()` cancels every remaining prover and awaits its teardown
|
|
121
|
+
(including teardowns still in flight for provers already removed by a prune or reap).
|
|
122
|
+
|
|
123
|
+
### Eager tx gathering
|
|
124
|
+
|
|
125
|
+
A `CheckpointProver` starts its tx gather + sub-tree pipeline **in its constructor**.
|
|
126
|
+
The tx provider is injected as a dependency,
|
|
127
|
+
and the `CheckpointProver` pulls its own txs via `txProvider.getTxsForBlock(block)` for each
|
|
128
|
+
block in its checkpoint.
|
|
129
|
+
|
|
130
|
+
This means the moment a checkpoint lands on L1, sub-tree proving is already in flight.
|
|
131
|
+
By the time the epoch closes (and the `EpochSession` is constructed), most or all of the
|
|
132
|
+
block-rollup proofs are already done — the `EpochSession` only has to drive the top tree.
|
|
133
|
+
|
|
134
|
+
## EpochSession lifecycle
|
|
135
|
+
|
|
136
|
+
An `EpochSession` is identified by a slot-based **spec**:
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
interface SessionSpec {
|
|
140
|
+
kind: 'full' | 'partial';
|
|
141
|
+
epochNumber: EpochNumber;
|
|
142
|
+
fromSlot: SlotNumber;
|
|
143
|
+
toSlot: SlotNumber;
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The spec declares *what to prove* (a slot range). The concrete checkpoint set the
|
|
148
|
+
`EpochSession` holds is the *implementation* of the spec — frozen at construction time,
|
|
149
|
+
derived from the canonical content for that slot range.
|
|
150
|
+
|
|
151
|
+
```mermaid
|
|
152
|
+
stateDiagram-v2
|
|
153
|
+
[*] --> initialized
|
|
154
|
+
initialized --> awaiting_checkpoints: start()
|
|
155
|
+
awaiting_checkpoints --> awaiting_root: sub-tree proofs ready, top-tree prove begins
|
|
156
|
+
awaiting_root --> publishing_proof: epoch proof ready, submit to L1
|
|
157
|
+
publishing_proof --> completed: publish succeeds
|
|
158
|
+
publishing_proof --> superseded: longer same-epoch candidate wins
|
|
159
|
+
publishing_proof --> failed: L1 submission errored (provers healthy)
|
|
160
|
+
awaiting_checkpoints --> stopped: a checkpoint prover failed
|
|
161
|
+
awaiting_root --> failed: top-tree prove errored (provers healthy)
|
|
162
|
+
initialized --> timed_out: deadline
|
|
163
|
+
awaiting_checkpoints --> timed_out: deadline (EpochSession or candidate)
|
|
164
|
+
awaiting_root --> timed_out: deadline (EpochSession or candidate)
|
|
165
|
+
awaiting_checkpoints --> cancelled: cancel()
|
|
166
|
+
awaiting_root --> cancelled: cancel()
|
|
167
|
+
completed --> [*]
|
|
168
|
+
superseded --> [*]
|
|
169
|
+
cancelled --> [*]
|
|
170
|
+
timed_out --> [*]
|
|
171
|
+
stopped --> [*]
|
|
172
|
+
failed --> [*]
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
A fault settles the `EpochSession` in one of two terminal states:
|
|
176
|
+
|
|
177
|
+
- **`stopped`** — a `CheckpointProver` under the session failed (its block proofs rejected). This may
|
|
178
|
+
be a prune-induced fork fault, so it is *not* a verdict on the epoch and is *not* uploaded. The
|
|
179
|
+
reconciler drops the session and, guarded by `isFailed()`, does not rebuild over the failed prover;
|
|
180
|
+
a prune/re-add installs a fresh prover and the epoch is retried.
|
|
181
|
+
- **`failed`** — the session's own work (top-tree prove or L1 submit) failed while *every* checkpoint
|
|
182
|
+
prover succeeded. Because healthy provers rule out a prune, this is a genuine, race-free failure
|
|
183
|
+
(`EpochSession.hasFailed()`). The reconciler retains such a full session (so the tick does not
|
|
184
|
+
re-prove a deterministically-failing epoch) and uploads a post-mortem exactly once. No prune/fault
|
|
185
|
+
classification is needed — the two states carry it.
|
|
186
|
+
|
|
187
|
+
The non-terminal states track the window between `start()` and the L1 submission:
|
|
188
|
+
|
|
189
|
+
- `awaiting-checkpoints` — a `TopTreeJob` is awaiting each checkpoint's sub-tree result
|
|
190
|
+
(`CheckpointProver.whenBlockProofsReady`) before the top-tree prove can begin.
|
|
191
|
+
- `awaiting-root` — the sub-tree proofs are ready and the top-tree (root) prove is running,
|
|
192
|
+
assembling the epoch proof (set via the `TopTreeJob` `beforeProve` hook).
|
|
193
|
+
- `publishing-proof` — the epoch proof is being submitted to L1 via `ProofPublishingService`.
|
|
194
|
+
|
|
195
|
+
`cancel()` and the deadline can fire during any of these pre-submit phases; a terminal state
|
|
196
|
+
set that way wins over the phase transitions (which are guarded by `isTerminal()`).
|
|
197
|
+
|
|
198
|
+
The `EpochSession` does three sequential things: (1) run a `TopTreeJob` over the frozen
|
|
199
|
+
checkpoint subset, (2) hand the resulting proof to `ProofPublishingService` as a
|
|
200
|
+
`PublishCandidate`, (3) translate the service's outcome into a terminal state.
|
|
201
|
+
Predecessor gating, same-epoch dedup, deadline enforcement, and the L1 tx are all
|
|
202
|
+
the `ProofPublishingService`'s concern; the `EpochSession` is just the producer of one
|
|
203
|
+
candidate and the observer of its outcome.
|
|
204
|
+
|
|
205
|
+
Outcome → state mapping:
|
|
206
|
+
|
|
207
|
+
| `PublishOutcome` | `EpochSession` state |
|
|
208
|
+
|---|---|
|
|
209
|
+
| `published` | `completed` |
|
|
210
|
+
| `superseded` | `superseded` |
|
|
211
|
+
| `failed` | `failed` |
|
|
212
|
+
| `expired` | `timed-out` |
|
|
213
|
+
| `withdrawn` | `cancelled` |
|
|
214
|
+
|
|
215
|
+
There is a single deadline — the proof submission window — that applies across both
|
|
216
|
+
proving and publishing. Before submission, the `EpochSession` arms its own timer against
|
|
217
|
+
it: if proving doesn't finish in time, the `EpochSession` enters `timed-out` via
|
|
218
|
+
`cancel('deadline')`. After submission, the publishing service enforces the same deadline
|
|
219
|
+
on the candidate. It's the same instant throughout; only which component enforces it
|
|
220
|
+
changes once the candidate has been handed off.
|
|
221
|
+
|
|
222
|
+
### Full vs partial
|
|
223
|
+
|
|
224
|
+
Every `EpochSession` — full or partial — has `fromSlot = firstSlotOfEpoch(N)`. The L1 rollup
|
|
225
|
+
contract requires every proof to extend from the previous epoch's proven tip, so
|
|
226
|
+
there's no value in starting later than the epoch boundary. The two kinds differ
|
|
227
|
+
only in `toSlot` and in how the publishing service treats their candidate:
|
|
228
|
+
|
|
229
|
+
- **Full** `EpochSession`s are opened by reconcile when the epoch is complete on L1 *and*
|
|
230
|
+
every archiver-reported checkpoint is present in the store. Their `toSlot` is
|
|
231
|
+
the epoch's last slot. The publishing service never auto-supersedes a `full`
|
|
232
|
+
candidate on proven-tip subsumption — the L1 contract records a `(epoch, prover-id)`
|
|
233
|
+
submission for every full-epoch proof, so even after another prover-node has
|
|
234
|
+
landed first, this prover's submission is still worthwhile.
|
|
235
|
+
- **Partial** `EpochSession`s are constructed by an explicit `startProof(epochNumber)` API
|
|
236
|
+
call. Their `toSlot` is the last canonical slot present at request time, which may
|
|
237
|
+
be earlier than the epoch's last slot. Partial candidates are an early-finish
|
|
238
|
+
optimisation: if the proven chain has caught up to or past `endBlock` by the time
|
|
239
|
+
the publishing service picks the winner, the partial resolves `'superseded'`
|
|
240
|
+
without spending L1 gas. Dedup: if the partial's spec collapses to the full's spec
|
|
241
|
+
(canonical content already covers the whole epoch), `startProof` awaits the
|
|
242
|
+
existing full `EpochSession` instead of opening a duplicate.
|
|
243
|
+
|
|
244
|
+
## ProofPublishingService
|
|
245
|
+
|
|
246
|
+
The service is a single per-prover-node owner of L1 submission. `EpochSession`s call
|
|
247
|
+
`submit(candidate)` and await one of five outcomes:
|
|
248
|
+
|
|
249
|
+
| Outcome | Meaning |
|
|
250
|
+
|---|---|
|
|
251
|
+
| `published` | L1 accepted the proof. |
|
|
252
|
+
| `superseded` | A longer same-epoch candidate won, or (for `partial` candidates) the proven tip has caught up to `endBlock`. |
|
|
253
|
+
| `failed` | L1 submission errored. |
|
|
254
|
+
| `expired` | The candidate's `deadline` elapsed before publishing started. |
|
|
255
|
+
| `withdrawn` | An `EpochSession` called `withdraw(uuid)` on a still-queued candidate. |
|
|
256
|
+
|
|
257
|
+
Key invariants:
|
|
258
|
+
|
|
259
|
+
- **One publish at a time** via a `SerialQueue` drain.
|
|
260
|
+
- **Fresh publisher per publish.** Each drain call constructs a new `ProverNodePublisher`
|
|
261
|
+
via the factory. There is no shared in-memory state across publishes.
|
|
262
|
+
- **Once an L1 publish starts, it runs to completion.** `withdraw` is a queue-only
|
|
263
|
+
operation: it removes a candidate that hasn't started publishing. An in-flight
|
|
264
|
+
candidate is left alone and its outcome reports whatever L1 returned. The
|
|
265
|
+
originating `EpochSession` has already moved to a terminal state via `cancel()` and
|
|
266
|
+
ignores the late outcome.
|
|
267
|
+
- **Drain reads the proven block number afresh** from `l2BlockSource` inside the
|
|
268
|
+
serial queue, so the eligibility
|
|
269
|
+
check is consistent with the publish that follows it on the same drain pass.
|
|
270
|
+
- **Per-candidate `deadline`** arms a `setTimeout` (against the injected `DateProvider`).
|
|
271
|
+
When it fires, a still-queued candidate resolves `'expired'`. An in-flight publish
|
|
272
|
+
is left alone (its outcome reports the natural L1 result).
|
|
273
|
+
- **Transient `publisherFactory.create()` failures are retried.** Instead of resolving
|
|
274
|
+
the candidate as `'failed'`, the service schedules another drain after a 1s backoff
|
|
275
|
+
and leaves the candidate in the queue. The candidate's `deadline` caps the total
|
|
276
|
+
retry window — persistent acquire failure resolves as `'expired'`.
|
|
277
|
+
|
|
278
|
+
### Eligibility
|
|
279
|
+
|
|
280
|
+
A candidate is eligible to publish when its **predecessor block is proven**
|
|
281
|
+
(`startBlock - 1 <= proven`). Among eligible candidates for the same epoch, the
|
|
282
|
+
one with the **highest `endBlock`** wins; the others resolve `'superseded'`.
|
|
283
|
+
Partial candidates whose `endBlock <= proven` are dropped before this check
|
|
284
|
+
(early-finish optimisation no longer helps); full candidates are never
|
|
285
|
+
auto-superseded on the proven tip.
|
|
286
|
+
|
|
287
|
+
## Event flow
|
|
288
|
+
|
|
289
|
+
### chain-checkpointed
|
|
290
|
+
|
|
291
|
+
```mermaid
|
|
292
|
+
sequenceDiagram
|
|
293
|
+
participant L2 as L2BlockStream
|
|
294
|
+
participant PN as ProverNode
|
|
295
|
+
participant CS as CheckpointStore
|
|
296
|
+
participant CP as CheckpointProver
|
|
297
|
+
participant SM as SessionManager
|
|
298
|
+
|
|
299
|
+
L2->>PN: chain-checkpointed{checkpoint}
|
|
300
|
+
PN->>PN: collectRegisterData (prev-header, l1ToL2 messages, sibling path)
|
|
301
|
+
PN->>CS: addOrUpdate(checkpoint, data)
|
|
302
|
+
alt content key new
|
|
303
|
+
CS->>CP: new CheckpointProver(args)
|
|
304
|
+
CP->>CP: eager gather + sub-tree start
|
|
305
|
+
else content key already live
|
|
306
|
+
CS->>CP: reuse existing prover
|
|
307
|
+
end
|
|
308
|
+
PN->>SM: onCheckpointAdded(epoch)
|
|
309
|
+
SM->>SM: queue reconcile({kind:'checkpoint', epoch})
|
|
310
|
+
SM->>SM: walk EpochSessions, recreate invalid
|
|
311
|
+
SM->>SM: open full EpochSession if epoch ready
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### chain-pruned
|
|
315
|
+
|
|
316
|
+
```mermaid
|
|
317
|
+
sequenceDiagram
|
|
318
|
+
participant L2 as L2BlockStream
|
|
319
|
+
participant PN as ProverNode
|
|
320
|
+
participant CS as CheckpointStore
|
|
321
|
+
participant SM as SessionManager
|
|
322
|
+
|
|
323
|
+
L2->>PN: chain-pruned{block}
|
|
324
|
+
PN->>CS: cancelAndRemoveAboveBlock(prunedToBlock)
|
|
325
|
+
CS->>CS: cancel + remove every CheckpointProver whose last block is above the target
|
|
326
|
+
PN->>SM: onPrune(affectedEpochs)
|
|
327
|
+
SM->>SM: queue reconcile({kind:'prune', affectedEpochs})
|
|
328
|
+
SM->>SM: walk EpochSessions, cancel-and-recreate those with shifted content
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### chain-proven
|
|
332
|
+
|
|
333
|
+
```mermaid
|
|
334
|
+
sequenceDiagram
|
|
335
|
+
participant L2 as L2BlockStream
|
|
336
|
+
participant PN as ProverNode
|
|
337
|
+
participant PS as ProofPublishingService
|
|
338
|
+
|
|
339
|
+
L2->>PN: chain-proven{block}
|
|
340
|
+
PN->>PS: onChainProven(blockNumber)
|
|
341
|
+
PS->>PS: scheduleDrain (wake-up only, no state cached)
|
|
342
|
+
PS->>PS: drain reads proven afresh, re-checks eligibility
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Periodic expiry sweep
|
|
346
|
+
|
|
347
|
+
```mermaid
|
|
348
|
+
sequenceDiagram
|
|
349
|
+
participant T as expiryTicker (RunningPromise)
|
|
350
|
+
participant PN as ProverNode
|
|
351
|
+
participant L2 as L2BlockStream
|
|
352
|
+
participant CC as ChonkCache
|
|
353
|
+
participant CS as CheckpointStore
|
|
354
|
+
|
|
355
|
+
T->>PN: checkEpochExpiry() (every poll interval)
|
|
356
|
+
PN->>L2: getSyncedL2SlotNumber()
|
|
357
|
+
PN->>PN: latestEpoch = getEpochAtSlot(latestSlot)
|
|
358
|
+
PN->>PN: newlyExpiredUpTo = latestEpoch - (proofSubmissionEpochs + 1)
|
|
359
|
+
loop for each newly-expired epoch
|
|
360
|
+
PN->>L2: getBlocks({epoch, onlyCheckpointed})
|
|
361
|
+
PN->>CC: releaseForBlocks(blocks)
|
|
362
|
+
PN->>CS: reapExpired(epoch)
|
|
363
|
+
end
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
The sweep is driven solely by the `expiryTicker` (a `RunningPromise` armed in `start()`), which
|
|
367
|
+
calls `checkEpochExpiry()` every poll interval whether or not block-stream events arrive. It is
|
|
368
|
+
deliberately **not** run from `handleBlockStreamEvent` — expiry is a background sweep keyed off the
|
|
369
|
+
archiver's synced slot, not part of event processing — and because a `RunningPromise` never overlaps
|
|
370
|
+
its own runs, no two sweeps can race. An epoch `E` is expired once the chain reaches the start of epoch
|
|
371
|
+
`E + proofSubmissionEpochs + 1` — the deadline beyond which an L1 submission for `E` would be rejected.
|
|
372
|
+
Expiry only releases the chonk cache and reaps `E`'s provers.
|
|
373
|
+
A monotonic high-water mark (`lastExpiredEpoch`) makes the sweep cheap: it only
|
|
374
|
+
advances after a sweep completes and never revisits an epoch. It is seeded at `start()` from the last
|
|
375
|
+
fully-proven epoch (`resolveLastFullyProvenEpoch`), so on a restart we never re-sweep epochs that already
|
|
376
|
+
reached L1.
|
|
377
|
+
|
|
378
|
+
### Periodic tick
|
|
379
|
+
|
|
380
|
+
`SessionManager.start()` arms a `RunningPromise` that fires
|
|
381
|
+
`reconcile({ kind: 'tick' })` every `tickIntervalMs`. The tick picks up epochs that
|
|
382
|
+
became complete by time alone (no fresh checkpoint event) and advances to the
|
|
383
|
+
next unproven epoch once the previous one lands on L1. The tick is not gated by any per-epoch
|
|
384
|
+
bookkeeping; two things keep it from re-proving a doomed epoch:
|
|
385
|
+
|
|
386
|
+
- `openFullSessionIfReady` refuses to build a session when any `CheckpointProver` in the set has
|
|
387
|
+
**failed** (`isFailed()`). So a prover fault (possibly a prune) skips the epoch cheaply each tick —
|
|
388
|
+
no session, no proving — until a prune/re-add installs a fresh prover.
|
|
389
|
+
- A session that failed on its own account (`hasFailed()` — top-tree/submit failed with every prover
|
|
390
|
+
healthy) is **retained** by `recreateInvalidSessions` rather than deleted, so the tick's
|
|
391
|
+
`fullSessions.has(epoch)` check skips it. It is replaced only when its canonical content changes (a
|
|
392
|
+
re-add), so a deterministically-failing epoch is not re-proved every tick.
|
|
393
|
+
|
|
394
|
+
Transient blockers (max-pending-jobs reached, archiver still indexing) create no session and no failed
|
|
395
|
+
prover, so the next tick simply tries again.
|
|
396
|
+
|
|
397
|
+
## Walkthroughs
|
|
398
|
+
|
|
399
|
+
### checkpoint-added → prune → checkpoint-added (reorg resilience)
|
|
400
|
+
|
|
401
|
+
State: epoch N has checkpoints c1..c4 (slots s1..s4). `fullSessions[N]` holds `EpochSession`
|
|
402
|
+
**A** with spec `{kind:'full', N, fromSlot:s1, toSlot:s4}`, referencing `[c1, c2, c3, c4]`.
|
|
403
|
+
|
|
404
|
+
1. **chain-pruned arrives, target c3.** The store cancels and removes c4 (its last block is
|
|
405
|
+
above the prune target). Reconcile fires: `EpochSession` A's frozen set `[c1, c2, c3, c4]`
|
|
406
|
+
includes the now-cancelled c4, so it no longer matches the store's `[c1, c2, c3]` →
|
|
407
|
+
`A.cancel('canonical content changed')`. Epoch N still complete on L1 → reconcile constructs
|
|
408
|
+
`EpochSession` **B** with the same spec `{full, N, s1, s4}` but checkpoints `[c1, c2, c3]`.
|
|
409
|
+
|
|
410
|
+
2. **`EpochSession` B starts top-tree proving over [c1, c2, c3].**
|
|
411
|
+
|
|
412
|
+
3. **chain-checkpointed arrives, target c4_re (same content key as old c4).** The old c4
|
|
413
|
+
prover was removed on the prune, so the store constructs a **fresh** `CheckpointProver` for
|
|
414
|
+
c4_re and starts its sub-tree work from scratch. (Its block-rollup jobs are content-addressed
|
|
415
|
+
in the proving broker, so any the old c4 already completed are reused rather than re-proved.)
|
|
416
|
+
|
|
417
|
+
4. **Reconcile fires.** `EpochSession` B's content for `(s1, s4)` is now `[c1, c2, c3, c4_re]`,
|
|
418
|
+
doesn't match its frozen `[c1, c2, c3]` → `B.cancel(...)`. Construct `EpochSession` **C** with
|
|
419
|
+
the same spec but checkpoints `[c1, c2, c3, c4_re]`.
|
|
420
|
+
|
|
421
|
+
5. **`EpochSession` C reuses the long-lived c1..c3 `CheckpointProver` instances and the fresh
|
|
422
|
+
c4_re.** Only c4_re's witnesses are regenerated; the top-tree is recomputed. The chonk cache
|
|
423
|
+
survived the reorg because no epoch in this range has expired yet.
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
### Partial request dedups against a running full `EpochSession`
|
|
427
|
+
|
|
428
|
+
The operator calls `startProof(N)` while the full `EpochSession` for epoch N is running with
|
|
429
|
+
c1..c4. Current canonical slot range is `(s1, s4)`, so the partial's computed spec is
|
|
430
|
+
`{partial, N, s1, s4}` — its `fromSlot`/`toSlot` exactly match the running full `EpochSession`'s. `startProof`
|
|
431
|
+
detects this and awaits the existing full instead of opening a duplicate: no partial
|
|
432
|
+
`EpochSession` is created and no second `TopTreeJob` is built. The caller simply blocks on the
|
|
433
|
+
full session's result and the epoch is proven once.
|
|
434
|
+
|
|
435
|
+
### True partial proof
|
|
436
|
+
|
|
437
|
+
The operator calls `startProof(N)` when only c1, c2 are canonical (epoch incomplete).
|
|
438
|
+
`fromSlot` is the epoch's first slot; `toSlot` is `s2` (the last canonical slot).
|
|
439
|
+
Partial `EpochSession` created with spec `{partial, N, firstSlotOfEpoch(N), s2}` and
|
|
440
|
+
checkpoints `[c1, c2]`.
|
|
441
|
+
|
|
442
|
+
When c3 later arrives in slot s3, the partial is **not** invalidated — c3's slot is
|
|
443
|
+
outside its range. If c2 is then pruned, the partial **is** invalidated (canonical
|
|
444
|
+
content for the same slot range is now just `[c1]`) and recreated with the same
|
|
445
|
+
spec but checkpoints `[c1]`. If c2 re-adds, the partial is invalidated again and
|
|
446
|
+
recreated with `[c1, c2]`.
|
|
447
|
+
|
|
448
|
+
## Design rationale
|
|
449
|
+
|
|
450
|
+
### Why slot-based specs (not checkpoint-based)?
|
|
451
|
+
|
|
452
|
+
A spec like "prove checkpoints 7..10" is invalidated by any reorg that renumbers
|
|
453
|
+
those checkpoints. A spec like "prove slots 350..399" survives renumbering — the
|
|
454
|
+
slot range is determined by epoch math and L1 constants, not by which checkpoints
|
|
455
|
+
happen to be canonical at the moment. Reconciliation preserves the slot range
|
|
456
|
+
across cancel-and-recreate cycles.
|
|
457
|
+
|
|
458
|
+
### Why does every `EpochSession` start at the epoch's first slot?
|
|
459
|
+
|
|
460
|
+
The L1 rollup contract validates that every submitted proof extends from the previous
|
|
461
|
+
proven tip — the `fromCheckpoint` of any submission must be the checkpoint immediately
|
|
462
|
+
after the current L1 proven head. Starting a partial `EpochSession` at a later slot would
|
|
463
|
+
mean the partial's `fromCheckpoint` lies past the proven tip, which the contract
|
|
464
|
+
rejects. Fixing `fromSlot` to `firstSlotOfEpoch(N)` for both kinds means partials and
|
|
465
|
+
fulls always share the same starting point; they differ only in `toSlot` and in the
|
|
466
|
+
submission decision.
|
|
467
|
+
|
|
468
|
+
### Why does a publishing service own L1 submission instead of the `EpochSession`?
|
|
469
|
+
|
|
470
|
+
Concentrating L1 submission gives us three properties for free that were awkward
|
|
471
|
+
or impossible when each `EpochSession` called the publisher directly:
|
|
472
|
+
|
|
473
|
+
1. **Atomic same-epoch dedup.** Multiple candidates for the same epoch (full +
|
|
474
|
+
partial, or partial-then-full as canonical content extends) can be in flight
|
|
475
|
+
at once; the service picks the winner under the serial drain so only one L1
|
|
476
|
+
tx is ever sent for the longer candidate.
|
|
477
|
+
2. **One source of truth for the proven tip.** Reading the proven block number
|
|
478
|
+
inside the drain means the eligibility check and the publish that follows are
|
|
479
|
+
guaranteed to use the same value. `EpochSession`s can't race each other on stale
|
|
480
|
+
reads.
|
|
481
|
+
3. **Per-candidate deadline and retry.** The service owns expiry timers and the
|
|
482
|
+
`publisherFactory.create()` retry loop. `EpochSession`s don't need to know about
|
|
483
|
+
either — they just await the outcome.
|
|
484
|
+
|
|
485
|
+
### Why is the chonk cache keyed by tx hash and released on finality?
|
|
486
|
+
|
|
487
|
+
Chonk-verifier proofs are tx-scoped: they prove a transaction's chonk circuit is
|
|
488
|
+
valid, independently of which block or epoch the tx lands in. A tx that gets
|
|
489
|
+
reorged out of one block and re-mined into another should not need to be re-proved.
|
|
490
|
+
Keying by tx hash makes the cache survive any reorg up to finality; releasing on
|
|
491
|
+
finality means we don't grow the cache indefinitely while still keeping every
|
|
492
|
+
reorg-relevant proof.
|
|
493
|
+
|
|
494
|
+
### Why is a pruned `CheckpointProver` removed rather than kept for a possible re-add?
|
|
495
|
+
|
|
496
|
+
A prover's sub-tree work forks world-state per block, and an L1 prune of a base block faults
|
|
497
|
+
those in-flight reads — so the work cannot survive the prune, and there is nothing to preserve
|
|
498
|
+
by keeping the prover around. Removing it on prune and rebuilding on re-add is therefore both
|
|
499
|
+
correct and simpler; the expensive block-rollup proofs are still reused when content re-appears,
|
|
500
|
+
because the proving broker is content-addressed independently of the prover's lifetime.
|
|
501
|
+
|
|
502
|
+
### How is a genuine failure told apart from a prune, without a racy classification?
|
|
503
|
+
|
|
504
|
+
Knowledge of an L1 reorg reaches the prover-node on two causally unordered channels: the control
|
|
505
|
+
plane (`chain-pruned` → `onPrune`) and the data plane (world-state unwinds, and an in-flight fork
|
|
506
|
+
read faults inside a `CheckpointProver` mid-proof). If the `EpochSession` reacted to a fault by asking
|
|
507
|
+
"was this a prune or a genuine failure?", every answer would sample control-plane state that lags the
|
|
508
|
+
data-plane unwind — racy by construction. We remove the question by pushing the fact down to where it
|
|
509
|
+
is unambiguous: a `CheckpointProver` records `isFailed()` when *its* block proofs reject. The session
|
|
510
|
+
then reads a clean signal: if any prover failed, the fault might be a prune (`stopped`) — don't upload,
|
|
511
|
+
don't rebuild over it, recover on re-add; if *no* prover failed yet the session's own top-tree/submit
|
|
512
|
+
work failed, that is definitively **not** a prune (`failed`) — a genuine, race-free failure that is
|
|
513
|
+
retained (so a deterministic failure isn't re-proved every tick) and uploaded once. No control-plane
|
|
514
|
+
sampling, no timing race — the two prover-level and session-level facts carry the whole decision.
|
|
515
|
+
|
|
516
|
+
## Configuration
|
|
517
|
+
|
|
518
|
+
| Env var | Description |
|
|
519
|
+
|---|---|
|
|
520
|
+
| `PROVER_NODE_POLLING_INTERVAL_MS` | Polling interval for the L2BlockStream and the SessionManager periodic tick. Default 1000 ms. |
|
|
521
|
+
| `PROVER_NODE_MAX_PENDING_JOBS` | Cap on the number of non-terminal `EpochSession`s (full + partial). When at limit, reconcile defers opening new full `EpochSession`s; explicit `startProof` calls throw. |
|
|
522
|
+
| `PROVER_NODE_EPOCH_PROVING_DELAY_MS` | Optional sleep at the start of each `EpochSession`, before the TopTreeJob is constructed. Used in tests to give late events time to land. |
|
|
523
|
+
| `TX_GATHERING_TIMEOUT_MS` | Per-block tx gather deadline used by each `CheckpointProver`. |
|
|
524
|
+
| `PROVER_NODE_FAILED_EPOCH_STORE` | If set, a full session that fails on its own account (top-tree/submit, provers healthy) uploads its proving data (every `CheckpointProver`'s txs + register-time data, regardless of sub-tree completion) to this file store. |
|
|
525
|
+
| `PROVER_NODE_DISABLE_PROOF_PUBLISH` | If true, the publishing service runs `analyzeEpochProofSubmission` (estimates L1 fees) instead of actually submitting. |
|
|
526
|
+
|
|
527
|
+
## Failure handling and observability
|
|
528
|
+
|
|
529
|
+
Loggers:
|
|
530
|
+
|
|
531
|
+
- `prover-node` — `ProverNode` itself (event dispatch, lifecycle).
|
|
532
|
+
- `prover-node:session-manager` — reconcile decisions, `EpochSession` opens / drops, tick.
|
|
533
|
+
- `prover-node:epoch-session` — per-`EpochSession` lifecycle (`Created EpochSession`,
|
|
534
|
+
`Top-tree proof ready`, `Submitted proof for epoch N`, etc.).
|
|
535
|
+
- `prover-node:proof-publishing-service` — candidate submit / withdraw / expire,
|
|
536
|
+
drain, publish attempts, transient acquire retries.
|
|
537
|
+
- `prover-node:l1-tx-publisher` — the per-publish `ProverNodePublisher`'s L1 work.
|
|
538
|
+
- `prover-node:checkpoint-store` — content-key collisions, reap decisions.
|
|
539
|
+
- `prover-node:checkpoint-prover` — sub-tree pipeline (gather, block processing).
|
|
540
|
+
- `prover-client:chonk-cache` — chonk-verifier cache enqueue / release events.
|
|
541
|
+
|
|
542
|
+
Failed proving data is uploaded to the configured file store (`PROVER_NODE_FAILED_EPOCH_STORE`) at two
|
|
543
|
+
levels, and re-proved offline by the matching downloader/rerunner: an epoch job via
|
|
544
|
+
`downloadEpochProvingJob` + `rerunEpochProvingJob`, and a single checkpoint via the same download plus
|
|
545
|
+
`rerunCheckpointProvingJob` (which rebuilds just that checkpoint's sub-tree prover and awaits its block
|
|
546
|
+
proofs — no epoch top-tree or L1 submit). Both upload levels build an `EpochProvingJobData` snapshot with
|
|
547
|
+
`SessionManager.buildProvingData(...)` — every `CheckpointProver`'s txs and register-time data, even if
|
|
548
|
+
its sub-tree never reached `isCompleted()` — and ship it via `uploadEpochProofFailure` alongside a
|
|
549
|
+
world-state + archiver backup:
|
|
550
|
+
|
|
551
|
+
- **Per checkpoint.** When a `CheckpointProver`'s block proofs reject for a non-cancel reason (a sub-tree
|
|
552
|
+
fault or a prune-induced fork fault), it fires its `onFailed` callback and `ProverNode` uploads that one
|
|
553
|
+
checkpoint via `tryUploadCheckpointFailure(prover)`. This fires for prune-induced faults too — that is
|
|
554
|
+
intentional; a prune-caused checkpoint snapshot is harmless, and *not* trying to tell prune from genuine
|
|
555
|
+
failure is exactly what keeps this race-free. A cancelled prover (control-plane prune / shutdown) is not
|
|
556
|
+
a failure and does not upload.
|
|
557
|
+
- **Per session.** When a full session ends in its own genuine failure (`EpochSession.hasFailed()` —
|
|
558
|
+
top-tree/submit failed with every prover healthy), the session manager fires `onSessionFailed` and
|
|
559
|
+
`ProverNode` uploads all the session's checkpoints via `tryUploadEpochFailure(...)`. This is race-free
|
|
560
|
+
(healthy provers rule out a prune) and fires once, since the failed session is retained and never re-run.
|
|
561
|
+
|
|
562
|
+
A `stopped` session (a prover under it failed) does not upload at the session level — its failed checkpoint
|
|
563
|
+
already uploaded itself. Each backup is a full world-state + archiver snapshot, so a prune that faults
|
|
564
|
+
several in-flight provers produces several uploads; this is accepted for the diagnostic value.
|
|
565
|
+
|
|
566
|
+
Metrics emitted by `EpochSession`s:
|
|
567
|
+
|
|
568
|
+
- `aztec.prover_node.execution_duration` — wall-clock time from `EpochSession` start to terminal.
|
|
569
|
+
- `aztec.prover_node.job_duration` — same, in seconds.
|
|
570
|
+
- `aztec.prover_node.job_checkpoints` / `_blocks` / `_transactions` — sizes of the
|
|
571
|
+
proven range.
|
|
572
|
+
- `aztec.prover_node.block_processing_duration` /
|
|
573
|
+
`aztec.prover_node.checkpoint_processing_duration` — sub-tree breakdown.
|
|
@@ -25,7 +25,7 @@ import { deserializeEpochProvingJobData } from '../job/epoch-proving-job-data.js
|
|
|
25
25
|
}, log, {
|
|
26
26
|
...config,
|
|
27
27
|
...metadata,
|
|
28
|
-
|
|
28
|
+
fileStore
|
|
29
29
|
});
|
|
30
30
|
const dataPath = urlJoin(location, 'data.bin');
|
|
31
31
|
const localPath = config.jobDataDownloadPath;
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import type { L1ContractsConfig } from '@aztec/ethereum/config';
|
|
2
2
|
import type { Logger } from '@aztec/foundation/log';
|
|
3
|
-
import type { DataStoreConfig } from '@aztec/kv-store/config';
|
|
4
3
|
import { type ProverClientConfig } from '@aztec/prover-client';
|
|
5
4
|
import { ProverBrokerConfig } from '@aztec/prover-client/broker';
|
|
5
|
+
import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
|
|
6
|
+
import type { GenesisData } from '@aztec/stdlib/world-state';
|
|
7
|
+
type RerunConfig = DataStoreConfig & ProverBrokerConfig & ProverClientConfig & Pick<L1ContractsConfig, 'aztecEpochDuration'>;
|
|
6
8
|
/**
|
|
7
9
|
* Given a local folder where `downloadEpochProvingJob` was called, creates a new archiver and world state
|
|
8
|
-
* using the state snapshots, and creates a new epoch proving
|
|
10
|
+
* using the state snapshots, and creates a new epoch proving session to prove the downloaded proving job.
|
|
9
11
|
* Proving is done with a local proving broker and agents as specified by the config.
|
|
10
12
|
*/
|
|
11
|
-
export declare function rerunEpochProvingJob(localPath: string, log: Logger, config:
|
|
12
|
-
|
|
13
|
+
export declare function rerunEpochProvingJob(localPath: string, log: Logger, config: RerunConfig, genesis?: GenesisData): Promise<"awaiting-checkpoints" | "awaiting-predecessor" | "awaiting-root" | "cancelled" | "completed" | "failed" | "initialized" | "publishing-proof" | "stopped" | "superseded" | "timed-out">;
|
|
14
|
+
/**
|
|
15
|
+
* Re-proves a single downloaded checkpoint proving job (as uploaded by a `CheckpointProver` failure).
|
|
16
|
+
* Reconstructs just that checkpoint's sub-tree prover from the snapshot and awaits its block proofs — no
|
|
17
|
+
* epoch top-tree, no L1 submission — so a checkpoint-level failure can be reproduced offline in isolation.
|
|
18
|
+
* Returns the block-rollup proof outputs on success; throws if the checkpoint fails to prove again.
|
|
19
|
+
*/
|
|
20
|
+
export declare function rerunCheckpointProvingJob(localPath: string, log: Logger, config: RerunConfig, genesis?: GenesisData): Promise<import("@aztec/stdlib/interfaces/server").PublicInputsAndRecursiveProof<import("@aztec/stdlib/rollup").BlockRollupPublicInputs, 480>[]>;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVydW4tZXBvY2gtcHJvdmluZy1qb2IuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hY3Rpb25zL3JlcnVuLWVwb2NoLXByb3Zpbmctam9iLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFaEUsT0FBTyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFcEQsT0FBTyxFQUFFLEtBQUssa0JBQWtCLEVBQXNCLE1BQU0sc0JBQXNCLENBQUM7QUFDbkYsT0FBTyxFQUFFLGtCQUFrQixFQUErQixNQUFNLDZCQUE2QixDQUFDO0FBTzlGLE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRzlELE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBVzdELEtBQUssV0FBVyxHQUFHLGVBQWUsR0FDaEMsa0JBQWtCLEdBQ2xCLGtCQUFrQixHQUNsQixJQUFJLENBQUMsaUJBQWlCLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztBQUVoRDs7OztHQUlHO0FBQ0gsd0JBQXNCLG9CQUFvQixDQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLE9BQU8sQ0FBQyxFQUFFLFdBQVcsbU1Bc0NwSDtBQUVEOzs7OztHQUtHO0FBQ0gsd0JBQXNCLHlCQUF5QixDQUM3QyxTQUFTLEVBQUUsTUFBTSxFQUNqQixHQUFHLEVBQUUsTUFBTSxFQUNYLE1BQU0sRUFBRSxXQUFXLEVBQ25CLE9BQU8sQ0FBQyxFQUFFLFdBQVcsbUpBaUJ0QiJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rerun-epoch-proving-job.d.ts","sourceRoot":"","sources":["../../src/actions/rerun-epoch-proving-job.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"rerun-epoch-proving-job.d.ts","sourceRoot":"","sources":["../../src/actions/rerun-epoch-proving-job.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAEpD,OAAO,EAAE,KAAK,kBAAkB,EAAsB,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAAE,kBAAkB,EAA+B,MAAM,6BAA6B,CAAC;AAO9F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAW7D,KAAK,WAAW,GAAG,eAAe,GAChC,kBAAkB,GAClB,kBAAkB,GAClB,IAAI,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,CAAC;AAEhD;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,WAAW,mMAsCpH;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,WAAW,EACnB,OAAO,CAAC,EAAE,WAAW,mJAiBtB"}
|