@aztec/sequencer-client 0.16.4 → 0.16.5

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.
Files changed (37) hide show
  1. package/dest/block_builder/solo_block_builder.d.ts +3 -3
  2. package/dest/block_builder/solo_block_builder.d.ts.map +1 -1
  3. package/dest/block_builder/solo_block_builder.js +26 -26
  4. package/dest/block_builder/types.d.ts +11 -2
  5. package/dest/block_builder/types.d.ts.map +1 -1
  6. package/dest/sequencer/utils.js +2 -2
  7. package/package.json +11 -11
  8. package/src/block_builder/index.ts +0 -24
  9. package/src/block_builder/solo_block_builder.ts +0 -758
  10. package/src/block_builder/types.ts +0 -16
  11. package/src/client/index.ts +0 -1
  12. package/src/client/sequencer-client.ts +0 -87
  13. package/src/config.ts +0 -76
  14. package/src/global_variable_builder/config.ts +0 -20
  15. package/src/global_variable_builder/global_builder.ts +0 -87
  16. package/src/global_variable_builder/index.ts +0 -16
  17. package/src/global_variable_builder/viem-reader.ts +0 -61
  18. package/src/index.ts +0 -15
  19. package/src/mocks/verification_keys.ts +0 -36
  20. package/src/prover/empty.ts +0 -74
  21. package/src/prover/index.ts +0 -53
  22. package/src/publisher/config.ts +0 -41
  23. package/src/publisher/index.ts +0 -14
  24. package/src/publisher/l1-publisher.ts +0 -291
  25. package/src/publisher/viem-tx-sender.ts +0 -195
  26. package/src/receiver.ts +0 -13
  27. package/src/sequencer/config.ts +0 -1
  28. package/src/sequencer/index.ts +0 -3
  29. package/src/sequencer/processed_tx.ts +0 -107
  30. package/src/sequencer/public_processor.ts +0 -433
  31. package/src/sequencer/sequencer.ts +0 -434
  32. package/src/sequencer/utils.ts +0 -25
  33. package/src/simulator/index.ts +0 -51
  34. package/src/simulator/public_executor.ts +0 -153
  35. package/src/simulator/public_kernel.ts +0 -54
  36. package/src/simulator/rollup.ts +0 -76
  37. package/src/utils.ts +0 -16
@@ -1,434 +0,0 @@
1
- import { GlobalVariables } from '@aztec/circuits.js';
2
- import { Fr } from '@aztec/foundation/fields';
3
- import { createDebugLogger } from '@aztec/foundation/log';
4
- import { RunningPromise } from '@aztec/foundation/running-promise';
5
- import { Timer, elapsed } from '@aztec/foundation/timer';
6
- import { P2P } from '@aztec/p2p';
7
- import { L1ToL2MessageSource, L2Block, L2BlockSource, MerkleTreeId, Tx } from '@aztec/types';
8
- import { L2BlockBuiltStats } from '@aztec/types/stats';
9
- import { WorldStateStatus, WorldStateSynchronizer } from '@aztec/world-state';
10
-
11
- import times from 'lodash.times';
12
-
13
- import { BlockBuilder } from '../block_builder/index.js';
14
- import { GlobalVariableBuilder } from '../global_variable_builder/global_builder.js';
15
- import { L1Publisher } from '../publisher/l1-publisher.js';
16
- import { ceilPowerOfTwo } from '../utils.js';
17
- import { SequencerConfig } from './config.js';
18
- import { ProcessedTx } from './processed_tx.js';
19
- import { PublicProcessorFactory } from './public_processor.js';
20
-
21
- /**
22
- * Sequencer client
23
- * - Wins a period of time to become the sequencer (depending on finalized protocol).
24
- * - Chooses a set of txs from the tx pool to be in the rollup.
25
- * - Simulate the rollup of txs.
26
- * - Adds proof requests to the request pool (not for this milestone).
27
- * - Receives results to those proofs from the network (repeats as necessary) (not for this milestone).
28
- * - Publishes L1 tx(s) to the rollup contract via RollupPublisher.
29
- */
30
- export class Sequencer {
31
- private runningPromise?: RunningPromise;
32
- private pollingIntervalMs: number = 1000;
33
- private maxTxsPerBlock = 32;
34
- private minTxsPerBLock = 1;
35
- private lastPublishedBlock = 0;
36
- private state = SequencerState.STOPPED;
37
-
38
- constructor(
39
- private publisher: L1Publisher,
40
- private globalsBuilder: GlobalVariableBuilder,
41
- private p2pClient: P2P,
42
- private worldState: WorldStateSynchronizer,
43
- private blockBuilder: BlockBuilder,
44
- private l2BlockSource: L2BlockSource,
45
- private l1ToL2MessageSource: L1ToL2MessageSource,
46
- private publicProcessorFactory: PublicProcessorFactory,
47
- config: SequencerConfig = {},
48
- private log = createDebugLogger('aztec:sequencer'),
49
- ) {
50
- this.updateConfig(config);
51
- this.log(`Initialized sequencer with ${this.minTxsPerBLock}-${this.maxTxsPerBlock} txs per block.`);
52
- }
53
-
54
- /**
55
- * Updates sequencer config.
56
- * @param config - New parameters.
57
- */
58
- public updateConfig(config: SequencerConfig) {
59
- if (config.transactionPollingIntervalMS) {
60
- this.pollingIntervalMs = config.transactionPollingIntervalMS;
61
- }
62
- if (config.maxTxsPerBlock) {
63
- this.maxTxsPerBlock = config.maxTxsPerBlock;
64
- }
65
- if (config.minTxsPerBlock) {
66
- this.minTxsPerBLock = config.minTxsPerBlock;
67
- }
68
- }
69
-
70
- /**
71
- * Starts the sequencer and moves to IDLE state. Blocks until the initial sync is complete.
72
- */
73
- public async start() {
74
- await this.initialSync();
75
-
76
- this.runningPromise = new RunningPromise(this.work.bind(this), this.pollingIntervalMs);
77
- this.runningPromise.start();
78
- this.state = SequencerState.IDLE;
79
- this.log('Sequencer started');
80
- }
81
-
82
- /**
83
- * Stops the sequencer from processing txs and moves to STOPPED state.
84
- */
85
- public async stop(): Promise<void> {
86
- await this.runningPromise?.stop();
87
- this.publisher.interrupt();
88
- this.state = SequencerState.STOPPED;
89
- this.log('Stopped sequencer');
90
- }
91
-
92
- /**
93
- * Starts a previously stopped sequencer.
94
- */
95
- public restart() {
96
- this.log('Restarting sequencer');
97
- this.publisher.restart();
98
- this.runningPromise!.start();
99
- this.state = SequencerState.IDLE;
100
- }
101
-
102
- /**
103
- * Returns the current state of the sequencer.
104
- * @returns An object with a state entry with one of SequencerState.
105
- */
106
- public status() {
107
- return { state: this.state };
108
- }
109
-
110
- protected async initialSync() {
111
- // TODO: Should we wait for world state to be ready, or is the caller expected to run await start?
112
- this.lastPublishedBlock = await this.worldState.status().then((s: WorldStateStatus) => s.syncedToL2Block);
113
- }
114
-
115
- /**
116
- * Grabs up to maxTxsPerBlock from the p2p client, constructs a block, and pushes it to L1.
117
- */
118
- protected async work() {
119
- try {
120
- // Update state when the previous block has been synced
121
- const prevBlockSynced = await this.isBlockSynced();
122
- if (prevBlockSynced && this.state === SequencerState.PUBLISHING_BLOCK) {
123
- this.log(`Block has been synced`);
124
- this.state = SequencerState.IDLE;
125
- }
126
-
127
- // Do not go forward with new block if the previous one has not been mined and processed
128
- if (!prevBlockSynced) {
129
- return;
130
- }
131
-
132
- const workTimer = new Timer();
133
- this.state = SequencerState.WAITING_FOR_TXS;
134
-
135
- // Get txs to build the new block
136
- const pendingTxs = await this.p2pClient.getTxs();
137
- if (pendingTxs.length < this.minTxsPerBLock) {
138
- return;
139
- }
140
- this.log.info(`Retrieved ${pendingTxs.length} txs from P2P pool`);
141
-
142
- const blockNumber = (await this.l2BlockSource.getBlockNumber()) + 1;
143
-
144
- /**
145
- * We'll call this function before running expensive operations to avoid wasted work.
146
- */
147
- const assertBlockHeight = async () => {
148
- const currentBlockNumber = await this.l2BlockSource.getBlockNumber();
149
- if (currentBlockNumber + 1 !== blockNumber) {
150
- throw new Error('New block was emitted while building block');
151
- }
152
- };
153
-
154
- const newGlobalVariables = await this.globalsBuilder.buildGlobalVariables(new Fr(blockNumber));
155
-
156
- // Filter out invalid txs
157
- // TODO: It should be responsibility of the P2P layer to validate txs before passing them on here
158
- const validTxs = await this.takeValidTxs(pendingTxs, newGlobalVariables);
159
- if (validTxs.length < this.minTxsPerBLock) {
160
- return;
161
- }
162
-
163
- this.log.info(`Building block ${blockNumber} with ${validTxs.length} transactions`);
164
- this.state = SequencerState.CREATING_BLOCK;
165
-
166
- const prevGlobalVariables = (await this.l2BlockSource.getBlock(-1))?.globalVariables ?? GlobalVariables.empty();
167
-
168
- // Process txs and drop the ones that fail processing
169
- // We create a fresh processor each time to reset any cached state (eg storage writes)
170
- const processor = await this.publicProcessorFactory.create(prevGlobalVariables, newGlobalVariables);
171
- const [publicProcessorDuration, [processedTxs, failedTxs]] = await elapsed(() => processor.process(validTxs));
172
- if (failedTxs.length > 0) {
173
- const failedTxData = failedTxs.map(fail => fail.tx);
174
- this.log(`Dropping failed txs ${(await Tx.getHashes(failedTxData)).join(', ')}`);
175
- await this.p2pClient.deleteTxs(await Tx.getHashes(failedTxData));
176
- }
177
-
178
- // Only accept processed transactions that are not double-spends,
179
- // public functions emitting nullifiers would pass earlier check but fail here.
180
- // Note that we're checking all nullifiers generated in the private execution twice,
181
- // we could store the ones already checked and skip them here as an optimization.
182
- const processedValidTxs = await this.takeValidTxs(processedTxs, newGlobalVariables);
183
-
184
- if (processedValidTxs.length === 0) {
185
- this.log('No txs processed correctly to build block. Exiting');
186
- return;
187
- }
188
-
189
- await assertBlockHeight();
190
-
191
- // Get l1 to l2 messages from the contract
192
- this.log('Requesting L1 to L2 messages from contract');
193
- const l1ToL2Messages = await this.getPendingL1ToL2Messages();
194
- this.log('Successfully retrieved L1 to L2 messages from contract');
195
-
196
- // Build the new block by running the rollup circuits
197
- this.log(`Assembling block with txs ${processedValidTxs.map(tx => tx.hash).join(', ')}`);
198
-
199
- await assertBlockHeight();
200
-
201
- const emptyTx = await processor.makeEmptyProcessedTx();
202
- const [rollupCircuitsDuration, block] = await elapsed(() =>
203
- this.buildBlock(processedValidTxs, l1ToL2Messages, emptyTx, newGlobalVariables),
204
- );
205
-
206
- this.log(`Assembled block ${block.number}`, {
207
- eventName: 'l2-block-built',
208
- duration: workTimer.ms(),
209
- publicProcessDuration: publicProcessorDuration,
210
- rollupCircuitsDuration: rollupCircuitsDuration,
211
- ...block.getStats(),
212
- } satisfies L2BlockBuiltStats);
213
-
214
- await assertBlockHeight();
215
-
216
- await this.publishExtendedContractData(processedValidTxs, block);
217
-
218
- await assertBlockHeight();
219
-
220
- await this.publishL2Block(block);
221
- this.log.info(`Submitted rollup block ${block.number} with ${processedValidTxs.length} transactions`);
222
- } catch (err) {
223
- this.log.error(`Rolling back world state DB due to error assembling block`, (err as any).stack);
224
- await this.worldState.getLatest().rollback();
225
- }
226
- }
227
-
228
- /**
229
- * Gets new extended contract data from the txs and publishes it on chain.
230
- * @param validTxs - The set of real transactions being published as part of the block.
231
- * @param block - The L2Block to be published.
232
- */
233
- protected async publishExtendedContractData(validTxs: ProcessedTx[], block: L2Block) {
234
- // Publishes contract data for txs to the network and awaits the tx to be mined
235
- this.state = SequencerState.PUBLISHING_CONTRACT_DATA;
236
- const newContractData = validTxs
237
- .map(tx => {
238
- // Currently can only have 1 new contract per tx
239
- return tx.newContracts[0];
240
- })
241
- .filter((cd): cd is Exclude<typeof cd, undefined> => cd !== undefined);
242
-
243
- const blockHash = block.getCalldataHash();
244
- this.log(`Publishing extended contract data with block hash ${blockHash.toString('hex')}`);
245
-
246
- const publishedContractData = await this.publisher.processNewContractData(block.number, blockHash, newContractData);
247
- if (publishedContractData) {
248
- this.log(`Successfully published new contract data for block ${block.number}`);
249
- } else if (!publishedContractData && newContractData.length) {
250
- this.log(`Failed to publish new contract data for block ${block.number}`);
251
- }
252
- }
253
-
254
- /**
255
- * Publishes the L2Block to the rollup contract.
256
- * @param block - The L2Block to be published.
257
- */
258
- protected async publishL2Block(block: L2Block) {
259
- // Publishes new block to the network and awaits the tx to be mined
260
- this.state = SequencerState.PUBLISHING_BLOCK;
261
- const publishedL2Block = await this.publisher.processL2Block(block);
262
- if (publishedL2Block) {
263
- this.log(`Successfully published block ${block.number}`);
264
- this.lastPublishedBlock = block.number;
265
- } else {
266
- throw new Error(`Failed to publish block`);
267
- }
268
- }
269
-
270
- protected async takeValidTxs<T extends Tx | ProcessedTx>(txs: T[], globalVariables: GlobalVariables): Promise<T[]> {
271
- const validTxs: T[] = [];
272
- const txsToDelete = [];
273
- const thisBlockNullifiers: Set<bigint> = new Set();
274
-
275
- // Process txs until we get to maxTxsPerBlock, rejecting double spends in the process
276
- for (const tx of txs) {
277
- if (tx.data.constants.txContext.chainId.value !== globalVariables.chainId.value) {
278
- this.log(
279
- `Deleting tx for incorrect chain ${tx.data.constants.txContext.chainId.toString()}, tx hash ${await Tx.getHash(
280
- tx,
281
- )}`,
282
- );
283
- txsToDelete.push(tx);
284
- continue;
285
- }
286
- if (await this.isTxDoubleSpend(tx)) {
287
- this.log(`Deleting double spend tx ${await Tx.getHash(tx)}`);
288
- txsToDelete.push(tx);
289
- continue;
290
- } else if (this.isTxDoubleSpendSameBlock(tx, thisBlockNullifiers)) {
291
- // We don't drop these txs from the p2p pool immediately since they become valid
292
- // again if the current block fails to be published for some reason.
293
- this.log(`Skipping tx with double-spend for this same block ${await Tx.getHash(tx)}`);
294
- continue;
295
- }
296
-
297
- tx.data.end.newNullifiers.forEach(n => thisBlockNullifiers.add(n.toBigInt()));
298
- validTxs.push(tx);
299
- if (validTxs.length >= this.maxTxsPerBlock) {
300
- break;
301
- }
302
- }
303
-
304
- // Make sure we remove these from the tx pool so we do not consider it again
305
- if (txsToDelete.length > 0) {
306
- await this.p2pClient.deleteTxs(await Tx.getHashes([...txsToDelete]));
307
- }
308
-
309
- return validTxs;
310
- }
311
-
312
- /**
313
- * Returns whether the previous block sent has been mined, and all dependencies have caught up with it.
314
- * @returns Boolean indicating if our dependencies are synced to the latest block.
315
- */
316
- protected async isBlockSynced() {
317
- const syncedBlocks = await Promise.all([
318
- this.worldState.status().then((s: WorldStateStatus) => s.syncedToL2Block),
319
- this.p2pClient.getStatus().then(s => s.syncedToL2Block),
320
- this.l2BlockSource.getBlockNumber(),
321
- this.l1ToL2MessageSource.getBlockNumber(),
322
- ]);
323
- const min = Math.min(...syncedBlocks);
324
- return min >= this.lastPublishedBlock;
325
- }
326
-
327
- /**
328
- * Pads the set of txs to a power of two and assembles a block by calling the block builder.
329
- * @param txs - Processed txs to include in the next block.
330
- * @param newL1ToL2Messages - L1 to L2 messages to be part of the block.
331
- * @param emptyTx - Empty tx to repeat at the end of the block to pad to a power of two.
332
- * @param globalVariables - Global variables to use in the block.
333
- * @returns The new block.
334
- */
335
- protected async buildBlock(
336
- txs: ProcessedTx[],
337
- newL1ToL2Messages: Fr[],
338
- emptyTx: ProcessedTx,
339
- globalVariables: GlobalVariables,
340
- ) {
341
- // Pad the txs array with empty txs to be a power of two, at least 4
342
- const txsTargetSize = Math.max(ceilPowerOfTwo(txs.length), 4);
343
- const emptyTxCount = txsTargetSize - txs.length;
344
-
345
- const allTxs = [...txs, ...times(emptyTxCount, () => emptyTx)];
346
- this.log(`Building block ${globalVariables.blockNumber}`);
347
-
348
- const [block] = await this.blockBuilder.buildL2Block(globalVariables, allTxs, newL1ToL2Messages);
349
- return block;
350
- }
351
-
352
- /**
353
- * Calls the archiver to pull upto `NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP` message keys
354
- * (archiver returns the top messages sorted by fees)
355
- * @returns An array of L1 to L2 messages' messageKeys
356
- */
357
- protected async getPendingL1ToL2Messages(): Promise<Fr[]> {
358
- return await this.l1ToL2MessageSource.getPendingL1ToL2Messages();
359
- }
360
-
361
- /**
362
- * Returns true if one of the tx nullifiers exist on the block being built.
363
- * @param tx - The tx to test.
364
- * @param thisBlockNullifiers - The nullifiers added so far.
365
- */
366
- protected isTxDoubleSpendSameBlock(tx: Tx | ProcessedTx, thisBlockNullifiers: Set<bigint>): boolean {
367
- // We only consider non-empty nullifiers
368
- const newNullifiers = tx.data.end.newNullifiers.filter(n => !n.isZero());
369
-
370
- for (const nullifier of newNullifiers) {
371
- if (thisBlockNullifiers.has(nullifier.toBigInt())) {
372
- return true;
373
- }
374
- }
375
- return false;
376
- }
377
-
378
- /**
379
- * Returns true if one of the transaction nullifiers exist.
380
- * Nullifiers prevent double spends in a private context.
381
- * @param tx - The transaction.
382
- * @returns Whether this is a problematic double spend that the L1 contract would reject.
383
- */
384
- protected async isTxDoubleSpend(tx: Tx | ProcessedTx): Promise<boolean> {
385
- // We only consider non-empty nullifiers
386
- const newNullifiers = tx.data.end.newNullifiers.filter(n => !n.isZero());
387
-
388
- // Ditch this tx if it has a repeated nullifiers
389
- const uniqNullifiers = new Set(newNullifiers.map(n => n.toBigInt()));
390
- if (uniqNullifiers.size !== newNullifiers.length) {
391
- return true;
392
- }
393
-
394
- for (const nullifier of newNullifiers) {
395
- // TODO(AD): this is an exhaustive search currently
396
- const db = this.worldState.getLatest();
397
- const indexInDb = await db.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer());
398
- if (indexInDb !== undefined) {
399
- return true;
400
- }
401
- }
402
- return false;
403
- }
404
- }
405
-
406
- /**
407
- * State of the sequencer.
408
- */
409
- export enum SequencerState {
410
- /**
411
- * Will move to WAITING_FOR_TXS after a configured amount of time.
412
- */
413
- IDLE,
414
- /**
415
- * Polling the P2P module for txs to include in a block. Will move to CREATING_BLOCK if there are valid txs to include, or back to IDLE otherwise.
416
- */
417
- WAITING_FOR_TXS,
418
- /**
419
- * Creating a new L2 block. Includes processing public function calls and running rollup circuits. Will move to PUBLISHING_CONTRACT_DATA.
420
- */
421
- CREATING_BLOCK,
422
- /**
423
- * Sending the tx to L1 with encrypted logs and awaiting it to be mined. Will move back to PUBLISHING_BLOCK once finished.
424
- */
425
- PUBLISHING_CONTRACT_DATA,
426
- /**
427
- * Sending the tx to L1 with the L2 block data and awaiting it to be mined. Will move to IDLE.
428
- */
429
- PUBLISHING_BLOCK,
430
- /**
431
- * Sequencer is stopped and not processing any txs from the pool.
432
- */
433
- STOPPED,
434
- }
@@ -1,25 +0,0 @@
1
- import { BlockHeader, Fr, GlobalVariables } from '@aztec/circuits.js';
2
- import { computeGlobalsHash } from '@aztec/circuits.js/abis';
3
- import { MerkleTreeOperations } from '@aztec/world-state';
4
-
5
- /**
6
- * Fetches the private, nullifier, contract tree and l1 to l2 messages tree roots from a given db and assembles a CombinedHistoricalTreeRoots object.
7
- */
8
- export async function getBlockHeader(
9
- db: MerkleTreeOperations,
10
- prevBlockGlobalVariables: GlobalVariables = GlobalVariables.empty(),
11
- ) {
12
- const prevGlobalsHash = computeGlobalsHash(prevBlockGlobalVariables);
13
- const roots = await db.getTreeRoots();
14
-
15
- return new BlockHeader(
16
- Fr.fromBuffer(roots.noteHashTreeRoot),
17
- Fr.fromBuffer(roots.nullifierTreeRoot),
18
- Fr.fromBuffer(roots.contractDataTreeRoot),
19
- Fr.fromBuffer(roots.l1Tol2MessagesTreeRoot),
20
- Fr.fromBuffer(roots.blocksTreeRoot),
21
- Fr.ZERO,
22
- Fr.fromBuffer(roots.publicDataTreeRoot),
23
- prevGlobalsHash,
24
- );
25
- }
@@ -1,51 +0,0 @@
1
- import {
2
- BaseOrMergeRollupPublicInputs,
3
- BaseRollupInputs,
4
- MergeRollupInputs,
5
- PublicKernelInputs,
6
- PublicKernelPublicInputs,
7
- RootRollupInputs,
8
- RootRollupPublicInputs,
9
- } from '@aztec/circuits.js';
10
-
11
- /**
12
- * Circuit simulator for the rollup circuits.
13
- */
14
- export interface RollupSimulator {
15
- /**
16
- * Simulates the base rollup circuit from its inputs.
17
- * @param input - Inputs to the circuit.
18
- * @returns The public inputs as outputs of the simulation.
19
- */
20
- baseRollupCircuit(input: BaseRollupInputs): Promise<BaseOrMergeRollupPublicInputs>;
21
- /**
22
- * Simulates the merge rollup circuit from its inputs.
23
- * @param input - Inputs to the circuit.
24
- * @returns The public inputs as outputs of the simulation.
25
- */
26
- mergeRollupCircuit(input: MergeRollupInputs): Promise<BaseOrMergeRollupPublicInputs>;
27
- /**
28
- * Simulates the root rollup circuit from its inputs.
29
- * @param input - Inputs to the circuit.
30
- * @returns The public inputs as outputs of the simulation.
31
- */
32
- rootRollupCircuit(input: RootRollupInputs): Promise<RootRollupPublicInputs>;
33
- }
34
-
35
- /**
36
- * Circuit simulator for the public kernel circuits.
37
- */
38
- export interface PublicKernelCircuitSimulator {
39
- /**
40
- * Simulates the public kernel circuit (with a previous private kernel circuit run) from its inputs.
41
- * @param inputs - Inputs to the circuit.
42
- * @returns The public inputs as outputs of the simulation.
43
- */
44
- publicKernelCircuitPrivateInput(inputs: PublicKernelInputs): Promise<PublicKernelPublicInputs>;
45
- /**
46
- * Simulates the public kernel circuit (with no previous public kernel circuit run) from its inputs.
47
- * @param inputs - Inputs to the circuit.
48
- * @returns The public inputs as outputs of the simulation.
49
- */
50
- publicKernelCircuitNonFirstIteration(inputs: PublicKernelInputs): Promise<PublicKernelPublicInputs>;
51
- }
@@ -1,153 +0,0 @@
1
- import { CommitmentsDB, MessageLoadOracleInputs, PublicContractsDB, PublicStateDB } from '@aztec/acir-simulator';
2
- import { AztecAddress, EthAddress, Fr, FunctionSelector } from '@aztec/circuits.js';
3
- import { computePublicDataTreeIndex } from '@aztec/circuits.js/abis';
4
- import { ContractDataSource, ExtendedContractData, L1ToL2MessageSource, MerkleTreeId, Tx } from '@aztec/types';
5
- import { MerkleTreeOperations } from '@aztec/world-state';
6
-
7
- /**
8
- * Implements the PublicContractsDB using a ContractDataSource.
9
- * Progressively records contracts in transaction as they are processed in a block.
10
- */
11
- export class ContractsDataSourcePublicDB implements PublicContractsDB {
12
- cache = new Map<string, ExtendedContractData>();
13
-
14
- constructor(private db: ContractDataSource) {}
15
-
16
- /**
17
- * Add new contracts from a transaction
18
- * @param tx - The transaction to add contracts from.
19
- */
20
- public addNewContracts(tx: Tx): Promise<void> {
21
- for (const contract of tx.newContracts) {
22
- const contractAddress = contract.contractData.contractAddress;
23
-
24
- if (contractAddress.isZero()) {
25
- continue;
26
- }
27
-
28
- this.cache.set(contractAddress.toString(), contract);
29
- }
30
-
31
- return Promise.resolve();
32
- }
33
-
34
- /**
35
- * Removes new contracts added from transactions
36
- * @param tx - The tx's contracts to be removed
37
- */
38
- public removeNewContracts(tx: Tx): Promise<void> {
39
- for (const contract of tx.newContracts) {
40
- const contractAddress = contract.contractData.contractAddress;
41
-
42
- if (contractAddress.isZero()) {
43
- continue;
44
- }
45
-
46
- this.cache.delete(contractAddress.toString());
47
- }
48
- return Promise.resolve();
49
- }
50
-
51
- async getBytecode(address: AztecAddress, selector: FunctionSelector): Promise<Buffer | undefined> {
52
- const contract = await this.#getContract(address);
53
- return contract?.getPublicFunction(selector)?.bytecode;
54
- }
55
- async getIsInternal(address: AztecAddress, selector: FunctionSelector): Promise<boolean | undefined> {
56
- const contract = await this.#getContract(address);
57
- return contract?.getPublicFunction(selector)?.isInternal;
58
- }
59
- async getPortalContractAddress(address: AztecAddress): Promise<EthAddress | undefined> {
60
- const contract = await this.#getContract(address);
61
- return contract?.contractData.portalContractAddress;
62
- }
63
-
64
- async #getContract(address: AztecAddress): Promise<ExtendedContractData | undefined> {
65
- return this.cache.get(address.toString()) ?? (await this.db.getExtendedContractData(address));
66
- }
67
- }
68
-
69
- /**
70
- * Implements the PublicStateDB using a world-state database.
71
- */
72
- export class WorldStatePublicDB implements PublicStateDB {
73
- private commitedWriteCache: Map<bigint, Fr> = new Map();
74
- private uncommitedWriteCache: Map<bigint, Fr> = new Map();
75
-
76
- constructor(private db: MerkleTreeOperations) {}
77
-
78
- /**
79
- * Reads a value from public storage, returning zero if none.
80
- * @param contract - Owner of the storage.
81
- * @param slot - Slot to read in the contract storage.
82
- * @returns The current value in the storage slot.
83
- */
84
- public async storageRead(contract: AztecAddress, slot: Fr): Promise<Fr> {
85
- const index = computePublicDataTreeIndex(contract, slot).value;
86
- const uncommited = this.uncommitedWriteCache.get(index);
87
- if (uncommited !== undefined) {
88
- return uncommited;
89
- }
90
- const commited = this.commitedWriteCache.get(index);
91
- if (commited !== undefined) {
92
- return commited;
93
- }
94
- const value = await this.db.getLeafValue(MerkleTreeId.PUBLIC_DATA_TREE, index);
95
- return value ? Fr.fromBuffer(value) : Fr.ZERO;
96
- }
97
-
98
- /**
99
- * Records a write to public storage.
100
- * @param contract - Owner of the storage.
101
- * @param slot - Slot to read in the contract storage.
102
- * @param newValue - The new value to store.
103
- */
104
- public storageWrite(contract: AztecAddress, slot: Fr, newValue: Fr): Promise<void> {
105
- const index = computePublicDataTreeIndex(contract, slot).value;
106
- this.uncommitedWriteCache.set(index, newValue);
107
- return Promise.resolve();
108
- }
109
-
110
- /**
111
- * Commit the pending changes to the DB.
112
- * @returns Nothing.
113
- */
114
- commit(): Promise<void> {
115
- for (const [k, v] of this.uncommitedWriteCache) {
116
- this.commitedWriteCache.set(k, v);
117
- }
118
- return this.rollback();
119
- }
120
-
121
- /**
122
- * Rollback the pending changes.
123
- * @returns Nothing.
124
- */
125
- rollback(): Promise<void> {
126
- this.uncommitedWriteCache = new Map<bigint, Fr>();
127
- return Promise.resolve();
128
- }
129
- }
130
-
131
- /**
132
- * Implements WorldState db using a world state database.
133
- */
134
- export class WorldStateDB implements CommitmentsDB {
135
- constructor(private db: MerkleTreeOperations, private l1ToL2MessageSource: L1ToL2MessageSource) {}
136
-
137
- public async getL1ToL2Message(messageKey: Fr): Promise<MessageLoadOracleInputs> {
138
- // todo: #697 - make this one lookup.
139
- const message = await this.l1ToL2MessageSource.getConfirmedL1ToL2Message(messageKey);
140
- const index = (await this.db.findLeafIndex(MerkleTreeId.L1_TO_L2_MESSAGES_TREE, messageKey.toBuffer()))!;
141
- const siblingPath = await this.db.getSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGES_TREE, index);
142
-
143
- return {
144
- message: message.toFieldArray(),
145
- siblingPath: siblingPath.toFieldArray(),
146
- index,
147
- };
148
- }
149
-
150
- public async getCommitmentIndex(commitment: Fr): Promise<bigint | undefined> {
151
- return await this.db.findLeafIndex(MerkleTreeId.NOTE_HASH_TREE, commitment.toBuffer());
152
- }
153
- }