@aztec/txe 0.0.1-commit.24de95ac → 0.0.1-commit.3469e52

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 (83) hide show
  1. package/dest/bin/index.d.ts +1 -1
  2. package/dest/constants.d.ts +3 -0
  3. package/dest/constants.d.ts.map +1 -0
  4. package/dest/constants.js +2 -0
  5. package/dest/index.d.ts +1 -1
  6. package/dest/index.d.ts.map +1 -1
  7. package/dest/index.js +3 -2
  8. package/dest/oracle/interfaces.d.ts +9 -6
  9. package/dest/oracle/interfaces.d.ts.map +1 -1
  10. package/dest/oracle/txe_oracle_public_context.d.ts +6 -6
  11. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  12. package/dest/oracle/txe_oracle_public_context.js +4 -6
  13. package/dest/oracle/txe_oracle_top_level_context.d.ts +22 -12
  14. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  15. package/dest/oracle/txe_oracle_top_level_context.js +124 -78
  16. package/dest/rpc_translator.d.ts +22 -13
  17. package/dest/rpc_translator.d.ts.map +1 -1
  18. package/dest/rpc_translator.js +87 -37
  19. package/dest/state_machine/archiver.d.ts +21 -51
  20. package/dest/state_machine/archiver.d.ts.map +1 -1
  21. package/dest/state_machine/archiver.js +62 -94
  22. package/dest/state_machine/dummy_p2p_client.d.ts +9 -6
  23. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  24. package/dest/state_machine/dummy_p2p_client.js +16 -8
  25. package/dest/state_machine/global_variable_builder.d.ts +6 -4
  26. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  27. package/dest/state_machine/global_variable_builder.js +13 -1
  28. package/dest/state_machine/index.d.ts +6 -6
  29. package/dest/state_machine/index.d.ts.map +1 -1
  30. package/dest/state_machine/index.js +22 -19
  31. package/dest/state_machine/mock_epoch_cache.d.ts +9 -9
  32. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  33. package/dest/state_machine/mock_epoch_cache.js +15 -12
  34. package/dest/state_machine/synchronizer.d.ts +5 -4
  35. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  36. package/dest/state_machine/synchronizer.js +5 -4
  37. package/dest/txe_session.d.ts +21 -13
  38. package/dest/txe_session.d.ts.map +1 -1
  39. package/dest/txe_session.js +96 -48
  40. package/dest/util/encoding.d.ts +615 -16
  41. package/dest/util/encoding.d.ts.map +1 -1
  42. package/dest/util/encoding.js +1 -1
  43. package/dest/util/expected_failure_error.d.ts +1 -1
  44. package/dest/util/expected_failure_error.d.ts.map +1 -1
  45. package/dest/util/txe_account_store.d.ts +10 -0
  46. package/dest/util/txe_account_store.d.ts.map +1 -0
  47. package/dest/util/{txe_account_data_provider.js → txe_account_store.js} +1 -1
  48. package/dest/util/txe_contract_store.d.ts +12 -0
  49. package/dest/util/txe_contract_store.d.ts.map +1 -0
  50. package/dest/util/{txe_contract_data_provider.js → txe_contract_store.js} +3 -3
  51. package/dest/util/txe_public_contract_data_source.d.ts +7 -6
  52. package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
  53. package/dest/util/txe_public_contract_data_source.js +11 -11
  54. package/dest/utils/block_creation.d.ts +21 -6
  55. package/dest/utils/block_creation.d.ts.map +1 -1
  56. package/dest/utils/block_creation.js +36 -4
  57. package/dest/utils/tx_effect_creation.d.ts +3 -3
  58. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  59. package/dest/utils/tx_effect_creation.js +4 -7
  60. package/package.json +18 -17
  61. package/src/constants.ts +3 -0
  62. package/src/index.ts +15 -12
  63. package/src/oracle/interfaces.ts +8 -5
  64. package/src/oracle/txe_oracle_public_context.ts +7 -12
  65. package/src/oracle/txe_oracle_top_level_context.ts +174 -105
  66. package/src/rpc_translator.ts +109 -45
  67. package/src/state_machine/archiver.ts +65 -117
  68. package/src/state_machine/dummy_p2p_client.ts +22 -10
  69. package/src/state_machine/global_variable_builder.ts +22 -4
  70. package/src/state_machine/index.ts +28 -19
  71. package/src/state_machine/mock_epoch_cache.ts +18 -19
  72. package/src/state_machine/synchronizer.ts +8 -7
  73. package/src/txe_session.ts +187 -82
  74. package/src/util/encoding.ts +1 -1
  75. package/src/util/{txe_account_data_provider.ts → txe_account_store.ts} +1 -1
  76. package/src/util/{txe_contract_data_provider.ts → txe_contract_store.ts} +3 -3
  77. package/src/util/txe_public_contract_data_source.ts +13 -12
  78. package/src/utils/block_creation.ts +47 -14
  79. package/src/utils/tx_effect_creation.ts +5 -12
  80. package/dest/util/txe_account_data_provider.d.ts +0 -10
  81. package/dest/util/txe_account_data_provider.d.ts.map +0 -1
  82. package/dest/util/txe_contract_data_provider.d.ts +0 -12
  83. package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
@@ -1,14 +1,16 @@
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
- packAsRetrievedNote,
9
+ packAsHintedNote,
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';
13
+ import { L2BlockHash } from '@aztec/stdlib/block';
12
14
  import { MerkleTreeId } from '@aztec/stdlib/trees';
13
15
 
14
16
  import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
@@ -29,6 +31,9 @@ import {
29
31
  toSingle,
30
32
  } from './util/encoding.js';
31
33
 
34
+ const MAX_EVENT_LEN = 12; // This is MAX_MESSAGE_CONTENT_LEN - PRIVATE_EVENT_RESERVED_FIELDS
35
+ const MAX_PRIVATE_EVENTS_PER_TXE_QUERY = 5;
36
+
32
37
  export class UnavailableOracleError extends Error {
33
38
  constructor(oracleName: string) {
34
39
  super(`${oracleName} oracles not available with the current handler`);
@@ -117,7 +122,7 @@ export class RPCTranslator {
117
122
  : undefined;
118
123
 
119
124
  const anchorBlockNumber = fromSingle(foreignAnchorBlockNumberIsSome).toBool()
120
- ? fromSingle(foreignAnchorBlockNumberValue).toNumber()
125
+ ? BlockNumber(fromSingle(foreignAnchorBlockNumberValue).toNumber())
121
126
  : undefined;
122
127
 
123
128
  const privateContextInputs = await this.stateHandler.enterPrivateState(contractAddress, anchorBlockNumber);
@@ -155,6 +160,12 @@ export class RPCTranslator {
155
160
 
156
161
  // TXE-specific oracles
157
162
 
163
+ txeGetDefaultAddress() {
164
+ const defaultAddress = this.handlerAsTxe().txeGetDefaultAddress();
165
+
166
+ return toForeignCallResult([toSingle(defaultAddress)]);
167
+ }
168
+
158
169
  async txeGetNextBlockNumber() {
159
170
  const nextBlockNumber = await this.handlerAsTxe().txeGetNextBlockNumber();
160
171
 
@@ -266,12 +277,40 @@ export class RPCTranslator {
266
277
  ]);
267
278
  }
268
279
 
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,
280
+ async txeGetPrivateEvents(
281
+ foreignSelector: ForeignCallSingle,
282
+ foreignContractAddress: ForeignCallSingle,
283
+ foreignScope: ForeignCallSingle,
274
284
  ) {
285
+ const selector = EventSelector.fromField(fromSingle(foreignSelector));
286
+ const contractAddress = addressFromSingle(foreignContractAddress);
287
+ const scope = addressFromSingle(foreignScope);
288
+
289
+ const events = await this.handlerAsTxe().txeGetPrivateEvents(selector, contractAddress, scope);
290
+
291
+ if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
292
+ throw new Error(`Array of length ${events.length} larger than maxLen ${MAX_PRIVATE_EVENTS_PER_TXE_QUERY}`);
293
+ }
294
+
295
+ if (events.some(e => e.length > MAX_EVENT_LEN)) {
296
+ throw new Error(`Some private event has length larger than maxLen ${MAX_EVENT_LEN}`);
297
+ }
298
+
299
+ // This is a workaround as Noir does not currently let us return nested structs with arrays. We instead return a raw
300
+ // multidimensional array in get_private_events_oracle and create the BoundedVecs here.
301
+ const rawArrayStorage = events
302
+ .map(e => e.concat(Array(MAX_EVENT_LEN - e.length).fill(new Fr(0))))
303
+ .concat(Array(MAX_PRIVATE_EVENTS_PER_TXE_QUERY - events.length).fill(Array(MAX_EVENT_LEN).fill(new Fr(0))))
304
+ .flat();
305
+ const eventLengths = events
306
+ .map(e => new Fr(e.length))
307
+ .concat(Array(MAX_PRIVATE_EVENTS_PER_TXE_QUERY - events.length).fill(new Fr(0)));
308
+ const queryLength = new Fr(events.length);
309
+
310
+ return toForeignCallResult([toArray(rawArrayStorage), toArray(eventLengths), toSingle(queryLength)]);
311
+ }
312
+
313
+ privateStoreInExecutionCache(foreignValues: ForeignCallArray, foreignHash: ForeignCallSingle) {
275
314
  const values = fromArray(foreignValues);
276
315
  const hash = fromSingle(foreignHash);
277
316
 
@@ -308,39 +347,41 @@ export class RPCTranslator {
308
347
  }
309
348
 
310
349
  async utilityStorageRead(
350
+ foreignBlockHash: ForeignCallSingle,
311
351
  foreignContractAddress: ForeignCallSingle,
312
352
  foreignStartStorageSlot: ForeignCallSingle,
313
- foreignBlockNumber: ForeignCallSingle,
314
353
  foreignNumberOfElements: ForeignCallSingle,
315
354
  ) {
355
+ const blockHash = L2BlockHash.fromString(foreignBlockHash);
316
356
  const contractAddress = addressFromSingle(foreignContractAddress);
317
357
  const startStorageSlot = fromSingle(foreignStartStorageSlot);
318
- const blockNumber = fromSingle(foreignBlockNumber).toNumber();
319
358
  const numberOfElements = fromSingle(foreignNumberOfElements).toNumber();
320
359
 
321
360
  const values = await this.handlerAsUtility().utilityStorageRead(
361
+ blockHash,
322
362
  contractAddress,
323
363
  startStorageSlot,
324
- blockNumber,
325
364
  numberOfElements,
326
365
  );
327
366
 
328
367
  return toForeignCallResult([toArray(values)]);
329
368
  }
330
369
 
331
- async utilityGetPublicDataWitness(foreignBlockNumber: ForeignCallSingle, foreignLeafSlot: ForeignCallSingle) {
332
- const blockNumber = fromSingle(foreignBlockNumber).toNumber();
370
+ async utilityGetPublicDataWitness(foreignBlockHash: ForeignCallSingle, foreignLeafSlot: ForeignCallSingle) {
371
+ const blockHash = L2BlockHash.fromString(foreignBlockHash);
333
372
  const leafSlot = fromSingle(foreignLeafSlot);
334
373
 
335
- const witness = await this.handlerAsUtility().utilityGetPublicDataWitness(blockNumber, leafSlot);
374
+ const witness = await this.handlerAsUtility().utilityGetPublicDataWitness(blockHash, leafSlot);
336
375
 
337
376
  if (!witness) {
338
- throw new Error(`Public data witness not found for slot ${leafSlot} at block ${blockNumber}.`);
377
+ throw new Error(`Public data witness not found for slot ${leafSlot} at block ${blockHash.toString()}.`);
339
378
  }
340
379
  return toForeignCallResult(witness.toNoirRepresentation());
341
380
  }
342
381
 
343
382
  async utilityGetNotes(
383
+ foreignOwnerIsSome: ForeignCallSingle,
384
+ foreignOwnerValue: ForeignCallSingle,
344
385
  foreignStorageSlot: ForeignCallSingle,
345
386
  foreignNumSelects: ForeignCallSingle,
346
387
  foreignSelectByIndexes: ForeignCallArray,
@@ -356,8 +397,12 @@ export class RPCTranslator {
356
397
  foreignOffset: ForeignCallSingle,
357
398
  foreignStatus: ForeignCallSingle,
358
399
  foreignMaxNotes: ForeignCallSingle,
359
- foreignPackedRetrievedNoteLength: ForeignCallSingle,
400
+ foreignPackedHintedNoteLength: ForeignCallSingle,
360
401
  ) {
402
+ // Parse Option<AztecAddress>: ownerIsSome is 0 for None, 1 for Some
403
+ const owner = fromSingle(foreignOwnerIsSome).toBool()
404
+ ? AztecAddress.fromField(fromSingle(foreignOwnerValue))
405
+ : undefined;
361
406
  const storageSlot = fromSingle(foreignStorageSlot);
362
407
  const numSelects = fromSingle(foreignNumSelects).toNumber();
363
408
  const selectByIndexes = fromArray(foreignSelectByIndexes).map(fr => fr.toNumber());
@@ -373,9 +418,10 @@ export class RPCTranslator {
373
418
  const offset = fromSingle(foreignOffset).toNumber();
374
419
  const status = fromSingle(foreignStatus).toNumber();
375
420
  const maxNotes = fromSingle(foreignMaxNotes).toNumber();
376
- const packedRetrievedNoteLength = fromSingle(foreignPackedRetrievedNoteLength).toNumber();
421
+ const packedHintedNoteLength = fromSingle(foreignPackedHintedNoteLength).toNumber();
377
422
 
378
423
  const noteDatas = await this.handlerAsUtility().utilityGetNotes(
424
+ owner,
379
425
  storageSlot,
380
426
  numSelects,
381
427
  selectByIndexes,
@@ -392,7 +438,17 @@ export class RPCTranslator {
392
438
  status,
393
439
  );
394
440
 
395
- const returnDataAsArrayOfArrays = noteDatas.map(packAsRetrievedNote);
441
+ const returnDataAsArrayOfArrays = noteDatas.map(noteData =>
442
+ packAsHintedNote({
443
+ contractAddress: noteData.contractAddress,
444
+ owner: noteData.owner,
445
+ randomness: noteData.randomness,
446
+ storageSlot: noteData.storageSlot,
447
+ noteNonce: noteData.noteNonce,
448
+ isPending: noteData.isPending,
449
+ note: noteData.note,
450
+ }),
451
+ );
396
452
 
397
453
  // Now we convert each sub-array to an array of ForeignCallSingles
398
454
  const returnDataAsArrayOfForeignCallSingleArrays = returnDataAsArrayOfArrays.map(subArray =>
@@ -401,28 +457,36 @@ export class RPCTranslator {
401
457
 
402
458
  // At last we convert the array of arrays to a bounded vec of arrays
403
459
  return toForeignCallResult(
404
- arrayOfArraysToBoundedVecOfArrays(
405
- returnDataAsArrayOfForeignCallSingleArrays,
406
- maxNotes,
407
- packedRetrievedNoteLength,
408
- ),
460
+ arrayOfArraysToBoundedVecOfArrays(returnDataAsArrayOfForeignCallSingleArrays, maxNotes, packedHintedNoteLength),
409
461
  );
410
462
  }
411
463
 
412
464
  privateNotifyCreatedNote(
465
+ foreignOwner: ForeignCallSingle,
413
466
  foreignStorageSlot: ForeignCallSingle,
467
+ foreignRandomness: ForeignCallSingle,
414
468
  foreignNoteTypeId: ForeignCallSingle,
415
469
  foreignNote: ForeignCallArray,
416
470
  foreignNoteHash: ForeignCallSingle,
417
471
  foreignCounter: ForeignCallSingle,
418
472
  ) {
473
+ const owner = addressFromSingle(foreignOwner);
419
474
  const storageSlot = fromSingle(foreignStorageSlot);
475
+ const randomness = fromSingle(foreignRandomness);
420
476
  const noteTypeId = NoteSelector.fromField(fromSingle(foreignNoteTypeId));
421
477
  const note = fromArray(foreignNote);
422
478
  const noteHash = fromSingle(foreignNoteHash);
423
479
  const counter = fromSingle(foreignCounter).toNumber();
424
480
 
425
- this.handlerAsPrivate().privateNotifyCreatedNote(storageSlot, noteTypeId, note, noteHash, counter);
481
+ this.handlerAsPrivate().privateNotifyCreatedNote(
482
+ owner,
483
+ storageSlot,
484
+ randomness,
485
+ noteTypeId,
486
+ note,
487
+ noteHash,
488
+ counter,
489
+ );
426
490
 
427
491
  return toForeignCallResult([]);
428
492
  }
@@ -501,17 +565,14 @@ export class RPCTranslator {
501
565
  );
502
566
  }
503
567
 
504
- async utilityGetNullifierMembershipWitness(
505
- foreignBlockNumber: ForeignCallSingle,
506
- foreignNullifier: ForeignCallSingle,
507
- ) {
508
- const blockNumber = fromSingle(foreignBlockNumber).toNumber();
568
+ async utilityGetNullifierMembershipWitness(foreignBlockHash: ForeignCallSingle, foreignNullifier: ForeignCallSingle) {
569
+ const blockHash = L2BlockHash.fromString(foreignBlockHash);
509
570
  const nullifier = fromSingle(foreignNullifier);
510
571
 
511
- const witness = await this.handlerAsUtility().utilityGetNullifierMembershipWitness(blockNumber, nullifier);
572
+ const witness = await this.handlerAsUtility().utilityGetNullifierMembershipWitness(blockHash, nullifier);
512
573
 
513
574
  if (!witness) {
514
- throw new Error(`Nullifier membership witness not found at block ${blockNumber}.`);
575
+ throw new Error(`Nullifier membership witness not found at block ${blockHash}.`);
515
576
  }
516
577
  return toForeignCallResult(witness.toNoirRepresentation());
517
578
  }
@@ -549,14 +610,20 @@ export class RPCTranslator {
549
610
  throw new Error('Enqueueing public calls is not supported in TestEnvironment::private_context');
550
611
  }
551
612
 
552
- async utilityGetUtilityContext() {
553
- const context = await this.handlerAsUtility().utilityGetUtilityContext();
613
+ public async privateIsSideEffectCounterRevertible(foreignSideEffectCounter: ForeignCallSingle) {
614
+ const sideEffectCounter = fromSingle(foreignSideEffectCounter).toNumber();
615
+ const isRevertible = await this.handlerAsPrivate().privateIsSideEffectCounterRevertible(sideEffectCounter);
616
+ return toForeignCallResult([toSingle(new Fr(isRevertible))]);
617
+ }
618
+
619
+ utilityGetUtilityContext() {
620
+ const context = this.handlerAsUtility().utilityGetUtilityContext();
554
621
 
555
622
  return toForeignCallResult(context.toNoirRepresentation());
556
623
  }
557
624
 
558
625
  async utilityGetBlockHeader(foreignBlockNumber: ForeignCallSingle) {
559
- const blockNumber = fromSingle(foreignBlockNumber).toNumber();
626
+ const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
560
627
 
561
628
  const header = await this.handlerAsUtility().utilityGetBlockHeader(blockNumber);
562
629
 
@@ -567,35 +634,35 @@ export class RPCTranslator {
567
634
  }
568
635
 
569
636
  async utilityGetMembershipWitness(
570
- foreignBlockNumber: ForeignCallSingle,
637
+ foreignBlockHash: ForeignCallSingle,
571
638
  foreignTreeId: ForeignCallSingle,
572
639
  foreignLeafValue: ForeignCallSingle,
573
640
  ) {
574
- const blockNumber = fromSingle(foreignBlockNumber).toNumber();
641
+ const blockHash = L2BlockHash.fromString(foreignBlockHash);
575
642
  const treeId = fromSingle(foreignTreeId).toNumber();
576
643
  const leafValue = fromSingle(foreignLeafValue);
577
644
 
578
- const witness = await this.handlerAsUtility().utilityGetMembershipWitness(blockNumber, treeId, leafValue);
645
+ const witness = await this.handlerAsUtility().utilityGetMembershipWitness(blockHash, treeId, leafValue);
579
646
 
580
647
  if (!witness) {
581
648
  throw new Error(
582
- `Membership witness in tree ${MerkleTreeId[treeId]} not found for value ${leafValue} at block ${blockNumber}.`,
649
+ `Membership witness in tree ${MerkleTreeId[treeId]} not found for value ${leafValue} at block ${blockHash}.`,
583
650
  );
584
651
  }
585
652
  return toForeignCallResult([toSingle(witness[0]), toArray(witness.slice(1))]);
586
653
  }
587
654
 
588
655
  async utilityGetLowNullifierMembershipWitness(
589
- foreignBlockNumber: ForeignCallSingle,
656
+ foreignBlockHash: ForeignCallSingle,
590
657
  foreignNullifier: ForeignCallSingle,
591
658
  ) {
592
- const blockNumber = fromSingle(foreignBlockNumber).toNumber();
659
+ const blockHash = L2BlockHash.fromString(foreignBlockHash);
593
660
  const nullifier = fromSingle(foreignNullifier);
594
661
 
595
- const witness = await this.handlerAsUtility().utilityGetLowNullifierMembershipWitness(blockNumber, nullifier);
662
+ const witness = await this.handlerAsUtility().utilityGetLowNullifierMembershipWitness(blockHash, nullifier);
596
663
 
597
664
  if (!witness) {
598
- throw new Error(`Low nullifier witness not found for nullifier ${nullifier} at block ${blockNumber}.`);
665
+ throw new Error(`Low nullifier witness not found for nullifier ${nullifier} at block ${blockHash}.`);
599
666
  }
600
667
  return toForeignCallResult(witness.toNoirRepresentation());
601
668
  }
@@ -921,7 +988,6 @@ export class RPCTranslator {
921
988
  foreignFrom: ForeignCallSingle,
922
989
  foreignTargetContractAddress: ForeignCallSingle,
923
990
  foreignFunctionSelector: ForeignCallSingle,
924
- _foreignArgsLength: ForeignCallSingle,
925
991
  foreignArgs: ForeignCallArray,
926
992
  foreignArgsHash: ForeignCallSingle,
927
993
  foreignIsStaticCall: ForeignCallSingle,
@@ -948,7 +1014,6 @@ export class RPCTranslator {
948
1014
  async txeSimulateUtilityFunction(
949
1015
  foreignTargetContractAddress: ForeignCallSingle,
950
1016
  foreignFunctionSelector: ForeignCallSingle,
951
- _foreignArgsLength: ForeignCallSingle,
952
1017
  foreignArgs: ForeignCallArray,
953
1018
  ) {
954
1019
  const targetContractAddress = addressFromSingle(foreignTargetContractAddress);
@@ -967,7 +1032,6 @@ export class RPCTranslator {
967
1032
  async txePublicCallNewFlow(
968
1033
  foreignFrom: ForeignCallSingle,
969
1034
  foreignAddress: ForeignCallSingle,
970
- _foreignLength: ForeignCallSingle,
971
1035
  foreignCalldata: ForeignCallArray,
972
1036
  foreignIsStaticCall: ForeignCallSingle,
973
1037
  ) {
@@ -1,151 +1,99 @@
1
- import { ArchiverStoreHelper, KVArchiverDataStore, type PublishedL2Block } from '@aztec/archiver';
1
+ import { ArchiverDataSourceBase, ArchiverDataStoreUpdater, KVArchiverDataStore } from '@aztec/archiver';
2
2
  import { GENESIS_ARCHIVE_ROOT } from '@aztec/constants';
3
+ import { CheckpointNumber, type EpochNumber, type 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';
5
6
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
6
- import type { AztecAddress } from '@aztec/stdlib/aztec-address';
7
- import type { L2Block, L2BlockSource, L2Tips, ValidateBlockResult } from '@aztec/stdlib/block';
8
- import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
7
+ import type { CheckpointId, L2BlockId, L2TipId, L2Tips, ValidateCheckpointResult } from '@aztec/stdlib/block';
8
+ import type { PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
9
9
  import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
10
- import type { BlockHeader } from '@aztec/stdlib/tx';
11
- import type { UInt64 } from '@aztec/stdlib/types';
12
10
 
13
- // We are extending the ArchiverDataStoreHelper here because it provides most of the endpoints needed by the
14
- // node for reading from and writing to state, without needing any of the extra overhead that the Archiver itself
15
- // requires (i.e. an L1 client)
16
- export class TXEArchiver extends ArchiverStoreHelper implements L2BlockSource {
11
+ /**
12
+ * TXE Archiver implementation.
13
+ * Provides most of the endpoints needed by the node for reading from and writing to state,
14
+ * without needing any of the extra overhead that the Archiver itself requires (i.e. an L1 client).
15
+ */
16
+ export class TXEArchiver extends ArchiverDataSourceBase {
17
+ private readonly updater = new ArchiverDataStoreUpdater(this.store);
18
+
17
19
  constructor(db: AztecAsyncKVStore) {
18
- super(new KVArchiverDataStore(db, 9999));
20
+ const store = new KVArchiverDataStore(db, 9999);
21
+ super(store);
19
22
  }
20
23
 
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
- ]);
26
-
27
- return opResults.every(Boolean);
24
+ // TXE-specific method for adding checkpoints
25
+ public async addCheckpoints(checkpoints: PublishedCheckpoint[], result?: ValidateCheckpointResult): Promise<boolean> {
26
+ await this.updater.setNewCheckpointData(checkpoints, result);
27
+ return true;
28
28
  }
29
29
 
30
- /**
31
- * Gets the number of the latest L2 block processed by the block source implementation.
32
- * @returns The number of the latest L2 block processed by the block source implementation.
33
- */
34
- public getBlockNumber(): Promise<number> {
35
- return this.store.getSynchedL2BlockNumber();
36
- }
30
+ // Abstract method implementations
37
31
 
38
- /**
39
- * Gets the number of the latest L2 block proven seen by the block source implementation.
40
- * @returns The number of the latest L2 block proven seen by the block source implementation.
41
- */
42
- public getProvenBlockNumber(): Promise<number> {
43
- return this.store.getSynchedL2BlockNumber();
32
+ public getRollupAddress(): Promise<EthAddress> {
33
+ throw new Error('TXE Archiver does not implement "getRollupAddress"');
44
34
  }
45
35
 
46
- /**
47
- * Gets a published l2 block. If a negative number is passed, the block returned is the most recent.
48
- * @param number - The block number to return (inclusive).
49
- * @returns The requested L2 block.
50
- */
51
- public override async getPublishedBlock(number: number): Promise<PublishedL2Block | undefined> {
52
- // If the number provided is -ve, then return the latest block.
53
- if (number < 0) {
54
- number = await this.store.getSynchedL2BlockNumber();
55
- }
56
- if (number == 0) {
57
- return undefined;
58
- }
59
- const blocks = await this.store.getPublishedBlocks(number, 1);
60
- return blocks.length === 0 ? undefined : blocks[0];
36
+ public getRegistryAddress(): Promise<EthAddress> {
37
+ throw new Error('TXE Archiver does not implement "getRegistryAddress"');
61
38
  }
62
39
 
63
- /**
64
- * Gets an l2 block. If a negative number is passed, the block returned is the most recent.
65
- * @param number - The block number to return (inclusive).
66
- * @returns The requested L2 block.
67
- */
68
- public getBlock(number: number | 'latest'): Promise<L2Block | undefined> {
69
- return this.getPublishedBlock(number != 'latest' ? number : -1).then(block => block?.block);
40
+ public getL1Constants(): Promise<L1RollupConstants> {
41
+ throw new Error('TXE Archiver does not implement "getL1Constants"');
70
42
  }
71
43
 
72
- /**
73
- * Gets an l2 block header.
74
- * @param number - The block number to return or 'latest' for the most recent one.
75
- * @returns The requested L2 block header.
76
- */
77
- public async getBlockHeader(number: number | 'latest'): Promise<BlockHeader | undefined> {
78
- if (number === 'latest') {
79
- number = await this.store.getSynchedL2BlockNumber();
80
- }
81
- if (number === 0) {
82
- return undefined;
83
- }
84
- const headers = await this.store.getBlockHeaders(number, 1);
85
- return headers.length === 0 ? undefined : headers[0];
44
+ public getGenesisValues(): Promise<{ genesisArchiveRoot: Fr }> {
45
+ return Promise.resolve({ genesisArchiveRoot: new Fr(GENESIS_ARCHIVE_ROOT) });
86
46
  }
87
47
 
88
- public getBlocks(from: number, limit: number, _proven?: boolean): Promise<L2Block[]> {
89
- return this.getPublishedBlocks(from, limit).then(blocks => blocks.map(b => b.block));
48
+ public getL1Timestamp(): Promise<bigint | undefined> {
49
+ throw new Error('TXE Archiver does not implement "getL1Timestamp"');
90
50
  }
91
51
 
92
- public getL2SlotNumber(): Promise<bigint> {
52
+ public async getL2Tips(): Promise<L2Tips> {
53
+ // In TXE there is no possibility of reorgs and no blocks are ever getting proven so we just set 'latest', 'proven'
54
+ // and 'finalized' to the latest block.
55
+ const blockHeader = await this.getBlockHeader('latest');
56
+ if (!blockHeader) {
57
+ throw new Error('L2Tips requested from TXE Archiver but no block header found');
58
+ }
59
+
60
+ const number = blockHeader.globalVariables.blockNumber;
61
+ const hash = (await blockHeader.hash()).toString();
62
+ const checkpointedBlock = await this.getCheckpointedBlock(number);
63
+ if (!checkpointedBlock) {
64
+ throw new Error(`L2Tips requested from TXE Archiver but no checkpointed block found for block number ${number}`);
65
+ }
66
+ const checkpoint = await this.store.getRangeOfCheckpoints(CheckpointNumber(number), 1);
67
+ if (checkpoint.length === 0) {
68
+ throw new Error(`L2Tips requested from TXE Archiver but no checkpoint found for block number ${number}`);
69
+ }
70
+ const blockId: L2BlockId = { number, hash };
71
+ const checkpointId: CheckpointId = {
72
+ number: checkpoint[0].checkpointNumber,
73
+ hash: checkpoint[0].header.hash().toString(),
74
+ };
75
+ const tipId: L2TipId = { block: blockId, checkpoint: checkpointId };
76
+ return {
77
+ proposed: blockId,
78
+ proven: tipId,
79
+ finalized: tipId,
80
+ checkpointed: tipId,
81
+ };
82
+ }
83
+
84
+ public getL2SlotNumber(): Promise<SlotNumber | undefined> {
93
85
  throw new Error('TXE Archiver does not implement "getL2SlotNumber"');
94
86
  }
95
87
 
96
- public getL2EpochNumber(): Promise<bigint> {
88
+ public getL2EpochNumber(): Promise<EpochNumber | undefined> {
97
89
  throw new Error('TXE Archiver does not implement "getL2EpochNumber"');
98
90
  }
99
91
 
100
- public getBlocksForEpoch(_epochNumber: bigint): Promise<L2Block[]> {
101
- throw new Error('TXE Archiver does not implement "getBlocksForEpoch"');
102
- }
103
-
104
- public getBlockHeadersForEpoch(_epochNumber: bigint): Promise<BlockHeader[]> {
105
- throw new Error('TXE Archiver does not implement "getBlockHeadersForEpoch"');
106
- }
107
-
108
- public isEpochComplete(_epochNumber: bigint): Promise<boolean> {
92
+ public isEpochComplete(_epochNumber: EpochNumber): Promise<boolean> {
109
93
  throw new Error('TXE Archiver does not implement "isEpochComplete"');
110
94
  }
111
95
 
112
- public getL2Tips(): Promise<L2Tips> {
113
- throw new Error('TXE Archiver does not implement "getL2Tips"');
114
- }
115
-
116
- public getL1Constants(): Promise<L1RollupConstants> {
117
- throw new Error('TXE Archiver does not implement "getL2Constants"');
118
- }
119
-
120
- public getGenesisValues(): Promise<{ genesisArchiveRoot: Fr }> {
121
- return Promise.resolve({ genesisArchiveRoot: new Fr(GENESIS_ARCHIVE_ROOT) });
122
- }
123
-
124
96
  public syncImmediate(): Promise<void> {
125
97
  throw new Error('TXE Archiver does not implement "syncImmediate"');
126
98
  }
127
-
128
- public getContract(_address: AztecAddress, _timestamp?: UInt64): Promise<ContractInstanceWithAddress | undefined> {
129
- throw new Error('TXE Archiver does not implement "getContract"');
130
- }
131
-
132
- public getRollupAddress(): Promise<EthAddress> {
133
- throw new Error('TXE Archiver does not implement "getRollupAddress"');
134
- }
135
-
136
- public getRegistryAddress(): Promise<EthAddress> {
137
- throw new Error('TXE Archiver does not implement "getRegistryAddress"');
138
- }
139
-
140
- public getL1Timestamp(): Promise<bigint> {
141
- throw new Error('TXE Archiver does not implement "getL1Timestamp"');
142
- }
143
-
144
- public isPendingChainInvalid(): Promise<boolean> {
145
- return Promise.resolve(false);
146
- }
147
-
148
- public override getPendingChainValidationStatus(): Promise<ValidateBlockResult> {
149
- return Promise.resolve({ valid: true });
150
- }
151
99
  }
@@ -1,8 +1,10 @@
1
+ import type { SlotNumber } from '@aztec/foundation/branded-types';
1
2
  import type {
2
3
  AuthRequest,
3
4
  ENR,
4
5
  P2P,
5
6
  P2PBlockReceivedCallback,
7
+ P2PCheckpointReceivedCallback,
6
8
  P2PConfig,
7
9
  P2PSyncState,
8
10
  PeerId,
@@ -13,7 +15,7 @@ import type {
13
15
  } from '@aztec/p2p';
14
16
  import type { EthAddress, L2BlockStreamEvent, L2Tips } from '@aztec/stdlib/block';
15
17
  import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
16
- import type { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
18
+ import type { BlockProposal, CheckpointAttestation, CheckpointProposal } from '@aztec/stdlib/p2p';
17
19
  import type { Tx, TxHash } from '@aztec/stdlib/tx';
18
20
 
19
21
  export class DummyP2P implements P2P {
@@ -41,10 +43,22 @@ export class DummyP2P implements P2P {
41
43
  throw new Error('DummyP2P does not implement "broadcastProposal"');
42
44
  }
43
45
 
46
+ public broadcastCheckpointProposal(_proposal: CheckpointProposal): Promise<void> {
47
+ throw new Error('DummyP2P does not implement "broadcastCheckpointProposal"');
48
+ }
49
+
50
+ public broadcastCheckpointAttestations(_attestations: CheckpointAttestation[]): Promise<void> {
51
+ throw new Error('DummyP2P does not implement "broadcastCheckpointAttestations"');
52
+ }
53
+
44
54
  public registerBlockProposalHandler(_handler: P2PBlockReceivedCallback): void {
45
55
  throw new Error('DummyP2P does not implement "registerBlockProposalHandler"');
46
56
  }
47
57
 
58
+ public registerCheckpointProposalHandler(_handler: P2PCheckpointReceivedCallback): void {
59
+ throw new Error('DummyP2P does not implement "registerCheckpointProposalHandler"');
60
+ }
61
+
48
62
  public requestTxs(_txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
49
63
  throw new Error('DummyP2P does not implement "requestTxs"');
50
64
  }
@@ -74,7 +88,9 @@ export class DummyP2P implements P2P {
74
88
  }
75
89
 
76
90
  public getTxStatus(_txHash: TxHash): Promise<'pending' | 'mined' | undefined> {
77
- throw new Error('DummyP2P does not implement "getTxStatus"');
91
+ // In TXE there is no concept of transactions but we need to implement this because of tagging. We return 'mined'
92
+ // tx status for any tx hash.
93
+ return Promise.resolve('mined');
78
94
  }
79
95
 
80
96
  public iteratePendingTxs(): AsyncIterableIterator<Tx> {
@@ -113,16 +129,12 @@ export class DummyP2P implements P2P {
113
129
  throw new Error('DummyP2P does not implement "getTxsByHash"');
114
130
  }
115
131
 
116
- public getAttestationsForSlot(_slot: bigint, _proposalId?: string): Promise<BlockAttestation[]> {
117
- throw new Error('DummyP2P does not implement "getAttestationForSlot"');
118
- }
119
-
120
- public deleteAttestation(_attestation: BlockAttestation): Promise<void> {
121
- return Promise.resolve();
132
+ public getCheckpointAttestationsForSlot(_slot: SlotNumber, _proposalId?: string): Promise<CheckpointAttestation[]> {
133
+ throw new Error('DummyP2P does not implement "getCheckpointAttestationsForSlot"');
122
134
  }
123
135
 
124
- public addAttestations(_attestations: BlockAttestation[]): Promise<void> {
125
- throw new Error('DummyP2P does not implement "addAttestations"');
136
+ public addCheckpointAttestations(_attestations: CheckpointAttestation[]): Promise<void> {
137
+ throw new Error('DummyP2P does not implement "addCheckpointAttestations"');
126
138
  }
127
139
 
128
140
  public getL2BlockHash(_number: number): Promise<string | undefined> {