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