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