@aztec/prover-client 0.76.4 → 0.77.0-testnet-ignition.21
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/bin/get-proof-inputs.js +18 -17
- package/dest/block_builder/index.d.ts +1 -1
- package/dest/block_builder/index.d.ts.map +1 -1
- package/dest/block_builder/index.js +0 -1
- package/dest/block_builder/light.d.ts +4 -2
- package/dest/block_builder/light.d.ts.map +1 -1
- package/dest/block_builder/light.js +28 -15
- package/dest/config.d.ts +2 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +10 -12
- package/dest/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +0 -1
- package/dest/mocks/fixtures.d.ts +4 -3
- package/dest/mocks/fixtures.d.ts.map +1 -1
- package/dest/mocks/fixtures.js +37 -30
- package/dest/mocks/test_context.d.ts +16 -12
- package/dest/mocks/test_context.d.ts.map +1 -1
- package/dest/mocks/test_context.js +85 -62
- package/dest/orchestrator/block-building-helpers.d.ts +12 -7
- package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
- package/dest/orchestrator/block-building-helpers.js +98 -87
- package/dest/orchestrator/block-proving-state.d.ts +13 -8
- package/dest/orchestrator/block-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/block-proving-state.js +101 -73
- package/dest/orchestrator/epoch-proving-state.d.ts +10 -6
- package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/epoch-proving-state.js +57 -41
- package/dest/orchestrator/index.js +0 -1
- package/dest/orchestrator/orchestrator.d.ts +7 -5
- package/dest/orchestrator/orchestrator.d.ts.map +1 -1
- package/dest/orchestrator/orchestrator.js +656 -654
- package/dest/orchestrator/orchestrator_metrics.js +4 -3
- package/dest/orchestrator/tx-proving-state.d.ts +7 -4
- package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/tx-proving-state.js +54 -52
- package/dest/prover-client/factory.d.ts +2 -2
- package/dest/prover-client/factory.d.ts.map +1 -1
- package/dest/prover-client/factory.js +0 -1
- package/dest/prover-client/index.js +0 -1
- package/dest/prover-client/prover-client.d.ts +3 -3
- package/dest/prover-client/prover-client.d.ts.map +1 -1
- package/dest/prover-client/prover-client.js +31 -26
- package/dest/prover-client/server-epoch-prover.d.ts +8 -5
- package/dest/prover-client/server-epoch-prover.d.ts.map +1 -1
- package/dest/prover-client/server-epoch-prover.js +4 -4
- package/dest/proving_broker/broker_prover_facade.d.ts +5 -3
- package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -1
- package/dest/proving_broker/broker_prover_facade.js +80 -67
- package/dest/proving_broker/config.d.ts +15 -2
- package/dest/proving_broker/config.d.ts.map +1 -1
- package/dest/proving_broker/config.js +49 -44
- 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 +1 -6
- package/dest/proving_broker/fixtures.d.ts +1 -1
- package/dest/proving_broker/fixtures.d.ts.map +1 -1
- package/dest/proving_broker/fixtures.js +2 -2
- package/dest/proving_broker/index.js +0 -1
- package/dest/proving_broker/proof_store/factory.d.ts +1 -1
- package/dest/proving_broker/proof_store/factory.d.ts.map +1 -1
- package/dest/proving_broker/proof_store/factory.js +9 -12
- package/dest/proving_broker/proof_store/gcs_proof_store.d.ts +3 -2
- package/dest/proving_broker/proof_store/gcs_proof_store.d.ts.map +1 -1
- package/dest/proving_broker/proof_store/gcs_proof_store.js +12 -7
- package/dest/proving_broker/proof_store/index.js +0 -1
- package/dest/proving_broker/proof_store/inline_proof_store.d.ts +3 -2
- package/dest/proving_broker/proof_store/inline_proof_store.d.ts.map +1 -1
- package/dest/proving_broker/proof_store/inline_proof_store.js +11 -7
- package/dest/proving_broker/proof_store/proof_store.d.ts +2 -1
- package/dest/proving_broker/proof_store/proof_store.d.ts.map +1 -1
- package/dest/proving_broker/proof_store/proof_store.js +3 -2
- package/dest/proving_broker/proving_agent.d.ts +3 -2
- package/dest/proving_broker/proving_agent.d.ts.map +1 -1
- package/dest/proving_broker/proving_agent.js +121 -124
- package/dest/proving_broker/proving_agent_instrumentation.d.ts +1 -1
- package/dest/proving_broker/proving_agent_instrumentation.d.ts.map +1 -1
- package/dest/proving_broker/proving_agent_instrumentation.js +6 -6
- package/dest/proving_broker/proving_broker.d.ts +4 -11
- package/dest/proving_broker/proving_broker.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker.js +490 -446
- package/dest/proving_broker/proving_broker_database/memory.d.ts +2 -2
- package/dest/proving_broker/proving_broker_database/memory.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker_database/memory.js +19 -13
- package/dest/proving_broker/proving_broker_database/persisted.d.ts +3 -3
- package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker_database/persisted.js +62 -29
- package/dest/proving_broker/proving_broker_database.d.ts +1 -1
- package/dest/proving_broker/proving_broker_database.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker_database.js +3 -2
- package/dest/proving_broker/proving_broker_instrumentation.d.ts +6 -2
- package/dest/proving_broker/proving_broker_instrumentation.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker_instrumentation.js +47 -22
- package/dest/proving_broker/proving_job_controller.d.ts +2 -1
- package/dest/proving_broker/proving_job_controller.d.ts.map +1 -1
- package/dest/proving_broker/proving_job_controller.js +81 -62
- package/dest/proving_broker/rpc.d.ts +4 -3
- package/dest/proving_broker/rpc.d.ts.map +1 -1
- package/dest/proving_broker/rpc.js +29 -25
- package/dest/test/mock_prover.d.ts +7 -5
- package/dest/test/mock_prover.d.ts.map +1 -1
- package/dest/test/mock_prover.js +13 -9
- package/package.json +16 -15
- package/src/bin/get-proof-inputs.ts +5 -6
- package/src/block_builder/index.ts +1 -1
- package/src/block_builder/light.ts +7 -10
- package/src/config.ts +2 -2
- package/src/index.ts +1 -1
- package/src/mocks/fixtures.ts +13 -15
- package/src/mocks/test_context.ts +60 -102
- package/src/orchestrator/block-building-helpers.ts +50 -45
- package/src/orchestrator/block-proving-state.ts +18 -22
- package/src/orchestrator/epoch-proving-state.ts +11 -16
- package/src/orchestrator/orchestrator.ts +26 -33
- package/src/orchestrator/tx-proving-state.ts +10 -13
- package/src/prover-client/factory.ts +2 -2
- package/src/prover-client/prover-client.ts +12 -12
- package/src/prover-client/server-epoch-prover.ts +8 -5
- package/src/proving_broker/broker_prover_facade.ts +29 -31
- package/src/proving_broker/config.ts +31 -3
- package/src/proving_broker/factory.ts +3 -11
- package/src/proving_broker/fixtures.ts +2 -1
- package/src/proving_broker/proof_store/factory.ts +1 -1
- package/src/proving_broker/proof_store/gcs_proof_store.ts +3 -3
- package/src/proving_broker/proof_store/inline_proof_store.ts +5 -5
- package/src/proving_broker/proof_store/proof_store.ts +9 -9
- package/src/proving_broker/proving_agent.ts +11 -11
- package/src/proving_broker/proving_agent_instrumentation.ts +5 -5
- package/src/proving_broker/proving_broker.ts +35 -32
- package/src/proving_broker/proving_broker_database/memory.ts +2 -2
- package/src/proving_broker/proving_broker_database/persisted.ts +8 -8
- package/src/proving_broker/proving_broker_database.ts +1 -1
- package/src/proving_broker/proving_broker_instrumentation.ts +24 -2
- package/src/proving_broker/proving_job_controller.ts +7 -7
- package/src/proving_broker/rpc.ts +6 -7
- package/src/test/mock_prover.ts +28 -30
|
@@ -1,18 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
}
|
|
7
|
+
import { AVM_PROOF_LENGTH_IN_FIELDS, AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, L1_TO_L2_MSG_SUBTREE_HEIGHT, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NUM_BASE_PARITY_PER_ROOT_PARITY } from '@aztec/constants';
|
|
5
8
|
import { padArrayEnd, times } from '@aztec/foundation/collection';
|
|
6
9
|
import { AbortError } from '@aztec/foundation/error';
|
|
10
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
7
11
|
import { createLogger } from '@aztec/foundation/log';
|
|
8
12
|
import { promiseWithResolvers } from '@aztec/foundation/promise';
|
|
9
13
|
import { assertLength } from '@aztec/foundation/serialize';
|
|
10
14
|
import { pushTestData } from '@aztec/foundation/testing';
|
|
11
15
|
import { elapsed } from '@aztec/foundation/timer';
|
|
12
|
-
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/
|
|
13
|
-
import {
|
|
16
|
+
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
17
|
+
import { L2Block } from '@aztec/stdlib/block';
|
|
18
|
+
import { BaseParityInputs } from '@aztec/stdlib/parity';
|
|
19
|
+
import { makeEmptyRecursiveProof } from '@aztec/stdlib/proofs';
|
|
20
|
+
import { EmptyBlockRootRollupInputs, PrivateBaseRollupInputs, SingleTxBlockRootRollupInputs, TubeInputs } from '@aztec/stdlib/rollup';
|
|
21
|
+
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
22
|
+
import { toNumBlobFields } from '@aztec/stdlib/tx';
|
|
23
|
+
import { VerificationKeyData } from '@aztec/stdlib/vks';
|
|
24
|
+
import { Attributes, getTelemetryClient, trackSpan, wrapCallbackInSpan } from '@aztec/telemetry-client';
|
|
14
25
|
import { inspect } from 'util';
|
|
15
|
-
import { buildBaseRollupHints, buildHeaderAndBodyFromTxs, getRootTreeSiblingPath, getSubtreeSiblingPath, getTreeSnapshot, validatePartialState, validateTx
|
|
26
|
+
import { buildBaseRollupHints, buildHeaderAndBodyFromTxs, getRootTreeSiblingPath, getSubtreeSiblingPath, getTreeSnapshot, validatePartialState, validateTx } from './block-building-helpers.js';
|
|
16
27
|
import { EpochProvingState } from './epoch-proving-state.js';
|
|
17
28
|
import { ProvingOrchestratorMetrics } from './orchestrator_metrics.js';
|
|
18
29
|
import { TxProvingState } from './tx-proving-state.js';
|
|
@@ -26,663 +37,654 @@ const logger = createLogger('prover-client:orchestrator');
|
|
|
26
37
|
* 5. Merge proofs are produced at each level of the tree until the root proof is produced
|
|
27
38
|
*
|
|
28
39
|
* The proving implementation is determined by the provided prover. This could be for example a local prover or a remote prover pool.
|
|
29
|
-
*/
|
|
30
|
-
/**
|
|
40
|
+
*/ /**
|
|
31
41
|
* The orchestrator, managing the flow of recursive proving operations required to build the rollup proof tree.
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (!provingState.verifyState()) {
|
|
125
|
-
throw new Error(`Invalid proving state when adding a tx`);
|
|
126
|
-
}
|
|
127
|
-
validateTx(tx);
|
|
128
|
-
logger.info(`Received transaction: ${tx.hash}`);
|
|
129
|
-
const [hints, treeSnapshots] = await this.prepareTransaction(tx, provingState);
|
|
130
|
-
const txProvingState = new TxProvingState(tx, hints, treeSnapshots);
|
|
131
|
-
const txIndex = provingState.addNewTx(txProvingState);
|
|
132
|
-
this.getOrEnqueueTube(provingState, txIndex);
|
|
133
|
-
if (txProvingState.requireAvmProof) {
|
|
134
|
-
logger.debug(`Enqueueing public VM for tx ${txIndex}`);
|
|
135
|
-
this.enqueueVM(provingState, txIndex);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
catch (err) {
|
|
139
|
-
throw new Error(`Error adding transaction ${tx.hash.toString()} to block ${blockNumber}: ${err.message}`, {
|
|
140
|
-
cause: err,
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Kickstarts tube circuits for the specified txs. These will be used during epoch proving.
|
|
147
|
-
* Note that if the tube circuits are not started this way, they will be started nontheless after processing.
|
|
148
|
-
*/
|
|
149
|
-
async startTubeCircuits(txs) {
|
|
150
|
-
if (!this.provingState?.verifyState()) {
|
|
151
|
-
throw new Error(`Invalid proving state, call startNewEpoch before starting tube circuits`);
|
|
152
|
-
}
|
|
153
|
-
for (const tx of txs) {
|
|
154
|
-
const txHash = (await tx.getTxHash()).toString();
|
|
155
|
-
const tubeInputs = new TubeInputs(tx.clientIvcProof);
|
|
156
|
-
const tubeProof = promiseWithResolvers();
|
|
157
|
-
logger.debug(`Starting tube circuit for tx ${txHash}`);
|
|
158
|
-
this.doEnqueueTube(txHash, tubeInputs, proof => tubeProof.resolve(proof));
|
|
159
|
-
this.provingState?.cachedTubeProofs.set(txHash, tubeProof.promise);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Marks the block as completed.
|
|
164
|
-
* Computes the block header and updates the archive tree.
|
|
165
|
-
*/
|
|
166
|
-
async setBlockCompleted(blockNumber, expectedHeader) {
|
|
167
|
-
const provingState = this.provingState?.getBlockProvingStateByBlockNumber(blockNumber);
|
|
168
|
-
if (!provingState) {
|
|
169
|
-
throw new Error(`Block proving state for ${blockNumber} not found`);
|
|
170
|
-
}
|
|
171
|
-
if (!provingState.spongeBlobState) {
|
|
172
|
-
// If we are completing an empty block, initialise the provingState.
|
|
173
|
-
// We will have 0 txs and no blob fields.
|
|
174
|
-
provingState.startNewBlock(0, 0);
|
|
175
|
-
}
|
|
42
|
+
*/ export class ProvingOrchestrator {
|
|
43
|
+
dbProvider;
|
|
44
|
+
prover;
|
|
45
|
+
proverId;
|
|
46
|
+
provingState;
|
|
47
|
+
pendingProvingJobs;
|
|
48
|
+
provingPromise;
|
|
49
|
+
metrics;
|
|
50
|
+
dbs;
|
|
51
|
+
constructor(dbProvider, prover, proverId = Fr.ZERO, telemetryClient = getTelemetryClient()){
|
|
52
|
+
this.dbProvider = dbProvider;
|
|
53
|
+
this.prover = prover;
|
|
54
|
+
this.proverId = proverId;
|
|
55
|
+
this.provingState = undefined;
|
|
56
|
+
this.pendingProvingJobs = [];
|
|
57
|
+
this.provingPromise = undefined;
|
|
58
|
+
this.dbs = new Map();
|
|
59
|
+
this.metrics = new ProvingOrchestratorMetrics(telemetryClient, 'ProvingOrchestrator');
|
|
60
|
+
}
|
|
61
|
+
get tracer() {
|
|
62
|
+
return this.metrics.tracer;
|
|
63
|
+
}
|
|
64
|
+
getProverId() {
|
|
65
|
+
return this.proverId;
|
|
66
|
+
}
|
|
67
|
+
stop() {
|
|
68
|
+
this.cancel();
|
|
69
|
+
return Promise.resolve();
|
|
70
|
+
}
|
|
71
|
+
startNewEpoch(epochNumber, firstBlockNumber, totalNumBlocks) {
|
|
72
|
+
const { promise: _promise, resolve, reject } = promiseWithResolvers();
|
|
73
|
+
const promise = _promise.catch((reason)=>({
|
|
74
|
+
status: 'failure',
|
|
75
|
+
reason
|
|
76
|
+
}));
|
|
77
|
+
if (totalNumBlocks <= 0 || !Number.isInteger(totalNumBlocks)) {
|
|
78
|
+
throw new Error(`Invalid number of blocks for epoch (got ${totalNumBlocks})`);
|
|
79
|
+
}
|
|
80
|
+
logger.info(`Starting epoch ${epochNumber} with ${totalNumBlocks} blocks`);
|
|
81
|
+
this.provingState = new EpochProvingState(epochNumber, firstBlockNumber, totalNumBlocks, resolve, reject);
|
|
82
|
+
this.provingPromise = promise;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Starts off a new block
|
|
86
|
+
* @param globalVariables - The global variables for the block
|
|
87
|
+
* @param l1ToL2Messages - The l1 to l2 messages for the block
|
|
88
|
+
* @returns A proving ticket, containing a promise notifying of proving completion
|
|
89
|
+
*/ async startNewBlock(globalVariables, l1ToL2Messages, previousBlockHeader) {
|
|
90
|
+
if (!this.provingState) {
|
|
91
|
+
throw new Error(`Invalid proving state, call startNewEpoch before starting a block`);
|
|
92
|
+
}
|
|
93
|
+
if (!this.provingState?.isAcceptingBlocks()) {
|
|
94
|
+
throw new Error(`Epoch not accepting further blocks`);
|
|
95
|
+
}
|
|
96
|
+
logger.info(`Starting block ${globalVariables.blockNumber.toNumber()} for slot ${globalVariables.slotNumber.toNumber()}`);
|
|
97
|
+
// Fork world state at the end of the immediately previous block
|
|
98
|
+
const db = await this.dbProvider.fork(globalVariables.blockNumber.toNumber() - 1);
|
|
99
|
+
this.dbs.set(globalVariables.blockNumber.toNumber(), db);
|
|
100
|
+
// we start the block by enqueueing all of the base parity circuits
|
|
101
|
+
const { l1ToL2MessageSubtreeSiblingPath, l1ToL2MessageTreeSnapshotAfterInsertion, baseParityInputs } = await this.prepareBaseParityInputs(l1ToL2Messages, db);
|
|
102
|
+
// Get archive snapshot before this block lands
|
|
103
|
+
const lastArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
|
|
104
|
+
const newArchiveSiblingPath = await getRootTreeSiblingPath(MerkleTreeId.ARCHIVE, db);
|
|
105
|
+
const blockProvingState = this.provingState.startNewBlock(globalVariables, l1ToL2Messages, l1ToL2MessageSubtreeSiblingPath, l1ToL2MessageTreeSnapshotAfterInsertion, lastArchive, newArchiveSiblingPath, previousBlockHeader);
|
|
106
|
+
// Enqueue base parity circuits for the block
|
|
107
|
+
for(let i = 0; i < baseParityInputs.length; i++){
|
|
108
|
+
this.enqueueBaseParityCircuit(blockProvingState, baseParityInputs[i], i);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* The interface to add simulated transactions to the scheduler. This can only be called once per block.
|
|
113
|
+
* @param txs - The transactions to be proven
|
|
114
|
+
*/ async addTxs(txs) {
|
|
115
|
+
if (!txs.length) {
|
|
116
|
+
// To avoid an ugly throw below. If we require an empty block, we can just call setBlockCompleted
|
|
117
|
+
// on a block with no txs. We cannot do that here because we cannot find the blockNumber without any txs.
|
|
118
|
+
logger.warn(`Provided no txs to orchestrator addTxs.`);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const blockNumber = txs[0].constants.globalVariables.blockNumber.toNumber();
|
|
122
|
+
const provingState = this.provingState?.getBlockProvingStateByBlockNumber(blockNumber);
|
|
123
|
+
if (!provingState) {
|
|
124
|
+
throw new Error(`Block proving state for ${blockNumber} not found`);
|
|
125
|
+
}
|
|
126
|
+
if (provingState.totalNumTxs) {
|
|
127
|
+
throw new Error(`Block ${blockNumber} has been initialized with transactions.`);
|
|
128
|
+
}
|
|
129
|
+
const numBlobFields = toNumBlobFields(txs);
|
|
130
|
+
provingState.startNewBlock(txs.length, numBlobFields);
|
|
131
|
+
logger.info(`Adding ${txs.length} transactions with ${numBlobFields} blob fields to block ${provingState.blockNumber}`);
|
|
132
|
+
for (const tx of txs){
|
|
133
|
+
try {
|
|
176
134
|
if (!provingState.verifyState()) {
|
|
177
|
-
throw new Error(`
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
logger.
|
|
181
|
-
await this.
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
return block;
|
|
193
|
-
}
|
|
194
|
-
async buildBlock(provingState, expectedHeader) {
|
|
195
|
-
// Collect all new nullifiers, commitments, and contracts from all txs in this block to build body
|
|
196
|
-
const txs = provingState.allTxs.map(a => a.processedTx);
|
|
197
|
-
// Get db for this block
|
|
198
|
-
const db = this.dbs.get(provingState.blockNumber);
|
|
199
|
-
// Given we've applied every change from this block, now assemble the block header
|
|
200
|
-
// and update the archive tree, so we're ready to start processing the next block
|
|
201
|
-
const { header, body } = await buildHeaderAndBodyFromTxs(txs, provingState.globalVariables, provingState.newL1ToL2Messages, db);
|
|
202
|
-
if (expectedHeader && !header.equals(expectedHeader)) {
|
|
203
|
-
logger.error(`Block header mismatch: header=${header} expectedHeader=${expectedHeader}`);
|
|
204
|
-
throw new Error('Block header mismatch');
|
|
205
|
-
}
|
|
206
|
-
logger.verbose(`Updating archive tree with block ${provingState.blockNumber} header ${(await header.hash()).toString()}`);
|
|
207
|
-
await db.updateArchive(header);
|
|
208
|
-
// Assemble the L2 block
|
|
209
|
-
const newArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
|
|
210
|
-
const l2Block = new L2Block(newArchive, header, body);
|
|
211
|
-
await this.verifyBuiltBlockAgainstSyncedState(l2Block, newArchive);
|
|
212
|
-
logger.verbose(`Orchestrator finalised block ${l2Block.number}`);
|
|
213
|
-
provingState.block = l2Block;
|
|
214
|
-
}
|
|
215
|
-
// Flagged as protected to disable in certain unit tests
|
|
216
|
-
async verifyBuiltBlockAgainstSyncedState(l2Block, newArchive) {
|
|
217
|
-
const syncedArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, this.dbProvider.getSnapshot(l2Block.number));
|
|
218
|
-
if (!syncedArchive.equals(newArchive)) {
|
|
219
|
-
throw new Error(`Archive tree mismatch for block ${l2Block.number}: world state synced to ${inspect(syncedArchive)} but built ${inspect(newArchive)}`);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
/**
|
|
223
|
-
* Cancel any further proving
|
|
224
|
-
*/
|
|
225
|
-
cancel() {
|
|
226
|
-
for (const controller of this.pendingProvingJobs) {
|
|
227
|
-
controller.abort();
|
|
228
|
-
}
|
|
229
|
-
this.provingState?.cancel();
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* Returns the proof for the current epoch.
|
|
233
|
-
*/
|
|
234
|
-
async finaliseEpoch() {
|
|
235
|
-
if (!this.provingState || !this.provingPromise) {
|
|
236
|
-
throw new Error(`Invalid proving state, an epoch must be proven before it can be finalised`);
|
|
237
|
-
}
|
|
238
|
-
const result = await this.provingPromise;
|
|
239
|
-
if (result.status === 'failure') {
|
|
240
|
-
throw new Error(`Epoch proving failed: ${result.reason}`);
|
|
241
|
-
}
|
|
242
|
-
const epochProofResult = this.provingState.getEpochProofResult();
|
|
243
|
-
pushTestData('epochProofResult', {
|
|
244
|
-
proof: epochProofResult.proof.toString(),
|
|
245
|
-
publicInputs: epochProofResult.publicInputs.toString(),
|
|
246
|
-
});
|
|
247
|
-
return epochProofResult;
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* Starts the proving process for the given transaction and adds it to our state
|
|
251
|
-
* @param tx - The transaction whose proving we wish to commence
|
|
252
|
-
* @param provingState - The proving state being worked on
|
|
253
|
-
*/
|
|
254
|
-
async prepareTransaction(tx, provingState) {
|
|
255
|
-
const txInputs = await this.prepareBaseRollupInputs(provingState, tx);
|
|
256
|
-
if (!txInputs) {
|
|
257
|
-
// This should not be possible
|
|
258
|
-
throw new Error(`Unable to add transaction, preparing base inputs failed`);
|
|
259
|
-
}
|
|
260
|
-
return txInputs;
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Enqueue a job to be scheduled
|
|
264
|
-
* @param provingState - The proving state object being operated on
|
|
265
|
-
* @param jobType - The type of job to be queued
|
|
266
|
-
* @param job - The actual job, returns a promise notifying of the job's completion
|
|
267
|
-
*/
|
|
268
|
-
deferredProving(provingState, request, callback) {
|
|
269
|
-
if (!provingState?.verifyState()) {
|
|
270
|
-
logger.debug(`Not enqueuing job, state no longer valid`);
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
const controller = new AbortController();
|
|
274
|
-
this.pendingProvingJobs.push(controller);
|
|
275
|
-
// We use a 'safeJob'. We don't want promise rejections in the proving pool, we want to capture the error here
|
|
276
|
-
// and reject the proving job whilst keeping the event loop free of rejections
|
|
277
|
-
const safeJob = async () => {
|
|
278
|
-
try {
|
|
279
|
-
// there's a delay between enqueueing this job and it actually running
|
|
280
|
-
if (controller.signal.aborted) {
|
|
281
|
-
return;
|
|
282
|
-
}
|
|
283
|
-
const result = await request(controller.signal);
|
|
284
|
-
if (!provingState?.verifyState()) {
|
|
285
|
-
logger.debug(`State no longer valid, discarding result`);
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
// we could have been cancelled whilst waiting for the result
|
|
289
|
-
// and the prover ignored the signal. Drop the result in that case
|
|
290
|
-
if (controller.signal.aborted) {
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
await callback(result);
|
|
294
|
-
}
|
|
295
|
-
catch (err) {
|
|
296
|
-
if (err instanceof AbortError) {
|
|
297
|
-
// operation was cancelled, probably because the block was cancelled
|
|
298
|
-
// drop this result
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
logger.error(`Error thrown when proving job`, err);
|
|
302
|
-
provingState.reject(`${err}`);
|
|
303
|
-
}
|
|
304
|
-
finally {
|
|
305
|
-
const index = this.pendingProvingJobs.indexOf(controller);
|
|
306
|
-
if (index > -1) {
|
|
307
|
-
this.pendingProvingJobs.splice(index, 1);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
};
|
|
311
|
-
// let the callstack unwind before adding the job to the queue
|
|
312
|
-
setImmediate(() => void safeJob());
|
|
313
|
-
}
|
|
314
|
-
async prepareBaseParityInputs(l1ToL2Messages, db) {
|
|
315
|
-
const l1ToL2MessagesPadded = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 'Too many L1 to L2 messages');
|
|
316
|
-
const baseParityInputs = times(NUM_BASE_PARITY_PER_ROOT_PARITY, i => BaseParityInputs.fromSlice(l1ToL2MessagesPadded, i, getVKTreeRoot()));
|
|
317
|
-
const l1ToL2MessageSubtreeSiblingPath = assertLength(await getSubtreeSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, L1_TO_L2_MSG_SUBTREE_HEIGHT, db), L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH);
|
|
318
|
-
// Update the local trees to include the new l1 to l2 messages
|
|
319
|
-
await db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
|
|
320
|
-
const l1ToL2MessageTreeSnapshotAfterInsertion = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db);
|
|
321
|
-
return {
|
|
322
|
-
l1ToL2MessageSubtreeSiblingPath,
|
|
323
|
-
l1ToL2MessageTreeSnapshotAfterInsertion,
|
|
324
|
-
baseParityInputs,
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
// Updates the merkle trees for a transaction. The first enqueued job for a transaction
|
|
328
|
-
async prepareBaseRollupInputs(provingState, tx) {
|
|
329
|
-
if (!provingState.verifyState() || !provingState.spongeBlobState) {
|
|
330
|
-
logger.debug('Not preparing base rollup inputs, state invalid');
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
const db = this.dbs.get(provingState.blockNumber);
|
|
334
|
-
// We build the base rollup inputs using a mock proof and verification key.
|
|
335
|
-
// These will be overwritten later once we have proven the tube circuit and any public kernels
|
|
336
|
-
const [ms, hints] = await elapsed(buildBaseRollupHints(tx, provingState.globalVariables, db, provingState.spongeBlobState));
|
|
337
|
-
this.metrics.recordBaseRollupInputs(ms);
|
|
338
|
-
const promises = [MerkleTreeId.NOTE_HASH_TREE, MerkleTreeId.NULLIFIER_TREE, MerkleTreeId.PUBLIC_DATA_TREE].map(async (id) => {
|
|
339
|
-
return { key: id, value: await getTreeSnapshot(id, db) };
|
|
135
|
+
throw new Error(`Invalid proving state when adding a tx`);
|
|
136
|
+
}
|
|
137
|
+
validateTx(tx);
|
|
138
|
+
logger.info(`Received transaction: ${tx.hash}`);
|
|
139
|
+
const [hints, treeSnapshots] = await this.prepareTransaction(tx, provingState);
|
|
140
|
+
const txProvingState = new TxProvingState(tx, hints, treeSnapshots);
|
|
141
|
+
const txIndex = provingState.addNewTx(txProvingState);
|
|
142
|
+
this.getOrEnqueueTube(provingState, txIndex);
|
|
143
|
+
if (txProvingState.requireAvmProof) {
|
|
144
|
+
logger.debug(`Enqueueing public VM for tx ${txIndex}`);
|
|
145
|
+
this.enqueueVM(provingState, txIndex);
|
|
146
|
+
}
|
|
147
|
+
} catch (err) {
|
|
148
|
+
throw new Error(`Error adding transaction ${tx.hash.toString()} to block ${blockNumber}: ${err.message}`, {
|
|
149
|
+
cause: err
|
|
340
150
|
});
|
|
341
|
-
const treeSnapshots = new Map((await Promise.all(promises)).map(obj => [obj.key, obj.value]));
|
|
342
|
-
if (!provingState.verifyState()) {
|
|
343
|
-
logger.debug(`Discarding proving job, state no longer valid`);
|
|
344
|
-
return;
|
|
345
|
-
}
|
|
346
|
-
return [hints, treeSnapshots];
|
|
347
151
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Kickstarts tube circuits for the specified txs. These will be used during epoch proving.
|
|
156
|
+
* Note that if the tube circuits are not started this way, they will be started nontheless after processing.
|
|
157
|
+
*/ async startTubeCircuits(txs) {
|
|
158
|
+
if (!this.provingState?.verifyState()) {
|
|
159
|
+
throw new Error(`Invalid proving state, call startNewEpoch before starting tube circuits`);
|
|
160
|
+
}
|
|
161
|
+
for (const tx of txs){
|
|
162
|
+
const txHash = (await tx.getTxHash()).toString();
|
|
163
|
+
const tubeInputs = new TubeInputs(tx.clientIvcProof);
|
|
164
|
+
const tubeProof = promiseWithResolvers();
|
|
165
|
+
logger.debug(`Starting tube circuit for tx ${txHash}`);
|
|
166
|
+
this.doEnqueueTube(txHash, tubeInputs, (proof)=>tubeProof.resolve(proof));
|
|
167
|
+
this.provingState?.cachedTubeProofs.set(txHash, tubeProof.promise);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Marks the block as completed.
|
|
172
|
+
* Computes the block header and updates the archive tree.
|
|
173
|
+
*/ async setBlockCompleted(blockNumber, expectedHeader) {
|
|
174
|
+
const provingState = this.provingState?.getBlockProvingStateByBlockNumber(blockNumber);
|
|
175
|
+
if (!provingState) {
|
|
176
|
+
throw new Error(`Block proving state for ${blockNumber} not found`);
|
|
177
|
+
}
|
|
178
|
+
if (!provingState.spongeBlobState) {
|
|
179
|
+
// If we are completing an empty block, initialise the provingState.
|
|
180
|
+
// We will have 0 txs and no blob fields.
|
|
181
|
+
provingState.startNewBlock(0, 0);
|
|
182
|
+
}
|
|
183
|
+
if (!provingState.verifyState()) {
|
|
184
|
+
throw new Error(`Block proving failed: ${provingState.error}`);
|
|
185
|
+
}
|
|
186
|
+
// And build the block header
|
|
187
|
+
logger.verbose(`Block ${blockNumber} completed. Assembling header.`);
|
|
188
|
+
await this.buildBlock(provingState, expectedHeader);
|
|
189
|
+
// If the proofs were faster than the block building, then we need to try the block root rollup again here
|
|
190
|
+
await this.checkAndEnqueueBlockRootRollup(provingState);
|
|
191
|
+
return provingState.block;
|
|
192
|
+
}
|
|
193
|
+
/** Returns the block as built for a given index. */ getBlock(index) {
|
|
194
|
+
const block = this.provingState?.blocks[index]?.block;
|
|
195
|
+
if (!block) {
|
|
196
|
+
throw new Error(`Block at index ${index} not available`);
|
|
197
|
+
}
|
|
198
|
+
return block;
|
|
199
|
+
}
|
|
200
|
+
async buildBlock(provingState, expectedHeader) {
|
|
201
|
+
// Collect all new nullifiers, commitments, and contracts from all txs in this block to build body
|
|
202
|
+
const txs = provingState.allTxs.map((a)=>a.processedTx);
|
|
203
|
+
// Get db for this block
|
|
204
|
+
const db = this.dbs.get(provingState.blockNumber);
|
|
205
|
+
// Given we've applied every change from this block, now assemble the block header
|
|
206
|
+
// and update the archive tree, so we're ready to start processing the next block
|
|
207
|
+
const { header, body } = await buildHeaderAndBodyFromTxs(txs, provingState.globalVariables, provingState.newL1ToL2Messages, db);
|
|
208
|
+
if (expectedHeader && !header.equals(expectedHeader)) {
|
|
209
|
+
logger.error(`Block header mismatch: header=${header} expectedHeader=${expectedHeader}`);
|
|
210
|
+
throw new Error('Block header mismatch');
|
|
211
|
+
}
|
|
212
|
+
logger.verbose(`Updating archive tree with block ${provingState.blockNumber} header ${(await header.hash()).toString()}`);
|
|
213
|
+
await db.updateArchive(header);
|
|
214
|
+
// Assemble the L2 block
|
|
215
|
+
const newArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
|
|
216
|
+
const l2Block = new L2Block(newArchive, header, body);
|
|
217
|
+
await this.verifyBuiltBlockAgainstSyncedState(l2Block, newArchive);
|
|
218
|
+
logger.verbose(`Orchestrator finalised block ${l2Block.number}`);
|
|
219
|
+
provingState.block = l2Block;
|
|
220
|
+
}
|
|
221
|
+
// Flagged as protected to disable in certain unit tests
|
|
222
|
+
async verifyBuiltBlockAgainstSyncedState(l2Block, newArchive) {
|
|
223
|
+
const syncedArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, this.dbProvider.getSnapshot(l2Block.number));
|
|
224
|
+
if (!syncedArchive.equals(newArchive)) {
|
|
225
|
+
throw new Error(`Archive tree mismatch for block ${l2Block.number}: world state synced to ${inspect(syncedArchive)} but built ${inspect(newArchive)}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Cancel any further proving
|
|
230
|
+
*/ cancel() {
|
|
231
|
+
for (const controller of this.pendingProvingJobs){
|
|
232
|
+
controller.abort();
|
|
233
|
+
}
|
|
234
|
+
this.provingState?.cancel();
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Returns the proof for the current epoch.
|
|
238
|
+
*/ async finaliseEpoch() {
|
|
239
|
+
if (!this.provingState || !this.provingPromise) {
|
|
240
|
+
throw new Error(`Invalid proving state, an epoch must be proven before it can be finalised`);
|
|
241
|
+
}
|
|
242
|
+
const result = await this.provingPromise;
|
|
243
|
+
if (result.status === 'failure') {
|
|
244
|
+
throw new Error(`Epoch proving failed: ${result.reason}`);
|
|
245
|
+
}
|
|
246
|
+
const epochProofResult = this.provingState.getEpochProofResult();
|
|
247
|
+
pushTestData('epochProofResult', {
|
|
248
|
+
proof: epochProofResult.proof.toString(),
|
|
249
|
+
publicInputs: epochProofResult.publicInputs.toString()
|
|
250
|
+
});
|
|
251
|
+
return epochProofResult;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Starts the proving process for the given transaction and adds it to our state
|
|
255
|
+
* @param tx - The transaction whose proving we wish to commence
|
|
256
|
+
* @param provingState - The proving state being worked on
|
|
257
|
+
*/ async prepareTransaction(tx, provingState) {
|
|
258
|
+
const txInputs = await this.prepareBaseRollupInputs(provingState, tx);
|
|
259
|
+
if (!txInputs) {
|
|
260
|
+
// This should not be possible
|
|
261
|
+
throw new Error(`Unable to add transaction, preparing base inputs failed`);
|
|
262
|
+
}
|
|
263
|
+
return txInputs;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Enqueue a job to be scheduled
|
|
267
|
+
* @param provingState - The proving state object being operated on
|
|
268
|
+
* @param jobType - The type of job to be queued
|
|
269
|
+
* @param job - The actual job, returns a promise notifying of the job's completion
|
|
270
|
+
*/ deferredProving(provingState, request, callback) {
|
|
271
|
+
if (!provingState?.verifyState()) {
|
|
272
|
+
logger.debug(`Not enqueuing job, state no longer valid`);
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
const controller = new AbortController();
|
|
276
|
+
this.pendingProvingJobs.push(controller);
|
|
277
|
+
// We use a 'safeJob'. We don't want promise rejections in the proving pool, we want to capture the error here
|
|
278
|
+
// and reject the proving job whilst keeping the event loop free of rejections
|
|
279
|
+
const safeJob = async ()=>{
|
|
280
|
+
try {
|
|
281
|
+
// there's a delay between enqueueing this job and it actually running
|
|
282
|
+
if (controller.signal.aborted) {
|
|
353
283
|
return;
|
|
354
284
|
}
|
|
355
|
-
const
|
|
356
|
-
const { processedTx } = txProvingState;
|
|
357
|
-
const { rollupType, inputs } = txProvingState.getBaseRollupTypeAndInputs();
|
|
358
|
-
logger.debug(`Enqueuing deferred proving base rollup for ${processedTx.hash.toString()}`);
|
|
359
|
-
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, `ProvingOrchestrator.prover.${inputs instanceof PrivateBaseRollupInputs ? 'getPrivateBaseRollupProof' : 'getPublicBaseRollupProof'}`, {
|
|
360
|
-
[Attributes.TX_HASH]: processedTx.hash.toString(),
|
|
361
|
-
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
362
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: rollupType,
|
|
363
|
-
}, signal => {
|
|
364
|
-
if (inputs instanceof PrivateBaseRollupInputs) {
|
|
365
|
-
return this.prover.getPrivateBaseRollupProof(inputs, signal, provingState.epochNumber);
|
|
366
|
-
}
|
|
367
|
-
else {
|
|
368
|
-
return this.prover.getPublicBaseRollupProof(inputs, signal, provingState.epochNumber);
|
|
369
|
-
}
|
|
370
|
-
}), async (result) => {
|
|
371
|
-
logger.debug(`Completed proof for ${rollupType} for tx ${processedTx.hash.toString()}`);
|
|
372
|
-
validatePartialState(result.inputs.end, txProvingState.treeSnapshots);
|
|
373
|
-
const leafLocation = provingState.setBaseRollupProof(txIndex, result);
|
|
374
|
-
if (provingState.totalNumTxs === 1) {
|
|
375
|
-
await this.checkAndEnqueueBlockRootRollup(provingState);
|
|
376
|
-
}
|
|
377
|
-
else {
|
|
378
|
-
await this.checkAndEnqueueNextMergeRollup(provingState, leafLocation);
|
|
379
|
-
}
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
// Enqueues the tube circuit for a given transaction index, or reuses the one already enqueued
|
|
383
|
-
// Once completed, will enqueue the next circuit, either a public kernel or the base rollup
|
|
384
|
-
getOrEnqueueTube(provingState, txIndex) {
|
|
385
|
-
if (!provingState.verifyState()) {
|
|
386
|
-
logger.debug('Not running tube circuit, state invalid');
|
|
387
|
-
return;
|
|
388
|
-
}
|
|
389
|
-
const txProvingState = provingState.getTxProvingState(txIndex);
|
|
390
|
-
const txHash = txProvingState.processedTx.hash.toString();
|
|
391
|
-
const handleResult = (result) => {
|
|
392
|
-
logger.debug(`Got tube proof for tx index: ${txIndex}`, { txHash });
|
|
393
|
-
txProvingState.setTubeProof(result);
|
|
394
|
-
this.provingState?.cachedTubeProofs.delete(txHash);
|
|
395
|
-
this.checkAndEnqueueNextTxCircuit(provingState, txIndex);
|
|
396
|
-
};
|
|
397
|
-
if (this.provingState?.cachedTubeProofs.has(txHash)) {
|
|
398
|
-
logger.debug(`Tube proof already enqueued for tx index: ${txIndex}`, { txHash });
|
|
399
|
-
void this.provingState.cachedTubeProofs.get(txHash).then(handleResult);
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
logger.debug(`Enqueuing tube circuit for tx index: ${txIndex}`);
|
|
403
|
-
this.doEnqueueTube(txHash, txProvingState.getTubeInputs(), handleResult);
|
|
404
|
-
}
|
|
405
|
-
doEnqueueTube(txHash, inputs, handler, provingState = this.provingState) {
|
|
285
|
+
const result = await request(controller.signal);
|
|
406
286
|
if (!provingState?.verifyState()) {
|
|
407
|
-
logger.debug(
|
|
287
|
+
logger.debug(`State no longer valid, discarding result`);
|
|
408
288
|
return;
|
|
409
289
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'tube-circuit',
|
|
414
|
-
}, signal => this.prover.getTubeProof(inputs, signal, this.provingState.epochNumber)), handler);
|
|
415
|
-
}
|
|
416
|
-
// Executes the merge rollup circuit and stored the output as intermediate state for the parent merge/block root circuit
|
|
417
|
-
// Enqueues the next level of merge if all inputs are available
|
|
418
|
-
enqueueMergeRollup(provingState, location) {
|
|
419
|
-
if (!provingState.verifyState()) {
|
|
420
|
-
logger.debug('Not running merge rollup. State no longer valid.');
|
|
290
|
+
// we could have been cancelled whilst waiting for the result
|
|
291
|
+
// and the prover ignored the signal. Drop the result in that case
|
|
292
|
+
if (controller.signal.aborted) {
|
|
421
293
|
return;
|
|
422
294
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
provingState.setMergeRollupProof(location, result);
|
|
429
|
-
await this.checkAndEnqueueNextMergeRollup(provingState, location);
|
|
430
|
-
});
|
|
431
|
-
}
|
|
432
|
-
// Executes the block root rollup circuit
|
|
433
|
-
async enqueueBlockRootRollup(provingState) {
|
|
434
|
-
if (!provingState.verifyState()) {
|
|
435
|
-
logger.debug('Not running block root rollup, state no longer valid');
|
|
436
|
-
return;
|
|
437
|
-
}
|
|
438
|
-
provingState.blockRootRollupStarted = true;
|
|
439
|
-
const { rollupType, inputs } = await provingState.getBlockRootRollupTypeAndInputs(this.proverId);
|
|
440
|
-
logger.debug(`Enqueuing ${rollupType} for block ${provingState.blockNumber} with ${provingState.newL1ToL2Messages.length} l1 to l2 msgs.`);
|
|
441
|
-
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getBlockRootRollupProof', {
|
|
442
|
-
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
443
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: rollupType,
|
|
444
|
-
}, signal => {
|
|
445
|
-
if (inputs instanceof EmptyBlockRootRollupInputs) {
|
|
446
|
-
return this.prover.getEmptyBlockRootRollupProof(inputs, signal, provingState.epochNumber);
|
|
447
|
-
}
|
|
448
|
-
else if (inputs instanceof SingleTxBlockRootRollupInputs) {
|
|
449
|
-
return this.prover.getSingleTxBlockRootRollupProof(inputs, signal, provingState.epochNumber);
|
|
450
|
-
}
|
|
451
|
-
else {
|
|
452
|
-
return this.prover.getBlockRootRollupProof(inputs, signal, provingState.epochNumber);
|
|
453
|
-
}
|
|
454
|
-
}), async (result) => {
|
|
455
|
-
provingState.setBlockRootRollupProof(result);
|
|
456
|
-
const header = await provingState.buildHeaderFromProvingOutputs(logger);
|
|
457
|
-
if (!(await header.hash()).equals(await provingState.block.header.hash())) {
|
|
458
|
-
logger.error(`Block header mismatch\nCircuit:${inspect(header)}\nComputed:${inspect(provingState.block.header)}`);
|
|
459
|
-
provingState.reject(`Block header hash mismatch`);
|
|
460
|
-
}
|
|
461
|
-
logger.debug(`Completed ${rollupType} proof for block ${provingState.block.number}`);
|
|
462
|
-
// validatePartialState(result.inputs.end, tx.treeSnapshots); // TODO(palla/prover)
|
|
463
|
-
const epochProvingState = this.provingState;
|
|
464
|
-
const leafLocation = epochProvingState.setBlockRootRollupProof(provingState.index, result);
|
|
465
|
-
if (epochProvingState.totalNumBlocks === 1) {
|
|
466
|
-
await this.enqueueEpochPadding(epochProvingState);
|
|
467
|
-
}
|
|
468
|
-
else {
|
|
469
|
-
this.checkAndEnqueueNextBlockMergeRollup(epochProvingState, leafLocation);
|
|
470
|
-
}
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
// Executes the base parity circuit and stores the intermediate state for the root parity circuit
|
|
474
|
-
// Enqueues the root parity circuit if all inputs are available
|
|
475
|
-
enqueueBaseParityCircuit(provingState, inputs, index) {
|
|
476
|
-
if (!provingState.verifyState()) {
|
|
477
|
-
logger.debug('Not running base parity. State no longer valid.');
|
|
478
|
-
return;
|
|
479
|
-
}
|
|
480
|
-
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getBaseParityProof', {
|
|
481
|
-
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
482
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-parity',
|
|
483
|
-
}, signal => this.prover.getBaseParityProof(inputs, signal, provingState.epochNumber)), provingOutput => {
|
|
484
|
-
provingState.setBaseParityProof(index, provingOutput);
|
|
485
|
-
this.checkAndEnqueueRootParityCircuit(provingState);
|
|
486
|
-
});
|
|
487
|
-
}
|
|
488
|
-
checkAndEnqueueRootParityCircuit(provingState) {
|
|
489
|
-
if (!provingState.isReadyForRootParity()) {
|
|
490
|
-
return;
|
|
491
|
-
}
|
|
492
|
-
this.enqueueRootParityCircuit(provingState);
|
|
493
|
-
}
|
|
494
|
-
// Runs the root parity circuit ans stored the outputs
|
|
495
|
-
// Enqueues the root rollup proof if all inputs are available
|
|
496
|
-
enqueueRootParityCircuit(provingState) {
|
|
497
|
-
if (!provingState.verifyState()) {
|
|
498
|
-
logger.debug('Not running root parity. State no longer valid.');
|
|
499
|
-
return;
|
|
500
|
-
}
|
|
501
|
-
const inputs = provingState.getRootParityInputs();
|
|
502
|
-
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getRootParityProof', {
|
|
503
|
-
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
504
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-parity',
|
|
505
|
-
}, signal => this.prover.getRootParityProof(inputs, signal, provingState.epochNumber)), async (result) => {
|
|
506
|
-
provingState.setRootParityProof(result);
|
|
507
|
-
await this.checkAndEnqueueBlockRootRollup(provingState);
|
|
508
|
-
});
|
|
509
|
-
}
|
|
510
|
-
// Executes the block merge rollup circuit and stored the output as intermediate state for the parent merge/block root circuit
|
|
511
|
-
// Enqueues the next level of merge if all inputs are available
|
|
512
|
-
enqueueBlockMergeRollup(provingState, location) {
|
|
513
|
-
if (!provingState.verifyState()) {
|
|
514
|
-
logger.debug('Not running block merge rollup. State no longer valid.');
|
|
515
|
-
return;
|
|
516
|
-
}
|
|
517
|
-
const inputs = provingState.getBlockMergeRollupInputs(location);
|
|
518
|
-
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getBlockMergeRollupProof', {
|
|
519
|
-
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
520
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'block-merge-rollup',
|
|
521
|
-
}, signal => this.prover.getBlockMergeRollupProof(inputs, signal, provingState.epochNumber)), result => {
|
|
522
|
-
provingState.setBlockMergeRollupProof(location, result);
|
|
523
|
-
this.checkAndEnqueueNextBlockMergeRollup(provingState, location);
|
|
524
|
-
});
|
|
525
|
-
}
|
|
526
|
-
async enqueueEpochPadding(provingState) {
|
|
527
|
-
if (!provingState.verifyState()) {
|
|
528
|
-
logger.debug('Not running epoch padding. State no longer valid.');
|
|
529
|
-
return;
|
|
530
|
-
}
|
|
531
|
-
logger.debug('Padding epoch proof with an empty block root proof.');
|
|
532
|
-
const inputs = await provingState.getPaddingBlockRootInputs(this.proverId);
|
|
533
|
-
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getEmptyBlockRootRollupProof', {
|
|
534
|
-
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
535
|
-
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'empty-block-root-rollup',
|
|
536
|
-
}, signal => this.prover.getEmptyBlockRootRollupProof(inputs, signal, provingState.epochNumber)), result => {
|
|
537
|
-
logger.debug('Completed proof for padding block root.');
|
|
538
|
-
provingState.setPaddingBlockRootProof(result);
|
|
539
|
-
this.checkAndEnqueueRootRollup(provingState);
|
|
540
|
-
});
|
|
541
|
-
}
|
|
542
|
-
// Executes the root rollup circuit
|
|
543
|
-
enqueueRootRollup(provingState) {
|
|
544
|
-
if (!provingState.verifyState()) {
|
|
545
|
-
logger.debug('Not running root rollup, state no longer valid');
|
|
295
|
+
await callback(result);
|
|
296
|
+
} catch (err) {
|
|
297
|
+
if (err instanceof AbortError) {
|
|
298
|
+
// operation was cancelled, probably because the block was cancelled
|
|
299
|
+
// drop this result
|
|
546
300
|
return;
|
|
547
301
|
}
|
|
548
|
-
logger.
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
await
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
}
|
|
663
|
-
(
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JjaGVzdHJhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL29yY2hlc3RyYXRvci9vcmNoZXN0cmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFDTCxPQUFPLEVBQ1AsWUFBWSxFQUlaLGVBQWUsR0FDaEIsTUFBTSxzQkFBc0IsQ0FBQztBQVE5QixPQUFPLEVBQ0wsMEJBQTBCLEVBQzFCLHFDQUFxQyxFQUVyQyxnQkFBZ0IsRUFFaEIsRUFBRSxFQUVGLDJCQUEyQixFQUMzQix3Q0FBd0MsRUFDeEMsbUNBQW1DLEVBQ25DLCtCQUErQixFQUUvQixtQkFBbUIsRUFDbkIsdUJBQXVCLEdBQ3hCLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUVMLDBCQUEwQixFQUMxQix1QkFBdUIsRUFDdkIsNkJBQTZCLEVBQzdCLFVBQVUsR0FDWCxNQUFNLDJCQUEyQixDQUFDO0FBQ25DLE9BQU8sRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDbEUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNqRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDM0QsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUVsRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDeEUsT0FBTyxFQUNMLFVBQVUsRUFHVixrQkFBa0IsRUFDbEIsU0FBUyxFQUNULGtCQUFrQixHQUNuQixNQUFNLHlCQUF5QixDQUFDO0FBRWpDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFB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
|
|
302
|
+
logger.error(`Error thrown when proving job`, err);
|
|
303
|
+
provingState.reject(`${err}`);
|
|
304
|
+
} finally{
|
|
305
|
+
const index = this.pendingProvingJobs.indexOf(controller);
|
|
306
|
+
if (index > -1) {
|
|
307
|
+
this.pendingProvingJobs.splice(index, 1);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
// let the callstack unwind before adding the job to the queue
|
|
312
|
+
setImmediate(()=>void safeJob());
|
|
313
|
+
}
|
|
314
|
+
async prepareBaseParityInputs(l1ToL2Messages, db) {
|
|
315
|
+
const l1ToL2MessagesPadded = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 'Too many L1 to L2 messages');
|
|
316
|
+
const baseParityInputs = times(NUM_BASE_PARITY_PER_ROOT_PARITY, (i)=>BaseParityInputs.fromSlice(l1ToL2MessagesPadded, i, getVKTreeRoot()));
|
|
317
|
+
const l1ToL2MessageSubtreeSiblingPath = assertLength(await getSubtreeSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, L1_TO_L2_MSG_SUBTREE_HEIGHT, db), L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH);
|
|
318
|
+
// Update the local trees to include the new l1 to l2 messages
|
|
319
|
+
await db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
|
|
320
|
+
const l1ToL2MessageTreeSnapshotAfterInsertion = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db);
|
|
321
|
+
return {
|
|
322
|
+
l1ToL2MessageSubtreeSiblingPath,
|
|
323
|
+
l1ToL2MessageTreeSnapshotAfterInsertion,
|
|
324
|
+
baseParityInputs
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
// Updates the merkle trees for a transaction. The first enqueued job for a transaction
|
|
328
|
+
async prepareBaseRollupInputs(provingState, tx) {
|
|
329
|
+
if (!provingState.verifyState() || !provingState.spongeBlobState) {
|
|
330
|
+
logger.debug('Not preparing base rollup inputs, state invalid');
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
const db = this.dbs.get(provingState.blockNumber);
|
|
334
|
+
// We build the base rollup inputs using a mock proof and verification key.
|
|
335
|
+
// These will be overwritten later once we have proven the tube circuit and any public kernels
|
|
336
|
+
const [ms, hints] = await elapsed(buildBaseRollupHints(tx, provingState.globalVariables, db, provingState.spongeBlobState));
|
|
337
|
+
this.metrics.recordBaseRollupInputs(ms);
|
|
338
|
+
const promises = [
|
|
339
|
+
MerkleTreeId.NOTE_HASH_TREE,
|
|
340
|
+
MerkleTreeId.NULLIFIER_TREE,
|
|
341
|
+
MerkleTreeId.PUBLIC_DATA_TREE
|
|
342
|
+
].map(async (id)=>{
|
|
343
|
+
return {
|
|
344
|
+
key: id,
|
|
345
|
+
value: await getTreeSnapshot(id, db)
|
|
346
|
+
};
|
|
347
|
+
});
|
|
348
|
+
const treeSnapshots = new Map((await Promise.all(promises)).map((obj)=>[
|
|
349
|
+
obj.key,
|
|
350
|
+
obj.value
|
|
351
|
+
]));
|
|
352
|
+
if (!provingState.verifyState()) {
|
|
353
|
+
logger.debug(`Discarding proving job, state no longer valid`);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
return [
|
|
357
|
+
hints,
|
|
358
|
+
treeSnapshots
|
|
359
|
+
];
|
|
360
|
+
}
|
|
361
|
+
// Executes the base rollup circuit and stored the output as intermediate state for the parent merge/root circuit
|
|
362
|
+
// Executes the next level of merge if all inputs are available
|
|
363
|
+
enqueueBaseRollup(provingState, txIndex) {
|
|
364
|
+
if (!provingState.verifyState()) {
|
|
365
|
+
logger.debug('Not running base rollup, state invalid');
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
const txProvingState = provingState.getTxProvingState(txIndex);
|
|
369
|
+
const { processedTx } = txProvingState;
|
|
370
|
+
const { rollupType, inputs } = txProvingState.getBaseRollupTypeAndInputs();
|
|
371
|
+
logger.debug(`Enqueuing deferred proving base rollup for ${processedTx.hash.toString()}`);
|
|
372
|
+
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, `ProvingOrchestrator.prover.${inputs instanceof PrivateBaseRollupInputs ? 'getPrivateBaseRollupProof' : 'getPublicBaseRollupProof'}`, {
|
|
373
|
+
[Attributes.TX_HASH]: processedTx.hash.toString(),
|
|
374
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
375
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: rollupType
|
|
376
|
+
}, (signal)=>{
|
|
377
|
+
if (inputs instanceof PrivateBaseRollupInputs) {
|
|
378
|
+
return this.prover.getPrivateBaseRollupProof(inputs, signal, provingState.epochNumber);
|
|
379
|
+
} else {
|
|
380
|
+
return this.prover.getPublicBaseRollupProof(inputs, signal, provingState.epochNumber);
|
|
381
|
+
}
|
|
382
|
+
}), async (result)=>{
|
|
383
|
+
logger.debug(`Completed proof for ${rollupType} for tx ${processedTx.hash.toString()}`);
|
|
384
|
+
validatePartialState(result.inputs.end, txProvingState.treeSnapshots);
|
|
385
|
+
const leafLocation = provingState.setBaseRollupProof(txIndex, result);
|
|
386
|
+
if (provingState.totalNumTxs === 1) {
|
|
387
|
+
await this.checkAndEnqueueBlockRootRollup(provingState);
|
|
388
|
+
} else {
|
|
389
|
+
await this.checkAndEnqueueNextMergeRollup(provingState, leafLocation);
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
// Enqueues the tube circuit for a given transaction index, or reuses the one already enqueued
|
|
394
|
+
// Once completed, will enqueue the next circuit, either a public kernel or the base rollup
|
|
395
|
+
getOrEnqueueTube(provingState, txIndex) {
|
|
396
|
+
if (!provingState.verifyState()) {
|
|
397
|
+
logger.debug('Not running tube circuit, state invalid');
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
const txProvingState = provingState.getTxProvingState(txIndex);
|
|
401
|
+
const txHash = txProvingState.processedTx.hash.toString();
|
|
402
|
+
const handleResult = (result)=>{
|
|
403
|
+
logger.debug(`Got tube proof for tx index: ${txIndex}`, {
|
|
404
|
+
txHash
|
|
405
|
+
});
|
|
406
|
+
txProvingState.setTubeProof(result);
|
|
407
|
+
this.provingState?.cachedTubeProofs.delete(txHash);
|
|
408
|
+
this.checkAndEnqueueNextTxCircuit(provingState, txIndex);
|
|
409
|
+
};
|
|
410
|
+
if (this.provingState?.cachedTubeProofs.has(txHash)) {
|
|
411
|
+
logger.debug(`Tube proof already enqueued for tx index: ${txIndex}`, {
|
|
412
|
+
txHash
|
|
413
|
+
});
|
|
414
|
+
void this.provingState.cachedTubeProofs.get(txHash).then(handleResult);
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
logger.debug(`Enqueuing tube circuit for tx index: ${txIndex}`);
|
|
418
|
+
this.doEnqueueTube(txHash, txProvingState.getTubeInputs(), handleResult);
|
|
419
|
+
}
|
|
420
|
+
doEnqueueTube(txHash, inputs, handler, provingState = this.provingState) {
|
|
421
|
+
if (!provingState?.verifyState()) {
|
|
422
|
+
logger.debug('Not running tube circuit, state invalid');
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getTubeProof', {
|
|
426
|
+
[Attributes.TX_HASH]: txHash,
|
|
427
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
428
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'tube-circuit'
|
|
429
|
+
}, (signal)=>this.prover.getTubeProof(inputs, signal, this.provingState.epochNumber)), handler);
|
|
430
|
+
}
|
|
431
|
+
// Executes the merge rollup circuit and stored the output as intermediate state for the parent merge/block root circuit
|
|
432
|
+
// Enqueues the next level of merge if all inputs are available
|
|
433
|
+
enqueueMergeRollup(provingState, location) {
|
|
434
|
+
if (!provingState.verifyState()) {
|
|
435
|
+
logger.debug('Not running merge rollup. State no longer valid.');
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
const inputs = provingState.getMergeRollupInputs(location);
|
|
439
|
+
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getMergeRollupProof', {
|
|
440
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
441
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'merge-rollup'
|
|
442
|
+
}, (signal)=>this.prover.getMergeRollupProof(inputs, signal, provingState.epochNumber)), async (result)=>{
|
|
443
|
+
provingState.setMergeRollupProof(location, result);
|
|
444
|
+
await this.checkAndEnqueueNextMergeRollup(provingState, location);
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
// Executes the block root rollup circuit
|
|
448
|
+
async enqueueBlockRootRollup(provingState) {
|
|
449
|
+
if (!provingState.verifyState()) {
|
|
450
|
+
logger.debug('Not running block root rollup, state no longer valid');
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
provingState.blockRootRollupStarted = true;
|
|
454
|
+
const { rollupType, inputs } = await provingState.getBlockRootRollupTypeAndInputs(this.proverId);
|
|
455
|
+
logger.debug(`Enqueuing ${rollupType} for block ${provingState.blockNumber} with ${provingState.newL1ToL2Messages.length} l1 to l2 msgs.`);
|
|
456
|
+
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getBlockRootRollupProof', {
|
|
457
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
458
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: rollupType
|
|
459
|
+
}, (signal)=>{
|
|
460
|
+
if (inputs instanceof EmptyBlockRootRollupInputs) {
|
|
461
|
+
return this.prover.getEmptyBlockRootRollupProof(inputs, signal, provingState.epochNumber);
|
|
462
|
+
} else if (inputs instanceof SingleTxBlockRootRollupInputs) {
|
|
463
|
+
return this.prover.getSingleTxBlockRootRollupProof(inputs, signal, provingState.epochNumber);
|
|
464
|
+
} else {
|
|
465
|
+
return this.prover.getBlockRootRollupProof(inputs, signal, provingState.epochNumber);
|
|
466
|
+
}
|
|
467
|
+
}), async (result)=>{
|
|
468
|
+
provingState.setBlockRootRollupProof(result);
|
|
469
|
+
const header = await provingState.buildHeaderFromProvingOutputs(logger);
|
|
470
|
+
if (!(await header.hash()).equals(await provingState.block.header.hash())) {
|
|
471
|
+
logger.error(`Block header mismatch\nCircuit:${inspect(header)}\nComputed:${inspect(provingState.block.header)}`);
|
|
472
|
+
provingState.reject(`Block header hash mismatch`);
|
|
473
|
+
}
|
|
474
|
+
logger.debug(`Completed ${rollupType} proof for block ${provingState.block.number}`);
|
|
475
|
+
// validatePartialState(result.inputs.end, tx.treeSnapshots); // TODO(palla/prover)
|
|
476
|
+
const epochProvingState = this.provingState;
|
|
477
|
+
const leafLocation = epochProvingState.setBlockRootRollupProof(provingState.index, result);
|
|
478
|
+
if (epochProvingState.totalNumBlocks === 1) {
|
|
479
|
+
await this.enqueueEpochPadding(epochProvingState);
|
|
480
|
+
} else {
|
|
481
|
+
this.checkAndEnqueueNextBlockMergeRollup(epochProvingState, leafLocation);
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
// Executes the base parity circuit and stores the intermediate state for the root parity circuit
|
|
486
|
+
// Enqueues the root parity circuit if all inputs are available
|
|
487
|
+
enqueueBaseParityCircuit(provingState, inputs, index) {
|
|
488
|
+
if (!provingState.verifyState()) {
|
|
489
|
+
logger.debug('Not running base parity. State no longer valid.');
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getBaseParityProof', {
|
|
493
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
494
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-parity'
|
|
495
|
+
}, (signal)=>this.prover.getBaseParityProof(inputs, signal, provingState.epochNumber)), (provingOutput)=>{
|
|
496
|
+
provingState.setBaseParityProof(index, provingOutput);
|
|
497
|
+
this.checkAndEnqueueRootParityCircuit(provingState);
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
checkAndEnqueueRootParityCircuit(provingState) {
|
|
501
|
+
if (!provingState.isReadyForRootParity()) {
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
this.enqueueRootParityCircuit(provingState);
|
|
505
|
+
}
|
|
506
|
+
// Runs the root parity circuit ans stored the outputs
|
|
507
|
+
// Enqueues the root rollup proof if all inputs are available
|
|
508
|
+
enqueueRootParityCircuit(provingState) {
|
|
509
|
+
if (!provingState.verifyState()) {
|
|
510
|
+
logger.debug('Not running root parity. State no longer valid.');
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
const inputs = provingState.getRootParityInputs();
|
|
514
|
+
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getRootParityProof', {
|
|
515
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
516
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-parity'
|
|
517
|
+
}, (signal)=>this.prover.getRootParityProof(inputs, signal, provingState.epochNumber)), async (result)=>{
|
|
518
|
+
provingState.setRootParityProof(result);
|
|
519
|
+
await this.checkAndEnqueueBlockRootRollup(provingState);
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
// Executes the block merge rollup circuit and stored the output as intermediate state for the parent merge/block root circuit
|
|
523
|
+
// Enqueues the next level of merge if all inputs are available
|
|
524
|
+
enqueueBlockMergeRollup(provingState, location) {
|
|
525
|
+
if (!provingState.verifyState()) {
|
|
526
|
+
logger.debug('Not running block merge rollup. State no longer valid.');
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
const inputs = provingState.getBlockMergeRollupInputs(location);
|
|
530
|
+
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getBlockMergeRollupProof', {
|
|
531
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
532
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'block-merge-rollup'
|
|
533
|
+
}, (signal)=>this.prover.getBlockMergeRollupProof(inputs, signal, provingState.epochNumber)), (result)=>{
|
|
534
|
+
provingState.setBlockMergeRollupProof(location, result);
|
|
535
|
+
this.checkAndEnqueueNextBlockMergeRollup(provingState, location);
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
async enqueueEpochPadding(provingState) {
|
|
539
|
+
if (!provingState.verifyState()) {
|
|
540
|
+
logger.debug('Not running epoch padding. State no longer valid.');
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
logger.debug('Padding epoch proof with an empty block root proof.');
|
|
544
|
+
const inputs = await provingState.getPaddingBlockRootInputs(this.proverId);
|
|
545
|
+
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getEmptyBlockRootRollupProof', {
|
|
546
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
547
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'empty-block-root-rollup'
|
|
548
|
+
}, (signal)=>this.prover.getEmptyBlockRootRollupProof(inputs, signal, provingState.epochNumber)), (result)=>{
|
|
549
|
+
logger.debug('Completed proof for padding block root.');
|
|
550
|
+
provingState.setPaddingBlockRootProof(result);
|
|
551
|
+
this.checkAndEnqueueRootRollup(provingState);
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
// Executes the root rollup circuit
|
|
555
|
+
enqueueRootRollup(provingState) {
|
|
556
|
+
if (!provingState.verifyState()) {
|
|
557
|
+
logger.debug('Not running root rollup, state no longer valid');
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
logger.debug(`Preparing root rollup`);
|
|
561
|
+
const inputs = provingState.getRootRollupInputs(this.proverId);
|
|
562
|
+
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getRootRollupProof', {
|
|
563
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
564
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-rollup'
|
|
565
|
+
}, (signal)=>this.prover.getRootRollupProof(inputs, signal, provingState.epochNumber)), (result)=>{
|
|
566
|
+
logger.verbose(`Orchestrator completed root rollup for epoch ${provingState.epochNumber}`);
|
|
567
|
+
provingState.setRootRollupProof(result);
|
|
568
|
+
provingState.resolve({
|
|
569
|
+
status: 'success'
|
|
570
|
+
});
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
async checkAndEnqueueNextMergeRollup(provingState, currentLocation) {
|
|
574
|
+
if (!provingState.isReadyForMergeRollup(currentLocation)) {
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
const parentLocation = provingState.getParentLocation(currentLocation);
|
|
578
|
+
if (parentLocation.level === 0) {
|
|
579
|
+
await this.checkAndEnqueueBlockRootRollup(provingState);
|
|
580
|
+
} else {
|
|
581
|
+
this.enqueueMergeRollup(provingState, parentLocation);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
async checkAndEnqueueBlockRootRollup(provingState) {
|
|
585
|
+
if (!provingState.isReadyForBlockRootRollup()) {
|
|
586
|
+
logger.debug('Not ready for root rollup');
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
if (provingState.blockRootRollupStarted) {
|
|
590
|
+
logger.debug('Block root rollup already started');
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
const blockNumber = provingState.blockNumber;
|
|
594
|
+
// TODO(palla/prover): This closes the fork only on the happy path. If this epoch orchestrator
|
|
595
|
+
// is aborted and never reaches this point, it will leak the fork. We need to add a global cleanup,
|
|
596
|
+
// but have to make sure it only runs once all operations are completed, otherwise some function here
|
|
597
|
+
// will attempt to access the fork after it was closed.
|
|
598
|
+
logger.debug(`Cleaning up world state fork for ${blockNumber}`);
|
|
599
|
+
void this.dbs.get(blockNumber)?.close().then(()=>this.dbs.delete(blockNumber)).catch((err)=>logger.error(`Error closing db for block ${blockNumber}`, err));
|
|
600
|
+
await this.enqueueBlockRootRollup(provingState);
|
|
601
|
+
}
|
|
602
|
+
checkAndEnqueueNextBlockMergeRollup(provingState, currentLocation) {
|
|
603
|
+
if (!provingState.isReadyForBlockMerge(currentLocation)) {
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
const parentLocation = provingState.getParentLocation(currentLocation);
|
|
607
|
+
if (parentLocation.level === 0) {
|
|
608
|
+
this.checkAndEnqueueRootRollup(provingState);
|
|
609
|
+
} else {
|
|
610
|
+
this.enqueueBlockMergeRollup(provingState, parentLocation);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
checkAndEnqueueRootRollup(provingState) {
|
|
614
|
+
if (!provingState.isReadyForRootRollup()) {
|
|
615
|
+
logger.debug('Not ready for root rollup');
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
this.enqueueRootRollup(provingState);
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Executes the VM circuit for a public function, will enqueue the corresponding kernel if the
|
|
622
|
+
* previous kernel is ready
|
|
623
|
+
* @param provingState - The proving state being operated on
|
|
624
|
+
* @param txIndex - The index of the transaction being proven
|
|
625
|
+
*/ enqueueVM(provingState, txIndex) {
|
|
626
|
+
if (!provingState.verifyState()) {
|
|
627
|
+
logger.debug(`Not running VM circuit as state is no longer valid`);
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
const txProvingState = provingState.getTxProvingState(txIndex);
|
|
631
|
+
// This function tries to do AVM proving. If there is a failure, it fakes the proof unless AVM_PROVING_STRICT is defined.
|
|
632
|
+
// Nothing downstream depends on the AVM proof yet. So having this mode lets us incrementally build the AVM circuit.
|
|
633
|
+
const doAvmProving = wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getAvmProof', {
|
|
634
|
+
[Attributes.TX_HASH]: txProvingState.processedTx.hash.toString()
|
|
635
|
+
}, async (signal)=>{
|
|
636
|
+
const inputs = txProvingState.getAvmInputs();
|
|
637
|
+
try {
|
|
638
|
+
return await this.prover.getAvmProof(inputs, signal, provingState.epochNumber);
|
|
639
|
+
} catch (err) {
|
|
640
|
+
if (process.env.AVM_PROVING_STRICT) {
|
|
641
|
+
logger.error(`Error thrown when proving AVM circuit with AVM_PROVING_STRICT on`, err);
|
|
642
|
+
throw err;
|
|
643
|
+
} else {
|
|
644
|
+
logger.warn(`Error thrown when proving AVM circuit but AVM_PROVING_STRICT is off. Faking AVM proof and carrying on. ${inspect(err)}.`);
|
|
645
|
+
return {
|
|
646
|
+
proof: makeEmptyRecursiveProof(AVM_PROOF_LENGTH_IN_FIELDS),
|
|
647
|
+
verificationKey: VerificationKeyData.makeFake(AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS)
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
});
|
|
652
|
+
this.deferredProving(provingState, doAvmProving, (proofAndVk)=>{
|
|
653
|
+
logger.debug(`Proven VM for tx index: ${txIndex}`);
|
|
654
|
+
txProvingState.setAvmProof(proofAndVk);
|
|
655
|
+
this.checkAndEnqueueNextTxCircuit(provingState, txIndex);
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
checkAndEnqueueNextTxCircuit(provingState, txIndex) {
|
|
659
|
+
const txProvingState = provingState.getTxProvingState(txIndex);
|
|
660
|
+
if (!txProvingState.ready()) {
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
// We must have completed all proving (tube proof and (if required) vm proof are generated), we now move to the base rollup.
|
|
664
|
+
logger.debug(`Public functions completed for tx ${txIndex} enqueueing base rollup`);
|
|
665
|
+
this.enqueueBaseRollup(provingState, txIndex);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
_ts_decorate([
|
|
669
|
+
trackSpan('ProvingOrchestrator.startNewBlock', (globalVariables)=>({
|
|
670
|
+
[Attributes.BLOCK_NUMBER]: globalVariables.blockNumber.toNumber()
|
|
671
|
+
}))
|
|
672
|
+
], ProvingOrchestrator.prototype, "startNewBlock", null);
|
|
673
|
+
_ts_decorate([
|
|
674
|
+
trackSpan('ProvingOrchestrator.addTxs', (txs)=>({
|
|
675
|
+
[Attributes.BLOCK_TXS_COUNT]: txs.length
|
|
676
|
+
}))
|
|
677
|
+
], ProvingOrchestrator.prototype, "addTxs", null);
|
|
678
|
+
_ts_decorate([
|
|
679
|
+
trackSpan('ProvingOrchestrator.startTubeCircuits')
|
|
680
|
+
], ProvingOrchestrator.prototype, "startTubeCircuits", null);
|
|
681
|
+
_ts_decorate([
|
|
682
|
+
trackSpan('ProvingOrchestrator.setBlockCompleted', (blockNumber)=>({
|
|
683
|
+
[Attributes.BLOCK_NUMBER]: blockNumber
|
|
684
|
+
}))
|
|
685
|
+
], ProvingOrchestrator.prototype, "setBlockCompleted", null);
|
|
686
|
+
_ts_decorate([
|
|
687
|
+
trackSpan('ProvingOrchestrator.prepareBaseRollupInputs', (_, tx)=>({
|
|
688
|
+
[Attributes.TX_HASH]: tx.hash.toString()
|
|
689
|
+
}))
|
|
690
|
+
], ProvingOrchestrator.prototype, "prepareBaseRollupInputs", null);
|