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