@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
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
type TxEffect,
|
|
10
10
|
makeEmptyProcessedTx,
|
|
11
11
|
makePaddingProcessedTx,
|
|
12
|
+
mapPublicKernelToCircuitName,
|
|
12
13
|
toTxEffect,
|
|
13
14
|
} from '@aztec/circuit-types';
|
|
14
15
|
import {
|
|
@@ -20,6 +21,7 @@ import {
|
|
|
20
21
|
type PublicInputsAndRecursiveProof,
|
|
21
22
|
type ServerCircuitProver,
|
|
22
23
|
} from '@aztec/circuit-types/interfaces';
|
|
24
|
+
import { type CircuitName } from '@aztec/circuit-types/stats';
|
|
23
25
|
import {
|
|
24
26
|
AGGREGATION_OBJECT_LENGTH,
|
|
25
27
|
AvmCircuitInputs,
|
|
@@ -53,6 +55,7 @@ import { createDebugLogger } from '@aztec/foundation/log';
|
|
|
53
55
|
import { promiseWithResolvers } from '@aztec/foundation/promise';
|
|
54
56
|
import { BufferReader, type Tuple } from '@aztec/foundation/serialize';
|
|
55
57
|
import { pushTestData } from '@aztec/foundation/testing';
|
|
58
|
+
import { Attributes, type TelemetryClient, type Tracer, trackSpan, wrapCallbackInSpan } from '@aztec/telemetry-client';
|
|
56
59
|
import { type MerkleTreeOperations } from '@aztec/world-state';
|
|
57
60
|
|
|
58
61
|
import { inspect } from 'util';
|
|
@@ -91,7 +94,16 @@ export class ProvingOrchestrator {
|
|
|
91
94
|
private pendingProvingJobs: AbortController[] = [];
|
|
92
95
|
private paddingTx: PaddingProcessedTx | undefined = undefined;
|
|
93
96
|
|
|
94
|
-
|
|
97
|
+
public readonly tracer: Tracer;
|
|
98
|
+
|
|
99
|
+
constructor(
|
|
100
|
+
private db: MerkleTreeOperations,
|
|
101
|
+
private prover: ServerCircuitProver,
|
|
102
|
+
telemetryClient: TelemetryClient,
|
|
103
|
+
private initialHeader?: Header,
|
|
104
|
+
) {
|
|
105
|
+
this.tracer = telemetryClient.getTracer('ProvingOrchestrator');
|
|
106
|
+
}
|
|
95
107
|
|
|
96
108
|
/**
|
|
97
109
|
* Resets the orchestrator's cached padding tx.
|
|
@@ -108,6 +120,10 @@ export class ProvingOrchestrator {
|
|
|
108
120
|
* @param verificationKeys - The private kernel verification keys
|
|
109
121
|
* @returns A proving ticket, containing a promise notifying of proving completion
|
|
110
122
|
*/
|
|
123
|
+
@trackSpan('ProvingOrchestrator.startNewBlock', (numTxs, globalVariables) => ({
|
|
124
|
+
[Attributes.BLOCK_SIZE]: numTxs,
|
|
125
|
+
[Attributes.BLOCK_NUMBER]: globalVariables.blockNumber.toNumber(),
|
|
126
|
+
}))
|
|
111
127
|
public async startNewBlock(
|
|
112
128
|
numTxs: number,
|
|
113
129
|
globalVariables: GlobalVariables,
|
|
@@ -119,10 +135,8 @@ export class ProvingOrchestrator {
|
|
|
119
135
|
this.initialHeader = await this.db.buildInitialHeader();
|
|
120
136
|
}
|
|
121
137
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (!Number.isInteger(numTxs) || numTxs < 2 || (numTxs & (numTxs - 1)) !== 0) {
|
|
125
|
-
throw new Error(`Length of txs for the block should be a power of two and at least two (got ${numTxs})`);
|
|
138
|
+
if (!Number.isInteger(numTxs) || numTxs < 2) {
|
|
139
|
+
throw new Error(`Length of txs for the block should be at least two (got ${numTxs})`);
|
|
126
140
|
}
|
|
127
141
|
// Cancel any currently proving block before starting a new one
|
|
128
142
|
this.cancelBlock();
|
|
@@ -193,6 +207,9 @@ export class ProvingOrchestrator {
|
|
|
193
207
|
* The interface to add a simulated transaction to the scheduler
|
|
194
208
|
* @param tx - The transaction to be proven
|
|
195
209
|
*/
|
|
210
|
+
@trackSpan('ProvingOrchestrator.addNewTx', tx => ({
|
|
211
|
+
[Attributes.TX_HASH]: tx.hash.toString(),
|
|
212
|
+
}))
|
|
196
213
|
public async addNewTx(tx: ProcessedTx): Promise<void> {
|
|
197
214
|
if (!this.provingState) {
|
|
198
215
|
throw new Error(`Invalid proving state, call startNewBlock before adding transactions`);
|
|
@@ -206,13 +223,29 @@ export class ProvingOrchestrator {
|
|
|
206
223
|
|
|
207
224
|
logger.info(`Received transaction: ${tx.hash}`);
|
|
208
225
|
|
|
226
|
+
if (tx.isEmpty) {
|
|
227
|
+
logger.warn(`Ignoring empty transaction ${tx.hash} - it will not be added to this block`);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
209
231
|
const [inputs, treeSnapshots] = await this.prepareTransaction(tx, this.provingState);
|
|
210
232
|
this.enqueueFirstProof(inputs, treeSnapshots, tx, this.provingState);
|
|
211
233
|
}
|
|
212
234
|
|
|
213
235
|
/**
|
|
214
|
-
* Marks the block as full and pads it
|
|
236
|
+
* Marks the block as full and pads it if required, no more transactions will be accepted.
|
|
215
237
|
*/
|
|
238
|
+
@trackSpan('ProvingOrchestrator.setBlockCompleted', function () {
|
|
239
|
+
if (!this.provingState) {
|
|
240
|
+
return {};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
[Attributes.BLOCK_NUMBER]: this.provingState!.globalVariables.blockNumber.toNumber(),
|
|
245
|
+
[Attributes.BLOCK_SIZE]: this.provingState!.totalNumTxs,
|
|
246
|
+
[Attributes.BLOCK_TXS_COUNT]: this.provingState!.transactionsReceived,
|
|
247
|
+
};
|
|
248
|
+
})
|
|
216
249
|
public async setBlockCompleted() {
|
|
217
250
|
if (!this.provingState) {
|
|
218
251
|
throw new Error(`Invalid proving state, call startNewBlock before adding transactions or completing the block`);
|
|
@@ -222,10 +255,15 @@ export class ProvingOrchestrator {
|
|
|
222
255
|
const paddingTxCount = this.provingState.totalNumTxs - this.provingState.transactionsReceived;
|
|
223
256
|
if (paddingTxCount === 0) {
|
|
224
257
|
return;
|
|
258
|
+
} else if (this.provingState.totalNumTxs > 2) {
|
|
259
|
+
throw new Error(`Block not ready for completion: expecting ${paddingTxCount} more transactions.`);
|
|
225
260
|
}
|
|
226
261
|
|
|
227
262
|
logger.debug(`Padding rollup with ${paddingTxCount} empty transactions`);
|
|
228
263
|
// Make an empty padding transaction
|
|
264
|
+
// Required for:
|
|
265
|
+
// 0 (when we want an empty block, largely for testing), or
|
|
266
|
+
// 1 (we need to pad with one tx as all rollup circuits require a pair of inputs) txs
|
|
229
267
|
// Insert it into the tree the required number of times to get all of the
|
|
230
268
|
// base rollup inputs
|
|
231
269
|
// Then enqueue the proving of all the transactions
|
|
@@ -264,18 +302,26 @@ export class ProvingOrchestrator {
|
|
|
264
302
|
logger.debug(`Enqueuing deferred proving for padding txs to enqueue ${txInputs.length} paddings`);
|
|
265
303
|
this.deferredProving(
|
|
266
304
|
provingState,
|
|
267
|
-
|
|
268
|
-
this.
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
305
|
+
wrapCallbackInSpan(
|
|
306
|
+
this.tracer,
|
|
307
|
+
'ProvingOrchestrator.prover.getEmptyPrivateKernelProof',
|
|
308
|
+
{
|
|
309
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
310
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'private-kernel-empty' as CircuitName,
|
|
311
|
+
},
|
|
312
|
+
signal =>
|
|
313
|
+
this.prover.getEmptyPrivateKernelProof(
|
|
314
|
+
{
|
|
315
|
+
// Chain id and version should not change even if the proving state does, so it's safe to use them for the padding tx
|
|
316
|
+
// which gets cached across multiple runs of the orchestrator with different proving states. If they were to change,
|
|
317
|
+
// we'd have to clear out the paddingTx here and regenerate it when they do.
|
|
318
|
+
chainId: unprovenPaddingTx.data.constants.txContext.chainId,
|
|
319
|
+
version: unprovenPaddingTx.data.constants.txContext.version,
|
|
320
|
+
header: unprovenPaddingTx.data.constants.historicalHeader,
|
|
321
|
+
},
|
|
322
|
+
signal,
|
|
323
|
+
),
|
|
324
|
+
),
|
|
279
325
|
result => {
|
|
280
326
|
logger.debug(`Completed proof for padding tx, now enqueuing ${txInputs.length} padding txs`);
|
|
281
327
|
this.paddingTx = makePaddingProcessedTx(result);
|
|
@@ -319,6 +365,13 @@ export class ProvingOrchestrator {
|
|
|
319
365
|
* Performs the final tree update for the block and returns the fully proven block.
|
|
320
366
|
* @returns The fully proven block and proof.
|
|
321
367
|
*/
|
|
368
|
+
@trackSpan('ProvingOrchestrator.finaliseBlock', function () {
|
|
369
|
+
return {
|
|
370
|
+
[Attributes.BLOCK_NUMBER]: this.provingState!.globalVariables.blockNumber.toNumber(),
|
|
371
|
+
[Attributes.BLOCK_TXS_COUNT]: this.provingState!.transactionsReceived,
|
|
372
|
+
[Attributes.BLOCK_SIZE]: this.provingState!.totalNumTxs,
|
|
373
|
+
};
|
|
374
|
+
})
|
|
322
375
|
public async finaliseBlock() {
|
|
323
376
|
try {
|
|
324
377
|
if (
|
|
@@ -496,6 +549,9 @@ export class ProvingOrchestrator {
|
|
|
496
549
|
}
|
|
497
550
|
|
|
498
551
|
// Updates the merkle trees for a transaction. The first enqueued job for a transaction
|
|
552
|
+
@trackSpan('ProvingOrchestrator.prepareBaseRollupInputs', (_, tx) => ({
|
|
553
|
+
[Attributes.TX_HASH]: tx.hash.toString(),
|
|
554
|
+
}))
|
|
499
555
|
private async prepareBaseRollupInputs(
|
|
500
556
|
provingState: ProvingState | undefined,
|
|
501
557
|
tx: ProcessedTx,
|
|
@@ -531,13 +587,18 @@ export class ProvingOrchestrator {
|
|
|
531
587
|
VerificationKeyAsFields,
|
|
532
588
|
],
|
|
533
589
|
) {
|
|
534
|
-
const mergeLevel
|
|
535
|
-
|
|
590
|
+
const [mergeLevel, indexWithinMergeLevel, indexWithinMerge] = provingState.findMergeLevel(
|
|
591
|
+
currentLevel,
|
|
592
|
+
currentIndex,
|
|
593
|
+
);
|
|
536
594
|
const mergeIndex = 2n ** mergeLevel - 1n + indexWithinMergeLevel;
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
595
|
+
const ready = provingState.storeMergeInputs(mergeInputs, Number(indexWithinMerge), Number(mergeIndex));
|
|
596
|
+
return {
|
|
597
|
+
ready,
|
|
598
|
+
indexWithinMergeLevel,
|
|
599
|
+
mergeLevel,
|
|
600
|
+
mergeInputData: provingState.getMergeInputs(Number(mergeIndex)),
|
|
601
|
+
};
|
|
541
602
|
}
|
|
542
603
|
|
|
543
604
|
// Executes the base rollup circuit and stored the output as intermediate state for the parent merge/root circuit
|
|
@@ -593,7 +654,16 @@ export class ProvingOrchestrator {
|
|
|
593
654
|
|
|
594
655
|
this.deferredProving(
|
|
595
656
|
provingState,
|
|
596
|
-
|
|
657
|
+
wrapCallbackInSpan(
|
|
658
|
+
this.tracer,
|
|
659
|
+
'ProvingOrchestrator.prover.getBaseRollupProof',
|
|
660
|
+
{
|
|
661
|
+
[Attributes.TX_HASH]: tx.processedTx.hash.toString(),
|
|
662
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
663
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-rollup' as CircuitName,
|
|
664
|
+
},
|
|
665
|
+
signal => this.prover.getBaseRollupProof(tx.baseRollupInputs, signal),
|
|
666
|
+
),
|
|
597
667
|
result => {
|
|
598
668
|
logger.debug(`Completed proof for base rollup for tx ${tx.processedTx.hash.toString()}`);
|
|
599
669
|
validatePartialState(result.inputs.end, tx.treeSnapshots);
|
|
@@ -622,7 +692,15 @@ export class ProvingOrchestrator {
|
|
|
622
692
|
|
|
623
693
|
this.deferredProving(
|
|
624
694
|
provingState,
|
|
625
|
-
|
|
695
|
+
wrapCallbackInSpan(
|
|
696
|
+
this.tracer,
|
|
697
|
+
'ProvingOrchestrator.prover.getMergeRollupProof',
|
|
698
|
+
{
|
|
699
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
700
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'merge-rollup' as CircuitName,
|
|
701
|
+
},
|
|
702
|
+
signal => this.prover.getMergeRollupProof(inputs, signal),
|
|
703
|
+
),
|
|
626
704
|
result => {
|
|
627
705
|
this.storeAndExecuteNextMergeLevel(provingState, level, index, [
|
|
628
706
|
result.inputs,
|
|
@@ -658,7 +736,15 @@ export class ProvingOrchestrator {
|
|
|
658
736
|
|
|
659
737
|
this.deferredProving(
|
|
660
738
|
provingState,
|
|
661
|
-
|
|
739
|
+
wrapCallbackInSpan(
|
|
740
|
+
this.tracer,
|
|
741
|
+
'ProvingOrchestrator.prover.getRootRollupProof',
|
|
742
|
+
{
|
|
743
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
744
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-rollup' as CircuitName,
|
|
745
|
+
},
|
|
746
|
+
signal => this.prover.getRootRollupProof(inputs, signal),
|
|
747
|
+
),
|
|
662
748
|
result => {
|
|
663
749
|
provingState.rootRollupPublicInputs = result.inputs;
|
|
664
750
|
provingState.finalAggregationObject = extractAggregationObject(
|
|
@@ -680,7 +766,15 @@ export class ProvingOrchestrator {
|
|
|
680
766
|
private enqueueBaseParityCircuit(provingState: ProvingState, inputs: BaseParityInputs, index: number) {
|
|
681
767
|
this.deferredProving(
|
|
682
768
|
provingState,
|
|
683
|
-
|
|
769
|
+
wrapCallbackInSpan(
|
|
770
|
+
this.tracer,
|
|
771
|
+
'ProvingOrchestrator.prover.getBaseParityProof',
|
|
772
|
+
{
|
|
773
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
774
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-parity' as CircuitName,
|
|
775
|
+
},
|
|
776
|
+
signal => this.prover.getBaseParityProof(inputs, signal),
|
|
777
|
+
),
|
|
684
778
|
rootInput => {
|
|
685
779
|
provingState.setRootParityInputs(rootInput, index);
|
|
686
780
|
if (provingState.areRootParityInputsReady()) {
|
|
@@ -701,7 +795,15 @@ export class ProvingOrchestrator {
|
|
|
701
795
|
private enqueueRootParityCircuit(provingState: ProvingState | undefined, inputs: RootParityInputs) {
|
|
702
796
|
this.deferredProving(
|
|
703
797
|
provingState,
|
|
704
|
-
|
|
798
|
+
wrapCallbackInSpan(
|
|
799
|
+
this.tracer,
|
|
800
|
+
'ProvingOrchestrator.prover.getRootParityProof',
|
|
801
|
+
{
|
|
802
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
803
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-parity' as CircuitName,
|
|
804
|
+
},
|
|
805
|
+
signal => this.prover.getRootParityProof(inputs, signal),
|
|
806
|
+
),
|
|
705
807
|
async rootInput => {
|
|
706
808
|
provingState!.finalRootParityInput = rootInput;
|
|
707
809
|
await this.checkAndEnqueueRootRollup(provingState);
|
|
@@ -770,25 +872,34 @@ export class ProvingOrchestrator {
|
|
|
770
872
|
if (publicFunction.vmRequest) {
|
|
771
873
|
// This function tries to do AVM proving. If there is a failure, it fakes the proof unless AVM_PROVING_STRICT is defined.
|
|
772
874
|
// Nothing downstream depends on the AVM proof yet. So having this mode lets us incrementally build the AVM circuit.
|
|
773
|
-
const doAvmProving =
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
publicFunction.vmRequest!.
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
875
|
+
const doAvmProving = wrapCallbackInSpan(
|
|
876
|
+
this.tracer,
|
|
877
|
+
'ProvingOrchestrator.prover.getAvmProof',
|
|
878
|
+
{
|
|
879
|
+
[Attributes.TX_HASH]: txProvingState.processedTx.hash.toString(),
|
|
880
|
+
[Attributes.APP_CIRCUIT_NAME]: publicFunction.vmRequest!.functionName,
|
|
881
|
+
},
|
|
882
|
+
async (signal: AbortSignal) => {
|
|
883
|
+
const inputs: AvmCircuitInputs = new AvmCircuitInputs(
|
|
884
|
+
publicFunction.vmRequest!.functionName,
|
|
885
|
+
publicFunction.vmRequest!.bytecode,
|
|
886
|
+
publicFunction.vmRequest!.calldata,
|
|
887
|
+
publicFunction.vmRequest!.kernelRequest.inputs.publicCall.callStackItem.publicInputs,
|
|
888
|
+
publicFunction.vmRequest!.avmHints,
|
|
889
|
+
);
|
|
890
|
+
try {
|
|
891
|
+
return await this.prover.getAvmProof(inputs, signal);
|
|
892
|
+
} catch (err) {
|
|
893
|
+
if (process.env.AVM_PROVING_STRICT) {
|
|
894
|
+
throw err;
|
|
895
|
+
} else {
|
|
896
|
+
logger.warn(`Error thrown when proving AVM circuit: ${err}`);
|
|
897
|
+
logger.warn(`AVM_PROVING_STRICT is off, faking AVM proof and carrying on...`);
|
|
898
|
+
return { proof: makeEmptyProof(), verificationKey: VerificationKeyData.makeFake() };
|
|
899
|
+
}
|
|
789
900
|
}
|
|
790
|
-
}
|
|
791
|
-
|
|
901
|
+
},
|
|
902
|
+
);
|
|
792
903
|
this.deferredProving(provingState, doAvmProving, proofAndVk => {
|
|
793
904
|
logger.debug(`Proven VM for function index ${functionIndex} of tx index ${txIndex}`);
|
|
794
905
|
this.checkAndEnqueuePublicKernel(provingState, txIndex, functionIndex, proofAndVk.proof);
|
|
@@ -834,13 +945,25 @@ export class ProvingOrchestrator {
|
|
|
834
945
|
|
|
835
946
|
this.deferredProving(
|
|
836
947
|
provingState,
|
|
837
|
-
(
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
948
|
+
wrapCallbackInSpan(
|
|
949
|
+
this.tracer,
|
|
950
|
+
request.type === PublicKernelType.TAIL
|
|
951
|
+
? 'ProvingOrchestrator.prover.getPublicTailProof'
|
|
952
|
+
: 'ProvingOrchestrator.prover.getPublicKernelProof',
|
|
953
|
+
{
|
|
954
|
+
[Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
|
|
955
|
+
[Attributes.PROTOCOL_CIRCUIT_NAME]: mapPublicKernelToCircuitName(request.type),
|
|
956
|
+
},
|
|
957
|
+
(
|
|
958
|
+
signal,
|
|
959
|
+
): Promise<PublicInputsAndRecursiveProof<KernelCircuitPublicInputs | PublicKernelCircuitPublicInputs>> => {
|
|
960
|
+
if (request.type === PublicKernelType.TAIL) {
|
|
961
|
+
return this.prover.getPublicTailProof(request, signal);
|
|
962
|
+
} else {
|
|
963
|
+
return this.prover.getPublicKernelProof(request, signal);
|
|
964
|
+
}
|
|
965
|
+
},
|
|
966
|
+
),
|
|
844
967
|
result => {
|
|
845
968
|
const nextKernelRequest = txProvingState.getNextPublicKernelFromKernelProof(
|
|
846
969
|
functionIndex,
|
|
@@ -879,5 +1002,9 @@ function extractAggregationObject(proof: Proof, numPublicInputs: number): Fr[] {
|
|
|
879
1002
|
Fr.SIZE_IN_BYTES * (numPublicInputs - AGGREGATION_OBJECT_LENGTH),
|
|
880
1003
|
Fr.SIZE_IN_BYTES * numPublicInputs,
|
|
881
1004
|
);
|
|
1005
|
+
// TODO(#7159): Remove the following workaround
|
|
1006
|
+
if (buffer.length === 0) {
|
|
1007
|
+
return Array.from({ length: AGGREGATION_OBJECT_LENGTH }, () => Fr.ZERO);
|
|
1008
|
+
}
|
|
882
1009
|
return BufferReader.asReader(buffer).readArray(AGGREGATION_OBJECT_LENGTH, Fr);
|
|
883
1010
|
}
|
|
@@ -71,6 +71,32 @@ export class ProvingState {
|
|
|
71
71
|
return BigInt(Math.ceil(Math.log2(this.totalNumTxs)) - 1);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
// Calculates the index and level of the parent rollup circuit
|
|
75
|
+
// Based on tree implementation in unbalanced_tree.ts -> batchInsert()
|
|
76
|
+
public findMergeLevel(currentLevel: bigint, currentIndex: bigint) {
|
|
77
|
+
const moveUpMergeLevel = (levelSize: number, index: bigint, nodeToShift: boolean) => {
|
|
78
|
+
levelSize /= 2;
|
|
79
|
+
if (levelSize & 1) {
|
|
80
|
+
[levelSize, nodeToShift] = nodeToShift ? [levelSize + 1, false] : [levelSize - 1, true];
|
|
81
|
+
}
|
|
82
|
+
index >>= 1n;
|
|
83
|
+
return { thisLevelSize: levelSize, thisIndex: index, shiftUp: nodeToShift };
|
|
84
|
+
};
|
|
85
|
+
let [thisLevelSize, shiftUp] = this.totalNumTxs & 1 ? [this.totalNumTxs - 1, true] : [this.totalNumTxs, false];
|
|
86
|
+
const maxLevel = this.numMergeLevels + 1n;
|
|
87
|
+
let placeholder = currentIndex;
|
|
88
|
+
for (let i = 0; i < maxLevel - currentLevel; i++) {
|
|
89
|
+
({ thisLevelSize, thisIndex: placeholder, shiftUp } = moveUpMergeLevel(thisLevelSize, placeholder, shiftUp));
|
|
90
|
+
}
|
|
91
|
+
let thisIndex = currentIndex;
|
|
92
|
+
let mergeLevel = currentLevel;
|
|
93
|
+
while (thisIndex >= thisLevelSize && mergeLevel != 0n) {
|
|
94
|
+
mergeLevel -= 1n;
|
|
95
|
+
({ thisLevelSize, thisIndex, shiftUp } = moveUpMergeLevel(thisLevelSize, thisIndex, shiftUp));
|
|
96
|
+
}
|
|
97
|
+
return [mergeLevel - 1n, thisIndex >> 1n, thisIndex & 1n];
|
|
98
|
+
}
|
|
99
|
+
|
|
74
100
|
// Adds a transaction to the proving state, returns it's index
|
|
75
101
|
// Will update the proving life cycle if this is the last transaction
|
|
76
102
|
public addNewTx(tx: TxProvingState) {
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
} from '@aztec/circuit-types/interfaces';
|
|
10
10
|
import { type Fr, type GlobalVariables, type Header, type VerificationKeys } from '@aztec/circuits.js';
|
|
11
11
|
import { NativeACVMSimulator } from '@aztec/simulator';
|
|
12
|
+
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
12
13
|
import { type WorldStateSynchronizer } from '@aztec/world-state';
|
|
13
14
|
|
|
14
15
|
import { type ProverClientConfig } from '../config.js';
|
|
@@ -28,11 +29,17 @@ export class TxProver implements ProverClient {
|
|
|
28
29
|
private config: ProverClientConfig,
|
|
29
30
|
private worldStateSynchronizer: WorldStateSynchronizer,
|
|
30
31
|
private vks: VerificationKeys,
|
|
32
|
+
private telemetry: TelemetryClient,
|
|
31
33
|
private agent?: ProverAgent,
|
|
32
34
|
initialHeader?: Header,
|
|
33
35
|
) {
|
|
34
36
|
this.queue = new MemoryProvingQueue(config.proverJobTimeoutMs, config.proverJobPollIntervalMs);
|
|
35
|
-
this.orchestrator = new ProvingOrchestrator(
|
|
37
|
+
this.orchestrator = new ProvingOrchestrator(
|
|
38
|
+
worldStateSynchronizer.getLatest(),
|
|
39
|
+
this.queue,
|
|
40
|
+
telemetry,
|
|
41
|
+
initialHeader,
|
|
42
|
+
);
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
async updateProverConfig(config: Partial<ProverClientConfig & { vks: VerificationKeys }>): Promise<void> {
|
|
@@ -43,7 +50,7 @@ export class TxProver implements ProverClient {
|
|
|
43
50
|
}
|
|
44
51
|
|
|
45
52
|
if (newConfig.realProofs !== this.config.realProofs && this.agent) {
|
|
46
|
-
const circuitProver = await TxProver.buildCircuitProver(newConfig);
|
|
53
|
+
const circuitProver = await TxProver.buildCircuitProver(newConfig, this.telemetry);
|
|
47
54
|
this.agent.setCircuitProver(circuitProver);
|
|
48
55
|
}
|
|
49
56
|
|
|
@@ -95,31 +102,35 @@ export class TxProver implements ProverClient {
|
|
|
95
102
|
config: ProverClientConfig,
|
|
96
103
|
vks: VerificationKeys,
|
|
97
104
|
worldStateSynchronizer: WorldStateSynchronizer,
|
|
105
|
+
telemetry: TelemetryClient,
|
|
98
106
|
initialHeader?: Header,
|
|
99
107
|
) {
|
|
100
108
|
const agent = config.proverAgentEnabled
|
|
101
109
|
? new ProverAgent(
|
|
102
|
-
await TxProver.buildCircuitProver(config),
|
|
110
|
+
await TxProver.buildCircuitProver(config, telemetry),
|
|
103
111
|
config.proverAgentConcurrency,
|
|
104
112
|
config.proverAgentPollInterval,
|
|
105
113
|
)
|
|
106
114
|
: undefined;
|
|
107
115
|
|
|
108
|
-
const prover = new TxProver(config, worldStateSynchronizer, vks, agent, initialHeader);
|
|
116
|
+
const prover = new TxProver(config, worldStateSynchronizer, vks, telemetry, agent, initialHeader);
|
|
109
117
|
await prover.start();
|
|
110
118
|
return prover;
|
|
111
119
|
}
|
|
112
120
|
|
|
113
|
-
private static async buildCircuitProver(
|
|
121
|
+
private static async buildCircuitProver(
|
|
122
|
+
config: ProverClientConfig,
|
|
123
|
+
telemetry: TelemetryClient,
|
|
124
|
+
): Promise<ServerCircuitProver> {
|
|
114
125
|
if (config.realProofs) {
|
|
115
|
-
return await BBNativeRollupProver.new(config);
|
|
126
|
+
return await BBNativeRollupProver.new(config, telemetry);
|
|
116
127
|
}
|
|
117
128
|
|
|
118
129
|
const simulationProvider = config.acvmBinaryPath
|
|
119
130
|
? new NativeACVMSimulator(config.acvmWorkingDirectory, config.acvmBinaryPath)
|
|
120
131
|
: undefined;
|
|
121
132
|
|
|
122
|
-
return new TestCircuitProver(simulationProvider);
|
|
133
|
+
return new TestCircuitProver(telemetry, simulationProvider);
|
|
123
134
|
}
|
|
124
135
|
|
|
125
136
|
/**
|