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