@aztec/prover-client 0.63.1 → 0.65.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/fixtures.d.ts.map +1 -1
- package/dest/mocks/fixtures.js +3 -3
- package/dest/mocks/test_context.d.ts +6 -8
- package/dest/mocks/test_context.d.ts.map +1 -1
- package/dest/mocks/test_context.js +17 -15
- package/dest/orchestrator/block-building-helpers.d.ts +2 -2
- package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
- package/dest/orchestrator/block-building-helpers.js +88 -60
- package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/tx-proving-state.js +8 -2
- package/dest/proving_broker/proving_agent.d.ts +33 -0
- package/dest/proving_broker/proving_agent.d.ts.map +1 -0
- package/dest/proving_broker/proving_agent.js +74 -0
- package/dest/proving_broker/proving_job_controller.d.ts +25 -0
- package/dest/proving_broker/proving_job_controller.d.ts.map +1 -0
- package/dest/proving_broker/proving_job_controller.js +112 -0
- package/dest/test/mock_prover.d.ts +12 -12
- package/dest/test/mock_prover.d.ts.map +1 -1
- package/dest/test/mock_prover.js +12 -12
- package/package.json +12 -12
- package/src/mocks/fixtures.ts +2 -9
- package/src/mocks/test_context.ts +38 -23
- package/src/orchestrator/block-building-helpers.ts +141 -94
- package/src/orchestrator/tx-proving-state.ts +9 -0
- package/src/proving_broker/proving_agent.ts +90 -0
- package/src/proving_broker/proving_job_controller.ts +148 -0
- package/src/test/mock_prover.ts +50 -11
|
@@ -13,10 +13,8 @@ import { type Fr } from '@aztec/foundation/fields';
|
|
|
13
13
|
import { type DebugLogger } from '@aztec/foundation/log';
|
|
14
14
|
import { openTmpStore } from '@aztec/kv-store/utils';
|
|
15
15
|
import {
|
|
16
|
-
type PublicExecutionResult,
|
|
17
|
-
PublicExecutionResultBuilder,
|
|
18
|
-
type PublicExecutor,
|
|
19
16
|
PublicProcessor,
|
|
17
|
+
PublicTxSimulator,
|
|
20
18
|
type SimulationProvider,
|
|
21
19
|
WASMSimulator,
|
|
22
20
|
type WorldStateDB,
|
|
@@ -25,10 +23,12 @@ import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
|
|
|
25
23
|
import { MerkleTrees } from '@aztec/world-state';
|
|
26
24
|
import { NativeWorldStateService } from '@aztec/world-state/native';
|
|
27
25
|
|
|
26
|
+
import { jest } from '@jest/globals';
|
|
28
27
|
import * as fs from 'fs/promises';
|
|
29
28
|
import { type MockProxy, mock } from 'jest-mock-extended';
|
|
30
29
|
|
|
31
30
|
import { TestCircuitProver } from '../../../bb-prover/src/test/test_circuit_prover.js';
|
|
31
|
+
import { AvmFinalizedCallResult } from '../../../simulator/src/avm/avm_contract_call_result.js';
|
|
32
32
|
import { type AvmPersistableStateManager } from '../../../simulator/src/avm/journal/journal.js';
|
|
33
33
|
import { ProvingOrchestrator } from '../orchestrator/index.js';
|
|
34
34
|
import { MemoryProvingQueue } from '../prover-agent/memory-proving-queue.js';
|
|
@@ -37,7 +37,7 @@ import { getEnvironmentConfig, getSimulationProvider, makeGlobals } from './fixt
|
|
|
37
37
|
|
|
38
38
|
export class TestContext {
|
|
39
39
|
constructor(
|
|
40
|
-
public
|
|
40
|
+
public publicTxSimulator: PublicTxSimulator,
|
|
41
41
|
public worldStateDB: MockProxy<WorldStateDB>,
|
|
42
42
|
public publicProcessor: PublicProcessor,
|
|
43
43
|
public simulationProvider: SimulationProvider,
|
|
@@ -66,7 +66,6 @@ export class TestContext {
|
|
|
66
66
|
const directoriesToCleanup: string[] = [];
|
|
67
67
|
const globalVariables = makeGlobals(blockNumber);
|
|
68
68
|
|
|
69
|
-
const publicExecutor = mock<PublicExecutor>();
|
|
70
69
|
const worldStateDB = mock<WorldStateDB>();
|
|
71
70
|
const telemetry = new NoopTelemetryClient();
|
|
72
71
|
|
|
@@ -83,13 +82,15 @@ export class TestContext {
|
|
|
83
82
|
publicDb = await ws.getLatest();
|
|
84
83
|
proverDb = await ws.getLatest();
|
|
85
84
|
}
|
|
85
|
+
worldStateDB.getMerkleInterface.mockReturnValue(publicDb);
|
|
86
86
|
|
|
87
|
-
const
|
|
87
|
+
const publicTxSimulator = new PublicTxSimulator(publicDb, worldStateDB, telemetry, globalVariables);
|
|
88
|
+
const processor = new PublicProcessor(
|
|
88
89
|
publicDb,
|
|
89
|
-
publicExecutor,
|
|
90
90
|
globalVariables,
|
|
91
91
|
Header.empty(),
|
|
92
92
|
worldStateDB,
|
|
93
|
+
publicTxSimulator,
|
|
93
94
|
telemetry,
|
|
94
95
|
);
|
|
95
96
|
|
|
@@ -124,7 +125,7 @@ export class TestContext {
|
|
|
124
125
|
agent.start(queue);
|
|
125
126
|
|
|
126
127
|
return new this(
|
|
127
|
-
|
|
128
|
+
publicTxSimulator,
|
|
128
129
|
worldStateDB,
|
|
129
130
|
processor,
|
|
130
131
|
simulationProvider,
|
|
@@ -154,25 +155,24 @@ export class TestContext {
|
|
|
154
155
|
) {
|
|
155
156
|
const defaultExecutorImplementation = (
|
|
156
157
|
_stateManager: AvmPersistableStateManager,
|
|
157
|
-
|
|
158
|
-
_globalVariables: GlobalVariables,
|
|
158
|
+
executionRequest: PublicExecutionRequest,
|
|
159
159
|
allocatedGas: Gas,
|
|
160
|
-
_transactionFee
|
|
160
|
+
_transactionFee: Fr,
|
|
161
|
+
_fnName: string,
|
|
161
162
|
) => {
|
|
162
163
|
for (const tx of txs) {
|
|
163
164
|
const allCalls = tx.publicTeardownFunctionCall.isEmpty()
|
|
164
165
|
? tx.enqueuedPublicFunctionCalls
|
|
165
166
|
: [...tx.enqueuedPublicFunctionCalls, tx.publicTeardownFunctionCall];
|
|
166
167
|
for (const request of allCalls) {
|
|
167
|
-
if (
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
return Promise.resolve(result);
|
|
168
|
+
if (executionRequest.callContext.equals(request.callContext)) {
|
|
169
|
+
return Promise.resolve(
|
|
170
|
+
new AvmFinalizedCallResult(/*reverted=*/ false, /*output=*/ [], /*gasLeft=*/ allocatedGas),
|
|
171
|
+
);
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
|
-
throw new Error(`Unexpected execution request: ${
|
|
175
|
+
throw new Error(`Unexpected execution request: ${executionRequest}`);
|
|
176
176
|
};
|
|
177
177
|
return await this.processPublicFunctionsWithMockExecutorImplementation(
|
|
178
178
|
txs,
|
|
@@ -183,21 +183,36 @@ export class TestContext {
|
|
|
183
183
|
);
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
|
|
186
|
+
private async processPublicFunctionsWithMockExecutorImplementation(
|
|
187
187
|
txs: Tx[],
|
|
188
188
|
maxTransactions: number,
|
|
189
189
|
txHandler?: ProcessedTxHandler,
|
|
190
190
|
txValidator?: TxValidator<ProcessedTx>,
|
|
191
191
|
executorMock?: (
|
|
192
192
|
stateManager: AvmPersistableStateManager,
|
|
193
|
-
|
|
194
|
-
globalVariables: GlobalVariables,
|
|
193
|
+
executionRequest: PublicExecutionRequest,
|
|
195
194
|
allocatedGas: Gas,
|
|
196
|
-
transactionFee
|
|
197
|
-
|
|
195
|
+
transactionFee: Fr,
|
|
196
|
+
fnName: string,
|
|
197
|
+
) => Promise<AvmFinalizedCallResult>,
|
|
198
198
|
) {
|
|
199
|
+
// Mock the internal private function. Borrowed from https://stackoverflow.com/a/71033167
|
|
200
|
+
const simulateInternal: jest.SpiedFunction<
|
|
201
|
+
(
|
|
202
|
+
stateManager: AvmPersistableStateManager,
|
|
203
|
+
executionResult: any,
|
|
204
|
+
allocatedGas: Gas,
|
|
205
|
+
transactionFee: any,
|
|
206
|
+
fnName: any,
|
|
207
|
+
) => Promise<AvmFinalizedCallResult>
|
|
208
|
+
> = jest.spyOn(
|
|
209
|
+
this.publicTxSimulator as unknown as {
|
|
210
|
+
simulateEnqueuedCallInternal: PublicTxSimulator['simulateEnqueuedCallInternal'];
|
|
211
|
+
},
|
|
212
|
+
'simulateEnqueuedCallInternal',
|
|
213
|
+
);
|
|
199
214
|
if (executorMock) {
|
|
200
|
-
|
|
215
|
+
simulateInternal.mockImplementation(executorMock);
|
|
201
216
|
}
|
|
202
217
|
return await this.publicProcessor.process(txs, maxTransactions, txHandler, txValidator);
|
|
203
218
|
}
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
ARCHIVE_HEIGHT,
|
|
11
11
|
AppendOnlyTreeSnapshot,
|
|
12
12
|
type BaseOrMergeRollupPublicInputs,
|
|
13
|
-
BaseRollupHints,
|
|
14
13
|
BlockMergeRollupInputs,
|
|
15
14
|
type BlockRootOrBlockMergePublicInputs,
|
|
16
15
|
ConstantRollupData,
|
|
@@ -32,25 +31,25 @@ import {
|
|
|
32
31
|
NULLIFIER_TREE_HEIGHT,
|
|
33
32
|
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
34
33
|
NullifierLeafPreimage,
|
|
35
|
-
PUBLIC_DATA_SUBTREE_HEIGHT,
|
|
36
|
-
PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH,
|
|
37
34
|
PUBLIC_DATA_TREE_HEIGHT,
|
|
38
35
|
type ParityPublicInputs,
|
|
39
36
|
PartialStateReference,
|
|
40
37
|
PreviousRollupBlockData,
|
|
41
38
|
PreviousRollupData,
|
|
39
|
+
PrivateBaseRollupHints,
|
|
40
|
+
PrivateBaseStateDiffHints,
|
|
41
|
+
PublicBaseRollupHints,
|
|
42
|
+
PublicBaseStateDiffHints,
|
|
42
43
|
PublicDataHint,
|
|
43
44
|
PublicDataTreeLeaf,
|
|
44
|
-
|
|
45
|
-
PublicDataWrite,
|
|
45
|
+
PublicDataTreeLeafPreimage,
|
|
46
46
|
type RecursiveProof,
|
|
47
47
|
RootRollupInputs,
|
|
48
|
-
StateDiffHints,
|
|
49
48
|
StateReference,
|
|
50
49
|
VK_TREE_HEIGHT,
|
|
51
50
|
type VerificationKeyAsFields,
|
|
52
51
|
} from '@aztec/circuits.js';
|
|
53
|
-
import {
|
|
52
|
+
import { makeTuple } from '@aztec/foundation/array';
|
|
54
53
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
55
54
|
import { sha256Trunc } from '@aztec/foundation/crypto';
|
|
56
55
|
import { type DebugLogger } from '@aztec/foundation/log';
|
|
@@ -123,6 +122,7 @@ export async function buildBaseRollupHints(
|
|
|
123
122
|
padArrayEnd(tx.txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX).map(n => n.toBuffer()),
|
|
124
123
|
NULLIFIER_SUBTREE_HEIGHT,
|
|
125
124
|
);
|
|
125
|
+
|
|
126
126
|
if (nullifierWitnessLeaves === undefined) {
|
|
127
127
|
throw new Error(`Could not craft nullifier batch insertion proofs`);
|
|
128
128
|
}
|
|
@@ -139,45 +139,109 @@ export async function buildBaseRollupHints(
|
|
|
139
139
|
i < nullifierSubtreeSiblingPathArray.length ? nullifierSubtreeSiblingPathArray[i] : Fr.ZERO,
|
|
140
140
|
);
|
|
141
141
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
142
|
+
if (tx.avmProvingRequest) {
|
|
143
|
+
// Build public base rollup hints
|
|
144
|
+
const stateDiffHints = PublicBaseStateDiffHints.from({
|
|
145
|
+
nullifierPredecessorPreimages: makeTuple(MAX_NULLIFIERS_PER_TX, i =>
|
|
146
|
+
i < nullifierWitnessLeaves.length
|
|
147
|
+
? (nullifierWitnessLeaves[i].leafPreimage as NullifierLeafPreimage)
|
|
148
|
+
: NullifierLeafPreimage.empty(),
|
|
149
|
+
),
|
|
150
|
+
nullifierPredecessorMembershipWitnesses: makeTuple(MAX_NULLIFIERS_PER_TX, i =>
|
|
151
|
+
i < nullifierPredecessorMembershipWitnessesWithoutPadding.length
|
|
152
|
+
? nullifierPredecessorMembershipWitnessesWithoutPadding[i]
|
|
153
|
+
: makeEmptyMembershipWitness(NULLIFIER_TREE_HEIGHT),
|
|
154
|
+
),
|
|
155
|
+
sortedNullifiers: makeTuple(MAX_NULLIFIERS_PER_TX, i => Fr.fromBuffer(sortednullifiers[i])),
|
|
156
|
+
sortedNullifierIndexes: makeTuple(MAX_NULLIFIERS_PER_TX, i => sortedNewLeavesIndexes[i]),
|
|
157
|
+
noteHashSubtreeSiblingPath,
|
|
158
|
+
nullifierSubtreeSiblingPath,
|
|
159
|
+
lowPublicDataWritesPreimages: padArrayEnd(
|
|
160
|
+
txPublicDataUpdateRequestInfo.lowPublicDataWritesPreimages,
|
|
161
|
+
PublicDataTreeLeafPreimage.empty(),
|
|
162
|
+
MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
163
|
+
),
|
|
164
|
+
lowPublicDataWritesMembershipWitnesses: padArrayEnd(
|
|
165
|
+
txPublicDataUpdateRequestInfo.lowPublicDataWritesMembershipWitnesses,
|
|
166
|
+
MembershipWitness.empty(PUBLIC_DATA_TREE_HEIGHT),
|
|
167
|
+
MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
168
|
+
),
|
|
169
|
+
publicDataTreeSiblingPaths: padArrayEnd(
|
|
170
|
+
txPublicDataUpdateRequestInfo.publicDataWritesSiblingPaths,
|
|
171
|
+
makeTuple(PUBLIC_DATA_TREE_HEIGHT, () => Fr.ZERO),
|
|
172
|
+
MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
173
|
+
),
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const blockHash = tx.constants.historicalHeader.hash();
|
|
177
|
+
const archiveRootMembershipWitness = await getMembershipWitnessFor(
|
|
178
|
+
blockHash,
|
|
179
|
+
MerkleTreeId.ARCHIVE,
|
|
180
|
+
ARCHIVE_HEIGHT,
|
|
181
|
+
db,
|
|
182
|
+
);
|
|
161
183
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
184
|
+
return PublicBaseRollupHints.from({
|
|
185
|
+
start,
|
|
186
|
+
stateDiffHints,
|
|
187
|
+
feePayerFeeJuiceBalanceReadHint: feePayerFeeJuiceBalanceReadHint,
|
|
188
|
+
archiveRootMembershipWitness,
|
|
189
|
+
constants,
|
|
190
|
+
});
|
|
191
|
+
} else {
|
|
192
|
+
if (
|
|
193
|
+
txPublicDataUpdateRequestInfo.lowPublicDataWritesMembershipWitnesses.length > 1 ||
|
|
194
|
+
txPublicDataUpdateRequestInfo.lowPublicDataWritesPreimages.length > 1 ||
|
|
195
|
+
txPublicDataUpdateRequestInfo.publicDataWritesSiblingPaths.length > 1
|
|
196
|
+
) {
|
|
197
|
+
throw new Error(`More than one public data write in a private only tx`);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const feeWriteLowLeafPreimage =
|
|
201
|
+
txPublicDataUpdateRequestInfo.lowPublicDataWritesPreimages[0] || PublicDataTreeLeafPreimage.empty();
|
|
202
|
+
const feeWriteLowLeafMembershipWitness =
|
|
203
|
+
txPublicDataUpdateRequestInfo.lowPublicDataWritesMembershipWitnesses[0] ||
|
|
204
|
+
MembershipWitness.empty<typeof PUBLIC_DATA_TREE_HEIGHT>(PUBLIC_DATA_TREE_HEIGHT);
|
|
205
|
+
const feeWriteSiblingPath =
|
|
206
|
+
txPublicDataUpdateRequestInfo.publicDataWritesSiblingPaths[0] ||
|
|
207
|
+
makeTuple(PUBLIC_DATA_TREE_HEIGHT, () => Fr.ZERO);
|
|
208
|
+
|
|
209
|
+
const stateDiffHints = PrivateBaseStateDiffHints.from({
|
|
210
|
+
nullifierPredecessorPreimages: makeTuple(MAX_NULLIFIERS_PER_TX, i =>
|
|
211
|
+
i < nullifierWitnessLeaves.length
|
|
212
|
+
? (nullifierWitnessLeaves[i].leafPreimage as NullifierLeafPreimage)
|
|
213
|
+
: NullifierLeafPreimage.empty(),
|
|
214
|
+
),
|
|
215
|
+
nullifierPredecessorMembershipWitnesses: makeTuple(MAX_NULLIFIERS_PER_TX, i =>
|
|
216
|
+
i < nullifierPredecessorMembershipWitnessesWithoutPadding.length
|
|
217
|
+
? nullifierPredecessorMembershipWitnessesWithoutPadding[i]
|
|
218
|
+
: makeEmptyMembershipWitness(NULLIFIER_TREE_HEIGHT),
|
|
219
|
+
),
|
|
220
|
+
sortedNullifiers: makeTuple(MAX_NULLIFIERS_PER_TX, i => Fr.fromBuffer(sortednullifiers[i])),
|
|
221
|
+
sortedNullifierIndexes: makeTuple(MAX_NULLIFIERS_PER_TX, i => sortedNewLeavesIndexes[i]),
|
|
222
|
+
noteHashSubtreeSiblingPath,
|
|
223
|
+
nullifierSubtreeSiblingPath,
|
|
224
|
+
feeWriteLowLeafPreimage,
|
|
225
|
+
feeWriteLowLeafMembershipWitness,
|
|
226
|
+
feeWriteSiblingPath,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
const blockHash = tx.constants.historicalHeader.hash();
|
|
230
|
+
const archiveRootMembershipWitness = await getMembershipWitnessFor(
|
|
231
|
+
blockHash,
|
|
232
|
+
MerkleTreeId.ARCHIVE,
|
|
233
|
+
ARCHIVE_HEIGHT,
|
|
234
|
+
db,
|
|
235
|
+
);
|
|
169
236
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
archiveRootMembershipWitness,
|
|
179
|
-
constants,
|
|
180
|
-
});
|
|
237
|
+
return PrivateBaseRollupHints.from({
|
|
238
|
+
start,
|
|
239
|
+
stateDiffHints,
|
|
240
|
+
feePayerFeeJuiceBalanceReadHint: feePayerFeeJuiceBalanceReadHint,
|
|
241
|
+
archiveRootMembershipWitness,
|
|
242
|
+
constants,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
181
245
|
}
|
|
182
246
|
|
|
183
247
|
async function getPublicDataHint(db: MerkleTreeWriteOperations, leafSlot: bigint) {
|
|
@@ -416,67 +480,50 @@ export function makeEmptyMembershipWitness<N extends number>(height: N) {
|
|
|
416
480
|
}
|
|
417
481
|
|
|
418
482
|
async function processPublicDataUpdateRequests(tx: ProcessedTx, db: MerkleTreeWriteOperations) {
|
|
419
|
-
const
|
|
420
|
-
tx.txEffect.publicDataWrites,
|
|
421
|
-
PublicDataWrite.empty(),
|
|
422
|
-
MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
423
|
-
);
|
|
424
|
-
|
|
425
|
-
const allPublicDataWrites = allPublicDataUpdateRequests.map(
|
|
483
|
+
const allPublicDataWrites = tx.txEffect.publicDataWrites.map(
|
|
426
484
|
({ leafSlot, value }) => new PublicDataTreeLeaf(leafSlot, value),
|
|
427
485
|
);
|
|
428
|
-
const { lowLeavesWitnessData, newSubtreeSiblingPath, sortedNewLeaves, sortedNewLeavesIndexes } = await db.batchInsert(
|
|
429
|
-
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
430
|
-
allPublicDataWrites.map(x => x.toBuffer()),
|
|
431
|
-
// TODO(#3675) remove oldValue from update requests
|
|
432
|
-
PUBLIC_DATA_SUBTREE_HEIGHT,
|
|
433
|
-
);
|
|
434
|
-
|
|
435
|
-
if (lowLeavesWitnessData === undefined) {
|
|
436
|
-
throw new Error(`Could not craft public data batch insertion proofs`);
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
const sortedPublicDataWrites = makeTuple(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, i => {
|
|
440
|
-
return PublicDataTreeLeaf.fromBuffer(sortedNewLeaves[i]);
|
|
441
|
-
});
|
|
442
|
-
|
|
443
|
-
const sortedPublicDataWritesIndexes = makeTuple(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, i => {
|
|
444
|
-
return sortedNewLeavesIndexes[i];
|
|
445
|
-
});
|
|
446
486
|
|
|
447
|
-
const
|
|
448
|
-
const
|
|
449
|
-
|
|
450
|
-
|
|
487
|
+
const lowPublicDataWritesPreimages = [];
|
|
488
|
+
const lowPublicDataWritesMembershipWitnesses = [];
|
|
489
|
+
const publicDataWritesSiblingPaths = [];
|
|
490
|
+
|
|
491
|
+
for (const write of allPublicDataWrites) {
|
|
492
|
+
if (write.isEmpty()) {
|
|
493
|
+
throw new Error(`Empty public data write in tx: ${toFriendlyJSON(tx)}`);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// TODO(Alvaro) write a specialized function for this? Internally add_or_update_value uses batch insertion anyway
|
|
497
|
+
const { lowLeavesWitnessData, newSubtreeSiblingPath } = await db.batchInsert(
|
|
498
|
+
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
499
|
+
[write.toBuffer()],
|
|
500
|
+
// TODO(#3675) remove oldValue from update requests
|
|
501
|
+
0,
|
|
502
|
+
);
|
|
451
503
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
const
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
504
|
+
if (lowLeavesWitnessData === undefined) {
|
|
505
|
+
throw new Error(`Could not craft public data batch insertion proofs`);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
const [lowLeafWitness] = lowLeavesWitnessData;
|
|
509
|
+
lowPublicDataWritesPreimages.push(lowLeafWitness.leafPreimage as PublicDataTreeLeafPreimage);
|
|
510
|
+
lowPublicDataWritesMembershipWitnesses.push(
|
|
511
|
+
MembershipWitness.fromBufferArray<typeof PUBLIC_DATA_TREE_HEIGHT>(
|
|
512
|
+
lowLeafWitness.index,
|
|
513
|
+
assertLength(lowLeafWitness.siblingPath.toBufferArray(), PUBLIC_DATA_TREE_HEIGHT),
|
|
514
|
+
),
|
|
460
515
|
);
|
|
461
|
-
});
|
|
462
516
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
typeof MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX
|
|
466
|
-
> = makeTuple(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, i => {
|
|
467
|
-
return lowLeavesWitnessData[i].leafPreimage as PublicDataTreeLeafPreimage;
|
|
468
|
-
});
|
|
517
|
+
const insertionSiblingPath = newSubtreeSiblingPath.toFields();
|
|
518
|
+
assertLength(insertionSiblingPath, PUBLIC_DATA_TREE_HEIGHT);
|
|
469
519
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
assertPermutation(allPublicDataWrites, sortedPublicDataWrites, sortedPublicDataWritesIndexes, (a, b) => a.equals(b));
|
|
520
|
+
publicDataWritesSiblingPaths.push(insertionSiblingPath as Tuple<Fr, typeof PUBLIC_DATA_TREE_HEIGHT>);
|
|
521
|
+
}
|
|
473
522
|
|
|
474
523
|
return {
|
|
475
524
|
lowPublicDataWritesPreimages,
|
|
476
525
|
lowPublicDataWritesMembershipWitnesses,
|
|
477
|
-
|
|
478
|
-
sortedPublicDataWrites,
|
|
479
|
-
sortedPublicDataWritesIndexes,
|
|
526
|
+
publicDataWritesSiblingPaths,
|
|
480
527
|
};
|
|
481
528
|
}
|
|
482
529
|
|
|
@@ -13,8 +13,10 @@ import {
|
|
|
13
13
|
AvmProofData,
|
|
14
14
|
type BaseRollupHints,
|
|
15
15
|
Fr,
|
|
16
|
+
PrivateBaseRollupHints,
|
|
16
17
|
PrivateBaseRollupInputs,
|
|
17
18
|
PrivateTubeData,
|
|
19
|
+
PublicBaseRollupHints,
|
|
18
20
|
PublicBaseRollupInputs,
|
|
19
21
|
PublicTubeData,
|
|
20
22
|
type TUBE_PROOF_LENGTH,
|
|
@@ -66,6 +68,9 @@ export class TxProvingState {
|
|
|
66
68
|
const vkData = this.getTubeVkData();
|
|
67
69
|
const tubeData = new PrivateTubeData(this.processedTx.data.toKernelCircuitPublicInputs(), this.tube.proof, vkData);
|
|
68
70
|
|
|
71
|
+
if (!(this.baseRollupHints instanceof PrivateBaseRollupHints)) {
|
|
72
|
+
throw new Error('Mismatched base rollup hints, expected private base rollup hints');
|
|
73
|
+
}
|
|
69
74
|
return new PrivateBaseRollupInputs(tubeData, this.baseRollupHints);
|
|
70
75
|
}
|
|
71
76
|
|
|
@@ -92,6 +97,10 @@ export class TxProvingState {
|
|
|
92
97
|
this.getAvmVkData(),
|
|
93
98
|
);
|
|
94
99
|
|
|
100
|
+
if (!(this.baseRollupHints instanceof PublicBaseRollupHints)) {
|
|
101
|
+
throw new Error('Mismatched base rollup hints, expected public base rollup hints');
|
|
102
|
+
}
|
|
103
|
+
|
|
95
104
|
return new PublicBaseRollupInputs(tubeData, avmProofData, this.baseRollupHints);
|
|
96
105
|
}
|
|
97
106
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ProvingError,
|
|
3
|
+
type ProvingRequestType,
|
|
4
|
+
type ServerCircuitProver,
|
|
5
|
+
type V2ProvingJob,
|
|
6
|
+
} from '@aztec/circuit-types';
|
|
7
|
+
import { createDebugLogger } from '@aztec/foundation/log';
|
|
8
|
+
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
9
|
+
|
|
10
|
+
import { type ProvingJobConsumer } from './proving_broker_interface.js';
|
|
11
|
+
import { ProvingJobController, ProvingJobStatus } from './proving_job_controller.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A helper class that encapsulates a circuit prover and connects it to a job source.
|
|
15
|
+
*/
|
|
16
|
+
export class ProvingAgent {
|
|
17
|
+
private currentJobController?: ProvingJobController;
|
|
18
|
+
private runningPromise: RunningPromise;
|
|
19
|
+
|
|
20
|
+
constructor(
|
|
21
|
+
/** The source of proving jobs */
|
|
22
|
+
private jobSource: ProvingJobConsumer,
|
|
23
|
+
/** The prover implementation to defer jobs to */
|
|
24
|
+
private circuitProver: ServerCircuitProver,
|
|
25
|
+
/** Optional list of allowed proof types to build */
|
|
26
|
+
private proofAllowList?: Array<ProvingRequestType>,
|
|
27
|
+
/** How long to wait between jobs */
|
|
28
|
+
private pollIntervalMs = 1000,
|
|
29
|
+
private log = createDebugLogger('aztec:proving-broker:proving-agent'),
|
|
30
|
+
) {
|
|
31
|
+
this.runningPromise = new RunningPromise(this.safeWork, this.pollIntervalMs);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public setCircuitProver(circuitProver: ServerCircuitProver): void {
|
|
35
|
+
this.circuitProver = circuitProver;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public isRunning(): boolean {
|
|
39
|
+
return this.runningPromise?.isRunning() ?? false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public start(): void {
|
|
43
|
+
this.runningPromise.start();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public async stop(): Promise<void> {
|
|
47
|
+
this.currentJobController?.abort();
|
|
48
|
+
await this.runningPromise.stop();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private safeWork = async () => {
|
|
52
|
+
try {
|
|
53
|
+
// every tick we need to
|
|
54
|
+
// (1) either do a heartbeat, telling the broker that we're working
|
|
55
|
+
// (2) get a new job
|
|
56
|
+
// If during (1) the broker returns a new job that means we can cancel the current job and start the new one
|
|
57
|
+
let maybeJob: { job: V2ProvingJob; time: number } | undefined;
|
|
58
|
+
if (this.currentJobController?.getStatus() === ProvingJobStatus.PROVING) {
|
|
59
|
+
maybeJob = await this.jobSource.reportProvingJobProgress(
|
|
60
|
+
this.currentJobController.getJobId(),
|
|
61
|
+
this.currentJobController.getStartedAt(),
|
|
62
|
+
{ allowList: this.proofAllowList },
|
|
63
|
+
);
|
|
64
|
+
} else {
|
|
65
|
+
maybeJob = await this.jobSource.getProvingJob({ allowList: this.proofAllowList });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!maybeJob) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (this.currentJobController?.getStatus() === ProvingJobStatus.PROVING) {
|
|
73
|
+
this.currentJobController?.abort();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const { job, time } = maybeJob;
|
|
77
|
+
this.currentJobController = new ProvingJobController(job, time, this.circuitProver, (err, result) => {
|
|
78
|
+
if (err) {
|
|
79
|
+
const retry = err.name === ProvingError.NAME ? (err as ProvingError).retry : false;
|
|
80
|
+
return this.jobSource.reportProvingJobError(job.id, err, retry);
|
|
81
|
+
} else if (result) {
|
|
82
|
+
return this.jobSource.reportProvingJobSuccess(job.id, result);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
this.currentJobController.start();
|
|
86
|
+
} catch (err) {
|
|
87
|
+
this.log.error(`Error in ProvingAgent: ${String(err)}`);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|