@aztec/prover-client 0.0.1-commit.a89ec08 → 0.0.1-commit.aa0c64f
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/config.d.ts +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +16 -2
- package/dest/light/lightweight_checkpoint_builder.d.ts +5 -2
- package/dest/light/lightweight_checkpoint_builder.d.ts.map +1 -1
- package/dest/light/lightweight_checkpoint_builder.js +36 -12
- package/dest/mocks/test_context.d.ts +11 -11
- package/dest/mocks/test_context.d.ts.map +1 -1
- package/dest/mocks/test_context.js +27 -29
- package/dest/orchestrator/block-building-helpers.d.ts +1 -1
- package/dest/orchestrator/checkpoint-proving-state.d.ts +20 -36
- package/dest/orchestrator/checkpoint-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/checkpoint-proving-state.js +22 -120
- package/dest/orchestrator/checkpoint-sub-tree-orchestrator.d.ts +161 -0
- package/dest/orchestrator/checkpoint-sub-tree-orchestrator.d.ts.map +1 -0
- package/dest/orchestrator/{orchestrator.js → checkpoint-sub-tree-orchestrator.js} +267 -451
- package/dest/orchestrator/chonk-cache.d.ts +39 -0
- package/dest/orchestrator/chonk-cache.d.ts.map +1 -0
- package/dest/orchestrator/chonk-cache.js +80 -0
- package/dest/orchestrator/index.d.ts +4 -2
- package/dest/orchestrator/index.d.ts.map +1 -1
- package/dest/orchestrator/index.js +3 -1
- package/dest/orchestrator/proving-scheduler.d.ts +81 -0
- package/dest/orchestrator/proving-scheduler.d.ts.map +1 -0
- package/dest/orchestrator/proving-scheduler.js +120 -0
- package/dest/orchestrator/top-tree-orchestrator.d.ts +88 -0
- package/dest/orchestrator/top-tree-orchestrator.d.ts.map +1 -0
- package/dest/orchestrator/top-tree-orchestrator.js +232 -0
- package/dest/orchestrator/top-tree-proving-state.d.ts +61 -0
- package/dest/orchestrator/top-tree-proving-state.d.ts.map +1 -0
- package/dest/orchestrator/top-tree-proving-state.js +185 -0
- package/dest/orchestrator/tx-proving-state.d.ts +3 -3
- package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
- package/dest/prover-client/prover-client.d.ts +61 -4
- package/dest/prover-client/prover-client.d.ts.map +1 -1
- package/dest/prover-client/prover-client.js +54 -7
- package/dest/proving_broker/broker_prover_facade.d.ts +3 -3
- package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -1
- package/dest/proving_broker/broker_prover_facade.js +15 -16
- package/dest/proving_broker/config.d.ts +9 -73
- package/dest/proving_broker/config.d.ts.map +1 -1
- package/dest/proving_broker/config.js +3 -3
- package/dest/proving_broker/index.d.ts +2 -1
- package/dest/proving_broker/index.d.ts.map +1 -1
- package/dest/proving_broker/index.js +1 -0
- package/dest/proving_broker/proving_broker.d.ts +2 -2
- package/dest/proving_broker/proving_broker.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker.js +92 -24
- package/dest/proving_broker/proving_broker_database/memory.d.ts +3 -1
- package/dest/proving_broker/proving_broker_database/memory.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker_database/memory.js +10 -0
- package/dest/proving_broker/proving_broker_database/persisted.d.ts +13 -2
- package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker_database/persisted.js +32 -5
- package/dest/proving_broker/proving_broker_database.d.ts +15 -1
- package/dest/proving_broker/proving_broker_database.d.ts.map +1 -1
- package/dest/proving_broker/rpc.d.ts +1 -1
- package/dest/proving_broker/rpc.d.ts.map +1 -1
- package/dest/proving_broker/rpc.js +64 -9
- package/dest/test/epoch_settlement.d.ts +36 -0
- package/dest/test/epoch_settlement.d.ts.map +1 -0
- package/dest/test/epoch_settlement.js +52 -0
- package/dest/test/index.d.ts +2 -0
- package/dest/test/index.d.ts.map +1 -0
- package/dest/test/index.js +1 -0
- package/dest/test/mock_prover.d.ts +4 -4
- package/dest/test/mock_prover.js +2 -2
- package/package.json +20 -19
- package/src/config.ts +18 -2
- package/src/light/lightweight_checkpoint_builder.ts +37 -20
- package/src/mocks/test_context.ts +26 -42
- package/src/orchestrator/checkpoint-proving-state.ts +21 -162
- package/src/orchestrator/{orchestrator.ts → checkpoint-sub-tree-orchestrator.ts} +415 -661
- package/src/orchestrator/chonk-cache.ts +99 -0
- package/src/orchestrator/index.ts +8 -1
- package/src/orchestrator/proving-scheduler.ts +160 -0
- package/src/orchestrator/top-tree-orchestrator.ts +384 -0
- package/src/orchestrator/top-tree-proving-state.ts +219 -0
- package/src/orchestrator/tx-proving-state.ts +3 -3
- package/src/prover-client/prover-client.ts +128 -18
- package/src/proving_broker/broker_prover_facade.ts +12 -18
- package/src/proving_broker/config.ts +3 -2
- package/src/proving_broker/index.ts +1 -0
- package/src/proving_broker/proving_broker.ts +84 -22
- package/src/proving_broker/proving_broker_database/memory.ts +10 -0
- package/src/proving_broker/proving_broker_database/persisted.ts +42 -7
- package/src/proving_broker/proving_broker_database.ts +16 -0
- package/src/proving_broker/rpc.ts +24 -21
- package/src/test/epoch_settlement.ts +82 -0
- package/src/test/index.ts +1 -0
- package/src/test/mock_prover.ts +2 -2
- package/dest/orchestrator/epoch-proving-state.d.ts +0 -75
- package/dest/orchestrator/epoch-proving-state.d.ts.map +0 -1
- package/dest/orchestrator/epoch-proving-state.js +0 -269
- package/dest/orchestrator/orchestrator.d.ts +0 -130
- package/dest/orchestrator/orchestrator.d.ts.map +0 -1
- package/dest/prover-client/server-epoch-prover.d.ts +0 -32
- package/dest/prover-client/server-epoch-prover.d.ts.map +0 -1
- package/dest/prover-client/server-epoch-prover.js +0 -40
- package/src/orchestrator/epoch-proving-state.ts +0 -380
- package/src/prover-client/server-epoch-prover.ts +0 -69
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { SpongeBlob, computeBlobsHashFromBlobs, encodeCheckpointEndMarker, getBlobsPerL1Block } from '@aztec/blob-lib';
|
|
2
|
-
import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
|
|
3
2
|
import { type CheckpointNumber, IndexWithinCheckpoint } from '@aztec/foundation/branded-types';
|
|
4
|
-
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
5
3
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
6
4
|
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
5
|
+
import { elapsed } from '@aztec/foundation/timer';
|
|
7
6
|
import { L2Block } from '@aztec/stdlib/block';
|
|
8
7
|
import { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
9
8
|
import type { MerkleTreeWriteOperations } from '@aztec/stdlib/interfaces/server';
|
|
10
9
|
import {
|
|
11
10
|
accumulateCheckpointOutHashes,
|
|
11
|
+
appendL1ToL2MessagesToTree,
|
|
12
12
|
computeCheckpointOutHash,
|
|
13
13
|
computeInHashFromL1ToL2Messages,
|
|
14
14
|
} from '@aztec/stdlib/messaging';
|
|
@@ -68,10 +68,7 @@ export class LightweightCheckpointBuilder {
|
|
|
68
68
|
feeAssetPriceModifier: bigint = 0n,
|
|
69
69
|
): Promise<LightweightCheckpointBuilder> {
|
|
70
70
|
// Insert l1-to-l2 messages into the tree.
|
|
71
|
-
await db
|
|
72
|
-
MerkleTreeId.L1_TO_L2_MESSAGE_TREE,
|
|
73
|
-
padArrayEnd<Fr, number>(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP),
|
|
74
|
-
);
|
|
71
|
+
await appendL1ToL2MessagesToTree(db, l1ToL2Messages);
|
|
75
72
|
|
|
76
73
|
return new LightweightCheckpointBuilder(
|
|
77
74
|
checkpointNumber,
|
|
@@ -116,6 +113,10 @@ export class LightweightCheckpointBuilder {
|
|
|
116
113
|
blockNumbers: existingBlocks.map(b => b.header.getBlockNumber()),
|
|
117
114
|
});
|
|
118
115
|
|
|
116
|
+
if (existingBlocks.length === 0) {
|
|
117
|
+
throw new Error(`Cannot resume checkpoint ${checkpointNumber} with no existing blocks`);
|
|
118
|
+
}
|
|
119
|
+
|
|
119
120
|
// Validate block order and consistency
|
|
120
121
|
for (let i = 1; i < existingBlocks.length; i++) {
|
|
121
122
|
const prev = existingBlocks[i - 1];
|
|
@@ -165,7 +166,8 @@ export class LightweightCheckpointBuilder {
|
|
|
165
166
|
globalVariables: GlobalVariables,
|
|
166
167
|
txs: ProcessedTx[],
|
|
167
168
|
opts: { insertTxsEffects?: boolean; expectedEndState?: StateReference } = {},
|
|
168
|
-
): Promise<L2Block> {
|
|
169
|
+
): Promise<{ block: L2Block; timings: Record<string, number> }> {
|
|
170
|
+
const timings: Record<string, number> = {};
|
|
169
171
|
const isFirstBlock = this.blocks.length === 0;
|
|
170
172
|
|
|
171
173
|
// Empty blocks are only allowed as the first block in a checkpoint
|
|
@@ -174,7 +176,9 @@ export class LightweightCheckpointBuilder {
|
|
|
174
176
|
}
|
|
175
177
|
|
|
176
178
|
if (isFirstBlock) {
|
|
177
|
-
|
|
179
|
+
const [msGetInitialArchive, initialArchive] = await elapsed(() => getTreeSnapshot(MerkleTreeId.ARCHIVE, this.db));
|
|
180
|
+
this.lastArchives.push(initialArchive);
|
|
181
|
+
timings.getInitialArchive = msGetInitialArchive;
|
|
178
182
|
}
|
|
179
183
|
|
|
180
184
|
const lastArchive = this.lastArchives.at(-1)!;
|
|
@@ -184,12 +188,17 @@ export class LightweightCheckpointBuilder {
|
|
|
184
188
|
`Inserting side effects for ${txs.length} txs for block ${globalVariables.blockNumber} into db`,
|
|
185
189
|
{ txs: txs.map(tx => tx.hash.toString()) },
|
|
186
190
|
);
|
|
191
|
+
let msInsertSideEffects = 0;
|
|
187
192
|
for (const tx of txs) {
|
|
188
|
-
await insertSideEffects(tx, this.db);
|
|
193
|
+
const [ms] = await elapsed(() => insertSideEffects(tx, this.db));
|
|
194
|
+
msInsertSideEffects += ms;
|
|
189
195
|
}
|
|
196
|
+
timings.insertSideEffects = msInsertSideEffects;
|
|
190
197
|
}
|
|
191
198
|
|
|
192
|
-
const endState = await this.db.getStateReference();
|
|
199
|
+
const [msGetEndState, endState] = await elapsed(() => this.db.getStateReference());
|
|
200
|
+
timings.getEndState = msGetEndState;
|
|
201
|
+
|
|
193
202
|
if (opts.expectedEndState && !endState.equals(opts.expectedEndState)) {
|
|
194
203
|
this.logger.error('End state after processing txs does not match expected end state', {
|
|
195
204
|
globalVariables: globalVariables.toInspect(),
|
|
@@ -199,19 +208,16 @@ export class LightweightCheckpointBuilder {
|
|
|
199
208
|
throw new Error(`End state does not match expected end state when building block ${globalVariables.blockNumber}`);
|
|
200
209
|
}
|
|
201
210
|
|
|
202
|
-
const { header, body, blockBlobFields } = await
|
|
203
|
-
txs,
|
|
204
|
-
lastArchive,
|
|
205
|
-
endState,
|
|
206
|
-
globalVariables,
|
|
207
|
-
this.spongeBlob,
|
|
208
|
-
isFirstBlock,
|
|
211
|
+
const [msBuildHeaderAndBody, { header, body, blockBlobFields }] = await elapsed(() =>
|
|
212
|
+
buildHeaderAndBodyFromTxs(txs, lastArchive, endState, globalVariables, this.spongeBlob, isFirstBlock),
|
|
209
213
|
);
|
|
214
|
+
timings.buildHeaderAndBody = msBuildHeaderAndBody;
|
|
210
215
|
|
|
211
216
|
header.state.validate();
|
|
212
217
|
|
|
213
218
|
await this.db.updateArchive(header);
|
|
214
|
-
const newArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, this.db);
|
|
219
|
+
const [msUpdateArchive, newArchive] = await elapsed(() => getTreeSnapshot(MerkleTreeId.ARCHIVE, this.db));
|
|
220
|
+
timings.updateArchive = msUpdateArchive;
|
|
215
221
|
this.lastArchives.push(newArchive);
|
|
216
222
|
|
|
217
223
|
const expectedNextLeafIndex = Number(globalVariables.blockNumber) + 1;
|
|
@@ -225,7 +231,8 @@ export class LightweightCheckpointBuilder {
|
|
|
225
231
|
const block = new L2Block(newArchive, header, body, this.checkpointNumber, indexWithinCheckpoint);
|
|
226
232
|
this.blocks.push(block);
|
|
227
233
|
|
|
228
|
-
await this.spongeBlob.absorb(blockBlobFields);
|
|
234
|
+
const [msSpongeAbsorb] = await elapsed(() => this.spongeBlob.absorb(blockBlobFields));
|
|
235
|
+
timings.spongeAbsorb = msSpongeAbsorb;
|
|
229
236
|
this.blobFields.push(...blockBlobFields);
|
|
230
237
|
|
|
231
238
|
this.logger.debug(`Built block ${header.getBlockNumber()}`, {
|
|
@@ -236,7 +243,7 @@ export class LightweightCheckpointBuilder {
|
|
|
236
243
|
txs: block.body.txEffects.map(tx => tx.txHash.toString()),
|
|
237
244
|
});
|
|
238
245
|
|
|
239
|
-
return block;
|
|
246
|
+
return { block, timings };
|
|
240
247
|
}
|
|
241
248
|
|
|
242
249
|
async completeCheckpoint(): Promise<Checkpoint> {
|
|
@@ -268,6 +275,7 @@ export class LightweightCheckpointBuilder {
|
|
|
268
275
|
const timestamp = blocks[blocks.length - 1].timestamp;
|
|
269
276
|
|
|
270
277
|
const totalManaUsed = blocks.reduce((acc, block) => acc.add(block.header.totalManaUsed), Fr.ZERO);
|
|
278
|
+
const accumulatedFees = blocks.reduce((acc, block) => acc.add(block.header.totalFees), Fr.ZERO);
|
|
271
279
|
|
|
272
280
|
const header = CheckpointHeader.from({
|
|
273
281
|
lastArchiveRoot: this.lastArchives[0].root,
|
|
@@ -281,6 +289,15 @@ export class LightweightCheckpointBuilder {
|
|
|
281
289
|
feeRecipient,
|
|
282
290
|
gasFees,
|
|
283
291
|
totalManaUsed,
|
|
292
|
+
accumulatedFees,
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
this.logger.debug(`Completed checkpoint ${this.checkpointNumber}`, {
|
|
296
|
+
checkpointNumber: this.checkpointNumber,
|
|
297
|
+
headerHash: header.hash().toString(),
|
|
298
|
+
checkpointOutHash: checkpointOutHash.toString(),
|
|
299
|
+
numPreviousCheckpointOutHashes: this.previousCheckpointOutHashes.length,
|
|
300
|
+
...header.toInspect(),
|
|
284
301
|
});
|
|
285
302
|
|
|
286
303
|
return new Checkpoint(newArchive, header, blocks, this.checkpointNumber, this.feeAssetPriceModifier);
|
|
@@ -5,13 +5,13 @@ import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
|
5
5
|
import { padArrayEnd, times, timesAsync } from '@aztec/foundation/collection';
|
|
6
6
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
7
7
|
import type { Logger } from '@aztec/foundation/log';
|
|
8
|
+
import { SerialQueue } from '@aztec/foundation/queue';
|
|
8
9
|
import type { FieldsOf } from '@aztec/foundation/types';
|
|
9
10
|
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
10
11
|
import { ProtocolContractsList } from '@aztec/protocol-contracts';
|
|
11
12
|
import { computeFeePayerBalanceLeafSlot } from '@aztec/protocol-contracts/fee-juice';
|
|
12
13
|
import { PublicDataWrite } from '@aztec/stdlib/avm';
|
|
13
14
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
14
|
-
import { EthAddress } from '@aztec/stdlib/block';
|
|
15
15
|
import type { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
16
16
|
import type { MerkleTreeWriteOperations, ServerCircuitProver } from '@aztec/stdlib/interfaces/server';
|
|
17
17
|
import type { CheckpointConstantData } from '@aztec/stdlib/rollup';
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
StateReference,
|
|
25
25
|
TreeSnapshots,
|
|
26
26
|
} from '@aztec/stdlib/tx';
|
|
27
|
+
import type { GenesisData } from '@aztec/stdlib/world-state';
|
|
27
28
|
import type { MerkleTreeAdminDatabase } from '@aztec/world-state';
|
|
28
29
|
import { NativeWorldStateService } from '@aztec/world-state/native';
|
|
29
30
|
|
|
@@ -35,12 +36,21 @@ import {
|
|
|
35
36
|
getTreeSnapshot,
|
|
36
37
|
insertSideEffects,
|
|
37
38
|
} from '../orchestrator/block-building-helpers.js';
|
|
38
|
-
import type { BlockProvingState } from '../orchestrator/block-proving-state.js';
|
|
39
|
-
import { ProvingOrchestrator } from '../orchestrator/index.js';
|
|
40
39
|
import { BrokerCircuitProverFacade } from '../proving_broker/broker_prover_facade.js';
|
|
41
40
|
import { TestBroker } from '../test/mock_prover.js';
|
|
42
41
|
import { getEnvironmentConfig, getSimulator, makeCheckpointConstants, makeGlobals } from './fixtures.js';
|
|
43
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Builds a started `SerialQueue` for use as an orchestrator's deferred-job queue in
|
|
45
|
+
* tests. Production wires a single shared queue via `ProverClient`; tests that construct
|
|
46
|
+
* orchestrators directly use one of these per orchestrator (or share one).
|
|
47
|
+
*/
|
|
48
|
+
export function makeTestDeferredJobQueue(concurrency = 10): SerialQueue {
|
|
49
|
+
const queue = new SerialQueue();
|
|
50
|
+
queue.start(concurrency);
|
|
51
|
+
return queue;
|
|
52
|
+
}
|
|
53
|
+
|
|
44
54
|
export class TestContext {
|
|
45
55
|
private headers: Map<number, BlockHeader> = new Map();
|
|
46
56
|
private checkpoints: Checkpoint[] = [];
|
|
@@ -56,7 +66,6 @@ export class TestContext {
|
|
|
56
66
|
public prover: ServerCircuitProver,
|
|
57
67
|
public broker: TestBroker,
|
|
58
68
|
public brokerProverFacade: BrokerCircuitProverFacade,
|
|
59
|
-
public orchestrator: TestProvingOrchestrator,
|
|
60
69
|
private feePayer: AztecAddress,
|
|
61
70
|
initialFeePayerBalance: Fr,
|
|
62
71
|
private directoriesToCleanup: string[],
|
|
@@ -65,10 +74,6 @@ export class TestContext {
|
|
|
65
74
|
this.feePayerBalance = initialFeePayerBalance;
|
|
66
75
|
}
|
|
67
76
|
|
|
68
|
-
public get epochProver() {
|
|
69
|
-
return this.orchestrator;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
77
|
static async new(
|
|
73
78
|
logger: Logger,
|
|
74
79
|
{
|
|
@@ -81,17 +86,16 @@ export class TestContext {
|
|
|
81
86
|
) {
|
|
82
87
|
const directoriesToCleanup: string[] = [];
|
|
83
88
|
|
|
84
|
-
const feePayer = AztecAddress.
|
|
89
|
+
const feePayer = AztecAddress.fromNumberUnsafe(42222);
|
|
85
90
|
const initialFeePayerBalance = new Fr(10n ** 20n);
|
|
86
91
|
const feePayerSlot = await computeFeePayerBalanceLeafSlot(feePayer);
|
|
87
|
-
const
|
|
92
|
+
const genesis: GenesisData = {
|
|
93
|
+
prefilledPublicData: [new PublicDataTreeLeaf(feePayerSlot, initialFeePayerBalance)],
|
|
94
|
+
genesisTimestamp: 0n,
|
|
95
|
+
};
|
|
88
96
|
|
|
89
97
|
// Separated dbs for public processor and prover - see public_processor for context
|
|
90
|
-
const ws = await NativeWorldStateService.tmp(
|
|
91
|
-
/*rollupAddress=*/ undefined,
|
|
92
|
-
/*cleanupTmpDir=*/ true,
|
|
93
|
-
prefilledPublicData,
|
|
94
|
-
);
|
|
98
|
+
const ws = await NativeWorldStateService.tmp(/*cleanupTmpDir=*/ true, genesis);
|
|
95
99
|
|
|
96
100
|
let localProver: ServerCircuitProver;
|
|
97
101
|
const config = await getEnvironmentConfig(logger);
|
|
@@ -104,8 +108,10 @@ export class TestContext {
|
|
|
104
108
|
bbBinaryPath: config.expectedBBPath,
|
|
105
109
|
bbWorkingDirectory: config.bbWorkingDirectory,
|
|
106
110
|
bbSkipCleanup: config.bbSkipCleanup,
|
|
107
|
-
numConcurrentIVCVerifiers:
|
|
111
|
+
numConcurrentIVCVerifiers: 8,
|
|
108
112
|
bbIVCConcurrency: 1,
|
|
113
|
+
bbChonkVerifyMaxBatch: 16,
|
|
114
|
+
bbChonkVerifyConcurrency: 6,
|
|
109
115
|
};
|
|
110
116
|
localProver = await createProver(bbConfig);
|
|
111
117
|
}
|
|
@@ -116,22 +122,11 @@ export class TestContext {
|
|
|
116
122
|
|
|
117
123
|
const broker = new TestBroker(proverCount, localProver);
|
|
118
124
|
const facade = new BrokerCircuitProverFacade(broker);
|
|
119
|
-
const orchestrator = new TestProvingOrchestrator(ws, facade, EthAddress.ZERO, false, 10);
|
|
120
125
|
|
|
121
126
|
await broker.start();
|
|
122
127
|
facade.start();
|
|
123
128
|
|
|
124
|
-
return new this(
|
|
125
|
-
ws,
|
|
126
|
-
localProver,
|
|
127
|
-
broker,
|
|
128
|
-
facade,
|
|
129
|
-
orchestrator,
|
|
130
|
-
feePayer,
|
|
131
|
-
initialFeePayerBalance,
|
|
132
|
-
directoriesToCleanup,
|
|
133
|
-
logger,
|
|
134
|
-
);
|
|
129
|
+
return new this(ws, localProver, broker, facade, feePayer, initialFeePayerBalance, directoriesToCleanup, logger);
|
|
135
130
|
}
|
|
136
131
|
|
|
137
132
|
public getFork() {
|
|
@@ -141,6 +136,7 @@ export class TestContext {
|
|
|
141
136
|
async cleanup() {
|
|
142
137
|
await this.brokerProverFacade.stop();
|
|
143
138
|
await this.broker.stop();
|
|
139
|
+
await this.worldState.close();
|
|
144
140
|
for (const dir of this.directoriesToCleanup.filter(x => x !== '')) {
|
|
145
141
|
try {
|
|
146
142
|
await fs.rm(dir, { recursive: true, force: true, maxRetries: 3 });
|
|
@@ -262,7 +258,7 @@ export class TestContext {
|
|
|
262
258
|
const txs = blockTxs[i];
|
|
263
259
|
const state = blockEndStates[i];
|
|
264
260
|
|
|
265
|
-
const block = await builder.addBlock(blockGlobalVariables[i], txs, {
|
|
261
|
+
const { block } = await builder.addBlock(blockGlobalVariables[i], txs, {
|
|
266
262
|
expectedEndState: state,
|
|
267
263
|
insertTxsEffects: true,
|
|
268
264
|
});
|
|
@@ -282,6 +278,7 @@ export class TestContext {
|
|
|
282
278
|
|
|
283
279
|
return {
|
|
284
280
|
constants,
|
|
281
|
+
checkpoint,
|
|
285
282
|
header: checkpoint.header,
|
|
286
283
|
blocks,
|
|
287
284
|
l1ToL2Messages,
|
|
@@ -349,16 +346,3 @@ export class TestContext {
|
|
|
349
346
|
return endStateReference;
|
|
350
347
|
}
|
|
351
348
|
}
|
|
352
|
-
|
|
353
|
-
class TestProvingOrchestrator extends ProvingOrchestrator {
|
|
354
|
-
public isVerifyBuiltBlockAgainstSyncedStateEnabled = false;
|
|
355
|
-
|
|
356
|
-
// Disable this check by default, since it requires seeding world state with the block being built
|
|
357
|
-
// This is only enabled in some tests with multiple blocks that populate the pending chain via makePendingBlock
|
|
358
|
-
protected override verifyBuiltBlockAgainstSyncedState(provingState: BlockProvingState): Promise<void> {
|
|
359
|
-
if (this.isVerifyBuiltBlockAgainstSyncedStateEnabled) {
|
|
360
|
-
return super.verifyBuiltBlockAgainstSyncedState(provingState);
|
|
361
|
-
}
|
|
362
|
-
return Promise.resolve();
|
|
363
|
-
}
|
|
364
|
-
}
|
|
@@ -1,66 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BatchedBlobAccumulator,
|
|
3
|
-
type FinalBlobBatchingChallenges,
|
|
4
|
-
SpongeBlob,
|
|
5
|
-
encodeCheckpointBlobDataFromBlocks,
|
|
6
|
-
} from '@aztec/blob-lib';
|
|
1
|
+
import { SpongeBlob } from '@aztec/blob-lib';
|
|
7
2
|
import {
|
|
8
3
|
type ARCHIVE_HEIGHT,
|
|
9
|
-
BLOBS_PER_CHECKPOINT,
|
|
10
|
-
FIELDS_PER_BLOB,
|
|
11
4
|
type L1_TO_L2_MSG_SUBTREE_ROOT_SIBLING_PATH_LENGTH,
|
|
12
5
|
type NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
|
|
13
6
|
NUM_MSGS_PER_BASE_PARITY,
|
|
14
|
-
OUT_HASH_TREE_HEIGHT,
|
|
15
7
|
} from '@aztec/constants';
|
|
16
8
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
17
9
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
18
|
-
import { BLS12Point } from '@aztec/foundation/curves/bls12';
|
|
19
10
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
20
11
|
import type { Tuple } from '@aztec/foundation/serialize';
|
|
21
12
|
import { type TreeNodeLocation, UnbalancedTreeStore } from '@aztec/foundation/trees';
|
|
22
13
|
import type { PublicInputsAndRecursiveProof } from '@aztec/stdlib/interfaces/server';
|
|
23
|
-
import { computeCheckpointOutHash } from '@aztec/stdlib/messaging';
|
|
24
14
|
import { ParityBasePrivateInputs } from '@aztec/stdlib/parity';
|
|
25
|
-
import {
|
|
26
|
-
BlockMergeRollupPrivateInputs,
|
|
27
|
-
BlockRollupPublicInputs,
|
|
28
|
-
CheckpointConstantData,
|
|
29
|
-
CheckpointRollupPublicInputs,
|
|
30
|
-
CheckpointRootRollupHints,
|
|
31
|
-
CheckpointRootRollupPrivateInputs,
|
|
32
|
-
CheckpointRootSingleBlockRollupPrivateInputs,
|
|
33
|
-
} from '@aztec/stdlib/rollup';
|
|
34
|
-
import type { CircuitName } from '@aztec/stdlib/stats';
|
|
15
|
+
import { BlockMergeRollupPrivateInputs, BlockRollupPublicInputs, CheckpointConstantData } from '@aztec/stdlib/rollup';
|
|
35
16
|
import type { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
|
|
36
17
|
import type { BlockHeader } from '@aztec/stdlib/tx';
|
|
37
18
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
38
19
|
|
|
39
|
-
import {
|
|
20
|
+
import { toProofData } from './block-building-helpers.js';
|
|
40
21
|
import { BlockProvingState, type ProofState } from './block-proving-state.js';
|
|
41
|
-
import type { EpochProvingState } from './epoch-proving-state.js';
|
|
42
|
-
|
|
43
|
-
type OutHashHint = {
|
|
44
|
-
treeSnapshot: AppendOnlyTreeSnapshot;
|
|
45
|
-
siblingPath: Tuple<Fr, typeof OUT_HASH_TREE_HEIGHT>;
|
|
46
|
-
};
|
|
47
22
|
|
|
48
23
|
export class CheckpointProvingState {
|
|
49
24
|
private blockProofs: UnbalancedTreeStore<
|
|
50
25
|
ProofState<BlockRollupPublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH>
|
|
51
26
|
>;
|
|
52
|
-
private checkpointRootProof:
|
|
53
|
-
| ProofState<CheckpointRollupPublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH>
|
|
54
|
-
| undefined;
|
|
55
27
|
private blocks: (BlockProvingState | undefined)[] = [];
|
|
56
|
-
private previousOutHashHint: OutHashHint | undefined;
|
|
57
|
-
private outHash: Fr | undefined;
|
|
58
|
-
// The snapshot and sibling path after the checkpoint's out hash is inserted.
|
|
59
|
-
// Stored here to be retrieved for the next checkpoint when it's added.
|
|
60
|
-
private newOutHashHint: OutHashHint | undefined;
|
|
61
|
-
private startBlobAccumulator: BatchedBlobAccumulator | undefined;
|
|
62
|
-
private endBlobAccumulator: BatchedBlobAccumulator | undefined;
|
|
63
|
-
private blobFields: Fr[] | undefined;
|
|
64
28
|
private error: string | undefined;
|
|
65
29
|
public readonly firstBlockNumber: BlockNumber;
|
|
66
30
|
|
|
@@ -68,7 +32,6 @@ export class CheckpointProvingState {
|
|
|
68
32
|
public readonly index: number,
|
|
69
33
|
public readonly constants: CheckpointConstantData,
|
|
70
34
|
public readonly totalNumBlocks: number,
|
|
71
|
-
private readonly finalBlobBatchingChallenges: FinalBlobBatchingChallenges,
|
|
72
35
|
private readonly headerOfLastBlockInPreviousCheckpoint: BlockHeader,
|
|
73
36
|
private readonly lastArchiveSiblingPath: Tuple<Fr, typeof ARCHIVE_HEIGHT>,
|
|
74
37
|
private readonly l1ToL2Messages: Fr[],
|
|
@@ -84,17 +47,16 @@ export class CheckpointProvingState {
|
|
|
84
47
|
Fr,
|
|
85
48
|
typeof L1_TO_L2_MSG_SUBTREE_ROOT_SIBLING_PATH_LENGTH
|
|
86
49
|
>,
|
|
87
|
-
public
|
|
88
|
-
|
|
50
|
+
public readonly epochNumber: number,
|
|
51
|
+
/** Owner's liveness check. `verifyState()` returns false once this returns false. */
|
|
52
|
+
private readonly isAlive: () => boolean,
|
|
53
|
+
/** Owner's failure callback. Invoked from `reject` to surface the error upward. */
|
|
54
|
+
private readonly onReject: (reason: string) => void,
|
|
89
55
|
) {
|
|
90
56
|
this.blockProofs = new UnbalancedTreeStore(totalNumBlocks);
|
|
91
57
|
this.firstBlockNumber = BlockNumber(headerOfLastBlockInPreviousCheckpoint.globalVariables.blockNumber + 1);
|
|
92
58
|
}
|
|
93
59
|
|
|
94
|
-
public get epochNumber(): number {
|
|
95
|
-
return this.parentEpoch.epochNumber;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
60
|
public startNewBlock(
|
|
99
61
|
blockNumber: BlockNumber,
|
|
100
62
|
timestamp: UInt64,
|
|
@@ -176,25 +138,6 @@ export class CheckpointProvingState {
|
|
|
176
138
|
this.blockProofs.setNode(location, { provingOutput });
|
|
177
139
|
}
|
|
178
140
|
|
|
179
|
-
public tryStartProvingCheckpointRoot() {
|
|
180
|
-
if (this.checkpointRootProof?.isProving) {
|
|
181
|
-
return false;
|
|
182
|
-
} else {
|
|
183
|
-
this.checkpointRootProof = { isProving: true };
|
|
184
|
-
return true;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
public setCheckpointRootRollupProof(
|
|
189
|
-
provingOutput: PublicInputsAndRecursiveProof<
|
|
190
|
-
CheckpointRollupPublicInputs,
|
|
191
|
-
typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
|
|
192
|
-
>,
|
|
193
|
-
): TreeNodeLocation {
|
|
194
|
-
this.checkpointRootProof = { provingOutput };
|
|
195
|
-
return this.parentEpoch.setCheckpointRootRollupProof(this.index, provingOutput);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
141
|
public getBaseParityInputs(baseParityIndex: number) {
|
|
199
142
|
const messages = padArrayEnd(
|
|
200
143
|
this.l1ToL2Messages.slice(
|
|
@@ -204,54 +147,7 @@ export class CheckpointProvingState {
|
|
|
204
147
|
Fr.ZERO,
|
|
205
148
|
NUM_MSGS_PER_BASE_PARITY,
|
|
206
149
|
);
|
|
207
|
-
return new ParityBasePrivateInputs(messages, this.constants.vkTreeRoot);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
public setOutHashHint(hint: OutHashHint) {
|
|
211
|
-
this.previousOutHashHint = hint;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
public getOutHashHint() {
|
|
215
|
-
return this.previousOutHashHint;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
public accumulateBlockOutHashes() {
|
|
219
|
-
if (this.isAcceptingBlocks() || this.blocks.some(b => !b?.hasEndState())) {
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
if (!this.outHash) {
|
|
224
|
-
const messagesPerBlock = this.blocks.map(b => b!.getTxEffects().map(tx => tx.l2ToL1Msgs));
|
|
225
|
-
this.outHash = computeCheckpointOutHash(messagesPerBlock);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
return this.outHash;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
public setOutHashHintForNextCheckpoint(hint: OutHashHint) {
|
|
232
|
-
this.newOutHashHint = hint;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
public getOutHashHintForNextCheckpoint() {
|
|
236
|
-
return this.newOutHashHint;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
public async accumulateBlobs(startBlobAccumulator: BatchedBlobAccumulator) {
|
|
240
|
-
if (this.isAcceptingBlocks() || this.blocks.some(b => !b?.hasEndState())) {
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
this.blobFields = encodeCheckpointBlobDataFromBlocks(this.blocks.map(b => b!.getBlockBlobData()));
|
|
245
|
-
this.endBlobAccumulator = await accumulateBlobs(this.blobFields!, startBlobAccumulator);
|
|
246
|
-
this.startBlobAccumulator = startBlobAccumulator;
|
|
247
|
-
|
|
248
|
-
await this.onBlobAccumulatorSet(this);
|
|
249
|
-
|
|
250
|
-
return this.endBlobAccumulator;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
public getEndBlobAccumulator() {
|
|
254
|
-
return this.endBlobAccumulator;
|
|
150
|
+
return new ParityBasePrivateInputs(messages, this.constants.vkTreeRoot, this.constants.proverId);
|
|
255
151
|
}
|
|
256
152
|
|
|
257
153
|
public getParentLocation(location: TreeNodeLocation) {
|
|
@@ -267,47 +163,6 @@ export class CheckpointProvingState {
|
|
|
267
163
|
return new BlockMergeRollupPrivateInputs([toProofData(left), toProofData(right)]);
|
|
268
164
|
}
|
|
269
165
|
|
|
270
|
-
public getCheckpointRootRollupType(): CircuitName {
|
|
271
|
-
return this.totalNumBlocks === 1 ? 'rollup-checkpoint-root-single-block' : 'rollup-checkpoint-root';
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
public async getCheckpointRootRollupInputs() {
|
|
275
|
-
const proofs = this.#getChildProofsForRoot();
|
|
276
|
-
const nonEmptyProofs = proofs.filter(p => !!p);
|
|
277
|
-
if (proofs.length !== nonEmptyProofs.length) {
|
|
278
|
-
throw new Error('At least one child is not ready for the checkpoint root rollup.');
|
|
279
|
-
}
|
|
280
|
-
if (!this.previousOutHashHint) {
|
|
281
|
-
throw new Error('Out hash hint is not set.');
|
|
282
|
-
}
|
|
283
|
-
if (!this.startBlobAccumulator) {
|
|
284
|
-
throw new Error('Start blob accumulator is not set.');
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// `blobFields` must've been set if `startBlobAccumulator` is set (in `accumulateBlobs`).
|
|
288
|
-
const blobFields = this.blobFields!;
|
|
289
|
-
|
|
290
|
-
const { blobCommitments, blobsHash } = await buildBlobHints(blobFields);
|
|
291
|
-
|
|
292
|
-
const hints = CheckpointRootRollupHints.from({
|
|
293
|
-
previousBlockHeader: this.headerOfLastBlockInPreviousCheckpoint,
|
|
294
|
-
previousArchiveSiblingPath: this.lastArchiveSiblingPath,
|
|
295
|
-
previousOutHash: this.previousOutHashHint.treeSnapshot,
|
|
296
|
-
newOutHashSiblingPath: this.previousOutHashHint.siblingPath,
|
|
297
|
-
startBlobAccumulator: this.startBlobAccumulator.toBlobAccumulator(),
|
|
298
|
-
finalBlobChallenges: this.finalBlobBatchingChallenges,
|
|
299
|
-
blobFields: padArrayEnd(blobFields, Fr.ZERO, FIELDS_PER_BLOB * BLOBS_PER_CHECKPOINT),
|
|
300
|
-
blobCommitments: padArrayEnd(blobCommitments, BLS12Point.ZERO, BLOBS_PER_CHECKPOINT),
|
|
301
|
-
blobsHash,
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
const [left, right] = nonEmptyProofs.map(p => toProofData(p));
|
|
305
|
-
|
|
306
|
-
return !right
|
|
307
|
-
? new CheckpointRootSingleBlockRollupPrivateInputs(left, hints)
|
|
308
|
-
: new CheckpointRootRollupPrivateInputs([left, right], hints);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
166
|
public getBlockProvingStateByBlockNumber(blockNumber: BlockNumber) {
|
|
312
167
|
const index = Number(blockNumber) - Number(this.firstBlockNumber);
|
|
313
168
|
return this.blocks[index];
|
|
@@ -317,13 +172,8 @@ export class CheckpointProvingState {
|
|
|
317
172
|
return !!this.blockProofs.getSibling(location)?.provingOutput;
|
|
318
173
|
}
|
|
319
174
|
|
|
320
|
-
public isReadyForCheckpointRoot() {
|
|
321
|
-
const allChildProofsReady = this.#getChildProofsForRoot().every(p => !!p);
|
|
322
|
-
return allChildProofsReady && !!this.previousOutHashHint && !!this.startBlobAccumulator;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
175
|
public verifyState() {
|
|
326
|
-
return this.
|
|
176
|
+
return this.isAlive();
|
|
327
177
|
}
|
|
328
178
|
|
|
329
179
|
public getError() {
|
|
@@ -337,13 +187,22 @@ export class CheckpointProvingState {
|
|
|
337
187
|
|
|
338
188
|
public reject(reason: string) {
|
|
339
189
|
this.error = reason;
|
|
340
|
-
this.
|
|
190
|
+
this.onReject(reason);
|
|
341
191
|
}
|
|
342
192
|
|
|
343
|
-
|
|
193
|
+
/**
|
|
194
|
+
* Returns the block-level proof outputs that feed into the checkpoint root rollup.
|
|
195
|
+
* Used by `CheckpointSubTreeOrchestrator` to surface its sub-tree result.
|
|
196
|
+
*/
|
|
197
|
+
public getSubTreeOutputProofs() {
|
|
344
198
|
const rootLocation = { level: 0, index: 0 };
|
|
345
199
|
return this.totalNumBlocks === 1
|
|
346
200
|
? [this.blockProofs.getNode(rootLocation)?.provingOutput] // If there's only 1 block, its proof will be stored at the root.
|
|
347
201
|
: this.blockProofs.getChildren(rootLocation).map(c => c?.provingOutput);
|
|
348
202
|
}
|
|
203
|
+
|
|
204
|
+
/** Sibling path of the archive tree captured before any block in this checkpoint landed. */
|
|
205
|
+
public getLastArchiveSiblingPath() {
|
|
206
|
+
return this.lastArchiveSiblingPath;
|
|
207
|
+
}
|
|
349
208
|
}
|