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