@aztec/prover-client 0.43.0 → 0.45.0
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/mocks/test_context.d.ts +2 -2
- package/dest/mocks/test_context.d.ts.map +1 -1
- package/dest/mocks/test_context.js +7 -5
- package/dest/orchestrator/orchestrator.d.ts +4 -2
- package/dest/orchestrator/orchestrator.d.ts.map +1 -1
- package/dest/orchestrator/orchestrator.js +607 -516
- package/dest/orchestrator/proving-state.d.ts +1 -0
- package/dest/orchestrator/proving-state.d.ts.map +1 -1
- package/dest/orchestrator/proving-state.js +26 -1
- package/dest/tx-prover/tx-prover.d.ts +3 -1
- package/dest/tx-prover/tx-prover.d.ts.map +1 -1
- package/dest/tx-prover/tx-prover.js +11 -10
- package/package.json +19 -10
- package/src/mocks/test_context.ts +9 -6
- package/src/orchestrator/orchestrator.ts +181 -54
- package/src/orchestrator/proving-state.ts +26 -0
- package/src/tx-prover/tx-prover.ts +18 -7
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __esDecorate, __runInitializers } from "tslib";
|
|
2
|
+
import { Body, L2Block, MerkleTreeId, PublicKernelType, Tx, makeEmptyProcessedTx, makePaddingProcessedTx, mapPublicKernelToCircuitName, toTxEffect, } from '@aztec/circuit-types';
|
|
2
3
|
import { BlockProofError, PROVING_STATUS, } from '@aztec/circuit-types/interfaces';
|
|
3
4
|
import { AGGREGATION_OBJECT_LENGTH, AvmCircuitInputs, BaseParityInputs, Fr, 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, RootParityInputs, VerificationKeyData, makeEmptyProof, } from '@aztec/circuits.js';
|
|
4
5
|
import { makeTuple } from '@aztec/foundation/array';
|
|
@@ -8,6 +9,7 @@ import { createDebugLogger } from '@aztec/foundation/log';
|
|
|
8
9
|
import { promiseWithResolvers } from '@aztec/foundation/promise';
|
|
9
10
|
import { BufferReader } from '@aztec/foundation/serialize';
|
|
10
11
|
import { pushTestData } from '@aztec/foundation/testing';
|
|
12
|
+
import { Attributes, trackSpan, wrapCallbackInSpan } from '@aztec/telemetry-client';
|
|
11
13
|
import { inspect } from 'util';
|
|
12
14
|
import { buildBaseRollupInput, createMergeRollupInputs, getRootRollupInput, getSubtreeSiblingPath, getTreeSnapshot, validatePartialState, validateRootOutput, validateTx, } from './block-building-helpers.js';
|
|
13
15
|
import { ProvingState } from './proving-state.js';
|
|
@@ -26,549 +28,638 @@ const logger = createDebugLogger('aztec:prover:proving-orchestrator');
|
|
|
26
28
|
/**
|
|
27
29
|
* The orchestrator, managing the flow of recursive proving operations required to build the rollup proof tree.
|
|
28
30
|
*/
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
* @param numTxs - The total number of transactions in the block. Must be a power of 2
|
|
47
|
-
* @param globalVariables - The global variables for the block
|
|
48
|
-
* @param l1ToL2Messages - The l1 to l2 messages for the block
|
|
49
|
-
* @param verificationKeys - The private kernel verification keys
|
|
50
|
-
* @returns A proving ticket, containing a promise notifying of proving completion
|
|
51
|
-
*/
|
|
52
|
-
async startNewBlock(numTxs, globalVariables, l1ToL2Messages, verificationKeys) {
|
|
53
|
-
// Create initial header if not done so yet
|
|
54
|
-
if (!this.initialHeader) {
|
|
55
|
-
this.initialHeader = await this.db.buildInitialHeader();
|
|
56
|
-
}
|
|
57
|
-
// Check that the length of the array of txs is a power of two
|
|
58
|
-
// See https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
|
|
59
|
-
if (!Number.isInteger(numTxs) || numTxs < 2 || (numTxs & (numTxs - 1)) !== 0) {
|
|
60
|
-
throw new Error(`Length of txs for the block should be a power of two and at least two (got ${numTxs})`);
|
|
61
|
-
}
|
|
62
|
-
// Cancel any currently proving block before starting a new one
|
|
63
|
-
this.cancelBlock();
|
|
64
|
-
logger.info(`Starting new block with ${numTxs} transactions`);
|
|
65
|
-
// we start the block by enqueueing all of the base parity circuits
|
|
66
|
-
let baseParityInputs = [];
|
|
67
|
-
let l1ToL2MessagesPadded;
|
|
68
|
-
try {
|
|
69
|
-
l1ToL2MessagesPadded = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
|
|
70
|
-
}
|
|
71
|
-
catch (err) {
|
|
72
|
-
throw new Error('Too many L1 to L2 messages');
|
|
73
|
-
}
|
|
74
|
-
baseParityInputs = Array.from({ length: NUM_BASE_PARITY_PER_ROOT_PARITY }, (_, i) => BaseParityInputs.fromSlice(l1ToL2MessagesPadded, i));
|
|
75
|
-
const messageTreeSnapshot = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, this.db);
|
|
76
|
-
const newL1ToL2MessageTreeRootSiblingPathArray = await getSubtreeSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, L1_TO_L2_MSG_SUBTREE_HEIGHT, this.db);
|
|
77
|
-
const newL1ToL2MessageTreeRootSiblingPath = makeTuple(L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, i => i < newL1ToL2MessageTreeRootSiblingPathArray.length ? newL1ToL2MessageTreeRootSiblingPathArray[i] : Fr.ZERO, 0);
|
|
78
|
-
// Update the local trees to include the new l1 to l2 messages
|
|
79
|
-
await this.db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
|
|
80
|
-
const { promise: _promise, resolve, reject } = promiseWithResolvers();
|
|
81
|
-
const promise = _promise.catch((reason) => ({
|
|
82
|
-
status: PROVING_STATUS.FAILURE,
|
|
83
|
-
reason,
|
|
84
|
-
}));
|
|
85
|
-
const provingState = new ProvingState(numTxs, resolve, reject, globalVariables, l1ToL2MessagesPadded, baseParityInputs.length, messageTreeSnapshot, newL1ToL2MessageTreeRootSiblingPath, verificationKeys);
|
|
86
|
-
for (let i = 0; i < baseParityInputs.length; i++) {
|
|
87
|
-
this.enqueueBaseParityCircuit(provingState, baseParityInputs[i], i);
|
|
88
|
-
}
|
|
89
|
-
this.provingState = provingState;
|
|
90
|
-
const ticket = {
|
|
91
|
-
provingPromise: promise,
|
|
92
|
-
};
|
|
93
|
-
return ticket;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* The interface to add a simulated transaction to the scheduler
|
|
97
|
-
* @param tx - The transaction to be proven
|
|
98
|
-
*/
|
|
99
|
-
async addNewTx(tx) {
|
|
100
|
-
if (!this.provingState) {
|
|
101
|
-
throw new Error(`Invalid proving state, call startNewBlock before adding transactions`);
|
|
102
|
-
}
|
|
103
|
-
if (!this.provingState.isAcceptingTransactions()) {
|
|
104
|
-
throw new Error(`Rollup not accepting further transactions`);
|
|
105
|
-
}
|
|
106
|
-
validateTx(tx);
|
|
107
|
-
logger.info(`Received transaction: ${tx.hash}`);
|
|
108
|
-
const [inputs, treeSnapshots] = await this.prepareTransaction(tx, this.provingState);
|
|
109
|
-
this.enqueueFirstProof(inputs, treeSnapshots, tx, this.provingState);
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Marks the block as full and pads it to the full power of 2 block size, no more transactions will be accepted.
|
|
113
|
-
*/
|
|
114
|
-
async setBlockCompleted() {
|
|
115
|
-
if (!this.provingState) {
|
|
116
|
-
throw new Error(`Invalid proving state, call startNewBlock before adding transactions or completing the block`);
|
|
117
|
-
}
|
|
118
|
-
// we may need to pad the rollup with empty transactions
|
|
119
|
-
const paddingTxCount = this.provingState.totalNumTxs - this.provingState.transactionsReceived;
|
|
120
|
-
if (paddingTxCount === 0) {
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
logger.debug(`Padding rollup with ${paddingTxCount} empty transactions`);
|
|
124
|
-
// Make an empty padding transaction
|
|
125
|
-
// Insert it into the tree the required number of times to get all of the
|
|
126
|
-
// base rollup inputs
|
|
127
|
-
// Then enqueue the proving of all the transactions
|
|
128
|
-
const unprovenPaddingTx = makeEmptyProcessedTx(this.initialHeader ?? (await this.db.buildInitialHeader()), this.provingState.globalVariables.chainId, this.provingState.globalVariables.version);
|
|
129
|
-
const txInputs = [];
|
|
130
|
-
for (let i = 0; i < paddingTxCount; i++) {
|
|
131
|
-
const [inputs, snapshot] = await this.prepareTransaction(unprovenPaddingTx, this.provingState);
|
|
132
|
-
const txInput = {
|
|
133
|
-
inputs,
|
|
134
|
-
snapshot,
|
|
135
|
-
};
|
|
136
|
-
txInputs.push(txInput);
|
|
137
|
-
}
|
|
138
|
-
// Now enqueue the proving
|
|
139
|
-
this.enqueuePaddingTxs(this.provingState, txInputs, unprovenPaddingTx);
|
|
140
|
-
}
|
|
141
|
-
// Enqueues the proving of the required padding transactions
|
|
142
|
-
// If the fully proven padding transaction is not available, this will first be proven
|
|
143
|
-
enqueuePaddingTxs(provingState, txInputs, unprovenPaddingTx) {
|
|
144
|
-
if (this.paddingTx) {
|
|
145
|
-
// We already have the padding transaction
|
|
146
|
-
logger.debug(`Enqueuing ${txInputs.length} padding transactions using existing padding tx`);
|
|
147
|
-
this.provePaddingTransactions(txInputs, this.paddingTx, provingState);
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
logger.debug(`Enqueuing deferred proving for padding txs to enqueue ${txInputs.length} paddings`);
|
|
151
|
-
this.deferredProving(provingState, signal => this.prover.getEmptyPrivateKernelProof({
|
|
152
|
-
// Chain id and version should not change even if the proving state does, so it's safe to use them for the padding tx
|
|
153
|
-
// which gets cached across multiple runs of the orchestrator with different proving states. If they were to change,
|
|
154
|
-
// we'd have to clear out the paddingTx here and regenerate it when they do.
|
|
155
|
-
chainId: unprovenPaddingTx.data.constants.txContext.chainId,
|
|
156
|
-
version: unprovenPaddingTx.data.constants.txContext.version,
|
|
157
|
-
header: unprovenPaddingTx.data.constants.historicalHeader,
|
|
158
|
-
}, signal), result => {
|
|
159
|
-
logger.debug(`Completed proof for padding tx, now enqueuing ${txInputs.length} padding txs`);
|
|
160
|
-
this.paddingTx = makePaddingProcessedTx(result);
|
|
161
|
-
this.provePaddingTransactions(txInputs, this.paddingTx, provingState);
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Prepares the cached sets of base rollup inputs for padding transactions and proves them
|
|
166
|
-
* @param txInputs - The base rollup inputs, start and end hash paths etc
|
|
167
|
-
* @param paddingTx - The padding tx, contains the header, proof, vk, public inputs used in the proof
|
|
168
|
-
* @param provingState - The block proving state
|
|
169
|
-
*/
|
|
170
|
-
provePaddingTransactions(txInputs, paddingTx, provingState) {
|
|
171
|
-
// The padding tx contains the proof and vk, generated separately from the base inputs
|
|
172
|
-
// Copy these into the base rollup inputs
|
|
173
|
-
for (let i = 0; i < txInputs.length; i++) {
|
|
174
|
-
txInputs[i].inputs.kernelData.vk = paddingTx.verificationKey;
|
|
175
|
-
txInputs[i].inputs.kernelData.proof = paddingTx.recursiveProof;
|
|
176
|
-
this.enqueueFirstProof(txInputs[i].inputs, txInputs[i].snapshot, paddingTx, provingState);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Cancel any further proving of the block
|
|
181
|
-
*/
|
|
182
|
-
cancelBlock() {
|
|
183
|
-
for (const controller of this.pendingProvingJobs) {
|
|
184
|
-
controller.abort();
|
|
185
|
-
}
|
|
186
|
-
this.provingState?.cancel();
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Performs the final tree update for the block and returns the fully proven block.
|
|
190
|
-
* @returns The fully proven block and proof.
|
|
191
|
-
*/
|
|
192
|
-
async finaliseBlock() {
|
|
193
|
-
try {
|
|
194
|
-
if (!this.provingState ||
|
|
195
|
-
!this.provingState.rootRollupPublicInputs ||
|
|
196
|
-
!this.provingState.finalProof ||
|
|
197
|
-
!this.provingState.finalAggregationObject) {
|
|
198
|
-
throw new Error(`Invalid proving state, a block must be proven before it can be finalised`);
|
|
31
|
+
let ProvingOrchestrator = (() => {
|
|
32
|
+
var _a;
|
|
33
|
+
let _instanceExtraInitializers = [];
|
|
34
|
+
let _startNewBlock_decorators;
|
|
35
|
+
let _addNewTx_decorators;
|
|
36
|
+
let _setBlockCompleted_decorators;
|
|
37
|
+
let _finaliseBlock_decorators;
|
|
38
|
+
let _prepareBaseRollupInputs_decorators;
|
|
39
|
+
return _a = class ProvingOrchestrator {
|
|
40
|
+
constructor(db, prover, telemetryClient, initialHeader) {
|
|
41
|
+
this.db = (__runInitializers(this, _instanceExtraInitializers), db);
|
|
42
|
+
this.prover = prover;
|
|
43
|
+
this.initialHeader = initialHeader;
|
|
44
|
+
this.provingState = undefined;
|
|
45
|
+
this.pendingProvingJobs = [];
|
|
46
|
+
this.paddingTx = undefined;
|
|
47
|
+
this.tracer = telemetryClient.getTracer('ProvingOrchestrator');
|
|
199
48
|
}
|
|
200
|
-
|
|
201
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Resets the orchestrator's cached padding tx.
|
|
51
|
+
*/
|
|
52
|
+
reset() {
|
|
53
|
+
this.paddingTx = undefined;
|
|
202
54
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Starts off a new block
|
|
57
|
+
* @param numTxs - The total number of transactions in the block. Must be a power of 2
|
|
58
|
+
* @param globalVariables - The global variables for the block
|
|
59
|
+
* @param l1ToL2Messages - The l1 to l2 messages for the block
|
|
60
|
+
* @param verificationKeys - The private kernel verification keys
|
|
61
|
+
* @returns A proving ticket, containing a promise notifying of proving completion
|
|
62
|
+
*/
|
|
63
|
+
async startNewBlock(numTxs, globalVariables, l1ToL2Messages, verificationKeys) {
|
|
64
|
+
// Create initial header if not done so yet
|
|
65
|
+
if (!this.initialHeader) {
|
|
66
|
+
this.initialHeader = await this.db.buildInitialHeader();
|
|
67
|
+
}
|
|
68
|
+
if (!Number.isInteger(numTxs) || numTxs < 2) {
|
|
69
|
+
throw new Error(`Length of txs for the block should be at least two (got ${numTxs})`);
|
|
70
|
+
}
|
|
71
|
+
// Cancel any currently proving block before starting a new one
|
|
72
|
+
this.cancelBlock();
|
|
73
|
+
logger.info(`Starting new block with ${numTxs} transactions`);
|
|
74
|
+
// we start the block by enqueueing all of the base parity circuits
|
|
75
|
+
let baseParityInputs = [];
|
|
76
|
+
let l1ToL2MessagesPadded;
|
|
77
|
+
try {
|
|
78
|
+
l1ToL2MessagesPadded = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
throw new Error('Too many L1 to L2 messages');
|
|
82
|
+
}
|
|
83
|
+
baseParityInputs = Array.from({ length: NUM_BASE_PARITY_PER_ROOT_PARITY }, (_, i) => BaseParityInputs.fromSlice(l1ToL2MessagesPadded, i));
|
|
84
|
+
const messageTreeSnapshot = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, this.db);
|
|
85
|
+
const newL1ToL2MessageTreeRootSiblingPathArray = await getSubtreeSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, L1_TO_L2_MSG_SUBTREE_HEIGHT, this.db);
|
|
86
|
+
const newL1ToL2MessageTreeRootSiblingPath = makeTuple(L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, i => i < newL1ToL2MessageTreeRootSiblingPathArray.length ? newL1ToL2MessageTreeRootSiblingPathArray[i] : Fr.ZERO, 0);
|
|
87
|
+
// Update the local trees to include the new l1 to l2 messages
|
|
88
|
+
await this.db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
|
|
89
|
+
const { promise: _promise, resolve, reject } = promiseWithResolvers();
|
|
90
|
+
const promise = _promise.catch((reason) => ({
|
|
91
|
+
status: PROVING_STATUS.FAILURE,
|
|
92
|
+
reason,
|
|
93
|
+
}));
|
|
94
|
+
const provingState = new ProvingState(numTxs, resolve, reject, globalVariables, l1ToL2MessagesPadded, baseParityInputs.length, messageTreeSnapshot, newL1ToL2MessageTreeRootSiblingPath, verificationKeys);
|
|
95
|
+
for (let i = 0; i < baseParityInputs.length; i++) {
|
|
96
|
+
this.enqueueBaseParityCircuit(provingState, baseParityInputs[i], i);
|
|
97
|
+
}
|
|
98
|
+
this.provingState = provingState;
|
|
99
|
+
const ticket = {
|
|
100
|
+
provingPromise: promise,
|
|
101
|
+
};
|
|
102
|
+
return ticket;
|
|
221
103
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
pushTestData('blockResults', {
|
|
230
|
-
block: l2Block.toString(),
|
|
231
|
-
proof: this.provingState.finalProof.toString(),
|
|
232
|
-
aggregationObject: blockResult.aggregationObject.map(x => x.toString()),
|
|
233
|
-
});
|
|
234
|
-
return blockResult;
|
|
235
|
-
}
|
|
236
|
-
catch (err) {
|
|
237
|
-
throw new BlockProofError(err && typeof err === 'object' && 'message' in err ? String(err.message) : String(err), this.provingState?.allTxs.map(x => Tx.getHash(x.processedTx)) ?? []);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* Starts the proving process for the given transaction and adds it to our state
|
|
242
|
-
* @param tx - The transaction whose proving we wish to commence
|
|
243
|
-
* @param provingState - The proving state being worked on
|
|
244
|
-
*/
|
|
245
|
-
async prepareTransaction(tx, provingState) {
|
|
246
|
-
// Pass the private kernel tail vk here as the previous one.
|
|
247
|
-
// If there are public functions then this key will be overwritten once the public tail has been proven
|
|
248
|
-
const previousKernelVerificationKey = provingState.privateKernelVerificationKeys.privateKernelCircuit;
|
|
249
|
-
const txInputs = await this.prepareBaseRollupInputs(provingState, tx, previousKernelVerificationKey);
|
|
250
|
-
if (!txInputs) {
|
|
251
|
-
// This should not be possible
|
|
252
|
-
throw new Error(`Unable to add padding transaction, preparing base inputs failed`);
|
|
253
|
-
}
|
|
254
|
-
return txInputs;
|
|
255
|
-
}
|
|
256
|
-
enqueueFirstProof(inputs, treeSnapshots, tx, provingState) {
|
|
257
|
-
const txProvingState = new TxProvingState(tx, inputs, treeSnapshots, provingState.privateKernelVerificationKeys.privateKernelToPublicCircuit);
|
|
258
|
-
const txIndex = provingState.addNewTx(txProvingState);
|
|
259
|
-
const numPublicKernels = txProvingState.getNumPublicKernels();
|
|
260
|
-
if (!numPublicKernels) {
|
|
261
|
-
// no public functions, go straight to the base rollup
|
|
262
|
-
logger.debug(`Enqueueing base rollup for tx ${txIndex}`);
|
|
263
|
-
this.enqueueBaseRollup(provingState, BigInt(txIndex), txProvingState);
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
// Enqueue all of the VM/kernel proving requests
|
|
267
|
-
// Rather than handle the Kernel Tail as a special case here, we will just handle it inside enqueueVM
|
|
268
|
-
for (let i = 0; i < numPublicKernels; i++) {
|
|
269
|
-
logger.debug(`Enqueueing public VM ${i} for tx ${txIndex}`);
|
|
270
|
-
this.enqueueVM(provingState, txIndex, i);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* Enqueue a job to be scheduled
|
|
275
|
-
* @param provingState - The proving state object being operated on
|
|
276
|
-
* @param jobType - The type of job to be queued
|
|
277
|
-
* @param job - The actual job, returns a promise notifying of the job's completion
|
|
278
|
-
*/
|
|
279
|
-
deferredProving(provingState, request, callback) {
|
|
280
|
-
if (!provingState?.verifyState()) {
|
|
281
|
-
logger.debug(`Not enqueuing job, state no longer valid`);
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
const controller = new AbortController();
|
|
285
|
-
this.pendingProvingJobs.push(controller);
|
|
286
|
-
// We use a 'safeJob'. We don't want promise rejections in the proving pool, we want to capture the error here
|
|
287
|
-
// and reject the proving job whilst keeping the event loop free of rejections
|
|
288
|
-
const safeJob = async () => {
|
|
289
|
-
try {
|
|
290
|
-
// there's a delay between enqueueing this job and it actually running
|
|
291
|
-
if (controller.signal.aborted) {
|
|
292
|
-
return;
|
|
104
|
+
/**
|
|
105
|
+
* The interface to add a simulated transaction to the scheduler
|
|
106
|
+
* @param tx - The transaction to be proven
|
|
107
|
+
*/
|
|
108
|
+
async addNewTx(tx) {
|
|
109
|
+
if (!this.provingState) {
|
|
110
|
+
throw new Error(`Invalid proving state, call startNewBlock before adding transactions`);
|
|
293
111
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
112
|
+
if (!this.provingState.isAcceptingTransactions()) {
|
|
113
|
+
throw new Error(`Rollup not accepting further transactions`);
|
|
114
|
+
}
|
|
115
|
+
validateTx(tx);
|
|
116
|
+
logger.info(`Received transaction: ${tx.hash}`);
|
|
117
|
+
if (tx.isEmpty) {
|
|
118
|
+
logger.warn(`Ignoring empty transaction ${tx.hash} - it will not be added to this block`);
|
|
297
119
|
return;
|
|
298
120
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
121
|
+
const [inputs, treeSnapshots] = await this.prepareTransaction(tx, this.provingState);
|
|
122
|
+
this.enqueueFirstProof(inputs, treeSnapshots, tx, this.provingState);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Marks the block as full and pads it if required, no more transactions will be accepted.
|
|
126
|
+
*/
|
|
127
|
+
async setBlockCompleted() {
|
|
128
|
+
if (!this.provingState) {
|
|
129
|
+
throw new Error(`Invalid proving state, call startNewBlock before adding transactions or completing the block`);
|
|
130
|
+
}
|
|
131
|
+
// we may need to pad the rollup with empty transactions
|
|
132
|
+
const paddingTxCount = this.provingState.totalNumTxs - this.provingState.transactionsReceived;
|
|
133
|
+
if (paddingTxCount === 0) {
|
|
302
134
|
return;
|
|
303
135
|
}
|
|
304
|
-
|
|
136
|
+
else if (this.provingState.totalNumTxs > 2) {
|
|
137
|
+
throw new Error(`Block not ready for completion: expecting ${paddingTxCount} more transactions.`);
|
|
138
|
+
}
|
|
139
|
+
logger.debug(`Padding rollup with ${paddingTxCount} empty transactions`);
|
|
140
|
+
// Make an empty padding transaction
|
|
141
|
+
// Required for:
|
|
142
|
+
// 0 (when we want an empty block, largely for testing), or
|
|
143
|
+
// 1 (we need to pad with one tx as all rollup circuits require a pair of inputs) txs
|
|
144
|
+
// Insert it into the tree the required number of times to get all of the
|
|
145
|
+
// base rollup inputs
|
|
146
|
+
// Then enqueue the proving of all the transactions
|
|
147
|
+
const unprovenPaddingTx = makeEmptyProcessedTx(this.initialHeader ?? (await this.db.buildInitialHeader()), this.provingState.globalVariables.chainId, this.provingState.globalVariables.version);
|
|
148
|
+
const txInputs = [];
|
|
149
|
+
for (let i = 0; i < paddingTxCount; i++) {
|
|
150
|
+
const [inputs, snapshot] = await this.prepareTransaction(unprovenPaddingTx, this.provingState);
|
|
151
|
+
const txInput = {
|
|
152
|
+
inputs,
|
|
153
|
+
snapshot,
|
|
154
|
+
};
|
|
155
|
+
txInputs.push(txInput);
|
|
156
|
+
}
|
|
157
|
+
// Now enqueue the proving
|
|
158
|
+
this.enqueuePaddingTxs(this.provingState, txInputs, unprovenPaddingTx);
|
|
305
159
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
160
|
+
// Enqueues the proving of the required padding transactions
|
|
161
|
+
// If the fully proven padding transaction is not available, this will first be proven
|
|
162
|
+
enqueuePaddingTxs(provingState, txInputs, unprovenPaddingTx) {
|
|
163
|
+
if (this.paddingTx) {
|
|
164
|
+
// We already have the padding transaction
|
|
165
|
+
logger.debug(`Enqueuing ${txInputs.length} padding transactions using existing padding tx`);
|
|
166
|
+
this.provePaddingTransactions(txInputs, this.paddingTx, provingState);
|
|
310
167
|
return;
|
|
311
168
|
}
|
|
312
|
-
logger.
|
|
313
|
-
provingState.
|
|
169
|
+
logger.debug(`Enqueuing deferred proving for padding txs to enqueue ${txInputs.length} paddings`);
|
|
170
|
+
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getEmptyPrivateKernelProof', {
|
|
171
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
172
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'private-kernel-empty',
|
|
173
|
+
}, signal => this.prover.getEmptyPrivateKernelProof({
|
|
174
|
+
// Chain id and version should not change even if the proving state does, so it's safe to use them for the padding tx
|
|
175
|
+
// which gets cached across multiple runs of the orchestrator with different proving states. If they were to change,
|
|
176
|
+
// we'd have to clear out the paddingTx here and regenerate it when they do.
|
|
177
|
+
chainId: unprovenPaddingTx.data.constants.txContext.chainId,
|
|
178
|
+
version: unprovenPaddingTx.data.constants.txContext.version,
|
|
179
|
+
header: unprovenPaddingTx.data.constants.historicalHeader,
|
|
180
|
+
}, signal)), result => {
|
|
181
|
+
logger.debug(`Completed proof for padding tx, now enqueuing ${txInputs.length} padding txs`);
|
|
182
|
+
this.paddingTx = makePaddingProcessedTx(result);
|
|
183
|
+
this.provePaddingTransactions(txInputs, this.paddingTx, provingState);
|
|
184
|
+
});
|
|
314
185
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
186
|
+
/**
|
|
187
|
+
* Prepares the cached sets of base rollup inputs for padding transactions and proves them
|
|
188
|
+
* @param txInputs - The base rollup inputs, start and end hash paths etc
|
|
189
|
+
* @param paddingTx - The padding tx, contains the header, proof, vk, public inputs used in the proof
|
|
190
|
+
* @param provingState - The block proving state
|
|
191
|
+
*/
|
|
192
|
+
provePaddingTransactions(txInputs, paddingTx, provingState) {
|
|
193
|
+
// The padding tx contains the proof and vk, generated separately from the base inputs
|
|
194
|
+
// Copy these into the base rollup inputs
|
|
195
|
+
for (let i = 0; i < txInputs.length; i++) {
|
|
196
|
+
txInputs[i].inputs.kernelData.vk = paddingTx.verificationKey;
|
|
197
|
+
txInputs[i].inputs.kernelData.proof = paddingTx.recursiveProof;
|
|
198
|
+
this.enqueueFirstProof(txInputs[i].inputs, txInputs[i].snapshot, paddingTx, provingState);
|
|
319
199
|
}
|
|
320
200
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
|
-
const inputs = await buildBaseRollupInput(tx, provingState.globalVariables, this.db, kernelVk);
|
|
332
|
-
const promises = [MerkleTreeId.NOTE_HASH_TREE, MerkleTreeId.NULLIFIER_TREE, MerkleTreeId.PUBLIC_DATA_TREE].map(async (id) => {
|
|
333
|
-
return { key: id, value: await getTreeSnapshot(id, this.db) };
|
|
334
|
-
});
|
|
335
|
-
const treeSnapshots = new Map((await Promise.all(promises)).map(obj => [obj.key, obj.value]));
|
|
336
|
-
if (!provingState?.verifyState()) {
|
|
337
|
-
logger.debug(`Discarding proving job, state no longer valid`);
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
return [inputs, treeSnapshots];
|
|
341
|
-
}
|
|
342
|
-
// Stores the intermediate inputs prepared for a merge proof
|
|
343
|
-
storeMergeInputs(provingState, currentLevel, currentIndex, mergeInputs) {
|
|
344
|
-
const mergeLevel = currentLevel - 1n;
|
|
345
|
-
const indexWithinMergeLevel = currentIndex >> 1n;
|
|
346
|
-
const mergeIndex = 2n ** mergeLevel - 1n + indexWithinMergeLevel;
|
|
347
|
-
const subscript = Number(mergeIndex);
|
|
348
|
-
const indexWithinMerge = Number(currentIndex & 1n);
|
|
349
|
-
const ready = provingState.storeMergeInputs(mergeInputs, indexWithinMerge, subscript);
|
|
350
|
-
return { ready, indexWithinMergeLevel, mergeLevel, mergeInputData: provingState.getMergeInputs(subscript) };
|
|
351
|
-
}
|
|
352
|
-
// Executes the base rollup circuit and stored the output as intermediate state for the parent merge/root circuit
|
|
353
|
-
// Executes the next level of merge if all inputs are available
|
|
354
|
-
enqueueBaseRollup(provingState, index, tx) {
|
|
355
|
-
if (!provingState?.verifyState()) {
|
|
356
|
-
logger.debug('Not running base rollup, state invalid');
|
|
357
|
-
return;
|
|
358
|
-
}
|
|
359
|
-
if (!tx.baseRollupInputs.kernelData.publicInputs.end.noteEncryptedLogsHash
|
|
360
|
-
.toBuffer()
|
|
361
|
-
.equals(tx.processedTx.noteEncryptedLogs.hash())) {
|
|
362
|
-
provingState.reject(`Note encrypted logs hash mismatch: ${tx.baseRollupInputs.kernelData.publicInputs.end.noteEncryptedLogsHash} === ${Fr.fromBuffer(tx.processedTx.noteEncryptedLogs.hash())}`);
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
if (!tx.baseRollupInputs.kernelData.publicInputs.end.encryptedLogsHash
|
|
366
|
-
.toBuffer()
|
|
367
|
-
.equals(tx.processedTx.encryptedLogs.hash())) {
|
|
368
|
-
// @todo This rejection messages is never seen. Never making it out to the logs
|
|
369
|
-
provingState.reject(`Encrypted logs hash mismatch: ${tx.baseRollupInputs.kernelData.publicInputs.end.encryptedLogsHash} === ${Fr.fromBuffer(tx.processedTx.encryptedLogs.hash())}`);
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
if (!tx.baseRollupInputs.kernelData.publicInputs.end.unencryptedLogsHash
|
|
373
|
-
.toBuffer()
|
|
374
|
-
.equals(tx.processedTx.unencryptedLogs.hash())) {
|
|
375
|
-
provingState.reject(`Unencrypted logs hash mismatch: ${tx.baseRollupInputs.kernelData.publicInputs.end.unencryptedLogsHash} === ${Fr.fromBuffer(tx.processedTx.unencryptedLogs.hash())}`);
|
|
376
|
-
return;
|
|
377
|
-
}
|
|
378
|
-
logger.debug(`Enqueuing deferred proving base rollup${tx.processedTx.isEmpty ? ' with padding tx' : ''} for ${tx.processedTx.hash.toString()}`);
|
|
379
|
-
this.deferredProving(provingState, signal => this.prover.getBaseRollupProof(tx.baseRollupInputs, signal), result => {
|
|
380
|
-
logger.debug(`Completed proof for base rollup for tx ${tx.processedTx.hash.toString()}`);
|
|
381
|
-
validatePartialState(result.inputs.end, tx.treeSnapshots);
|
|
382
|
-
const currentLevel = provingState.numMergeLevels + 1n;
|
|
383
|
-
this.storeAndExecuteNextMergeLevel(provingState, currentLevel, index, [
|
|
384
|
-
result.inputs,
|
|
385
|
-
result.proof,
|
|
386
|
-
result.verificationKey.keyAsFields,
|
|
387
|
-
]);
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
// Executes the merge rollup circuit and stored the output as intermediate state for the parent merge/root circuit
|
|
391
|
-
// Enqueues the next level of merge if all inputs are available
|
|
392
|
-
enqueueMergeRollup(provingState, level, index, mergeInputData) {
|
|
393
|
-
const inputs = createMergeRollupInputs([mergeInputData.inputs[0], mergeInputData.proofs[0], mergeInputData.verificationKeys[0]], [mergeInputData.inputs[1], mergeInputData.proofs[1], mergeInputData.verificationKeys[1]]);
|
|
394
|
-
this.deferredProving(provingState, signal => this.prover.getMergeRollupProof(inputs, signal), result => {
|
|
395
|
-
this.storeAndExecuteNextMergeLevel(provingState, level, index, [
|
|
396
|
-
result.inputs,
|
|
397
|
-
result.proof,
|
|
398
|
-
result.verificationKey.keyAsFields,
|
|
399
|
-
]);
|
|
400
|
-
});
|
|
401
|
-
}
|
|
402
|
-
// Executes the root rollup circuit
|
|
403
|
-
async enqueueRootRollup(provingState) {
|
|
404
|
-
if (!provingState?.verifyState()) {
|
|
405
|
-
logger.debug('Not running root rollup, state no longer valid');
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
408
|
-
const mergeInputData = provingState.getMergeInputs(0);
|
|
409
|
-
const rootParityInput = provingState.finalRootParityInput;
|
|
410
|
-
const inputs = await getRootRollupInput(mergeInputData.inputs[0], mergeInputData.proofs[0], mergeInputData.verificationKeys[0], mergeInputData.inputs[1], mergeInputData.proofs[1], mergeInputData.verificationKeys[1], rootParityInput, provingState.newL1ToL2Messages, provingState.messageTreeSnapshot, provingState.messageTreeRootSiblingPath, this.db);
|
|
411
|
-
this.deferredProving(provingState, signal => this.prover.getRootRollupProof(inputs, signal), result => {
|
|
412
|
-
provingState.rootRollupPublicInputs = result.inputs;
|
|
413
|
-
provingState.finalAggregationObject = extractAggregationObject(result.proof.binaryProof, result.verificationKey.numPublicInputs);
|
|
414
|
-
provingState.finalProof = result.proof.binaryProof;
|
|
415
|
-
const provingResult = {
|
|
416
|
-
status: PROVING_STATUS.SUCCESS,
|
|
417
|
-
};
|
|
418
|
-
provingState.resolve(provingResult);
|
|
419
|
-
});
|
|
420
|
-
}
|
|
421
|
-
// Executes the base parity circuit and stores the intermediate state for the root parity circuit
|
|
422
|
-
// Enqueues the root parity circuit if all inputs are available
|
|
423
|
-
enqueueBaseParityCircuit(provingState, inputs, index) {
|
|
424
|
-
this.deferredProving(provingState, signal => this.prover.getBaseParityProof(inputs, signal), rootInput => {
|
|
425
|
-
provingState.setRootParityInputs(rootInput, index);
|
|
426
|
-
if (provingState.areRootParityInputsReady()) {
|
|
427
|
-
const rootParityInputs = new RootParityInputs(provingState.rootParityInput);
|
|
428
|
-
this.enqueueRootParityCircuit(provingState, rootParityInputs);
|
|
201
|
+
/**
|
|
202
|
+
* Cancel any further proving of the block
|
|
203
|
+
*/
|
|
204
|
+
cancelBlock() {
|
|
205
|
+
for (const controller of this.pendingProvingJobs) {
|
|
206
|
+
controller.abort();
|
|
207
|
+
}
|
|
208
|
+
this.provingState?.cancel();
|
|
429
209
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
this.deferredProving(provingState, signal => this.prover.getRootParityProof(inputs, signal), async (rootInput) => {
|
|
436
|
-
provingState.finalRootParityInput = rootInput;
|
|
437
|
-
await this.checkAndEnqueueRootRollup(provingState);
|
|
438
|
-
});
|
|
439
|
-
}
|
|
440
|
-
async checkAndEnqueueRootRollup(provingState) {
|
|
441
|
-
if (!provingState?.isReadyForRootRollup()) {
|
|
442
|
-
logger.debug('Not ready for root rollup');
|
|
443
|
-
return;
|
|
444
|
-
}
|
|
445
|
-
await this.enqueueRootRollup(provingState);
|
|
446
|
-
}
|
|
447
|
-
/**
|
|
448
|
-
* Stores the inputs to a merge/root circuit and enqueues the circuit if ready
|
|
449
|
-
* @param provingState - The proving state being operated on
|
|
450
|
-
* @param currentLevel - The level of the merge/root circuit
|
|
451
|
-
* @param currentIndex - The index of the merge/root circuit
|
|
452
|
-
* @param mergeInputData - The inputs to be stored
|
|
453
|
-
*/
|
|
454
|
-
storeAndExecuteNextMergeLevel(provingState, currentLevel, currentIndex, mergeInputData) {
|
|
455
|
-
const result = this.storeMergeInputs(provingState, currentLevel, currentIndex, mergeInputData);
|
|
456
|
-
// Are we ready to execute the next circuit?
|
|
457
|
-
if (!result.ready) {
|
|
458
|
-
return;
|
|
459
|
-
}
|
|
460
|
-
if (result.mergeLevel === 0n) {
|
|
461
|
-
// TODO (alexg) remove this `void`
|
|
462
|
-
void this.checkAndEnqueueRootRollup(provingState);
|
|
463
|
-
}
|
|
464
|
-
else {
|
|
465
|
-
// onto the next merge level
|
|
466
|
-
this.enqueueMergeRollup(provingState, result.mergeLevel, result.indexWithinMergeLevel, result.mergeInputData);
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
/**
|
|
470
|
-
* Executes the VM circuit for a public function, will enqueue the corresponding kernel if the
|
|
471
|
-
* previous kernel is ready
|
|
472
|
-
* @param provingState - The proving state being operated on
|
|
473
|
-
* @param txIndex - The index of the transaction being proven
|
|
474
|
-
* @param functionIndex - The index of the function/kernel being proven
|
|
475
|
-
*/
|
|
476
|
-
enqueueVM(provingState, txIndex, functionIndex) {
|
|
477
|
-
if (!provingState?.verifyState()) {
|
|
478
|
-
logger.debug(`Not running VM circuit as state is no longer valid`);
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
481
|
-
const txProvingState = provingState.getTxProvingState(txIndex);
|
|
482
|
-
const publicFunction = txProvingState.getPublicFunctionState(functionIndex);
|
|
483
|
-
// If there is a VM request, we need to prove it. Otherwise, continue with the kernel.
|
|
484
|
-
if (publicFunction.vmRequest) {
|
|
485
|
-
// This function tries to do AVM proving. If there is a failure, it fakes the proof unless AVM_PROVING_STRICT is defined.
|
|
486
|
-
// Nothing downstream depends on the AVM proof yet. So having this mode lets us incrementally build the AVM circuit.
|
|
487
|
-
const doAvmProving = async (signal) => {
|
|
488
|
-
const inputs = new AvmCircuitInputs(publicFunction.vmRequest.bytecode, publicFunction.vmRequest.calldata, publicFunction.vmRequest.kernelRequest.inputs.publicCall.callStackItem.publicInputs, publicFunction.vmRequest.avmHints);
|
|
210
|
+
/**
|
|
211
|
+
* Performs the final tree update for the block and returns the fully proven block.
|
|
212
|
+
* @returns The fully proven block and proof.
|
|
213
|
+
*/
|
|
214
|
+
async finaliseBlock() {
|
|
489
215
|
try {
|
|
490
|
-
|
|
216
|
+
if (!this.provingState ||
|
|
217
|
+
!this.provingState.rootRollupPublicInputs ||
|
|
218
|
+
!this.provingState.finalProof ||
|
|
219
|
+
!this.provingState.finalAggregationObject) {
|
|
220
|
+
throw new Error(`Invalid proving state, a block must be proven before it can be finalised`);
|
|
221
|
+
}
|
|
222
|
+
if (this.provingState.block) {
|
|
223
|
+
throw new Error('Block already finalised');
|
|
224
|
+
}
|
|
225
|
+
const rootRollupOutputs = this.provingState.rootRollupPublicInputs;
|
|
226
|
+
logger?.debug(`Updating and validating root trees`);
|
|
227
|
+
await this.db.updateArchive(rootRollupOutputs.header);
|
|
228
|
+
await validateRootOutput(rootRollupOutputs, this.db);
|
|
229
|
+
// Collect all new nullifiers, commitments, and contracts from all txs in this block
|
|
230
|
+
const gasFees = this.provingState.globalVariables.gasFees;
|
|
231
|
+
const nonEmptyTxEffects = this.provingState.allTxs.map(txProvingState => toTxEffect(txProvingState.processedTx, gasFees)).filter(txEffect => !txEffect.isEmpty());
|
|
232
|
+
const blockBody = new Body(nonEmptyTxEffects);
|
|
233
|
+
const l2Block = L2Block.fromFields({
|
|
234
|
+
archive: rootRollupOutputs.archive,
|
|
235
|
+
header: rootRollupOutputs.header,
|
|
236
|
+
body: blockBody,
|
|
237
|
+
});
|
|
238
|
+
if (!l2Block.body.getTxsEffectsHash().equals(rootRollupOutputs.header.contentCommitment.txsEffectsHash)) {
|
|
239
|
+
logger.debug(inspect(blockBody));
|
|
240
|
+
throw new Error(`Txs effects hash mismatch, ${l2Block.body
|
|
241
|
+
.getTxsEffectsHash()
|
|
242
|
+
.toString('hex')} == ${rootRollupOutputs.header.contentCommitment.txsEffectsHash.toString('hex')} `);
|
|
243
|
+
}
|
|
244
|
+
logger.info(`Successfully proven block ${l2Block.number}!`);
|
|
245
|
+
this.provingState.block = l2Block;
|
|
246
|
+
const blockResult = {
|
|
247
|
+
proof: this.provingState.finalProof,
|
|
248
|
+
aggregationObject: this.provingState.finalAggregationObject,
|
|
249
|
+
block: l2Block,
|
|
250
|
+
};
|
|
251
|
+
pushTestData('blockResults', {
|
|
252
|
+
block: l2Block.toString(),
|
|
253
|
+
proof: this.provingState.finalProof.toString(),
|
|
254
|
+
aggregationObject: blockResult.aggregationObject.map(x => x.toString()),
|
|
255
|
+
});
|
|
256
|
+
return blockResult;
|
|
491
257
|
}
|
|
492
258
|
catch (err) {
|
|
493
|
-
|
|
494
|
-
|
|
259
|
+
throw new BlockProofError(err && typeof err === 'object' && 'message' in err ? String(err.message) : String(err), this.provingState?.allTxs.map(x => Tx.getHash(x.processedTx)) ?? []);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Starts the proving process for the given transaction and adds it to our state
|
|
264
|
+
* @param tx - The transaction whose proving we wish to commence
|
|
265
|
+
* @param provingState - The proving state being worked on
|
|
266
|
+
*/
|
|
267
|
+
async prepareTransaction(tx, provingState) {
|
|
268
|
+
// Pass the private kernel tail vk here as the previous one.
|
|
269
|
+
// If there are public functions then this key will be overwritten once the public tail has been proven
|
|
270
|
+
const previousKernelVerificationKey = provingState.privateKernelVerificationKeys.privateKernelCircuit;
|
|
271
|
+
const txInputs = await this.prepareBaseRollupInputs(provingState, tx, previousKernelVerificationKey);
|
|
272
|
+
if (!txInputs) {
|
|
273
|
+
// This should not be possible
|
|
274
|
+
throw new Error(`Unable to add padding transaction, preparing base inputs failed`);
|
|
275
|
+
}
|
|
276
|
+
return txInputs;
|
|
277
|
+
}
|
|
278
|
+
enqueueFirstProof(inputs, treeSnapshots, tx, provingState) {
|
|
279
|
+
const txProvingState = new TxProvingState(tx, inputs, treeSnapshots, provingState.privateKernelVerificationKeys.privateKernelToPublicCircuit);
|
|
280
|
+
const txIndex = provingState.addNewTx(txProvingState);
|
|
281
|
+
const numPublicKernels = txProvingState.getNumPublicKernels();
|
|
282
|
+
if (!numPublicKernels) {
|
|
283
|
+
// no public functions, go straight to the base rollup
|
|
284
|
+
logger.debug(`Enqueueing base rollup for tx ${txIndex}`);
|
|
285
|
+
this.enqueueBaseRollup(provingState, BigInt(txIndex), txProvingState);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
// Enqueue all of the VM/kernel proving requests
|
|
289
|
+
// Rather than handle the Kernel Tail as a special case here, we will just handle it inside enqueueVM
|
|
290
|
+
for (let i = 0; i < numPublicKernels; i++) {
|
|
291
|
+
logger.debug(`Enqueueing public VM ${i} for tx ${txIndex}`);
|
|
292
|
+
this.enqueueVM(provingState, txIndex, i);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Enqueue a job to be scheduled
|
|
297
|
+
* @param provingState - The proving state object being operated on
|
|
298
|
+
* @param jobType - The type of job to be queued
|
|
299
|
+
* @param job - The actual job, returns a promise notifying of the job's completion
|
|
300
|
+
*/
|
|
301
|
+
deferredProving(provingState, request, callback) {
|
|
302
|
+
if (!provingState?.verifyState()) {
|
|
303
|
+
logger.debug(`Not enqueuing job, state no longer valid`);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
const controller = new AbortController();
|
|
307
|
+
this.pendingProvingJobs.push(controller);
|
|
308
|
+
// We use a 'safeJob'. We don't want promise rejections in the proving pool, we want to capture the error here
|
|
309
|
+
// and reject the proving job whilst keeping the event loop free of rejections
|
|
310
|
+
const safeJob = async () => {
|
|
311
|
+
try {
|
|
312
|
+
// there's a delay between enqueueing this job and it actually running
|
|
313
|
+
if (controller.signal.aborted) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const result = await request(controller.signal);
|
|
317
|
+
if (!provingState?.verifyState()) {
|
|
318
|
+
logger.debug(`State no longer valid, discarding result`);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
// we could have been cancelled whilst waiting for the result
|
|
322
|
+
// and the prover ignored the signal. Drop the result in that case
|
|
323
|
+
if (controller.signal.aborted) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
await callback(result);
|
|
495
327
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
328
|
+
catch (err) {
|
|
329
|
+
if (err instanceof AbortError) {
|
|
330
|
+
// operation was cancelled, probably because the block was cancelled
|
|
331
|
+
// drop this result
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
logger.error(`Error thrown when proving job`);
|
|
335
|
+
provingState.reject(`${err}`);
|
|
336
|
+
}
|
|
337
|
+
finally {
|
|
338
|
+
const index = this.pendingProvingJobs.indexOf(controller);
|
|
339
|
+
if (index > -1) {
|
|
340
|
+
this.pendingProvingJobs.splice(index, 1);
|
|
341
|
+
}
|
|
500
342
|
}
|
|
343
|
+
};
|
|
344
|
+
// let the callstack unwind before adding the job to the queue
|
|
345
|
+
setImmediate(safeJob);
|
|
346
|
+
}
|
|
347
|
+
// Updates the merkle trees for a transaction. The first enqueued job for a transaction
|
|
348
|
+
async prepareBaseRollupInputs(provingState, tx, kernelVk) {
|
|
349
|
+
if (!provingState?.verifyState()) {
|
|
350
|
+
logger.debug('Not preparing base rollup inputs, state invalid');
|
|
351
|
+
return;
|
|
501
352
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
checkAndEnqueuePublicKernel(provingState, txIndex, functionIndex, vmProof) {
|
|
513
|
-
const txProvingState = provingState.getTxProvingState(txIndex);
|
|
514
|
-
const kernelRequest = txProvingState.getNextPublicKernelFromVMProof(functionIndex, vmProof);
|
|
515
|
-
if (kernelRequest.code === TX_PROVING_CODE.READY) {
|
|
516
|
-
if (kernelRequest.function === undefined) {
|
|
517
|
-
// Should not be possible
|
|
518
|
-
throw new Error(`Error occurred, public function request undefined after VM proof completed`);
|
|
353
|
+
const inputs = await buildBaseRollupInput(tx, provingState.globalVariables, this.db, kernelVk);
|
|
354
|
+
const promises = [MerkleTreeId.NOTE_HASH_TREE, MerkleTreeId.NULLIFIER_TREE, MerkleTreeId.PUBLIC_DATA_TREE].map(async (id) => {
|
|
355
|
+
return { key: id, value: await getTreeSnapshot(id, this.db) };
|
|
356
|
+
});
|
|
357
|
+
const treeSnapshots = new Map((await Promise.all(promises)).map(obj => [obj.key, obj.value]));
|
|
358
|
+
if (!provingState?.verifyState()) {
|
|
359
|
+
logger.debug(`Discarding proving job, state no longer valid`);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
return [inputs, treeSnapshots];
|
|
519
363
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
364
|
+
// Stores the intermediate inputs prepared for a merge proof
|
|
365
|
+
storeMergeInputs(provingState, currentLevel, currentIndex, mergeInputs) {
|
|
366
|
+
const [mergeLevel, indexWithinMergeLevel, indexWithinMerge] = provingState.findMergeLevel(currentLevel, currentIndex);
|
|
367
|
+
const mergeIndex = 2n ** mergeLevel - 1n + indexWithinMergeLevel;
|
|
368
|
+
const ready = provingState.storeMergeInputs(mergeInputs, Number(indexWithinMerge), Number(mergeIndex));
|
|
369
|
+
return {
|
|
370
|
+
ready,
|
|
371
|
+
indexWithinMergeLevel,
|
|
372
|
+
mergeLevel,
|
|
373
|
+
mergeInputData: provingState.getMergeInputs(Number(mergeIndex)),
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
// Executes the base rollup circuit and stored the output as intermediate state for the parent merge/root circuit
|
|
377
|
+
// Executes the next level of merge if all inputs are available
|
|
378
|
+
enqueueBaseRollup(provingState, index, tx) {
|
|
379
|
+
if (!provingState?.verifyState()) {
|
|
380
|
+
logger.debug('Not running base rollup, state invalid');
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
if (!tx.baseRollupInputs.kernelData.publicInputs.end.noteEncryptedLogsHash
|
|
384
|
+
.toBuffer()
|
|
385
|
+
.equals(tx.processedTx.noteEncryptedLogs.hash())) {
|
|
386
|
+
provingState.reject(`Note encrypted logs hash mismatch: ${tx.baseRollupInputs.kernelData.publicInputs.end.noteEncryptedLogsHash} === ${Fr.fromBuffer(tx.processedTx.noteEncryptedLogs.hash())}`);
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
if (!tx.baseRollupInputs.kernelData.publicInputs.end.encryptedLogsHash
|
|
390
|
+
.toBuffer()
|
|
391
|
+
.equals(tx.processedTx.encryptedLogs.hash())) {
|
|
392
|
+
// @todo This rejection messages is never seen. Never making it out to the logs
|
|
393
|
+
provingState.reject(`Encrypted logs hash mismatch: ${tx.baseRollupInputs.kernelData.publicInputs.end.encryptedLogsHash} === ${Fr.fromBuffer(tx.processedTx.encryptedLogs.hash())}`);
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
if (!tx.baseRollupInputs.kernelData.publicInputs.end.unencryptedLogsHash
|
|
397
|
+
.toBuffer()
|
|
398
|
+
.equals(tx.processedTx.unencryptedLogs.hash())) {
|
|
399
|
+
provingState.reject(`Unencrypted logs hash mismatch: ${tx.baseRollupInputs.kernelData.publicInputs.end.unencryptedLogsHash} === ${Fr.fromBuffer(tx.processedTx.unencryptedLogs.hash())}`);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
logger.debug(`Enqueuing deferred proving base rollup${tx.processedTx.isEmpty ? ' with padding tx' : ''} for ${tx.processedTx.hash.toString()}`);
|
|
403
|
+
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getBaseRollupProof', {
|
|
404
|
+
[Attributes.TX_HASH]: tx.processedTx.hash.toString(),
|
|
405
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
406
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-rollup',
|
|
407
|
+
}, signal => this.prover.getBaseRollupProof(tx.baseRollupInputs, signal)), result => {
|
|
408
|
+
logger.debug(`Completed proof for base rollup for tx ${tx.processedTx.hash.toString()}`);
|
|
409
|
+
validatePartialState(result.inputs.end, tx.treeSnapshots);
|
|
410
|
+
const currentLevel = provingState.numMergeLevels + 1n;
|
|
411
|
+
this.storeAndExecuteNextMergeLevel(provingState, currentLevel, index, [
|
|
412
|
+
result.inputs,
|
|
413
|
+
result.proof,
|
|
414
|
+
result.verificationKey.keyAsFields,
|
|
415
|
+
]);
|
|
416
|
+
});
|
|
541
417
|
}
|
|
542
|
-
|
|
543
|
-
|
|
418
|
+
// Executes the merge rollup circuit and stored the output as intermediate state for the parent merge/root circuit
|
|
419
|
+
// Enqueues the next level of merge if all inputs are available
|
|
420
|
+
enqueueMergeRollup(provingState, level, index, mergeInputData) {
|
|
421
|
+
const inputs = createMergeRollupInputs([mergeInputData.inputs[0], mergeInputData.proofs[0], mergeInputData.verificationKeys[0]], [mergeInputData.inputs[1], mergeInputData.proofs[1], mergeInputData.verificationKeys[1]]);
|
|
422
|
+
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getMergeRollupProof', {
|
|
423
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
424
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'merge-rollup',
|
|
425
|
+
}, signal => this.prover.getMergeRollupProof(inputs, signal)), result => {
|
|
426
|
+
this.storeAndExecuteNextMergeLevel(provingState, level, index, [
|
|
427
|
+
result.inputs,
|
|
428
|
+
result.proof,
|
|
429
|
+
result.verificationKey.keyAsFields,
|
|
430
|
+
]);
|
|
431
|
+
});
|
|
544
432
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
433
|
+
// Executes the root rollup circuit
|
|
434
|
+
async enqueueRootRollup(provingState) {
|
|
435
|
+
if (!provingState?.verifyState()) {
|
|
436
|
+
logger.debug('Not running root rollup, state no longer valid');
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
const mergeInputData = provingState.getMergeInputs(0);
|
|
440
|
+
const rootParityInput = provingState.finalRootParityInput;
|
|
441
|
+
const inputs = await getRootRollupInput(mergeInputData.inputs[0], mergeInputData.proofs[0], mergeInputData.verificationKeys[0], mergeInputData.inputs[1], mergeInputData.proofs[1], mergeInputData.verificationKeys[1], rootParityInput, provingState.newL1ToL2Messages, provingState.messageTreeSnapshot, provingState.messageTreeRootSiblingPath, this.db);
|
|
442
|
+
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getRootRollupProof', {
|
|
443
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
444
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-rollup',
|
|
445
|
+
}, signal => this.prover.getRootRollupProof(inputs, signal)), result => {
|
|
446
|
+
provingState.rootRollupPublicInputs = result.inputs;
|
|
447
|
+
provingState.finalAggregationObject = extractAggregationObject(result.proof.binaryProof, result.verificationKey.numPublicInputs);
|
|
448
|
+
provingState.finalProof = result.proof.binaryProof;
|
|
449
|
+
const provingResult = {
|
|
450
|
+
status: PROVING_STATUS.SUCCESS,
|
|
451
|
+
};
|
|
452
|
+
provingState.resolve(provingResult);
|
|
453
|
+
});
|
|
551
454
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
this.
|
|
559
|
-
|
|
455
|
+
// Executes the base parity circuit and stores the intermediate state for the root parity circuit
|
|
456
|
+
// Enqueues the root parity circuit if all inputs are available
|
|
457
|
+
enqueueBaseParityCircuit(provingState, inputs, index) {
|
|
458
|
+
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getBaseParityProof', {
|
|
459
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
460
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-parity',
|
|
461
|
+
}, signal => this.prover.getBaseParityProof(inputs, signal)), rootInput => {
|
|
462
|
+
provingState.setRootParityInputs(rootInput, index);
|
|
463
|
+
if (provingState.areRootParityInputsReady()) {
|
|
464
|
+
const rootParityInputs = new RootParityInputs(provingState.rootParityInput);
|
|
465
|
+
this.enqueueRootParityCircuit(provingState, rootParityInputs);
|
|
466
|
+
}
|
|
467
|
+
});
|
|
560
468
|
}
|
|
561
|
-
//
|
|
562
|
-
if
|
|
563
|
-
|
|
564
|
-
|
|
469
|
+
// Runs the root parity circuit ans stored the outputs
|
|
470
|
+
// Enqueues the root rollup proof if all inputs are available
|
|
471
|
+
enqueueRootParityCircuit(provingState, inputs) {
|
|
472
|
+
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getRootParityProof', {
|
|
473
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
474
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-parity',
|
|
475
|
+
}, signal => this.prover.getRootParityProof(inputs, signal)), async (rootInput) => {
|
|
476
|
+
provingState.finalRootParityInput = rootInput;
|
|
477
|
+
await this.checkAndEnqueueRootRollup(provingState);
|
|
478
|
+
});
|
|
565
479
|
}
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
480
|
+
async checkAndEnqueueRootRollup(provingState) {
|
|
481
|
+
if (!provingState?.isReadyForRootRollup()) {
|
|
482
|
+
logger.debug('Not ready for root rollup');
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
await this.enqueueRootRollup(provingState);
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Stores the inputs to a merge/root circuit and enqueues the circuit if ready
|
|
489
|
+
* @param provingState - The proving state being operated on
|
|
490
|
+
* @param currentLevel - The level of the merge/root circuit
|
|
491
|
+
* @param currentIndex - The index of the merge/root circuit
|
|
492
|
+
* @param mergeInputData - The inputs to be stored
|
|
493
|
+
*/
|
|
494
|
+
storeAndExecuteNextMergeLevel(provingState, currentLevel, currentIndex, mergeInputData) {
|
|
495
|
+
const result = this.storeMergeInputs(provingState, currentLevel, currentIndex, mergeInputData);
|
|
496
|
+
// Are we ready to execute the next circuit?
|
|
497
|
+
if (!result.ready) {
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
if (result.mergeLevel === 0n) {
|
|
501
|
+
// TODO (alexg) remove this `void`
|
|
502
|
+
void this.checkAndEnqueueRootRollup(provingState);
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
// onto the next merge level
|
|
506
|
+
this.enqueueMergeRollup(provingState, result.mergeLevel, result.indexWithinMergeLevel, result.mergeInputData);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Executes the VM circuit for a public function, will enqueue the corresponding kernel if the
|
|
511
|
+
* previous kernel is ready
|
|
512
|
+
* @param provingState - The proving state being operated on
|
|
513
|
+
* @param txIndex - The index of the transaction being proven
|
|
514
|
+
* @param functionIndex - The index of the function/kernel being proven
|
|
515
|
+
*/
|
|
516
|
+
enqueueVM(provingState, txIndex, functionIndex) {
|
|
517
|
+
if (!provingState?.verifyState()) {
|
|
518
|
+
logger.debug(`Not running VM circuit as state is no longer valid`);
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
const txProvingState = provingState.getTxProvingState(txIndex);
|
|
522
|
+
const publicFunction = txProvingState.getPublicFunctionState(functionIndex);
|
|
523
|
+
// If there is a VM request, we need to prove it. Otherwise, continue with the kernel.
|
|
524
|
+
if (publicFunction.vmRequest) {
|
|
525
|
+
// This function tries to do AVM proving. If there is a failure, it fakes the proof unless AVM_PROVING_STRICT is defined.
|
|
526
|
+
// Nothing downstream depends on the AVM proof yet. So having this mode lets us incrementally build the AVM circuit.
|
|
527
|
+
const doAvmProving = wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getAvmProof', {
|
|
528
|
+
[Attributes.TX_HASH]: txProvingState.processedTx.hash.toString(),
|
|
529
|
+
[Attributes.APP_CIRCUIT_NAME]: publicFunction.vmRequest.functionName,
|
|
530
|
+
}, async (signal) => {
|
|
531
|
+
const inputs = new AvmCircuitInputs(publicFunction.vmRequest.functionName, publicFunction.vmRequest.bytecode, publicFunction.vmRequest.calldata, publicFunction.vmRequest.kernelRequest.inputs.publicCall.callStackItem.publicInputs, publicFunction.vmRequest.avmHints);
|
|
532
|
+
try {
|
|
533
|
+
return await this.prover.getAvmProof(inputs, signal);
|
|
534
|
+
}
|
|
535
|
+
catch (err) {
|
|
536
|
+
if (process.env.AVM_PROVING_STRICT) {
|
|
537
|
+
throw err;
|
|
538
|
+
}
|
|
539
|
+
else {
|
|
540
|
+
logger.warn(`Error thrown when proving AVM circuit: ${err}`);
|
|
541
|
+
logger.warn(`AVM_PROVING_STRICT is off, faking AVM proof and carrying on...`);
|
|
542
|
+
return { proof: makeEmptyProof(), verificationKey: VerificationKeyData.makeFake() };
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
this.deferredProving(provingState, doAvmProving, proofAndVk => {
|
|
547
|
+
logger.debug(`Proven VM for function index ${functionIndex} of tx index ${txIndex}`);
|
|
548
|
+
this.checkAndEnqueuePublicKernel(provingState, txIndex, functionIndex, proofAndVk.proof);
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
else {
|
|
552
|
+
this.checkAndEnqueuePublicKernel(provingState, txIndex, functionIndex, /*vmProof=*/ makeEmptyProof());
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
checkAndEnqueuePublicKernel(provingState, txIndex, functionIndex, vmProof) {
|
|
556
|
+
const txProvingState = provingState.getTxProvingState(txIndex);
|
|
557
|
+
const kernelRequest = txProvingState.getNextPublicKernelFromVMProof(functionIndex, vmProof);
|
|
558
|
+
if (kernelRequest.code === TX_PROVING_CODE.READY) {
|
|
559
|
+
if (kernelRequest.function === undefined) {
|
|
560
|
+
// Should not be possible
|
|
561
|
+
throw new Error(`Error occurred, public function request undefined after VM proof completed`);
|
|
562
|
+
}
|
|
563
|
+
logger.debug(`Enqueuing kernel from VM for tx ${txIndex}, function ${functionIndex}`);
|
|
564
|
+
this.enqueuePublicKernel(provingState, txIndex, functionIndex);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Executes the kernel circuit for a public function, will enqueue the next kernel circuit if it's VM is already proven
|
|
569
|
+
* or the base rollup circuit if there are no more kernels to be proven
|
|
570
|
+
* @param provingState - The proving state being operated on
|
|
571
|
+
* @param txIndex - The index of the transaction being proven
|
|
572
|
+
* @param functionIndex - The index of the function/kernel being proven
|
|
573
|
+
*/
|
|
574
|
+
enqueuePublicKernel(provingState, txIndex, functionIndex) {
|
|
575
|
+
if (!provingState?.verifyState()) {
|
|
576
|
+
logger.debug(`Not running public kernel circuit as state is no longer valid`);
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
const txProvingState = provingState.getTxProvingState(txIndex);
|
|
580
|
+
const request = txProvingState.getPublicFunctionState(functionIndex).publicKernelRequest;
|
|
581
|
+
this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, request.type === PublicKernelType.TAIL
|
|
582
|
+
? 'ProvingOrchestrator.prover.getPublicTailProof'
|
|
583
|
+
: 'ProvingOrchestrator.prover.getPublicKernelProof', {
|
|
584
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
585
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: mapPublicKernelToCircuitName(request.type),
|
|
586
|
+
}, (signal) => {
|
|
587
|
+
if (request.type === PublicKernelType.TAIL) {
|
|
588
|
+
return this.prover.getPublicTailProof(request, signal);
|
|
589
|
+
}
|
|
590
|
+
else {
|
|
591
|
+
return this.prover.getPublicKernelProof(request, signal);
|
|
592
|
+
}
|
|
593
|
+
}), result => {
|
|
594
|
+
const nextKernelRequest = txProvingState.getNextPublicKernelFromKernelProof(functionIndex, result.proof, result.verificationKey);
|
|
595
|
+
// What's the status of the next kernel?
|
|
596
|
+
if (nextKernelRequest.code === TX_PROVING_CODE.NOT_READY) {
|
|
597
|
+
// Must be waiting on a VM proof
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
if (nextKernelRequest.code === TX_PROVING_CODE.COMPLETED) {
|
|
601
|
+
// We must have completed all public function proving, we now move to the base rollup
|
|
602
|
+
logger.debug(`Public functions completed for tx ${txIndex} enqueueing base rollup`);
|
|
603
|
+
// Take the final public tail proof and verification key and pass them to the base rollup
|
|
604
|
+
txProvingState.baseRollupInputs.kernelData.proof = result.proof;
|
|
605
|
+
txProvingState.baseRollupInputs.kernelData.vk = result.verificationKey;
|
|
606
|
+
this.enqueueBaseRollup(provingState, BigInt(txIndex), txProvingState);
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
// There must be another kernel ready to be proven
|
|
610
|
+
if (nextKernelRequest.function === undefined) {
|
|
611
|
+
// Should not be possible
|
|
612
|
+
throw new Error(`Error occurred, public function request undefined after kernel proof completed`);
|
|
613
|
+
}
|
|
614
|
+
this.enqueuePublicKernel(provingState, txIndex, functionIndex + 1);
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
},
|
|
618
|
+
(() => {
|
|
619
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
620
|
+
_startNewBlock_decorators = [trackSpan('ProvingOrchestrator.startNewBlock', (numTxs, globalVariables) => ({
|
|
621
|
+
[Attributes.BLOCK_SIZE]: numTxs,
|
|
622
|
+
[Attributes.BLOCK_NUMBER]: globalVariables.blockNumber.toNumber(),
|
|
623
|
+
}))];
|
|
624
|
+
_addNewTx_decorators = [trackSpan('ProvingOrchestrator.addNewTx', tx => ({
|
|
625
|
+
[Attributes.TX_HASH]: tx.hash.toString(),
|
|
626
|
+
}))];
|
|
627
|
+
_setBlockCompleted_decorators = [trackSpan('ProvingOrchestrator.setBlockCompleted', function () {
|
|
628
|
+
if (!this.provingState) {
|
|
629
|
+
return {};
|
|
630
|
+
}
|
|
631
|
+
return {
|
|
632
|
+
[Attributes.BLOCK_NUMBER]: this.provingState.globalVariables.blockNumber.toNumber(),
|
|
633
|
+
[Attributes.BLOCK_SIZE]: this.provingState.totalNumTxs,
|
|
634
|
+
[Attributes.BLOCK_TXS_COUNT]: this.provingState.transactionsReceived,
|
|
635
|
+
};
|
|
636
|
+
})];
|
|
637
|
+
_finaliseBlock_decorators = [trackSpan('ProvingOrchestrator.finaliseBlock', function () {
|
|
638
|
+
return {
|
|
639
|
+
[Attributes.BLOCK_NUMBER]: this.provingState.globalVariables.blockNumber.toNumber(),
|
|
640
|
+
[Attributes.BLOCK_TXS_COUNT]: this.provingState.transactionsReceived,
|
|
641
|
+
[Attributes.BLOCK_SIZE]: this.provingState.totalNumTxs,
|
|
642
|
+
};
|
|
643
|
+
})];
|
|
644
|
+
_prepareBaseRollupInputs_decorators = [trackSpan('ProvingOrchestrator.prepareBaseRollupInputs', (_, tx) => ({
|
|
645
|
+
[Attributes.TX_HASH]: tx.hash.toString(),
|
|
646
|
+
}))];
|
|
647
|
+
__esDecorate(_a, null, _startNewBlock_decorators, { kind: "method", name: "startNewBlock", static: false, private: false, access: { has: obj => "startNewBlock" in obj, get: obj => obj.startNewBlock }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
648
|
+
__esDecorate(_a, null, _addNewTx_decorators, { kind: "method", name: "addNewTx", static: false, private: false, access: { has: obj => "addNewTx" in obj, get: obj => obj.addNewTx }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
649
|
+
__esDecorate(_a, null, _setBlockCompleted_decorators, { kind: "method", name: "setBlockCompleted", static: false, private: false, access: { has: obj => "setBlockCompleted" in obj, get: obj => obj.setBlockCompleted }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
650
|
+
__esDecorate(_a, null, _finaliseBlock_decorators, { kind: "method", name: "finaliseBlock", static: false, private: false, access: { has: obj => "finaliseBlock" in obj, get: obj => obj.finaliseBlock }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
651
|
+
__esDecorate(_a, null, _prepareBaseRollupInputs_decorators, { kind: "method", name: "prepareBaseRollupInputs", static: false, private: false, access: { has: obj => "prepareBaseRollupInputs" in obj, get: obj => obj.prepareBaseRollupInputs }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
652
|
+
if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
653
|
+
})(),
|
|
654
|
+
_a;
|
|
655
|
+
})();
|
|
656
|
+
export { ProvingOrchestrator };
|
|
570
657
|
function extractAggregationObject(proof, numPublicInputs) {
|
|
571
658
|
const buffer = proof.buffer.subarray(Fr.SIZE_IN_BYTES * (numPublicInputs - AGGREGATION_OBJECT_LENGTH), Fr.SIZE_IN_BYTES * numPublicInputs);
|
|
659
|
+
// TODO(#7159): Remove the following workaround
|
|
660
|
+
if (buffer.length === 0) {
|
|
661
|
+
return Array.from({ length: AGGREGATION_OBJECT_LENGTH }, () => Fr.ZERO);
|
|
662
|
+
}
|
|
572
663
|
return BufferReader.asReader(buffer).readArray(AGGREGATION_OBJECT_LENGTH, Fr);
|
|
573
664
|
}
|
|
574
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JjaGVzdHJhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL29yY2hlc3RyYXRvci9vcmNoZXN0cmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLElBQUksRUFDSixPQUFPLEVBQ1AsWUFBWSxFQUdaLGdCQUFnQixFQUNoQixFQUFFLEVBRUYsb0JBQW9CLEVBQ3BCLHNCQUFzQixFQUN0QixVQUFVLEdBQ1gsTUFBTSxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLEVBQ0wsZUFBZSxFQUVmLGNBQWMsR0FLZixNQUFNLGlDQUFpQyxDQUFDO0FBQ3pDLE9BQU8sRUFDTCx5QkFBeUIsRUFDekIsZ0JBQWdCLEVBRWhCLGdCQUFnQixFQUVoQixFQUFFLEVBSUYsMkJBQTJCLEVBQzNCLHdDQUF3QyxFQUV4QyxtQ0FBbUMsRUFDbkMsK0JBQStCLEVBTS9CLGdCQUFnQixFQUVoQixtQkFBbUIsRUFFbkIsY0FBYyxHQUNmLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3BELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDckQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDMUQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDakUsT0FBTyxFQUFFLFlBQVksRUFBYyxNQUFNLDZCQUE2QixDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUd6RCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRS9CLE9BQU8sRUFDTCxvQkFBb0IsRUFDcEIsdUJBQXVCLEVBQ3ZCLGtCQUFrQixFQUNsQixxQkFBcUIsRUFDckIsZUFBZSxFQUNmLG9C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
|
|
665
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JjaGVzdHJhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL29yY2hlc3RyYXRvci9vcmNoZXN0cmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFDTCxJQUFJLEVBQ0osT0FBTyxFQUNQLFlBQVksRUFHWixnQkFBZ0IsRUFDaEIsRUFBRSxFQUVGLG9CQUFvQixFQUNwQixzQkFBc0IsRUFDdEIsNEJBQTRCLEVBQzVCLFVBQVUsR0FDWCxNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFDTCxlQUFlLEVBRWYsY0FBYyxHQUtmLE1BQU0saUNBQWlDLENBQUM7QUFFekMsT0FBTyxFQUNMLHlCQUF5QixFQUN6QixnQkFBZ0IsRUFFaEIsZ0JBQWdCLEVBRWhCLEVBQUUsRUFJRiwyQkFBMkIsRUFDM0Isd0NBQXdDLEVBRXhDLG1DQUFtQyxFQUNuQywrQkFBK0IsRUFNL0IsZ0JBQWdCLEVBRWhCLG1CQUFtQixFQUVuQixjQUFjLEdBQ2YsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDcEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzNELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNqRSxPQUFPLEVBQUUsWUFBWSxFQUFjLE1BQU0sNkJBQTZCLENBQUM7QUFDdkUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxVQUFVLEVBQXFDLFNBQVMsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBR3ZILE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7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
|