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