@aztec/txe 0.0.1-commit.b655e406 → 0.0.1-commit.c7c42ec

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 (79) hide show
  1. package/dest/bin/index.d.ts +1 -1
  2. package/dest/index.d.ts +1 -1
  3. package/dest/index.d.ts.map +1 -1
  4. package/dest/index.js +3 -2
  5. package/dest/oracle/interfaces.d.ts +9 -6
  6. package/dest/oracle/interfaces.d.ts.map +1 -1
  7. package/dest/oracle/txe_oracle_public_context.d.ts +5 -5
  8. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  9. package/dest/oracle/txe_oracle_public_context.js +4 -6
  10. package/dest/oracle/txe_oracle_top_level_context.d.ts +20 -12
  11. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  12. package/dest/oracle/txe_oracle_top_level_context.js +95 -63
  13. package/dest/rpc_translator.d.ts +17 -8
  14. package/dest/rpc_translator.d.ts.map +1 -1
  15. package/dest/rpc_translator.js +69 -20
  16. package/dest/state_machine/archiver.d.ts +31 -14
  17. package/dest/state_machine/archiver.d.ts.map +1 -1
  18. package/dest/state_machine/archiver.js +105 -17
  19. package/dest/state_machine/dummy_p2p_client.d.ts +4 -2
  20. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  21. package/dest/state_machine/dummy_p2p_client.js +6 -1
  22. package/dest/state_machine/global_variable_builder.d.ts +5 -3
  23. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  24. package/dest/state_machine/global_variable_builder.js +12 -0
  25. package/dest/state_machine/index.d.ts +5 -5
  26. package/dest/state_machine/index.d.ts.map +1 -1
  27. package/dest/state_machine/index.js +14 -20
  28. package/dest/state_machine/mock_epoch_cache.d.ts +6 -5
  29. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  30. package/dest/state_machine/mock_epoch_cache.js +8 -7
  31. package/dest/state_machine/synchronizer.d.ts +5 -4
  32. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  33. package/dest/state_machine/synchronizer.js +5 -4
  34. package/dest/txe_session.d.ts +19 -13
  35. package/dest/txe_session.d.ts.map +1 -1
  36. package/dest/txe_session.js +55 -41
  37. package/dest/util/encoding.d.ts +623 -24
  38. package/dest/util/encoding.d.ts.map +1 -1
  39. package/dest/util/encoding.js +1 -1
  40. package/dest/util/expected_failure_error.d.ts +1 -1
  41. package/dest/util/expected_failure_error.d.ts.map +1 -1
  42. package/dest/util/txe_account_store.d.ts +10 -0
  43. package/dest/util/txe_account_store.d.ts.map +1 -0
  44. package/dest/util/{txe_account_data_provider.js → txe_account_store.js} +1 -1
  45. package/dest/util/txe_contract_store.d.ts +12 -0
  46. package/dest/util/txe_contract_store.d.ts.map +1 -0
  47. package/dest/util/{txe_contract_data_provider.js → txe_contract_store.js} +3 -3
  48. package/dest/util/txe_public_contract_data_source.d.ts +7 -6
  49. package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
  50. package/dest/util/txe_public_contract_data_source.js +11 -11
  51. package/dest/utils/block_creation.d.ts +19 -4
  52. package/dest/utils/block_creation.d.ts.map +1 -1
  53. package/dest/utils/block_creation.js +24 -3
  54. package/dest/utils/tx_effect_creation.d.ts +4 -3
  55. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  56. package/dest/utils/tx_effect_creation.js +6 -6
  57. package/package.json +18 -17
  58. package/src/index.ts +15 -12
  59. package/src/oracle/interfaces.ts +8 -5
  60. package/src/oracle/txe_oracle_public_context.ts +6 -11
  61. package/src/oracle/txe_oracle_top_level_context.ts +126 -88
  62. package/src/rpc_translator.ts +90 -20
  63. package/src/state_machine/archiver.ts +141 -29
  64. package/src/state_machine/dummy_p2p_client.ts +9 -2
  65. package/src/state_machine/global_variable_builder.ts +21 -3
  66. package/src/state_machine/index.ts +19 -18
  67. package/src/state_machine/mock_epoch_cache.ts +12 -11
  68. package/src/state_machine/synchronizer.ts +8 -7
  69. package/src/txe_session.ts +113 -72
  70. package/src/util/encoding.ts +1 -1
  71. package/src/util/{txe_account_data_provider.ts → txe_account_store.ts} +1 -1
  72. package/src/util/{txe_contract_data_provider.ts → txe_contract_store.ts} +3 -3
  73. package/src/util/txe_public_contract_data_source.ts +13 -12
  74. package/src/utils/block_creation.ts +35 -3
  75. package/src/utils/tx_effect_creation.ts +8 -7
  76. package/dest/util/txe_account_data_provider.d.ts +0 -10
  77. package/dest/util/txe_account_data_provider.d.ts.map +0 -1
  78. package/dest/util/txe_contract_data_provider.d.ts +0 -12
  79. package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
@@ -1,13 +1,14 @@
1
1
  import type { ContractInstanceWithAddress } from '@aztec/aztec.js/contracts';
2
2
  import { Fr, Point } from '@aztec/aztec.js/fields';
3
3
  import { MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX } from '@aztec/constants';
4
+ import { BlockNumber } from '@aztec/foundation/branded-types';
4
5
  import {
5
6
  type IMiscOracle,
6
7
  type IPrivateExecutionOracle,
7
8
  type IUtilityExecutionOracle,
8
9
  packAsRetrievedNote,
9
10
  } from '@aztec/pxe/simulator';
10
- import { type ContractArtifact, FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
11
+ import { type ContractArtifact, EventSelector, FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
11
12
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
12
13
  import { MerkleTreeId } from '@aztec/stdlib/trees';
13
14
 
@@ -29,6 +30,9 @@ import {
29
30
  toSingle,
30
31
  } from './util/encoding.js';
31
32
 
33
+ const MAX_EVENT_LEN = 12; // This is MAX_MESSAGE_CONTENT_LEN - PRIVATE_EVENT_RESERVED_FIELDS
34
+ const MAX_PRIVATE_EVENTS_PER_TXE_QUERY = 5;
35
+
32
36
  export class UnavailableOracleError extends Error {
33
37
  constructor(oracleName: string) {
34
38
  super(`${oracleName} oracles not available with the current handler`);
@@ -117,7 +121,7 @@ export class RPCTranslator {
117
121
  : undefined;
118
122
 
119
123
  const anchorBlockNumber = fromSingle(foreignAnchorBlockNumberIsSome).toBool()
120
- ? fromSingle(foreignAnchorBlockNumberValue).toNumber()
124
+ ? BlockNumber(fromSingle(foreignAnchorBlockNumberValue).toNumber())
121
125
  : undefined;
122
126
 
123
127
  const privateContextInputs = await this.stateHandler.enterPrivateState(contractAddress, anchorBlockNumber);
@@ -155,6 +159,12 @@ export class RPCTranslator {
155
159
 
156
160
  // TXE-specific oracles
157
161
 
162
+ txeGetDefaultAddress() {
163
+ const defaultAddress = this.handlerAsTxe().txeGetDefaultAddress();
164
+
165
+ return toForeignCallResult([toSingle(defaultAddress)]);
166
+ }
167
+
158
168
  async txeGetNextBlockNumber() {
159
169
  const nextBlockNumber = await this.handlerAsTxe().txeGetNextBlockNumber();
160
170
 
@@ -266,12 +276,40 @@ export class RPCTranslator {
266
276
  ]);
267
277
  }
268
278
 
269
- // Since the argument is a slice, noir automatically adds a length field to oracle call.
270
- privateStoreInExecutionCache(
271
- _foreignLength: ForeignCallSingle,
272
- foreignValues: ForeignCallArray,
273
- foreignHash: ForeignCallSingle,
279
+ async txeGetPrivateEvents(
280
+ foreignSelector: ForeignCallSingle,
281
+ foreignContractAddress: ForeignCallSingle,
282
+ foreignScope: ForeignCallSingle,
274
283
  ) {
284
+ const selector = EventSelector.fromField(fromSingle(foreignSelector));
285
+ const contractAddress = addressFromSingle(foreignContractAddress);
286
+ const scope = addressFromSingle(foreignScope);
287
+
288
+ const events = await this.handlerAsTxe().txeGetPrivateEvents(selector, contractAddress, scope);
289
+
290
+ if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
291
+ throw new Error(`Array of length ${events.length} larger than maxLen ${MAX_PRIVATE_EVENTS_PER_TXE_QUERY}`);
292
+ }
293
+
294
+ if (events.some(e => e.length > MAX_EVENT_LEN)) {
295
+ throw new Error(`Some private event has length larger than maxLen ${MAX_EVENT_LEN}`);
296
+ }
297
+
298
+ // This is a workaround as Noir does not currently let us return nested structs with arrays. We instead return a raw
299
+ // multidimensional array in get_private_events_oracle and create the BoundedVecs here.
300
+ const rawArrayStorage = events
301
+ .map(e => e.concat(Array(MAX_EVENT_LEN - e.length).fill(new Fr(0))))
302
+ .concat(Array(MAX_PRIVATE_EVENTS_PER_TXE_QUERY - events.length).fill(Array(MAX_EVENT_LEN).fill(new Fr(0))))
303
+ .flat();
304
+ const eventLengths = events
305
+ .map(e => new Fr(e.length))
306
+ .concat(Array(MAX_PRIVATE_EVENTS_PER_TXE_QUERY - events.length).fill(new Fr(0)));
307
+ const queryLength = new Fr(events.length);
308
+
309
+ return toForeignCallResult([toArray(rawArrayStorage), toArray(eventLengths), toSingle(queryLength)]);
310
+ }
311
+
312
+ privateStoreInExecutionCache(foreignValues: ForeignCallArray, foreignHash: ForeignCallSingle) {
275
313
  const values = fromArray(foreignValues);
276
314
  const hash = fromSingle(foreignHash);
277
315
 
@@ -315,7 +353,7 @@ export class RPCTranslator {
315
353
  ) {
316
354
  const contractAddress = addressFromSingle(foreignContractAddress);
317
355
  const startStorageSlot = fromSingle(foreignStartStorageSlot);
318
- const blockNumber = fromSingle(foreignBlockNumber).toNumber();
356
+ const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
319
357
  const numberOfElements = fromSingle(foreignNumberOfElements).toNumber();
320
358
 
321
359
  const values = await this.handlerAsUtility().utilityStorageRead(
@@ -329,7 +367,7 @@ export class RPCTranslator {
329
367
  }
330
368
 
331
369
  async utilityGetPublicDataWitness(foreignBlockNumber: ForeignCallSingle, foreignLeafSlot: ForeignCallSingle) {
332
- const blockNumber = fromSingle(foreignBlockNumber).toNumber();
370
+ const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
333
371
  const leafSlot = fromSingle(foreignLeafSlot);
334
372
 
335
373
  const witness = await this.handlerAsUtility().utilityGetPublicDataWitness(blockNumber, leafSlot);
@@ -341,6 +379,8 @@ export class RPCTranslator {
341
379
  }
342
380
 
343
381
  async utilityGetNotes(
382
+ foreignOwnerIsSome: ForeignCallSingle,
383
+ foreignOwnerValue: ForeignCallSingle,
344
384
  foreignStorageSlot: ForeignCallSingle,
345
385
  foreignNumSelects: ForeignCallSingle,
346
386
  foreignSelectByIndexes: ForeignCallArray,
@@ -358,6 +398,10 @@ export class RPCTranslator {
358
398
  foreignMaxNotes: ForeignCallSingle,
359
399
  foreignPackedRetrievedNoteLength: ForeignCallSingle,
360
400
  ) {
401
+ // Parse Option<AztecAddress>: ownerIsSome is 0 for None, 1 for Some
402
+ const owner = fromSingle(foreignOwnerIsSome).toBool()
403
+ ? AztecAddress.fromField(fromSingle(foreignOwnerValue))
404
+ : undefined;
361
405
  const storageSlot = fromSingle(foreignStorageSlot);
362
406
  const numSelects = fromSingle(foreignNumSelects).toNumber();
363
407
  const selectByIndexes = fromArray(foreignSelectByIndexes).map(fr => fr.toNumber());
@@ -376,6 +420,7 @@ export class RPCTranslator {
376
420
  const packedRetrievedNoteLength = fromSingle(foreignPackedRetrievedNoteLength).toNumber();
377
421
 
378
422
  const noteDatas = await this.handlerAsUtility().utilityGetNotes(
423
+ owner,
379
424
  storageSlot,
380
425
  numSelects,
381
426
  selectByIndexes,
@@ -392,7 +437,17 @@ export class RPCTranslator {
392
437
  status,
393
438
  );
394
439
 
395
- const returnDataAsArrayOfArrays = noteDatas.map(packAsRetrievedNote);
440
+ const returnDataAsArrayOfArrays = noteDatas.map(noteData =>
441
+ packAsRetrievedNote({
442
+ contractAddress: noteData.contractAddress,
443
+ owner: noteData.owner,
444
+ randomness: noteData.randomness,
445
+ storageSlot: noteData.storageSlot,
446
+ noteNonce: noteData.noteNonce,
447
+ index: noteData.index,
448
+ note: noteData.note,
449
+ }),
450
+ );
396
451
 
397
452
  // Now we convert each sub-array to an array of ForeignCallSingles
398
453
  const returnDataAsArrayOfForeignCallSingleArrays = returnDataAsArrayOfArrays.map(subArray =>
@@ -410,19 +465,31 @@ export class RPCTranslator {
410
465
  }
411
466
 
412
467
  privateNotifyCreatedNote(
468
+ foreignOwner: ForeignCallSingle,
413
469
  foreignStorageSlot: ForeignCallSingle,
470
+ foreignRandomness: ForeignCallSingle,
414
471
  foreignNoteTypeId: ForeignCallSingle,
415
472
  foreignNote: ForeignCallArray,
416
473
  foreignNoteHash: ForeignCallSingle,
417
474
  foreignCounter: ForeignCallSingle,
418
475
  ) {
476
+ const owner = addressFromSingle(foreignOwner);
419
477
  const storageSlot = fromSingle(foreignStorageSlot);
478
+ const randomness = fromSingle(foreignRandomness);
420
479
  const noteTypeId = NoteSelector.fromField(fromSingle(foreignNoteTypeId));
421
480
  const note = fromArray(foreignNote);
422
481
  const noteHash = fromSingle(foreignNoteHash);
423
482
  const counter = fromSingle(foreignCounter).toNumber();
424
483
 
425
- this.handlerAsPrivate().privateNotifyCreatedNote(storageSlot, noteTypeId, note, noteHash, counter);
484
+ this.handlerAsPrivate().privateNotifyCreatedNote(
485
+ owner,
486
+ storageSlot,
487
+ randomness,
488
+ noteTypeId,
489
+ note,
490
+ noteHash,
491
+ counter,
492
+ );
426
493
 
427
494
  return toForeignCallResult([]);
428
495
  }
@@ -505,7 +572,7 @@ export class RPCTranslator {
505
572
  foreignBlockNumber: ForeignCallSingle,
506
573
  foreignNullifier: ForeignCallSingle,
507
574
  ) {
508
- const blockNumber = fromSingle(foreignBlockNumber).toNumber();
575
+ const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
509
576
  const nullifier = fromSingle(foreignNullifier);
510
577
 
511
578
  const witness = await this.handlerAsUtility().utilityGetNullifierMembershipWitness(blockNumber, nullifier);
@@ -549,14 +616,20 @@ export class RPCTranslator {
549
616
  throw new Error('Enqueueing public calls is not supported in TestEnvironment::private_context');
550
617
  }
551
618
 
552
- async utilityGetUtilityContext() {
553
- const context = await this.handlerAsUtility().utilityGetUtilityContext();
619
+ public async privateIsSideEffectCounterRevertible(foreignSideEffectCounter: ForeignCallSingle) {
620
+ const sideEffectCounter = fromSingle(foreignSideEffectCounter).toNumber();
621
+ const isRevertible = await this.handlerAsPrivate().privateIsSideEffectCounterRevertible(sideEffectCounter);
622
+ return toForeignCallResult([toSingle(new Fr(isRevertible))]);
623
+ }
624
+
625
+ utilityGetUtilityContext() {
626
+ const context = this.handlerAsUtility().utilityGetUtilityContext();
554
627
 
555
628
  return toForeignCallResult(context.toNoirRepresentation());
556
629
  }
557
630
 
558
631
  async utilityGetBlockHeader(foreignBlockNumber: ForeignCallSingle) {
559
- const blockNumber = fromSingle(foreignBlockNumber).toNumber();
632
+ const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
560
633
 
561
634
  const header = await this.handlerAsUtility().utilityGetBlockHeader(blockNumber);
562
635
 
@@ -571,7 +644,7 @@ export class RPCTranslator {
571
644
  foreignTreeId: ForeignCallSingle,
572
645
  foreignLeafValue: ForeignCallSingle,
573
646
  ) {
574
- const blockNumber = fromSingle(foreignBlockNumber).toNumber();
647
+ const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
575
648
  const treeId = fromSingle(foreignTreeId).toNumber();
576
649
  const leafValue = fromSingle(foreignLeafValue);
577
650
 
@@ -589,7 +662,7 @@ export class RPCTranslator {
589
662
  foreignBlockNumber: ForeignCallSingle,
590
663
  foreignNullifier: ForeignCallSingle,
591
664
  ) {
592
- const blockNumber = fromSingle(foreignBlockNumber).toNumber();
665
+ const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
593
666
  const nullifier = fromSingle(foreignNullifier);
594
667
 
595
668
  const witness = await this.handlerAsUtility().utilityGetLowNullifierMembershipWitness(blockNumber, nullifier);
@@ -921,7 +994,6 @@ export class RPCTranslator {
921
994
  foreignFrom: ForeignCallSingle,
922
995
  foreignTargetContractAddress: ForeignCallSingle,
923
996
  foreignFunctionSelector: ForeignCallSingle,
924
- _foreignArgsLength: ForeignCallSingle,
925
997
  foreignArgs: ForeignCallArray,
926
998
  foreignArgsHash: ForeignCallSingle,
927
999
  foreignIsStaticCall: ForeignCallSingle,
@@ -948,7 +1020,6 @@ export class RPCTranslator {
948
1020
  async txeSimulateUtilityFunction(
949
1021
  foreignTargetContractAddress: ForeignCallSingle,
950
1022
  foreignFunctionSelector: ForeignCallSingle,
951
- _foreignArgsLength: ForeignCallSingle,
952
1023
  foreignArgs: ForeignCallArray,
953
1024
  ) {
954
1025
  const targetContractAddress = addressFromSingle(foreignTargetContractAddress);
@@ -967,7 +1038,6 @@ export class RPCTranslator {
967
1038
  async txePublicCallNewFlow(
968
1039
  foreignFrom: ForeignCallSingle,
969
1040
  foreignAddress: ForeignCallSingle,
970
- _foreignLength: ForeignCallSingle,
971
1041
  foreignCalldata: ForeignCallArray,
972
1042
  foreignIsStaticCall: ForeignCallSingle,
973
1043
  ) {
@@ -1,10 +1,22 @@
1
- import { ArchiverStoreHelper, KVArchiverDataStore, type PublishedL2Block } from '@aztec/archiver';
1
+ import { ArchiverStoreHelper, KVArchiverDataStore } from '@aztec/archiver';
2
2
  import { GENESIS_ARCHIVE_ROOT } from '@aztec/constants';
3
+ import { BlockNumber, CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
4
+ import { Fr } from '@aztec/foundation/curves/bn254';
3
5
  import type { EthAddress } from '@aztec/foundation/eth-address';
4
- import { Fr } from '@aztec/foundation/fields';
6
+ import { isDefined } from '@aztec/foundation/types';
5
7
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
6
8
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
7
- import type { L2Block, L2BlockSource, L2Tips, ValidateBlockResult } from '@aztec/stdlib/block';
9
+ import {
10
+ CommitteeAttestation,
11
+ L2Block,
12
+ type L2BlockId,
13
+ type L2BlockNew,
14
+ type L2BlockSource,
15
+ type L2Tips,
16
+ PublishedL2Block,
17
+ type ValidateBlockResult,
18
+ } from '@aztec/stdlib/block';
19
+ import { Checkpoint, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
8
20
  import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
9
21
  import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
10
22
  import type { BlockHeader } from '@aztec/stdlib/tx';
@@ -18,11 +30,28 @@ export class TXEArchiver extends ArchiverStoreHelper implements L2BlockSource {
18
30
  super(new KVArchiverDataStore(db, 9999));
19
31
  }
20
32
 
21
- public override async addBlocks(blocks: PublishedL2Block[]): Promise<boolean> {
22
- const opResults = await Promise.all([
23
- this.store.addLogs(blocks.map(block => block.block)),
24
- this.store.addBlocks(blocks),
25
- ]);
33
+ public async getBlock(number: BlockNumber): Promise<L2Block | undefined> {
34
+ if (number === 0) {
35
+ return undefined;
36
+ }
37
+ const publishedBlocks = await this.getPublishedBlocks(number, 1);
38
+ if (publishedBlocks.length === 0) {
39
+ return undefined;
40
+ }
41
+ return publishedBlocks[0].block;
42
+ }
43
+
44
+ public async getBlocks(from: BlockNumber, limit: number, proven?: boolean): Promise<L2Block[]> {
45
+ const publishedBlocks = await this.getPublishedBlocks(from, limit, proven);
46
+ return publishedBlocks.map(x => x.block);
47
+ }
48
+
49
+ public override async addCheckpoints(
50
+ checkpoints: PublishedCheckpoint[],
51
+ _result?: ValidateBlockResult,
52
+ ): Promise<boolean> {
53
+ const allBlocks = checkpoints.flatMap(ch => ch.checkpoint.blocks);
54
+ const opResults = await Promise.all([this.store.addLogs(allBlocks), this.store.addCheckpoints(checkpoints)]);
26
55
 
27
56
  return opResults.every(Boolean);
28
57
  }
@@ -31,16 +60,16 @@ export class TXEArchiver extends ArchiverStoreHelper implements L2BlockSource {
31
60
  * Gets the number of the latest L2 block processed by the block source implementation.
32
61
  * @returns The number of the latest L2 block processed by the block source implementation.
33
62
  */
34
- public getBlockNumber(): Promise<number> {
35
- return this.store.getSynchedL2BlockNumber();
63
+ public getBlockNumber(): Promise<BlockNumber> {
64
+ return this.store.getLatestBlockNumber();
36
65
  }
37
66
 
38
67
  /**
39
68
  * Gets the number of the latest L2 block proven seen by the block source implementation.
40
69
  * @returns The number of the latest L2 block proven seen by the block source implementation.
41
70
  */
42
- public getProvenBlockNumber(): Promise<number> {
43
- return this.store.getSynchedL2BlockNumber();
71
+ public override getProvenBlockNumber(): Promise<BlockNumber> {
72
+ return this.store.getProvenBlockNumber();
44
73
  }
45
74
 
46
75
  /**
@@ -48,16 +77,55 @@ export class TXEArchiver extends ArchiverStoreHelper implements L2BlockSource {
48
77
  * @param number - The block number to return (inclusive).
49
78
  * @returns The requested L2 block.
50
79
  */
51
- public override async getPublishedBlock(number: number): Promise<PublishedL2Block | undefined> {
80
+ public async getPublishedBlock(number: number): Promise<PublishedL2Block | undefined> {
52
81
  // If the number provided is -ve, then return the latest block.
53
82
  if (number < 0) {
54
- number = await this.store.getSynchedL2BlockNumber();
83
+ number = await this.store.getLatestBlockNumber();
55
84
  }
56
85
  if (number == 0) {
57
86
  return undefined;
58
87
  }
59
- const blocks = await this.store.getPublishedBlocks(number, 1);
60
- return blocks.length === 0 ? undefined : blocks[0];
88
+ const publishedBlocks = await this.retrievePublishedBlocks(BlockNumber(number), 1);
89
+ return publishedBlocks.length === 0 ? undefined : publishedBlocks[0];
90
+ }
91
+
92
+ getPublishedBlocks(from: BlockNumber, limit: number, proven?: boolean): Promise<PublishedL2Block[]> {
93
+ return this.retrievePublishedBlocks(from, limit, proven);
94
+ }
95
+
96
+ private async retrievePublishedBlocks(
97
+ from: BlockNumber,
98
+ limit: number,
99
+ proven?: boolean,
100
+ ): Promise<PublishedL2Block[]> {
101
+ const checkpoints = await this.store.getRangeOfCheckpoints(CheckpointNumber(from), limit);
102
+ const provenCheckpointNumber = await this.store.getProvenCheckpointNumber();
103
+ const blocks = (
104
+ await Promise.all(checkpoints.map(ch => this.store.getBlocksForCheckpoint(ch.checkpointNumber)))
105
+ ).filter(isDefined);
106
+
107
+ const olbBlocks: PublishedL2Block[] = [];
108
+ for (let i = 0; i < checkpoints.length; i++) {
109
+ const blockForCheckpoint = blocks[i][0];
110
+ const checkpoint = checkpoints[i];
111
+ if (proven === true && checkpoint.checkpointNumber > provenCheckpointNumber) {
112
+ continue;
113
+ }
114
+ const oldCheckpoint = new Checkpoint(
115
+ blockForCheckpoint.archive,
116
+ checkpoint.header,
117
+ [blockForCheckpoint],
118
+ checkpoint.checkpointNumber,
119
+ );
120
+ const oldBlock = L2Block.fromCheckpoint(oldCheckpoint);
121
+ const publishedBlock = new PublishedL2Block(
122
+ oldBlock,
123
+ checkpoint.l1,
124
+ checkpoint.attestations.map(x => CommitteeAttestation.fromBuffer(x)),
125
+ );
126
+ olbBlocks.push(publishedBlock);
127
+ }
128
+ return olbBlocks;
61
129
  }
62
130
 
63
131
  /**
@@ -65,8 +133,20 @@ export class TXEArchiver extends ArchiverStoreHelper implements L2BlockSource {
65
133
  * @param number - The block number to return (inclusive).
66
134
  * @returns The requested L2 block.
67
135
  */
68
- public getBlock(number: number | 'latest'): Promise<L2Block | undefined> {
69
- return this.getPublishedBlock(number != 'latest' ? number : -1).then(block => block?.block);
136
+ public getL2Block(number: BlockNumber | 'latest'): Promise<L2Block | undefined> {
137
+ return this.getPublishedBlock(number != 'latest' ? number : -1).then(b => b?.block);
138
+ }
139
+
140
+ /**
141
+ * Gets an L2 block (new format).
142
+ * @param number - The block number to return.
143
+ * @returns The requested L2 block.
144
+ */
145
+ public getL2BlockNew(number: BlockNumber): Promise<L2BlockNew | undefined> {
146
+ if (number === 0) {
147
+ return Promise.resolve(undefined);
148
+ }
149
+ return this.store.getBlock(number);
70
150
  }
71
151
 
72
152
  /**
@@ -76,41 +156,66 @@ export class TXEArchiver extends ArchiverStoreHelper implements L2BlockSource {
76
156
  */
77
157
  public async getBlockHeader(number: number | 'latest'): Promise<BlockHeader | undefined> {
78
158
  if (number === 'latest') {
79
- number = await this.store.getSynchedL2BlockNumber();
159
+ number = await this.store.getLatestBlockNumber();
80
160
  }
81
161
  if (number === 0) {
82
162
  return undefined;
83
163
  }
84
- const headers = await this.store.getBlockHeaders(number, 1);
164
+ const headers = await this.store.getBlockHeaders(BlockNumber(number), 1);
85
165
  return headers.length === 0 ? undefined : headers[0];
86
166
  }
87
167
 
88
- public getBlocks(from: number, limit: number, _proven?: boolean): Promise<L2Block[]> {
89
- return this.getPublishedBlocks(from, limit).then(blocks => blocks.map(b => b.block));
168
+ public getBlockRange(from: number, limit: number, _proven?: boolean): Promise<L2Block[]> {
169
+ return this.getPublishedBlocks(BlockNumber(from), limit).then(blocks => blocks.map(b => b.block));
170
+ }
171
+
172
+ public getPublishedCheckpoints(_from: CheckpointNumber, _limit: number): Promise<PublishedCheckpoint[]> {
173
+ throw new Error('TXE Archiver does not implement "getPublishedCheckpoints"');
174
+ }
175
+
176
+ public getCheckpointByArchive(_archive: Fr): Promise<Checkpoint | undefined> {
177
+ throw new Error('TXE Archiver does not implement "getCheckpointByArchive"');
90
178
  }
91
179
 
92
- public getL2SlotNumber(): Promise<bigint> {
180
+ public getL2SlotNumber(): Promise<SlotNumber | undefined> {
93
181
  throw new Error('TXE Archiver does not implement "getL2SlotNumber"');
94
182
  }
95
183
 
96
- public getL2EpochNumber(): Promise<bigint> {
184
+ public getL2EpochNumber(): Promise<EpochNumber> {
97
185
  throw new Error('TXE Archiver does not implement "getL2EpochNumber"');
98
186
  }
99
187
 
100
- public getBlocksForEpoch(_epochNumber: bigint): Promise<L2Block[]> {
188
+ public getCheckpointsForEpoch(_epochNumber: EpochNumber): Promise<Checkpoint[]> {
189
+ throw new Error('TXE Archiver does not implement "getCheckpointsForEpoch"');
190
+ }
191
+
192
+ public getBlocksForEpoch(_epochNumber: EpochNumber): Promise<L2Block[]> {
101
193
  throw new Error('TXE Archiver does not implement "getBlocksForEpoch"');
102
194
  }
103
195
 
104
- public getBlockHeadersForEpoch(_epochNumber: bigint): Promise<BlockHeader[]> {
196
+ public getBlockHeadersForEpoch(_epochNumber: EpochNumber): Promise<BlockHeader[]> {
105
197
  throw new Error('TXE Archiver does not implement "getBlockHeadersForEpoch"');
106
198
  }
107
199
 
108
- public isEpochComplete(_epochNumber: bigint): Promise<boolean> {
200
+ public isEpochComplete(_epochNumber: EpochNumber): Promise<boolean> {
109
201
  throw new Error('TXE Archiver does not implement "isEpochComplete"');
110
202
  }
111
203
 
112
- public getL2Tips(): Promise<L2Tips> {
113
- throw new Error('TXE Archiver does not implement "getL2Tips"');
204
+ public async getL2Tips(): Promise<L2Tips> {
205
+ // In TXE there is no possibility of reorgs and no blocks are ever getting proven so we just set 'latest', 'proven'
206
+ // and 'finalized' to the latest block.
207
+ const blockHeader = await this.getBlockHeader('latest');
208
+ if (!blockHeader) {
209
+ throw new Error('L2Tips requested from TXE Archiver but no block header found');
210
+ }
211
+
212
+ const number = blockHeader.globalVariables.blockNumber;
213
+ const hash = (await blockHeader.hash()).toString();
214
+ return {
215
+ latest: { number, hash } as L2BlockId,
216
+ proven: { number, hash } as L2BlockId,
217
+ finalized: { number, hash } as L2BlockId,
218
+ };
114
219
  }
115
220
 
116
221
  public getL1Constants(): Promise<L1RollupConstants> {
@@ -148,4 +253,11 @@ export class TXEArchiver extends ArchiverStoreHelper implements L2BlockSource {
148
253
  public override getPendingChainValidationStatus(): Promise<ValidateBlockResult> {
149
254
  return Promise.resolve({ valid: true });
150
255
  }
256
+
257
+ getPublishedBlockByHash(_blockHash: Fr): Promise<PublishedL2Block | undefined> {
258
+ throw new Error('Method not implemented.');
259
+ }
260
+ getPublishedBlockByArchive(_archive: Fr): Promise<PublishedL2Block | undefined> {
261
+ throw new Error('Method not implemented.');
262
+ }
151
263
  }
@@ -1,3 +1,4 @@
1
+ import type { SlotNumber } from '@aztec/foundation/branded-types';
1
2
  import type {
2
3
  AuthRequest,
3
4
  ENR,
@@ -17,6 +18,10 @@ import type { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
17
18
  import type { Tx, TxHash } from '@aztec/stdlib/tx';
18
19
 
19
20
  export class DummyP2P implements P2P {
21
+ public broadcastAttestations(_attestations: BlockAttestation[]): Promise<void> {
22
+ return Promise.resolve();
23
+ }
24
+
20
25
  public validate(_txs: Tx[]): Promise<void> {
21
26
  return Promise.resolve();
22
27
  }
@@ -74,7 +79,9 @@ export class DummyP2P implements P2P {
74
79
  }
75
80
 
76
81
  public getTxStatus(_txHash: TxHash): Promise<'pending' | 'mined' | undefined> {
77
- throw new Error('DummyP2P does not implement "getTxStatus"');
82
+ // In TXE there is no concept of transactions but we need to implement this because of tagging. We return 'mined'
83
+ // tx status for any tx hash.
84
+ return Promise.resolve('mined');
78
85
  }
79
86
 
80
87
  public iteratePendingTxs(): AsyncIterableIterator<Tx> {
@@ -113,7 +120,7 @@ export class DummyP2P implements P2P {
113
120
  throw new Error('DummyP2P does not implement "getTxsByHash"');
114
121
  }
115
122
 
116
- public getAttestationsForSlot(_slot: bigint, _proposalId?: string): Promise<BlockAttestation[]> {
123
+ public getAttestationsForSlot(_slot: SlotNumber, _proposalId?: string): Promise<BlockAttestation[]> {
117
124
  throw new Error('DummyP2P does not implement "getAttestationForSlot"');
118
125
  }
119
126
 
@@ -1,8 +1,9 @@
1
+ import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
1
2
  import type { EthAddress } from '@aztec/foundation/eth-address';
2
3
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
3
4
  import { GasFees } from '@aztec/stdlib/gas';
4
5
  import { makeGlobalVariables } from '@aztec/stdlib/testing';
5
- import { type GlobalVariableBuilder, GlobalVariables } from '@aztec/stdlib/tx';
6
+ import { type CheckpointGlobalVariables, type GlobalVariableBuilder, GlobalVariables } from '@aztec/stdlib/tx';
6
7
 
7
8
  export class TXEGlobalVariablesBuilder implements GlobalVariableBuilder {
8
9
  public getCurrentBaseFees(): Promise<GasFees> {
@@ -10,11 +11,28 @@ export class TXEGlobalVariablesBuilder implements GlobalVariableBuilder {
10
11
  }
11
12
 
12
13
  public buildGlobalVariables(
13
- _blockNumber: number,
14
+ _blockNumber: BlockNumber,
14
15
  _coinbase: EthAddress,
15
16
  _feeRecipient: AztecAddress,
16
- _slotNumber?: bigint,
17
+ _slotNumber?: SlotNumber,
17
18
  ): Promise<GlobalVariables> {
18
19
  return Promise.resolve(makeGlobalVariables());
19
20
  }
21
+
22
+ public buildCheckpointGlobalVariables(
23
+ _coinbase: EthAddress,
24
+ _feeRecipient: AztecAddress,
25
+ _slotNumber: SlotNumber,
26
+ ): Promise<CheckpointGlobalVariables> {
27
+ const vars = makeGlobalVariables();
28
+ return Promise.resolve({
29
+ chainId: vars.chainId,
30
+ version: vars.version,
31
+ slotNumber: vars.slotNumber,
32
+ timestamp: vars.timestamp,
33
+ coinbase: vars.coinbase,
34
+ feeRecipient: vars.feeRecipient,
35
+ gasFees: vars.gasFees,
36
+ });
37
+ }
20
38
  }
@@ -2,8 +2,9 @@ import { type AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node';
2
2
  import { TestCircuitVerifier } from '@aztec/bb-prover/test';
3
3
  import { createLogger } from '@aztec/foundation/log';
4
4
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
5
- import { SyncDataProvider } from '@aztec/pxe/server';
6
- import { type L2Block, PublishedL2Block } from '@aztec/stdlib/block';
5
+ import { AnchorBlockStore } from '@aztec/pxe/server';
6
+ import { L2Block } from '@aztec/stdlib/block';
7
+ import { L1PublishedData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
7
8
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
8
9
  import { getPackageVersion } from '@aztec/stdlib/update-checker';
9
10
 
@@ -21,13 +22,13 @@ export class TXEStateMachine {
21
22
  public node: AztecNode,
22
23
  public synchronizer: TXESynchronizer,
23
24
  public archiver: TXEArchiver,
24
- public syncDataProvider: SyncDataProvider,
25
+ public anchorBlockStore: AnchorBlockStore,
25
26
  ) {}
26
27
 
27
28
  public static async create(db: AztecAsyncKVStore) {
28
29
  const archiver = new TXEArchiver(db);
29
30
  const synchronizer = await TXESynchronizer.create();
30
- const syncDataProvider = new SyncDataProvider(db);
31
+ const anchorBlockStore = new AnchorBlockStore(db);
31
32
 
32
33
  const aztecNodeConfig = {} as AztecNodeConfig;
33
34
 
@@ -54,24 +55,24 @@ export class TXEStateMachine {
54
55
  log,
55
56
  );
56
57
 
57
- return new this(node, synchronizer, archiver, syncDataProvider);
58
+ return new this(node, synchronizer, archiver, anchorBlockStore);
58
59
  }
59
60
 
60
61
  public async handleL2Block(block: L2Block) {
62
+ const checkpoint = block.toCheckpoint();
63
+ const publishedCheckpoint = new PublishedCheckpoint(
64
+ checkpoint,
65
+ new L1PublishedData(
66
+ BigInt(block.header.globalVariables.blockNumber),
67
+ block.header.globalVariables.timestamp,
68
+ block.header.globalVariables.blockNumber.toString(),
69
+ ),
70
+ [],
71
+ );
61
72
  await Promise.all([
62
- this.synchronizer.handleL2Block(block),
63
- this.archiver.addBlocks([
64
- PublishedL2Block.fromFields({
65
- block,
66
- l1: {
67
- blockHash: block.header.globalVariables.blockNumber.toString(),
68
- blockNumber: BigInt(block.header.globalVariables.blockNumber),
69
- timestamp: block.header.globalVariables.timestamp,
70
- },
71
- attestations: [],
72
- }),
73
- ]),
74
- this.syncDataProvider.setHeader(block.getBlockHeader()),
73
+ this.synchronizer.handleL2Block(block.toL2Block()),
74
+ this.archiver.addCheckpoints([publishedCheckpoint], undefined),
75
+ this.anchorBlockStore.setHeader(block.getBlockHeader()),
75
76
  ]);
76
77
  }
77
78
  }