@aztec/prover-client 3.0.0-nightly.20250917 → 3.0.0-nightly.20250919
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/block-factory/light.d.ts +5 -3
- package/dest/block-factory/light.d.ts.map +1 -1
- package/dest/block-factory/light.js +16 -9
- package/dest/mocks/fixtures.d.ts +3 -1
- package/dest/mocks/fixtures.d.ts.map +1 -1
- package/dest/mocks/fixtures.js +19 -2
- package/dest/mocks/test_context.d.ts +30 -9
- package/dest/mocks/test_context.d.ts.map +1 -1
- package/dest/mocks/test_context.js +68 -15
- package/dest/orchestrator/block-building-helpers.d.ts +16 -14
- package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
- package/dest/orchestrator/block-building-helpers.js +69 -66
- package/dest/orchestrator/block-proving-state.d.ts +59 -52
- package/dest/orchestrator/block-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/block-proving-state.js +215 -187
- package/dest/orchestrator/checkpoint-proving-state.d.ts +62 -0
- package/dest/orchestrator/checkpoint-proving-state.d.ts.map +1 -0
- package/dest/orchestrator/checkpoint-proving-state.js +208 -0
- package/dest/orchestrator/epoch-proving-state.d.ts +32 -25
- package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/epoch-proving-state.js +132 -81
- package/dest/orchestrator/orchestrator.d.ts +25 -24
- package/dest/orchestrator/orchestrator.d.ts.map +1 -1
- package/dest/orchestrator/orchestrator.js +331 -203
- package/dest/orchestrator/tx-proving-state.d.ts +3 -3
- package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/tx-proving-state.js +5 -5
- package/dest/prover-client/server-epoch-prover.d.ts +8 -7
- package/dest/prover-client/server-epoch-prover.d.ts.map +1 -1
- package/dest/prover-client/server-epoch-prover.js +7 -7
- package/dest/proving_broker/broker_prover_facade.d.ts +18 -13
- package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -1
- package/dest/proving_broker/broker_prover_facade.js +36 -21
- package/dest/proving_broker/fixtures.js +1 -1
- package/dest/proving_broker/proof_store/index.d.ts +1 -0
- package/dest/proving_broker/proof_store/index.d.ts.map +1 -1
- package/dest/proving_broker/proof_store/index.js +1 -0
- package/dest/proving_broker/proving_broker.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker.js +27 -16
- package/dest/proving_broker/proving_job_controller.d.ts.map +1 -1
- package/dest/proving_broker/proving_job_controller.js +34 -14
- package/dest/test/mock_prover.d.ts +18 -13
- package/dest/test/mock_prover.d.ts.map +1 -1
- package/dest/test/mock_prover.js +31 -16
- package/package.json +16 -17
- package/src/block-factory/light.ts +33 -9
- package/src/mocks/fixtures.ts +25 -7
- package/src/mocks/test_context.ts +113 -21
- package/src/orchestrator/block-building-helpers.ts +107 -93
- package/src/orchestrator/block-proving-state.ts +232 -244
- package/src/orchestrator/checkpoint-proving-state.ts +294 -0
- package/src/orchestrator/epoch-proving-state.ts +169 -121
- package/src/orchestrator/orchestrator.ts +483 -262
- package/src/orchestrator/tx-proving-state.ts +6 -6
- package/src/prover-client/server-epoch-prover.ts +30 -16
- package/src/proving_broker/broker_prover_facade.ts +151 -83
- package/src/proving_broker/fixtures.ts +1 -1
- package/src/proving_broker/proof_store/index.ts +1 -0
- package/src/proving_broker/proving_broker.ts +34 -16
- package/src/proving_broker/proving_job_controller.ts +34 -14
- package/src/test/mock_prover.ts +125 -54
- package/dest/bin/get-proof-inputs.d.ts +0 -2
- package/dest/bin/get-proof-inputs.d.ts.map +0 -1
- package/dest/bin/get-proof-inputs.js +0 -51
- package/src/bin/get-proof-inputs.ts +0 -59
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BlobAccumulatorPublicInputs, FinalBlobBatchingChallenges } from '@aztec/blob-lib';
|
|
1
|
+
import { BatchedBlob, BlobAccumulatorPublicInputs, FinalBlobBatchingChallenges, SpongeBlob } from '@aztec/blob-lib';
|
|
2
2
|
import {
|
|
3
3
|
L1_TO_L2_MSG_SUBTREE_HEIGHT,
|
|
4
4
|
L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH,
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
7
7
|
NUM_BASE_PARITY_PER_ROOT_PARITY,
|
|
8
8
|
} from '@aztec/constants';
|
|
9
|
-
import { padArrayEnd
|
|
9
|
+
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
10
10
|
import { AbortError } from '@aztec/foundation/error';
|
|
11
11
|
import { Fr } from '@aztec/foundation/fields';
|
|
12
12
|
import { createLogger } from '@aztec/foundation/log';
|
|
@@ -15,9 +15,8 @@ import { assertLength } from '@aztec/foundation/serialize';
|
|
|
15
15
|
import { pushTestData } from '@aztec/foundation/testing';
|
|
16
16
|
import { elapsed } from '@aztec/foundation/timer';
|
|
17
17
|
import type { TreeNodeLocation } from '@aztec/foundation/trees';
|
|
18
|
-
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
19
18
|
import { readAvmMinimalPublicTxInputsFromFile } from '@aztec/simulator/public/fixtures';
|
|
20
|
-
import { EthAddress,
|
|
19
|
+
import { EthAddress, createBlockEndMarker } from '@aztec/stdlib/block';
|
|
21
20
|
import type {
|
|
22
21
|
EpochProver,
|
|
23
22
|
ForkMerkleTreeOperations,
|
|
@@ -26,17 +25,23 @@ import type {
|
|
|
26
25
|
ServerCircuitProver,
|
|
27
26
|
} from '@aztec/stdlib/interfaces/server';
|
|
28
27
|
import type { PrivateToPublicKernelCircuitPublicInputs } from '@aztec/stdlib/kernel';
|
|
29
|
-
import {
|
|
28
|
+
import type { Proof } from '@aztec/stdlib/proofs';
|
|
30
29
|
import {
|
|
31
30
|
type BaseRollupHints,
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
BlockRootEmptyTxFirstRollupPrivateInputs,
|
|
32
|
+
BlockRootFirstRollupPrivateInputs,
|
|
33
|
+
BlockRootSingleTxFirstRollupPrivateInputs,
|
|
34
|
+
BlockRootSingleTxRollupPrivateInputs,
|
|
35
|
+
CheckpointConstantData,
|
|
36
|
+
CheckpointRootSingleBlockRollupPrivateInputs,
|
|
37
|
+
PrivateTxBaseRollupPrivateInputs,
|
|
34
38
|
PublicTubePrivateInputs,
|
|
35
|
-
|
|
39
|
+
RootRollupPublicInputs,
|
|
36
40
|
} from '@aztec/stdlib/rollup';
|
|
37
41
|
import type { CircuitName } from '@aztec/stdlib/stats';
|
|
38
42
|
import { type AppendOnlyTreeSnapshot, MerkleTreeId } from '@aztec/stdlib/trees';
|
|
39
|
-
import {
|
|
43
|
+
import type { BlockHeader, ProcessedTx, Tx } from '@aztec/stdlib/tx';
|
|
44
|
+
import type { UInt64 } from '@aztec/stdlib/types';
|
|
40
45
|
import {
|
|
41
46
|
Attributes,
|
|
42
47
|
type TelemetryClient,
|
|
@@ -49,7 +54,8 @@ import {
|
|
|
49
54
|
import { inspect } from 'util';
|
|
50
55
|
|
|
51
56
|
import {
|
|
52
|
-
|
|
57
|
+
buildBlockHeaderFromTxs,
|
|
58
|
+
buildHeaderFromCircuitOutputs,
|
|
53
59
|
getLastSiblingPath,
|
|
54
60
|
getPublicTubePrivateInputsFromTx,
|
|
55
61
|
getRootTreeSiblingPath,
|
|
@@ -60,6 +66,7 @@ import {
|
|
|
60
66
|
validateTx,
|
|
61
67
|
} from './block-building-helpers.js';
|
|
62
68
|
import type { BlockProvingState } from './block-proving-state.js';
|
|
69
|
+
import type { CheckpointProvingState } from './checkpoint-proving-state.js';
|
|
63
70
|
import { EpochProvingState, type ProvingResult, type TreeSnapshots } from './epoch-proving-state.js';
|
|
64
71
|
import { ProvingOrchestratorMetrics } from './orchestrator_metrics.js';
|
|
65
72
|
import { TxProvingState } from './tx-proving-state.js';
|
|
@@ -112,80 +119,141 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
112
119
|
|
|
113
120
|
public startNewEpoch(
|
|
114
121
|
epochNumber: number,
|
|
115
|
-
|
|
116
|
-
|
|
122
|
+
firstCheckpointNumber: Fr,
|
|
123
|
+
totalNumCheckpoints: number,
|
|
117
124
|
finalBlobBatchingChallenges: FinalBlobBatchingChallenges,
|
|
118
125
|
) {
|
|
126
|
+
if (this.provingState?.verifyState()) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
`Cannot start epoch ${epochNumber} when epoch ${this.provingState.epochNumber} is still being processed.`,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
119
132
|
const { promise: _promise, resolve, reject } = promiseWithResolvers<ProvingResult>();
|
|
120
133
|
const promise = _promise.catch((reason): ProvingResult => ({ status: 'failure', reason }));
|
|
121
|
-
|
|
122
|
-
throw new Error(`Invalid number of blocks for epoch (got ${totalNumBlocks})`);
|
|
123
|
-
}
|
|
124
|
-
logger.info(`Starting epoch ${epochNumber} with ${totalNumBlocks} blocks`);
|
|
134
|
+
logger.info(`Starting epoch ${epochNumber} with ${totalNumCheckpoints} checkpoints.`);
|
|
125
135
|
this.provingState = new EpochProvingState(
|
|
126
136
|
epochNumber,
|
|
127
|
-
|
|
128
|
-
|
|
137
|
+
firstCheckpointNumber,
|
|
138
|
+
totalNumCheckpoints,
|
|
129
139
|
finalBlobBatchingChallenges,
|
|
140
|
+
provingState => this.checkAndEnqueueCheckpointRootRollup(provingState),
|
|
130
141
|
resolve,
|
|
131
142
|
reject,
|
|
132
143
|
);
|
|
133
144
|
this.provingPromise = promise;
|
|
134
145
|
}
|
|
135
146
|
|
|
147
|
+
public async startNewCheckpoint(
|
|
148
|
+
constants: CheckpointConstantData,
|
|
149
|
+
l1ToL2Messages: Fr[],
|
|
150
|
+
totalNumBlocks: number,
|
|
151
|
+
totalNumBlobFields: number,
|
|
152
|
+
headerOfLastBlockInPreviousCheckpoint: BlockHeader,
|
|
153
|
+
) {
|
|
154
|
+
if (!this.provingState) {
|
|
155
|
+
throw new Error('Empty epoch proving state. Call startNewEpoch before starting a checkpoint.');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (!this.provingState.isAcceptingCheckpoints()) {
|
|
159
|
+
throw new Error(`Epoch not accepting further checkpoints.`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Fork world state at the end of the immediately previous block.
|
|
163
|
+
const lastBlockNumber = headerOfLastBlockInPreviousCheckpoint.globalVariables.blockNumber;
|
|
164
|
+
const db = await this.dbProvider.fork(lastBlockNumber);
|
|
165
|
+
|
|
166
|
+
const firstBlockNumber = lastBlockNumber + 1;
|
|
167
|
+
this.dbs.set(firstBlockNumber, db);
|
|
168
|
+
|
|
169
|
+
// Get archive sibling path before any block in this checkpoint lands.
|
|
170
|
+
const lastArchiveSiblingPath = await getLastSiblingPath(MerkleTreeId.ARCHIVE, db);
|
|
171
|
+
|
|
172
|
+
// Insert all the l1 to l2 messages into the db. And get the states before and after the insertion.
|
|
173
|
+
const {
|
|
174
|
+
lastL1ToL2MessageTreeSnapshot,
|
|
175
|
+
lastL1ToL2MessageSubtreeSiblingPath,
|
|
176
|
+
newL1ToL2MessageTreeSnapshot,
|
|
177
|
+
newL1ToL2MessageSubtreeSiblingPath,
|
|
178
|
+
} = await this.updateL1ToL2MessageTree(l1ToL2Messages, db);
|
|
179
|
+
|
|
180
|
+
this.provingState.startNewCheckpoint(
|
|
181
|
+
constants,
|
|
182
|
+
totalNumBlocks,
|
|
183
|
+
totalNumBlobFields,
|
|
184
|
+
headerOfLastBlockInPreviousCheckpoint,
|
|
185
|
+
lastArchiveSiblingPath,
|
|
186
|
+
l1ToL2Messages,
|
|
187
|
+
lastL1ToL2MessageTreeSnapshot,
|
|
188
|
+
lastL1ToL2MessageSubtreeSiblingPath,
|
|
189
|
+
newL1ToL2MessageTreeSnapshot,
|
|
190
|
+
newL1ToL2MessageSubtreeSiblingPath,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
136
194
|
/**
|
|
137
195
|
* Starts off a new block
|
|
138
|
-
* @param
|
|
139
|
-
* @param
|
|
140
|
-
*
|
|
196
|
+
* @param blockNumber - The block number
|
|
197
|
+
* @param timestamp - The timestamp of the block. This is only required for constructing the private inputs for the
|
|
198
|
+
* block that doesn't have any txs.
|
|
199
|
+
* @param totalNumTxs - The total number of txs in the block
|
|
141
200
|
*/
|
|
142
|
-
@trackSpan('ProvingOrchestrator.startNewBlock',
|
|
143
|
-
[Attributes.BLOCK_NUMBER]:
|
|
201
|
+
@trackSpan('ProvingOrchestrator.startNewBlock', blockNumber => ({
|
|
202
|
+
[Attributes.BLOCK_NUMBER]: blockNumber,
|
|
144
203
|
}))
|
|
145
|
-
public async startNewBlock(
|
|
204
|
+
public async startNewBlock(blockNumber: number, timestamp: UInt64, totalNumTxs: number) {
|
|
146
205
|
if (!this.provingState) {
|
|
147
|
-
throw new Error(
|
|
206
|
+
throw new Error('Empty epoch proving state. Call startNewEpoch before starting a block.');
|
|
148
207
|
}
|
|
149
208
|
|
|
150
|
-
|
|
151
|
-
|
|
209
|
+
const checkpointProvingState = this.provingState.getCheckpointProvingStateByBlockNumber(blockNumber);
|
|
210
|
+
if (!checkpointProvingState) {
|
|
211
|
+
throw new Error(`Checkpoint not started. Call startNewCheckpoint first.`);
|
|
152
212
|
}
|
|
153
213
|
|
|
154
|
-
|
|
214
|
+
if (!checkpointProvingState.isAcceptingBlocks()) {
|
|
215
|
+
throw new Error(`Checkpoint not accepting further blocks.`);
|
|
216
|
+
}
|
|
155
217
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
this.dbs.set(globalVariables.blockNumber, db);
|
|
218
|
+
const constants = checkpointProvingState.constants;
|
|
219
|
+
logger.info(`Starting block ${blockNumber} for slot ${constants.slotNumber.toNumber()}.`);
|
|
159
220
|
|
|
160
|
-
//
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
// Get archive snapshot before this block lands
|
|
169
|
-
const lastArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
|
|
170
|
-
const lastArchiveSiblingPath = await getLastSiblingPath(MerkleTreeId.ARCHIVE, db);
|
|
171
|
-
const newArchiveSiblingPath = await getRootTreeSiblingPath(MerkleTreeId.ARCHIVE, db);
|
|
221
|
+
// Fork the db only when it's not already set. The db for the first block is set in `startNewCheckpoint`.
|
|
222
|
+
if (!this.dbs.has(blockNumber)) {
|
|
223
|
+
// Fork world state at the end of the immediately previous block
|
|
224
|
+
const db = await this.dbProvider.fork(blockNumber - 1);
|
|
225
|
+
this.dbs.set(blockNumber, db);
|
|
226
|
+
}
|
|
227
|
+
const db = this.dbs.get(blockNumber)!;
|
|
172
228
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
229
|
+
// Get archive snapshot and sibling path before any txs in this block lands.
|
|
230
|
+
const lastArchiveTreeSnapshot = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
|
|
231
|
+
const lastArchiveSiblingPath = await getRootTreeSiblingPath(MerkleTreeId.ARCHIVE, db);
|
|
232
|
+
|
|
233
|
+
const blockProvingState = checkpointProvingState.startNewBlock(
|
|
234
|
+
blockNumber,
|
|
235
|
+
timestamp,
|
|
236
|
+
totalNumTxs,
|
|
237
|
+
lastArchiveTreeSnapshot,
|
|
180
238
|
lastArchiveSiblingPath,
|
|
181
|
-
newArchiveSiblingPath,
|
|
182
|
-
previousBlockHeader,
|
|
183
|
-
this.proverId,
|
|
184
239
|
);
|
|
185
240
|
|
|
186
|
-
// Enqueue base parity circuits for the block
|
|
187
|
-
|
|
188
|
-
|
|
241
|
+
// Enqueue base parity circuits for the first block in the checkpoint.
|
|
242
|
+
if (blockProvingState.index === 0) {
|
|
243
|
+
for (let i = 0; i < NUM_BASE_PARITY_PER_ROOT_PARITY; i++) {
|
|
244
|
+
this.enqueueBaseParityCircuit(checkpointProvingState, blockProvingState, i);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Because `addTxs` won't be called for a block without txs, and that's where the sponge blob state is computed.
|
|
249
|
+
// We need to set its end sponge blob here, which will become the start sponge blob for the next block.
|
|
250
|
+
if (totalNumTxs === 0) {
|
|
251
|
+
const endSpongeBlob = blockProvingState.getStartSpongeBlob().clone();
|
|
252
|
+
await endSpongeBlob.absorb([createBlockEndMarker(0)]);
|
|
253
|
+
blockProvingState.setEndSpongeBlob(endSpongeBlob);
|
|
254
|
+
|
|
255
|
+
// And also try to accumulate the blobs as far as we can:
|
|
256
|
+
await this.provingState.setBlobAccumulators();
|
|
189
257
|
}
|
|
190
258
|
}
|
|
191
259
|
|
|
@@ -197,28 +265,40 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
197
265
|
[Attributes.BLOCK_TXS_COUNT]: txs.length,
|
|
198
266
|
}))
|
|
199
267
|
public async addTxs(txs: ProcessedTx[]): Promise<void> {
|
|
268
|
+
if (!this.provingState) {
|
|
269
|
+
throw new Error(`Empty epoch proving state. Call startNewEpoch before adding txs.`);
|
|
270
|
+
}
|
|
271
|
+
|
|
200
272
|
if (!txs.length) {
|
|
201
273
|
// To avoid an ugly throw below. If we require an empty block, we can just call setBlockCompleted
|
|
202
274
|
// on a block with no txs. We cannot do that here because we cannot find the blockNumber without any txs.
|
|
203
275
|
logger.warn(`Provided no txs to orchestrator addTxs.`);
|
|
204
276
|
return;
|
|
205
277
|
}
|
|
278
|
+
|
|
206
279
|
const blockNumber = txs[0].globalVariables.blockNumber;
|
|
207
|
-
const provingState = this.provingState
|
|
280
|
+
const provingState = this.provingState.getBlockProvingStateByBlockNumber(blockNumber!);
|
|
208
281
|
if (!provingState) {
|
|
209
|
-
throw new Error(`
|
|
282
|
+
throw new Error(`Proving state for block ${blockNumber} not found. Call startNewBlock first.`);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (provingState.totalNumTxs !== txs.length) {
|
|
286
|
+
throw new Error(
|
|
287
|
+
`Block ${blockNumber} should be filled with ${provingState.totalNumTxs} txs. Received ${txs.length} txs.`,
|
|
288
|
+
);
|
|
210
289
|
}
|
|
211
290
|
|
|
212
|
-
if (provingState.
|
|
291
|
+
if (!provingState.isAcceptingTxs()) {
|
|
213
292
|
throw new Error(`Block ${blockNumber} has been initialized with transactions.`);
|
|
214
293
|
}
|
|
215
294
|
|
|
216
|
-
|
|
217
|
-
|
|
295
|
+
logger.info(`Adding ${txs.length} transactions to block ${blockNumber}`);
|
|
296
|
+
|
|
297
|
+
const db = this.dbs.get(blockNumber)!;
|
|
298
|
+
const lastArchive = provingState.lastArchiveTreeSnapshot;
|
|
299
|
+
const newL1ToL2MessageTreeSnapshot = provingState.newL1ToL2MessageTreeSnapshot;
|
|
300
|
+
const spongeBlobState = provingState.getStartSpongeBlob().clone();
|
|
218
301
|
|
|
219
|
-
logger.info(
|
|
220
|
-
`Adding ${txs.length} transactions with ${numBlobFields} blob fields to block ${provingState.blockNumber}`,
|
|
221
|
-
);
|
|
222
302
|
for (const tx of txs) {
|
|
223
303
|
try {
|
|
224
304
|
if (!provingState.verifyState()) {
|
|
@@ -229,7 +309,21 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
229
309
|
|
|
230
310
|
logger.info(`Received transaction: ${tx.hash}`);
|
|
231
311
|
|
|
232
|
-
const
|
|
312
|
+
const startSpongeBlob = spongeBlobState.clone();
|
|
313
|
+
const [hints, treeSnapshots] = await this.prepareBaseRollupInputs(
|
|
314
|
+
tx,
|
|
315
|
+
lastArchive,
|
|
316
|
+
newL1ToL2MessageTreeSnapshot,
|
|
317
|
+
startSpongeBlob,
|
|
318
|
+
db,
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
if (!provingState.verifyState()) {
|
|
322
|
+
throw new Error(`Unable to add transaction, preparing base inputs failed`);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
await spongeBlobState.absorb(tx.txEffect.toBlobFields());
|
|
326
|
+
|
|
233
327
|
const txProvingState = new TxProvingState(tx, hints, treeSnapshots);
|
|
234
328
|
const txIndex = provingState.addNewTx(txProvingState);
|
|
235
329
|
if (txProvingState.requireAvmProof) {
|
|
@@ -246,6 +340,13 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
246
340
|
});
|
|
247
341
|
}
|
|
248
342
|
}
|
|
343
|
+
|
|
344
|
+
await spongeBlobState.absorb([createBlockEndMarker(txs.length)]);
|
|
345
|
+
|
|
346
|
+
provingState.setEndSpongeBlob(spongeBlobState);
|
|
347
|
+
|
|
348
|
+
// Txs have been added to the block. Now try to accumulate the blobs as far as we can:
|
|
349
|
+
await this.provingState.setBlobAccumulators();
|
|
249
350
|
}
|
|
250
351
|
|
|
251
352
|
/**
|
|
@@ -255,7 +356,7 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
255
356
|
@trackSpan('ProvingOrchestrator.startTubeCircuits')
|
|
256
357
|
public startTubeCircuits(txs: Tx[]) {
|
|
257
358
|
if (!this.provingState?.verifyState()) {
|
|
258
|
-
throw new Error(`
|
|
359
|
+
throw new Error(`Empty epoch proving state. call startNewEpoch before starting tube circuits.`);
|
|
259
360
|
}
|
|
260
361
|
const publicTxs = txs.filter(tx => tx.data.forPublic);
|
|
261
362
|
for (const tx of publicTxs) {
|
|
@@ -272,7 +373,7 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
272
373
|
this.doEnqueueTube(txHash, privateInputs, proof => {
|
|
273
374
|
tubeProof.resolve(proof);
|
|
274
375
|
});
|
|
275
|
-
this.provingState
|
|
376
|
+
this.provingState.cachedTubeProofs.set(txHash, tubeProof.promise);
|
|
276
377
|
}
|
|
277
378
|
return Promise.resolve();
|
|
278
379
|
}
|
|
@@ -284,58 +385,50 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
284
385
|
@trackSpan('ProvingOrchestrator.setBlockCompleted', (blockNumber: number) => ({
|
|
285
386
|
[Attributes.BLOCK_NUMBER]: blockNumber,
|
|
286
387
|
}))
|
|
287
|
-
public async setBlockCompleted(blockNumber: number, expectedHeader?: BlockHeader): Promise<
|
|
388
|
+
public async setBlockCompleted(blockNumber: number, expectedHeader?: BlockHeader): Promise<BlockHeader> {
|
|
288
389
|
const provingState = this.provingState?.getBlockProvingStateByBlockNumber(blockNumber);
|
|
289
390
|
if (!provingState) {
|
|
290
391
|
throw new Error(`Block proving state for ${blockNumber} not found`);
|
|
291
392
|
}
|
|
292
393
|
|
|
293
|
-
if
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
394
|
+
// Abort with specific error for the block if there's one.
|
|
395
|
+
const error = provingState.getError();
|
|
396
|
+
if (error) {
|
|
397
|
+
throw new Error(`Block proving failed: ${error}`);
|
|
297
398
|
}
|
|
298
399
|
|
|
400
|
+
// Abort if the proving state is not valid due to errors occurred elsewhere.
|
|
299
401
|
if (!provingState.verifyState()) {
|
|
300
|
-
throw new Error(`
|
|
402
|
+
throw new Error(`Invalid proving state when completing block ${blockNumber}.`);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (provingState.isAcceptingTxs()) {
|
|
406
|
+
throw new Error(
|
|
407
|
+
`Block ${blockNumber} is still accepting txs. Call setBlockCompleted after all txs have been added.`,
|
|
408
|
+
);
|
|
301
409
|
}
|
|
302
410
|
|
|
303
411
|
// And build the block header
|
|
304
412
|
logger.verbose(`Block ${blockNumber} completed. Assembling header.`);
|
|
305
|
-
await this.
|
|
413
|
+
const header = await this.buildL2BlockHeader(provingState, expectedHeader);
|
|
306
414
|
|
|
307
|
-
|
|
308
|
-
await this.provingState?.setBlobAccumulators(blockNumber);
|
|
415
|
+
await this.verifyBuiltBlockAgainstSyncedState(provingState);
|
|
309
416
|
|
|
310
|
-
|
|
311
|
-
await this.checkAndEnqueueBlockRootRollup(provingState);
|
|
312
|
-
return provingState.block!;
|
|
417
|
+
return header;
|
|
313
418
|
}
|
|
314
419
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
const
|
|
318
|
-
if (!block) {
|
|
319
|
-
throw new Error(`Block at index ${index} not available`);
|
|
320
|
-
}
|
|
321
|
-
return block;
|
|
322
|
-
}
|
|
420
|
+
private async buildL2BlockHeader(provingState: BlockProvingState, expectedHeader?: BlockHeader) {
|
|
421
|
+
// Collect all txs in this block to build the header. The function calling this has made sure that all txs have been added.
|
|
422
|
+
const txs = provingState.getProcessedTxs();
|
|
323
423
|
|
|
324
|
-
|
|
325
|
-
// Collect all new nullifiers, commitments, and contracts from all txs in this block to build body
|
|
326
|
-
const txs = provingState.allTxs.map(a => a.processedTx);
|
|
424
|
+
const startSpongeBlob = provingState.getStartSpongeBlob();
|
|
327
425
|
|
|
328
426
|
// Get db for this block
|
|
329
427
|
const db = this.dbs.get(provingState.blockNumber)!;
|
|
330
428
|
|
|
331
429
|
// Given we've applied every change from this block, now assemble the block header
|
|
332
430
|
// and update the archive tree, so we're ready to start processing the next block
|
|
333
|
-
const
|
|
334
|
-
txs,
|
|
335
|
-
provingState.globalVariables,
|
|
336
|
-
provingState.newL1ToL2Messages,
|
|
337
|
-
db,
|
|
338
|
-
);
|
|
431
|
+
const header = await buildBlockHeaderFromTxs(txs, provingState.getGlobalVariables(), startSpongeBlob, db);
|
|
339
432
|
|
|
340
433
|
if (expectedHeader && !header.equals(expectedHeader)) {
|
|
341
434
|
logger.error(`Block header mismatch: header=${header} expectedHeader=${expectedHeader}`);
|
|
@@ -347,26 +440,65 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
347
440
|
);
|
|
348
441
|
await db.updateArchive(header);
|
|
349
442
|
|
|
350
|
-
|
|
351
|
-
const newArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
|
|
352
|
-
const l2Block = new L2Block(newArchive, header, body);
|
|
353
|
-
|
|
354
|
-
await this.verifyBuiltBlockAgainstSyncedState(l2Block, newArchive);
|
|
443
|
+
provingState.setBuiltBlockHeader(header);
|
|
355
444
|
|
|
356
|
-
|
|
357
|
-
provingState.setBlock(l2Block);
|
|
445
|
+
return header;
|
|
358
446
|
}
|
|
359
447
|
|
|
360
448
|
// Flagged as protected to disable in certain unit tests
|
|
361
|
-
protected async verifyBuiltBlockAgainstSyncedState(
|
|
362
|
-
const
|
|
449
|
+
protected async verifyBuiltBlockAgainstSyncedState(provingState: BlockProvingState) {
|
|
450
|
+
const builtBlockHeader = provingState.getBuiltBlockHeader();
|
|
451
|
+
if (!builtBlockHeader) {
|
|
452
|
+
logger.debug('Block header not built yet, skipping header check.');
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
const output = provingState.getBlockRootRollupOutput();
|
|
457
|
+
if (!output) {
|
|
458
|
+
logger.debug('Block root rollup proof not built yet, skipping header check.');
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
const header = await buildHeaderFromCircuitOutputs(output);
|
|
462
|
+
|
|
463
|
+
if (!(await header.hash()).equals(await builtBlockHeader.hash())) {
|
|
464
|
+
logger.error(`Block header mismatch.\nCircuit: ${inspect(header)}\nComputed: ${inspect(builtBlockHeader)}`);
|
|
465
|
+
provingState.reject(`Block header hash mismatch.`);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// Get db for this block
|
|
470
|
+
const blockNumber = provingState.blockNumber;
|
|
471
|
+
const db = this.dbs.get(blockNumber)!;
|
|
472
|
+
|
|
473
|
+
const newArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
|
|
474
|
+
const syncedArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, this.dbProvider.getSnapshot(blockNumber));
|
|
363
475
|
if (!syncedArchive.equals(newArchive)) {
|
|
364
|
-
|
|
365
|
-
`Archive tree mismatch for block ${
|
|
476
|
+
logger.error(
|
|
477
|
+
`Archive tree mismatch for block ${blockNumber}: world state synced to ${inspect(
|
|
366
478
|
syncedArchive,
|
|
367
479
|
)} but built ${inspect(newArchive)}`,
|
|
368
480
|
);
|
|
481
|
+
provingState.reject(`Archive tree mismatch.`);
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
const circuitArchive = output.newArchive;
|
|
486
|
+
if (!newArchive.equals(circuitArchive)) {
|
|
487
|
+
logger.error(`New archive mismatch.\nCircuit: ${output.newArchive}\nComputed: ${newArchive}`);
|
|
488
|
+
provingState.reject(`New archive mismatch.`);
|
|
489
|
+
return;
|
|
369
490
|
}
|
|
491
|
+
|
|
492
|
+
// TODO(palla/prover): This closes the fork only on the happy path. If this epoch orchestrator
|
|
493
|
+
// is aborted and never reaches this point, it will leak the fork. We need to add a global cleanup,
|
|
494
|
+
// but have to make sure it only runs once all operations are completed, otherwise some function here
|
|
495
|
+
// will attempt to access the fork after it was closed.
|
|
496
|
+
logger.debug(`Cleaning up world state fork for ${blockNumber}`);
|
|
497
|
+
void this.dbs
|
|
498
|
+
.get(blockNumber)
|
|
499
|
+
?.close()
|
|
500
|
+
.then(() => this.dbs.delete(blockNumber))
|
|
501
|
+
.catch(err => logger.error(`Error closing db for block ${blockNumber}`, err));
|
|
370
502
|
}
|
|
371
503
|
|
|
372
504
|
/**
|
|
@@ -383,7 +515,11 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
383
515
|
/**
|
|
384
516
|
* Returns the proof for the current epoch.
|
|
385
517
|
*/
|
|
386
|
-
public async finalizeEpoch() {
|
|
518
|
+
public async finalizeEpoch(): Promise<{
|
|
519
|
+
publicInputs: RootRollupPublicInputs;
|
|
520
|
+
proof: Proof;
|
|
521
|
+
batchedBlobInputs: BatchedBlob;
|
|
522
|
+
}> {
|
|
387
523
|
if (!this.provingState || !this.provingPromise) {
|
|
388
524
|
throw new Error(`Invalid proving state, an epoch must be proven before it can be finalized`);
|
|
389
525
|
}
|
|
@@ -393,14 +529,7 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
393
529
|
throw new Error(`Epoch proving failed: ${result.reason}`);
|
|
394
530
|
}
|
|
395
531
|
|
|
396
|
-
|
|
397
|
-
// TODO(MW): EpochProvingState uses this.blocks.filter(b => !!b).length as total blocks, use this below:
|
|
398
|
-
const finalBlock = this.provingState.blocks[this.provingState.totalNumBlocks - 1];
|
|
399
|
-
if (!finalBlock || !finalBlock.endBlobAccumulator) {
|
|
400
|
-
throw new Error(`Epoch's final block not ready for finalize`);
|
|
401
|
-
}
|
|
402
|
-
const finalBatchedBlob = await finalBlock.endBlobAccumulator.finalize();
|
|
403
|
-
this.provingState.setFinalBatchedBlob(finalBatchedBlob);
|
|
532
|
+
await this.provingState.finalizeBatchedBlob();
|
|
404
533
|
|
|
405
534
|
const epochProofResult = this.provingState.getEpochProofResult();
|
|
406
535
|
|
|
@@ -412,20 +541,6 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
412
541
|
return epochProofResult;
|
|
413
542
|
}
|
|
414
543
|
|
|
415
|
-
/**
|
|
416
|
-
* Starts the proving process for the given transaction and adds it to our state
|
|
417
|
-
* @param tx - The transaction whose proving we wish to commence
|
|
418
|
-
* @param provingState - The proving state being worked on
|
|
419
|
-
*/
|
|
420
|
-
private async prepareTransaction(tx: ProcessedTx, provingState: BlockProvingState) {
|
|
421
|
-
const txInputs = await this.prepareBaseRollupInputs(provingState, tx);
|
|
422
|
-
if (!txInputs) {
|
|
423
|
-
// This should not be possible
|
|
424
|
-
throw new Error(`Unable to add transaction, preparing base inputs failed`);
|
|
425
|
-
}
|
|
426
|
-
return txInputs;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
544
|
/**
|
|
430
545
|
* Enqueue a job to be scheduled
|
|
431
546
|
* @param provingState - The proving state object being operated on
|
|
@@ -433,11 +548,11 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
433
548
|
* @param job - The actual job, returns a promise notifying of the job's completion
|
|
434
549
|
*/
|
|
435
550
|
private deferredProving<T>(
|
|
436
|
-
provingState: EpochProvingState |
|
|
551
|
+
provingState: EpochProvingState | CheckpointProvingState | BlockProvingState,
|
|
437
552
|
request: (signal: AbortSignal) => Promise<T>,
|
|
438
553
|
callback: (result: T) => void | Promise<void>,
|
|
439
554
|
) {
|
|
440
|
-
if (!provingState
|
|
555
|
+
if (!provingState.verifyState()) {
|
|
441
556
|
logger.debug(`Not enqueuing job, state no longer valid`);
|
|
442
557
|
return;
|
|
443
558
|
}
|
|
@@ -455,7 +570,7 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
455
570
|
}
|
|
456
571
|
|
|
457
572
|
const result = await request(controller.signal);
|
|
458
|
-
if (!provingState
|
|
573
|
+
if (!provingState.verifyState()) {
|
|
459
574
|
logger.debug(`State no longer valid, discarding result`);
|
|
460
575
|
return;
|
|
461
576
|
}
|
|
@@ -488,58 +603,58 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
488
603
|
setImmediate(() => void safeJob());
|
|
489
604
|
}
|
|
490
605
|
|
|
491
|
-
private async
|
|
606
|
+
private async updateL1ToL2MessageTree(l1ToL2Messages: Fr[], db: MerkleTreeWriteOperations) {
|
|
492
607
|
const l1ToL2MessagesPadded = padArrayEnd(
|
|
493
608
|
l1ToL2Messages,
|
|
494
609
|
Fr.ZERO,
|
|
495
610
|
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
496
611
|
'Too many L1 to L2 messages',
|
|
497
612
|
);
|
|
498
|
-
const baseParityInputs = times(NUM_BASE_PARITY_PER_ROOT_PARITY, i =>
|
|
499
|
-
BaseParityInputs.fromSlice(l1ToL2MessagesPadded, i, getVKTreeRoot()),
|
|
500
|
-
);
|
|
501
613
|
|
|
502
|
-
const
|
|
503
|
-
|
|
504
|
-
const l1ToL2MessageSubtreeSiblingPath = assertLength(
|
|
614
|
+
const lastL1ToL2MessageTreeSnapshot = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db);
|
|
615
|
+
const lastL1ToL2MessageSubtreeSiblingPath = assertLength(
|
|
505
616
|
await getSubtreeSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, L1_TO_L2_MSG_SUBTREE_HEIGHT, db),
|
|
506
617
|
L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH,
|
|
507
618
|
);
|
|
508
619
|
|
|
509
620
|
// Update the local trees to include the new l1 to l2 messages
|
|
510
621
|
await db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
|
|
511
|
-
|
|
622
|
+
|
|
623
|
+
const newL1ToL2MessageTreeSnapshot = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db);
|
|
624
|
+
const newL1ToL2MessageSubtreeSiblingPath = assertLength(
|
|
625
|
+
await getSubtreeSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, L1_TO_L2_MSG_SUBTREE_HEIGHT, db),
|
|
626
|
+
L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH,
|
|
627
|
+
);
|
|
512
628
|
|
|
513
629
|
return {
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
630
|
+
lastL1ToL2MessageTreeSnapshot,
|
|
631
|
+
lastL1ToL2MessageSubtreeSiblingPath,
|
|
632
|
+
newL1ToL2MessageTreeSnapshot,
|
|
633
|
+
newL1ToL2MessageSubtreeSiblingPath,
|
|
518
634
|
};
|
|
519
635
|
}
|
|
520
636
|
|
|
521
637
|
// Updates the merkle trees for a transaction. The first enqueued job for a transaction
|
|
522
|
-
@trackSpan('ProvingOrchestrator.prepareBaseRollupInputs',
|
|
638
|
+
@trackSpan('ProvingOrchestrator.prepareBaseRollupInputs', tx => ({
|
|
523
639
|
[Attributes.TX_HASH]: tx.hash.toString(),
|
|
524
640
|
}))
|
|
525
641
|
private async prepareBaseRollupInputs(
|
|
526
|
-
provingState: BlockProvingState,
|
|
527
642
|
tx: ProcessedTx,
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
643
|
+
lastArchive: AppendOnlyTreeSnapshot,
|
|
644
|
+
newL1ToL2MessageTreeSnapshot: AppendOnlyTreeSnapshot,
|
|
645
|
+
startSpongeBlob: SpongeBlob,
|
|
646
|
+
db: MerkleTreeWriteOperations,
|
|
647
|
+
): Promise<[BaseRollupHints, TreeSnapshots]> {
|
|
648
|
+
// We build the base rollup inputs using a mock proof and verification key.
|
|
649
|
+
// These will be overwritten later once we have proven the tube circuit and any public kernels
|
|
536
650
|
const [ms, hints] = await elapsed(
|
|
537
651
|
insertSideEffectsAndBuildBaseRollupHints(
|
|
538
652
|
tx,
|
|
539
|
-
|
|
540
|
-
|
|
653
|
+
lastArchive,
|
|
654
|
+
newL1ToL2MessageTreeSnapshot,
|
|
655
|
+
startSpongeBlob,
|
|
656
|
+
this.proverId.toField(),
|
|
541
657
|
db,
|
|
542
|
-
provingState.spongeBlobState,
|
|
543
658
|
),
|
|
544
659
|
);
|
|
545
660
|
|
|
@@ -552,10 +667,6 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
552
667
|
);
|
|
553
668
|
const treeSnapshots: TreeSnapshots = new Map((await Promise.all(promises)).map(obj => [obj.key, obj.value]));
|
|
554
669
|
|
|
555
|
-
if (!provingState.verifyState()) {
|
|
556
|
-
logger.debug(`Discarding proving job, state no longer valid`);
|
|
557
|
-
return;
|
|
558
|
-
}
|
|
559
670
|
return [hints, treeSnapshots];
|
|
560
671
|
}
|
|
561
672
|
|
|
@@ -567,6 +678,11 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
567
678
|
return;
|
|
568
679
|
}
|
|
569
680
|
|
|
681
|
+
if (!provingState.tryStartProvingBase(txIndex)) {
|
|
682
|
+
logger.debug(`Base rollup for tx ${txIndex} already started.`);
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
|
|
570
686
|
const txProvingState = provingState.getTxProvingState(txIndex);
|
|
571
687
|
const { processedTx } = txProvingState;
|
|
572
688
|
const { rollupType, inputs } = txProvingState.getBaseRollupTypeAndInputs();
|
|
@@ -578,28 +694,30 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
578
694
|
wrapCallbackInSpan(
|
|
579
695
|
this.tracer,
|
|
580
696
|
`ProvingOrchestrator.prover.${
|
|
581
|
-
inputs instanceof
|
|
697
|
+
inputs instanceof PrivateTxBaseRollupPrivateInputs
|
|
698
|
+
? 'getPrivateTxBaseRollupProof'
|
|
699
|
+
: 'getPublicTxBaseRollupProof'
|
|
582
700
|
}`,
|
|
583
701
|
{
|
|
584
702
|
[Attributes.TX_HASH]: processedTx.hash.toString(),
|
|
585
703
|
[Attributes.PROTOCOL_CIRCUIT_NAME]: rollupType,
|
|
586
704
|
},
|
|
587
705
|
signal => {
|
|
588
|
-
if (inputs instanceof
|
|
589
|
-
return this.prover.
|
|
706
|
+
if (inputs instanceof PrivateTxBaseRollupPrivateInputs) {
|
|
707
|
+
return this.prover.getPrivateTxBaseRollupProof(inputs, signal, provingState.epochNumber);
|
|
590
708
|
} else {
|
|
591
|
-
return this.prover.
|
|
709
|
+
return this.prover.getPublicTxBaseRollupProof(inputs, signal, provingState.epochNumber);
|
|
592
710
|
}
|
|
593
711
|
},
|
|
594
712
|
),
|
|
595
|
-
|
|
713
|
+
result => {
|
|
596
714
|
logger.debug(`Completed proof for ${rollupType} for tx ${processedTx.hash.toString()}`);
|
|
597
|
-
validatePartialState(result.inputs.
|
|
715
|
+
validatePartialState(result.inputs.endPartialState, txProvingState.treeSnapshots);
|
|
598
716
|
const leafLocation = provingState.setBaseRollupProof(txIndex, result);
|
|
599
717
|
if (provingState.totalNumTxs === 1) {
|
|
600
|
-
|
|
718
|
+
this.checkAndEnqueueBlockRootRollup(provingState);
|
|
601
719
|
} else {
|
|
602
|
-
|
|
720
|
+
this.checkAndEnqueueNextMergeRollup(provingState, leafLocation);
|
|
603
721
|
}
|
|
604
722
|
},
|
|
605
723
|
);
|
|
@@ -649,7 +767,7 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
649
767
|
) => void,
|
|
650
768
|
provingState: EpochProvingState | BlockProvingState = this.provingState!,
|
|
651
769
|
) {
|
|
652
|
-
if (!provingState
|
|
770
|
+
if (!provingState.verifyState()) {
|
|
653
771
|
logger.debug('Not running tube circuit, state invalid');
|
|
654
772
|
return;
|
|
655
773
|
}
|
|
@@ -661,9 +779,9 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
661
779
|
'ProvingOrchestrator.prover.getPublicTubeProof',
|
|
662
780
|
{
|
|
663
781
|
[Attributes.TX_HASH]: txHash,
|
|
664
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'public
|
|
782
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'tube-public' satisfies CircuitName,
|
|
665
783
|
},
|
|
666
|
-
signal => this.prover.getPublicTubeProof(inputs, signal,
|
|
784
|
+
signal => this.prover.getPublicTubeProof(inputs, signal, provingState.epochNumber),
|
|
667
785
|
),
|
|
668
786
|
handler,
|
|
669
787
|
);
|
|
@@ -677,39 +795,45 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
677
795
|
return;
|
|
678
796
|
}
|
|
679
797
|
|
|
798
|
+
if (!provingState.tryStartProvingMerge(location)) {
|
|
799
|
+
logger.debug('Merge rollup already started.');
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
|
|
680
803
|
const inputs = provingState.getMergeRollupInputs(location);
|
|
681
804
|
|
|
682
805
|
this.deferredProving(
|
|
683
806
|
provingState,
|
|
684
807
|
wrapCallbackInSpan(
|
|
685
808
|
this.tracer,
|
|
686
|
-
'ProvingOrchestrator.prover.
|
|
809
|
+
'ProvingOrchestrator.prover.getTxMergeRollupProof',
|
|
687
810
|
{
|
|
688
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'merge
|
|
811
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'rollup-tx-merge' satisfies CircuitName,
|
|
689
812
|
},
|
|
690
|
-
signal => this.prover.
|
|
813
|
+
signal => this.prover.getTxMergeRollupProof(inputs, signal, provingState.epochNumber),
|
|
691
814
|
),
|
|
692
|
-
|
|
815
|
+
result => {
|
|
693
816
|
provingState.setMergeRollupProof(location, result);
|
|
694
|
-
|
|
817
|
+
this.checkAndEnqueueNextMergeRollup(provingState, location);
|
|
695
818
|
},
|
|
696
819
|
);
|
|
697
820
|
}
|
|
698
821
|
|
|
699
822
|
// Executes the block root rollup circuit
|
|
700
|
-
private
|
|
823
|
+
private enqueueBlockRootRollup(provingState: BlockProvingState) {
|
|
701
824
|
if (!provingState.verifyState()) {
|
|
702
825
|
logger.debug('Not running block root rollup, state no longer valid');
|
|
703
826
|
return;
|
|
704
827
|
}
|
|
705
828
|
|
|
706
|
-
provingState.
|
|
829
|
+
if (!provingState.tryStartProvingBlockRoot()) {
|
|
830
|
+
logger.debug('Block root rollup already started.');
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
707
833
|
|
|
708
|
-
const { rollupType, inputs } =
|
|
834
|
+
const { rollupType, inputs } = provingState.getBlockRootRollupTypeAndInputs();
|
|
709
835
|
|
|
710
|
-
logger.debug(
|
|
711
|
-
`Enqueuing ${rollupType} for block ${provingState.blockNumber} with ${provingState.newL1ToL2Messages.length} l1 to l2 msgs.`,
|
|
712
|
-
);
|
|
836
|
+
logger.debug(`Enqueuing ${rollupType} for block ${provingState.blockNumber}.`);
|
|
713
837
|
|
|
714
838
|
this.deferredProving(
|
|
715
839
|
provingState,
|
|
@@ -720,56 +844,32 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
720
844
|
[Attributes.PROTOCOL_CIRCUIT_NAME]: rollupType,
|
|
721
845
|
},
|
|
722
846
|
signal => {
|
|
723
|
-
if (inputs instanceof
|
|
724
|
-
return this.prover.
|
|
725
|
-
} else if (inputs instanceof
|
|
726
|
-
return this.prover.
|
|
847
|
+
if (inputs instanceof BlockRootFirstRollupPrivateInputs) {
|
|
848
|
+
return this.prover.getBlockRootFirstRollupProof(inputs, signal, provingState.epochNumber);
|
|
849
|
+
} else if (inputs instanceof BlockRootSingleTxFirstRollupPrivateInputs) {
|
|
850
|
+
return this.prover.getBlockRootSingleTxFirstRollupProof(inputs, signal, provingState.epochNumber);
|
|
851
|
+
} else if (inputs instanceof BlockRootEmptyTxFirstRollupPrivateInputs) {
|
|
852
|
+
return this.prover.getBlockRootEmptyTxFirstRollupProof(inputs, signal, provingState.epochNumber);
|
|
853
|
+
} else if (inputs instanceof BlockRootSingleTxRollupPrivateInputs) {
|
|
854
|
+
return this.prover.getBlockRootSingleTxRollupProof(inputs, signal, provingState.epochNumber);
|
|
727
855
|
} else {
|
|
728
856
|
return this.prover.getBlockRootRollupProof(inputs, signal, provingState.epochNumber);
|
|
729
857
|
}
|
|
730
858
|
},
|
|
731
859
|
),
|
|
732
860
|
async result => {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
if (!(await header.hash()).equals(await provingState.block!.header.hash())) {
|
|
736
|
-
logger.error(
|
|
737
|
-
`Block header mismatch.\nCircuit: ${inspect(header)}\nComputed: ${inspect(provingState.block!.header)}`,
|
|
738
|
-
);
|
|
739
|
-
provingState.reject(`Block header hash mismatch.`);
|
|
740
|
-
}
|
|
861
|
+
// If the proofs were slower than the block header building, then we need to try validating the block header hashes here.
|
|
862
|
+
await this.verifyBuiltBlockAgainstSyncedState(provingState);
|
|
741
863
|
|
|
742
|
-
|
|
743
|
-
const circuitArchiveRoot = result.inputs.newArchive.root;
|
|
744
|
-
if (!dbArchiveRoot.equals(circuitArchiveRoot)) {
|
|
745
|
-
logger.error(
|
|
746
|
-
`New archive root mismatch.\nCircuit: ${result.inputs.newArchive.root}\nComputed: ${dbArchiveRoot}`,
|
|
747
|
-
);
|
|
748
|
-
provingState.reject(`New archive root mismatch.`);
|
|
749
|
-
}
|
|
864
|
+
logger.debug(`Completed ${rollupType} proof for block ${provingState.blockNumber}`);
|
|
750
865
|
|
|
751
|
-
const
|
|
752
|
-
|
|
753
|
-
);
|
|
754
|
-
const circuitEndBlobAccumulatorState = result.inputs.blobPublicInputs.endBlobAccumulator;
|
|
755
|
-
if (!circuitEndBlobAccumulatorState.equals(endBlobAccumulatorPublicInputs)) {
|
|
756
|
-
logger.error(
|
|
757
|
-
`Blob accumulator state mismatch.\nCircuit: ${inspect(circuitEndBlobAccumulatorState)}\nComputed: ${inspect(
|
|
758
|
-
endBlobAccumulatorPublicInputs,
|
|
759
|
-
)}`,
|
|
760
|
-
);
|
|
761
|
-
provingState.reject(`Blob accumulator state mismatch.`);
|
|
762
|
-
}
|
|
866
|
+
const leafLocation = provingState.setBlockRootRollupProof(result);
|
|
867
|
+
const checkpointProvingState = provingState.parentCheckpoint;
|
|
763
868
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
const epochProvingState = this.provingState!;
|
|
768
|
-
const leafLocation = epochProvingState.setBlockRootRollupProof(provingState.index, result);
|
|
769
|
-
if (epochProvingState.totalNumBlocks === 1) {
|
|
770
|
-
this.enqueueEpochPadding(epochProvingState);
|
|
869
|
+
if (checkpointProvingState.totalNumBlocks === 1) {
|
|
870
|
+
this.checkAndEnqueueCheckpointRootRollup(checkpointProvingState);
|
|
771
871
|
} else {
|
|
772
|
-
this.checkAndEnqueueNextBlockMergeRollup(
|
|
872
|
+
this.checkAndEnqueueNextBlockMergeRollup(checkpointProvingState, leafLocation);
|
|
773
873
|
}
|
|
774
874
|
},
|
|
775
875
|
);
|
|
@@ -777,24 +877,35 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
777
877
|
|
|
778
878
|
// Executes the base parity circuit and stores the intermediate state for the root parity circuit
|
|
779
879
|
// Enqueues the root parity circuit if all inputs are available
|
|
780
|
-
private enqueueBaseParityCircuit(
|
|
880
|
+
private enqueueBaseParityCircuit(
|
|
881
|
+
checkpointProvingState: CheckpointProvingState,
|
|
882
|
+
provingState: BlockProvingState,
|
|
883
|
+
baseParityIndex: number,
|
|
884
|
+
) {
|
|
781
885
|
if (!provingState.verifyState()) {
|
|
782
886
|
logger.debug('Not running base parity. State no longer valid.');
|
|
783
887
|
return;
|
|
784
888
|
}
|
|
785
889
|
|
|
890
|
+
if (!provingState.tryStartProvingBaseParity(baseParityIndex)) {
|
|
891
|
+
logger.warn(`Base parity ${baseParityIndex} already started.`);
|
|
892
|
+
return;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
const inputs = checkpointProvingState.getBaseParityInputs(baseParityIndex);
|
|
896
|
+
|
|
786
897
|
this.deferredProving(
|
|
787
898
|
provingState,
|
|
788
899
|
wrapCallbackInSpan(
|
|
789
900
|
this.tracer,
|
|
790
901
|
'ProvingOrchestrator.prover.getBaseParityProof',
|
|
791
902
|
{
|
|
792
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'base
|
|
903
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'parity-base' satisfies CircuitName,
|
|
793
904
|
},
|
|
794
905
|
signal => this.prover.getBaseParityProof(inputs, signal, provingState.epochNumber),
|
|
795
906
|
),
|
|
796
907
|
provingOutput => {
|
|
797
|
-
provingState.setBaseParityProof(
|
|
908
|
+
provingState.setBaseParityProof(baseParityIndex, provingOutput);
|
|
798
909
|
this.checkAndEnqueueRootParityCircuit(provingState);
|
|
799
910
|
},
|
|
800
911
|
);
|
|
@@ -816,7 +927,12 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
816
927
|
return;
|
|
817
928
|
}
|
|
818
929
|
|
|
819
|
-
|
|
930
|
+
if (!provingState.tryStartProvingRootParity()) {
|
|
931
|
+
logger.debug('Root parity already started.');
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
const inputs = provingState.getParityRootInputs();
|
|
820
936
|
|
|
821
937
|
this.deferredProving(
|
|
822
938
|
provingState,
|
|
@@ -824,25 +940,30 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
824
940
|
this.tracer,
|
|
825
941
|
'ProvingOrchestrator.prover.getRootParityProof',
|
|
826
942
|
{
|
|
827
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'root
|
|
943
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'parity-root' satisfies CircuitName,
|
|
828
944
|
},
|
|
829
945
|
signal => this.prover.getRootParityProof(inputs, signal, provingState.epochNumber),
|
|
830
946
|
),
|
|
831
|
-
|
|
947
|
+
result => {
|
|
832
948
|
provingState.setRootParityProof(result);
|
|
833
|
-
|
|
949
|
+
this.checkAndEnqueueBlockRootRollup(provingState);
|
|
834
950
|
},
|
|
835
951
|
);
|
|
836
952
|
}
|
|
837
953
|
|
|
838
954
|
// Executes the block merge rollup circuit and stored the output as intermediate state for the parent merge/block root circuit
|
|
839
955
|
// Enqueues the next level of merge if all inputs are available
|
|
840
|
-
private enqueueBlockMergeRollup(provingState:
|
|
956
|
+
private enqueueBlockMergeRollup(provingState: CheckpointProvingState, location: TreeNodeLocation) {
|
|
841
957
|
if (!provingState.verifyState()) {
|
|
842
958
|
logger.debug('Not running block merge rollup. State no longer valid.');
|
|
843
959
|
return;
|
|
844
960
|
}
|
|
845
961
|
|
|
962
|
+
if (!provingState.tryStartProvingBlockMerge(location)) {
|
|
963
|
+
logger.debug('Block merge rollup already started.');
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
|
|
846
967
|
const inputs = provingState.getBlockMergeRollupInputs(location);
|
|
847
968
|
this.deferredProving(
|
|
848
969
|
provingState,
|
|
@@ -850,7 +971,7 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
850
971
|
this.tracer,
|
|
851
972
|
'ProvingOrchestrator.prover.getBlockMergeRollupProof',
|
|
852
973
|
{
|
|
853
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'block-merge
|
|
974
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'rollup-block-merge' satisfies CircuitName,
|
|
854
975
|
},
|
|
855
976
|
signal => this.prover.getBlockMergeRollupProof(inputs, signal, provingState.epochNumber),
|
|
856
977
|
),
|
|
@@ -861,29 +982,126 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
861
982
|
);
|
|
862
983
|
}
|
|
863
984
|
|
|
985
|
+
private enqueueCheckpointRootRollup(provingState: CheckpointProvingState) {
|
|
986
|
+
if (!provingState.verifyState()) {
|
|
987
|
+
logger.debug('Not running checkpoint root rollup. State no longer valid.');
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
if (!provingState.tryStartProvingCheckpointRoot()) {
|
|
992
|
+
logger.debug('Checkpoint root rollup already started.');
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
const rollupType = provingState.getCheckpointRootRollupType();
|
|
997
|
+
|
|
998
|
+
logger.debug(`Enqueuing ${rollupType} for checkpoint ${provingState.index}.`);
|
|
999
|
+
|
|
1000
|
+
this.deferredProving(
|
|
1001
|
+
provingState,
|
|
1002
|
+
wrapCallbackInSpan(
|
|
1003
|
+
this.tracer,
|
|
1004
|
+
'ProvingOrchestrator.prover.getCheckpointRootRollupProof',
|
|
1005
|
+
{
|
|
1006
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: rollupType,
|
|
1007
|
+
},
|
|
1008
|
+
async signal => {
|
|
1009
|
+
const inputs = await provingState.getCheckpointRootRollupInputs();
|
|
1010
|
+
if (inputs instanceof CheckpointRootSingleBlockRollupPrivateInputs) {
|
|
1011
|
+
return this.prover.getCheckpointRootSingleBlockRollupProof(inputs, signal, provingState.epochNumber);
|
|
1012
|
+
} else {
|
|
1013
|
+
return this.prover.getCheckpointRootRollupProof(inputs, signal, provingState.epochNumber);
|
|
1014
|
+
}
|
|
1015
|
+
},
|
|
1016
|
+
),
|
|
1017
|
+
result => {
|
|
1018
|
+
const computedEndBlobAccumulatorState = BlobAccumulatorPublicInputs.fromBatchedBlobAccumulator(
|
|
1019
|
+
provingState.getEndBlobAccumulator()!,
|
|
1020
|
+
);
|
|
1021
|
+
const circuitEndBlobAccumulatorState = result.inputs.endBlobAccumulator;
|
|
1022
|
+
if (!circuitEndBlobAccumulatorState.equals(computedEndBlobAccumulatorState)) {
|
|
1023
|
+
logger.error(
|
|
1024
|
+
`Blob accumulator state mismatch.\nCircuit: ${inspect(circuitEndBlobAccumulatorState)}\nComputed: ${inspect(
|
|
1025
|
+
computedEndBlobAccumulatorState,
|
|
1026
|
+
)}`,
|
|
1027
|
+
);
|
|
1028
|
+
provingState.reject(`Blob accumulator state mismatch.`);
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
logger.debug(`Completed ${rollupType} proof for checkpoint ${provingState.index}.`);
|
|
1033
|
+
|
|
1034
|
+
const leafLocation = provingState.setCheckpointRootRollupProof(result);
|
|
1035
|
+
const epochProvingState = provingState.parentEpoch;
|
|
1036
|
+
|
|
1037
|
+
if (epochProvingState.totalNumCheckpoints === 1) {
|
|
1038
|
+
this.enqueueEpochPadding(epochProvingState);
|
|
1039
|
+
} else {
|
|
1040
|
+
this.checkAndEnqueueNextCheckpointMergeRollup(epochProvingState, leafLocation);
|
|
1041
|
+
}
|
|
1042
|
+
},
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
private enqueueCheckpointMergeRollup(provingState: EpochProvingState, location: TreeNodeLocation) {
|
|
1047
|
+
if (!provingState.verifyState()) {
|
|
1048
|
+
logger.debug('Not running checkpoint merge rollup. State no longer valid.');
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
if (!provingState.tryStartProvingCheckpointMerge(location)) {
|
|
1053
|
+
logger.debug('Checkpoint merge rollup already started.');
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
const inputs = provingState.getCheckpointMergeRollupInputs(location);
|
|
1058
|
+
|
|
1059
|
+
this.deferredProving(
|
|
1060
|
+
provingState,
|
|
1061
|
+
wrapCallbackInSpan(
|
|
1062
|
+
this.tracer,
|
|
1063
|
+
'ProvingOrchestrator.prover.getCheckpointMergeRollupProof',
|
|
1064
|
+
{
|
|
1065
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'rollup-checkpoint-merge' satisfies CircuitName,
|
|
1066
|
+
},
|
|
1067
|
+
signal => this.prover.getCheckpointMergeRollupProof(inputs, signal, provingState.epochNumber),
|
|
1068
|
+
),
|
|
1069
|
+
result => {
|
|
1070
|
+
logger.debug('Completed proof for checkpoint merge rollup.');
|
|
1071
|
+
provingState.setCheckpointMergeRollupProof(location, result);
|
|
1072
|
+
this.checkAndEnqueueNextCheckpointMergeRollup(provingState, location);
|
|
1073
|
+
},
|
|
1074
|
+
);
|
|
1075
|
+
}
|
|
1076
|
+
|
|
864
1077
|
private enqueueEpochPadding(provingState: EpochProvingState) {
|
|
865
1078
|
if (!provingState.verifyState()) {
|
|
866
1079
|
logger.debug('Not running epoch padding. State no longer valid.');
|
|
867
1080
|
return;
|
|
868
1081
|
}
|
|
869
1082
|
|
|
1083
|
+
if (!provingState.tryStartProvingPaddingCheckpoint()) {
|
|
1084
|
+
logger.debug('Padding checkpoint already started.');
|
|
1085
|
+
return;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
870
1088
|
logger.debug('Padding epoch proof with a padding block root proof.');
|
|
871
1089
|
|
|
872
|
-
const inputs = provingState.
|
|
1090
|
+
const inputs = provingState.getPaddingCheckpointInputs();
|
|
873
1091
|
|
|
874
1092
|
this.deferredProving(
|
|
875
1093
|
provingState,
|
|
876
1094
|
wrapCallbackInSpan(
|
|
877
1095
|
this.tracer,
|
|
878
|
-
'ProvingOrchestrator.prover.
|
|
1096
|
+
'ProvingOrchestrator.prover.getCheckpointPaddingRollupProof',
|
|
879
1097
|
{
|
|
880
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: '
|
|
1098
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'rollup-checkpoint-padding' satisfies CircuitName,
|
|
881
1099
|
},
|
|
882
|
-
signal => this.prover.
|
|
1100
|
+
signal => this.prover.getCheckpointPaddingRollupProof(inputs, signal, provingState.epochNumber),
|
|
883
1101
|
),
|
|
884
1102
|
result => {
|
|
885
|
-
logger.debug('Completed proof for padding
|
|
886
|
-
provingState.
|
|
1103
|
+
logger.debug('Completed proof for padding checkpoint.');
|
|
1104
|
+
provingState.setCheckpointPaddingProof(result);
|
|
887
1105
|
this.checkAndEnqueueRootRollup(provingState);
|
|
888
1106
|
},
|
|
889
1107
|
);
|
|
@@ -906,7 +1124,7 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
906
1124
|
this.tracer,
|
|
907
1125
|
'ProvingOrchestrator.prover.getRootRollupProof',
|
|
908
1126
|
{
|
|
909
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'root
|
|
1127
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'rollup-root' satisfies CircuitName,
|
|
910
1128
|
},
|
|
911
1129
|
signal => this.prover.getRootRollupProof(inputs, signal, provingState.epochNumber),
|
|
912
1130
|
),
|
|
@@ -918,48 +1136,51 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
918
1136
|
);
|
|
919
1137
|
}
|
|
920
1138
|
|
|
921
|
-
private
|
|
1139
|
+
private checkAndEnqueueNextMergeRollup(provingState: BlockProvingState, currentLocation: TreeNodeLocation) {
|
|
922
1140
|
if (!provingState.isReadyForMergeRollup(currentLocation)) {
|
|
923
1141
|
return;
|
|
924
1142
|
}
|
|
925
1143
|
|
|
926
1144
|
const parentLocation = provingState.getParentLocation(currentLocation);
|
|
927
1145
|
if (parentLocation.level === 0) {
|
|
928
|
-
|
|
1146
|
+
this.checkAndEnqueueBlockRootRollup(provingState);
|
|
929
1147
|
} else {
|
|
930
1148
|
this.enqueueMergeRollup(provingState, parentLocation);
|
|
931
1149
|
}
|
|
932
1150
|
}
|
|
933
1151
|
|
|
934
|
-
private
|
|
935
|
-
const blockNumber = provingState.blockNumber;
|
|
936
|
-
// Accumulate as far as we can, in case blocks came in out of order and we are behind:
|
|
937
|
-
await this.provingState?.setBlobAccumulators(blockNumber);
|
|
1152
|
+
private checkAndEnqueueBlockRootRollup(provingState: BlockProvingState) {
|
|
938
1153
|
if (!provingState.isReadyForBlockRootRollup()) {
|
|
939
1154
|
logger.debug('Not ready for block root rollup');
|
|
940
1155
|
return;
|
|
941
1156
|
}
|
|
942
|
-
|
|
943
|
-
|
|
1157
|
+
|
|
1158
|
+
this.enqueueBlockRootRollup(provingState);
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
private checkAndEnqueueNextBlockMergeRollup(provingState: CheckpointProvingState, currentLocation: TreeNodeLocation) {
|
|
1162
|
+
if (!provingState.isReadyForBlockMerge(currentLocation)) {
|
|
944
1163
|
return;
|
|
945
1164
|
}
|
|
946
1165
|
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
?.close()
|
|
955
|
-
.then(() => this.dbs.delete(blockNumber))
|
|
956
|
-
.catch(err => logger.error(`Error closing db for block ${blockNumber}`, err));
|
|
1166
|
+
const parentLocation = provingState.getParentLocation(currentLocation);
|
|
1167
|
+
if (parentLocation.level === 0) {
|
|
1168
|
+
this.checkAndEnqueueCheckpointRootRollup(provingState);
|
|
1169
|
+
} else {
|
|
1170
|
+
this.enqueueBlockMergeRollup(provingState, parentLocation);
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
957
1173
|
|
|
958
|
-
|
|
1174
|
+
private checkAndEnqueueCheckpointRootRollup(provingState: CheckpointProvingState) {
|
|
1175
|
+
if (!provingState.isReadyForCheckpointRoot()) {
|
|
1176
|
+
return;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
this.enqueueCheckpointRootRollup(provingState);
|
|
959
1180
|
}
|
|
960
1181
|
|
|
961
|
-
private
|
|
962
|
-
if (!provingState.
|
|
1182
|
+
private checkAndEnqueueNextCheckpointMergeRollup(provingState: EpochProvingState, currentLocation: TreeNodeLocation) {
|
|
1183
|
+
if (!provingState.isReadyForCheckpointMerge(currentLocation)) {
|
|
963
1184
|
return;
|
|
964
1185
|
}
|
|
965
1186
|
|
|
@@ -967,7 +1188,7 @@ export class ProvingOrchestrator implements EpochProver {
|
|
|
967
1188
|
if (parentLocation.level === 0) {
|
|
968
1189
|
this.checkAndEnqueueRootRollup(provingState);
|
|
969
1190
|
} else {
|
|
970
|
-
this.
|
|
1191
|
+
this.enqueueCheckpointMergeRollup(provingState, parentLocation);
|
|
971
1192
|
}
|
|
972
1193
|
}
|
|
973
1194
|
|