@aztec/txe 0.0.1-commit.8afd444 → 0.0.1-commit.8f9871590

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 (33) hide show
  1. package/dest/oracle/txe_oracle_top_level_context.d.ts +2 -2
  2. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  3. package/dest/oracle/txe_oracle_top_level_context.js +79 -21
  4. package/dest/rpc_translator.d.ts +4 -4
  5. package/dest/rpc_translator.d.ts.map +1 -1
  6. package/dest/rpc_translator.js +3 -3
  7. package/dest/state_machine/archiver.d.ts +1 -1
  8. package/dest/state_machine/archiver.d.ts.map +1 -1
  9. package/dest/state_machine/archiver.js +2 -0
  10. package/dest/state_machine/dummy_p2p_client.d.ts +11 -8
  11. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  12. package/dest/state_machine/dummy_p2p_client.js +21 -12
  13. package/dest/state_machine/index.d.ts +5 -5
  14. package/dest/state_machine/index.d.ts.map +1 -1
  15. package/dest/state_machine/index.js +14 -9
  16. package/dest/state_machine/mock_epoch_cache.d.ts +3 -1
  17. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  18. package/dest/state_machine/mock_epoch_cache.js +4 -0
  19. package/dest/txe_session.d.ts +1 -1
  20. package/dest/txe_session.d.ts.map +1 -1
  21. package/dest/txe_session.js +67 -8
  22. package/dest/utils/block_creation.d.ts +1 -1
  23. package/dest/utils/block_creation.d.ts.map +1 -1
  24. package/dest/utils/block_creation.js +3 -1
  25. package/package.json +15 -15
  26. package/src/oracle/txe_oracle_top_level_context.ts +70 -72
  27. package/src/rpc_translator.ts +3 -3
  28. package/src/state_machine/archiver.ts +2 -0
  29. package/src/state_machine/dummy_p2p_client.ts +29 -15
  30. package/src/state_machine/index.ts +24 -9
  31. package/src/state_machine/mock_epoch_cache.ts +5 -0
  32. package/src/txe_session.ts +63 -53
  33. package/src/utils/block_creation.ts +3 -1
@@ -6,6 +6,8 @@ import type {
6
6
  P2PBlockReceivedCallback,
7
7
  P2PCheckpointReceivedCallback,
8
8
  P2PConfig,
9
+ P2PDuplicateAttestationCallback,
10
+ P2PDuplicateProposalCallback,
9
11
  P2PSyncState,
10
12
  PeerId,
11
13
  ReqRespSubProtocol,
@@ -16,7 +18,7 @@ import type {
16
18
  import type { EthAddress, L2BlockStreamEvent, L2Tips } from '@aztec/stdlib/block';
17
19
  import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
18
20
  import type { BlockProposal, CheckpointAttestation, CheckpointProposal } from '@aztec/stdlib/p2p';
19
- import type { Tx, TxHash } from '@aztec/stdlib/tx';
21
+ import type { BlockHeader, Tx, TxHash } from '@aztec/stdlib/tx';
20
22
 
21
23
  export class DummyP2P implements P2P {
22
24
  public validate(_txs: Tx[]): Promise<void> {
@@ -71,8 +73,8 @@ export class DummyP2P implements P2P {
71
73
  throw new Error('DummyP2P does not implement "sendTx"');
72
74
  }
73
75
 
74
- public deleteTxs(_txHashes: TxHash[]): Promise<void> {
75
- throw new Error('DummyP2P does not implement "deleteTxs"');
76
+ public handleFailedExecution(_txHashes: TxHash[]): Promise<void> {
77
+ throw new Error('DummyP2P does not implement "handleFailedExecution"');
76
78
  }
77
79
 
78
80
  public getTxByHashFromPool(_txHash: TxHash): Promise<Tx | undefined> {
@@ -97,6 +99,10 @@ export class DummyP2P implements P2P {
97
99
  throw new Error('DummyP2P does not implement "iteratePendingTxs"');
98
100
  }
99
101
 
102
+ public iterateEligiblePendingTxs(): AsyncIterableIterator<Tx> {
103
+ throw new Error('DummyP2P does not implement "iterateEligiblePendingTxs"');
104
+ }
105
+
100
106
  public getPendingTxCount(): Promise<number> {
101
107
  throw new Error('DummyP2P does not implement "getPendingTxCount"');
102
108
  }
@@ -133,8 +139,8 @@ export class DummyP2P implements P2P {
133
139
  throw new Error('DummyP2P does not implement "getCheckpointAttestationsForSlot"');
134
140
  }
135
141
 
136
- public addCheckpointAttestations(_attestations: CheckpointAttestation[]): Promise<void> {
137
- throw new Error('DummyP2P does not implement "addCheckpointAttestations"');
142
+ public addOwnCheckpointAttestations(_attestations: CheckpointAttestation[]): Promise<void> {
143
+ throw new Error('DummyP2P does not implement "addOwnCheckpointAttestations"');
138
144
  }
139
145
 
140
146
  public getL2BlockHash(_number: number): Promise<string | undefined> {
@@ -157,14 +163,6 @@ export class DummyP2P implements P2P {
157
163
  throw new Error('DummyP2P does not implement "sync"');
158
164
  }
159
165
 
160
- public requestTxsByHash(_txHashes: TxHash[]): Promise<Tx[]> {
161
- throw new Error('DummyP2P does not implement "requestTxsByHash"');
162
- }
163
-
164
- public getTxs(_filter: 'all' | 'pending' | 'mined'): Promise<Tx[]> {
165
- throw new Error('DummyP2P does not implement "getTxs"');
166
- }
167
-
168
166
  public getTxsByHashFromPool(_txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
169
167
  throw new Error('DummyP2P does not implement "getTxsByHashFromPool"');
170
168
  }
@@ -189,8 +187,12 @@ export class DummyP2P implements P2P {
189
187
  throw new Error('DummyP2P does not implement "getSyncedLatestSlot"');
190
188
  }
191
189
 
192
- markTxsAsNonEvictable(_: TxHash[]): Promise<void> {
193
- throw new Error('DummyP2P does not implement "markTxsAsNonEvictable".');
190
+ protectTxs(_txHashes: TxHash[], _blockHeader: BlockHeader): Promise<TxHash[]> {
191
+ throw new Error('DummyP2P does not implement "protectTxs".');
192
+ }
193
+
194
+ prepareForSlot(_slotNumber: SlotNumber): Promise<void> {
195
+ return Promise.resolve();
194
196
  }
195
197
 
196
198
  addReqRespSubProtocol(
@@ -206,4 +208,16 @@ export class DummyP2P implements P2P {
206
208
 
207
209
  //This is no-op
208
210
  public registerThisValidatorAddresses(_address: EthAddress[]): void {}
211
+
212
+ public registerDuplicateProposalCallback(_callback: P2PDuplicateProposalCallback): void {
213
+ throw new Error('DummyP2P does not implement "registerDuplicateProposalCallback"');
214
+ }
215
+
216
+ public registerDuplicateAttestationCallback(_callback: P2PDuplicateAttestationCallback): void {
217
+ throw new Error('DummyP2P does not implement "registerDuplicateAttestationCallback"');
218
+ }
219
+
220
+ public hasBlockProposalsForSlot(_slot: SlotNumber): Promise<boolean> {
221
+ throw new Error('DummyP2P does not implement "hasBlockProposalsForSlot"');
222
+ }
209
223
  }
@@ -3,8 +3,7 @@ import { TestCircuitVerifier } from '@aztec/bb-prover/test';
3
3
  import { CheckpointNumber } from '@aztec/foundation/branded-types';
4
4
  import { Fr } from '@aztec/foundation/curves/bn254';
5
5
  import { createLogger } from '@aztec/foundation/log';
6
- import type { AztecAsyncKVStore } from '@aztec/kv-store';
7
- import { AnchorBlockStore } from '@aztec/pxe/server';
6
+ import { type AnchorBlockStore, type ContractStore, ContractSyncService, type NoteStore } from '@aztec/pxe/server';
8
7
  import { L2Block } from '@aztec/stdlib/block';
9
8
  import { Checkpoint, L1PublishedData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
10
9
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
@@ -26,13 +25,16 @@ export class TXEStateMachine {
26
25
  public synchronizer: TXESynchronizer,
27
26
  public archiver: TXEArchiver,
28
27
  public anchorBlockStore: AnchorBlockStore,
28
+ public contractSyncService: ContractSyncService,
29
29
  ) {}
30
30
 
31
- public static async create(db: AztecAsyncKVStore) {
32
- const archiver = new TXEArchiver(db);
31
+ public static async create(
32
+ archiver: TXEArchiver,
33
+ anchorBlockStore: AnchorBlockStore,
34
+ contractStore: ContractStore,
35
+ noteStore: NoteStore,
36
+ ) {
33
37
  const synchronizer = await TXESynchronizer.create();
34
- const anchorBlockStore = new AnchorBlockStore(db);
35
-
36
38
  const aztecNodeConfig = {} as AztecNodeConfig;
37
39
 
38
40
  const log = createLogger('txe_node');
@@ -58,11 +60,21 @@ export class TXEStateMachine {
58
60
  log,
59
61
  );
60
62
 
61
- return new this(node, synchronizer, archiver, anchorBlockStore);
63
+ const contractSyncService = new ContractSyncService(
64
+ node,
65
+ contractStore,
66
+ noteStore,
67
+ createLogger('txe:contract_sync'),
68
+ );
69
+
70
+ return new this(node, synchronizer, archiver, anchorBlockStore, contractSyncService);
62
71
  }
63
72
 
64
73
  public async handleL2Block(block: L2Block) {
65
- // Create a checkpoint from the block manually
74
+ // Create a checkpoint from the block manually.
75
+ // TXE uses 1-block-per-checkpoint for testing simplicity, so we can use block number as checkpoint number.
76
+ // This uses the deprecated fromBlockNumber method intentionally for the TXE testing environment.
77
+ const checkpointNumber = CheckpointNumber.fromBlockNumber(block.number);
66
78
  const checkpoint = new Checkpoint(
67
79
  block.archive,
68
80
  CheckpointHeader.from({
@@ -79,7 +91,7 @@ export class TXEStateMachine {
79
91
  totalManaUsed: block.header.totalManaUsed,
80
92
  }),
81
93
  [block],
82
- CheckpointNumber.fromBlockNumber(block.number),
94
+ checkpointNumber,
83
95
  );
84
96
 
85
97
  const publishedCheckpoint = new PublishedCheckpoint(
@@ -91,6 +103,9 @@ export class TXEStateMachine {
91
103
  ),
92
104
  [],
93
105
  );
106
+ // Wipe contract sync cache when anchor block changes (mirrors BlockSynchronizer behavior)
107
+ this.contractSyncService.wipe();
108
+
94
109
  await Promise.all([
95
110
  this.synchronizer.handleL2Block(block),
96
111
  this.archiver.addCheckpoints([publishedCheckpoint], undefined),
@@ -1,6 +1,7 @@
1
1
  import type { EpochAndSlot, EpochCacheInterface, EpochCommitteeInfo, SlotTag } from '@aztec/epoch-cache';
2
2
  import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
3
3
  import { EthAddress } from '@aztec/foundation/eth-address';
4
+ import { EmptyL1RollupConstants, type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
4
5
 
5
6
  /**
6
7
  * Mock implementation of the EpochCacheInterface used to satisfy dependencies of AztecNodeService.
@@ -64,4 +65,8 @@ export class MockEpochCache implements EpochCacheInterface {
64
65
  filterInCommittee(_slot: SlotTag, _validators: EthAddress[]): Promise<EthAddress[]> {
65
66
  return Promise.resolve([]);
66
67
  }
68
+
69
+ getL1Constants(): L1RollupConstants {
70
+ return EmptyL1RollupConstants;
71
+ }
67
72
  }
@@ -4,8 +4,10 @@ import { type Logger, createLogger } from '@aztec/foundation/log';
4
4
  import { KeyStore } from '@aztec/key-store';
5
5
  import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
6
6
  import type { ProtocolContract } from '@aztec/protocol-contracts';
7
+ import type { AccessScopes } from '@aztec/pxe/client/lazy';
7
8
  import {
8
9
  AddressStore,
10
+ AnchorBlockStore,
9
11
  CapsuleStore,
10
12
  JobCoordinator,
11
13
  NoteService,
@@ -49,6 +51,7 @@ import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfac
49
51
  import { TXEOraclePublicContext } from './oracle/txe_oracle_public_context.js';
50
52
  import { TXEOracleTopLevelContext } from './oracle/txe_oracle_top_level_context.js';
51
53
  import { RPCTranslator } from './rpc_translator.js';
54
+ import { TXEArchiver } from './state_machine/archiver.js';
52
55
  import { TXEStateMachine } from './state_machine/index.js';
53
56
  import type { ForeignCallArgs, ForeignCallResult } from './util/encoding.js';
54
57
  import { TXEAccountStore } from './util/txe_account_store.js';
@@ -176,7 +179,9 @@ export class TXESession implements TXESessionStateHandler {
176
179
  await contractStore.addContractInstance(instance);
177
180
  }
178
181
 
179
- const stateMachine = await TXEStateMachine.create(store);
182
+ const archiver = new TXEArchiver(store);
183
+ const anchorBlockStore = new AnchorBlockStore(store);
184
+ const stateMachine = await TXEStateMachine.create(archiver, anchorBlockStore, contractStore, noteStore);
180
185
 
181
186
  const nextBlockTimestamp = BigInt(Math.floor(new Date().getTime() / 1000));
182
187
  const version = new Fr(await stateMachine.node.getVersion());
@@ -319,6 +324,7 @@ export class TXESession implements TXESessionStateHandler {
319
324
 
320
325
  await new NoteService(this.noteStore, this.stateMachine.node, anchorBlock!, this.currentJobId).syncNoteNullifiers(
321
326
  contractAddress,
327
+ 'ALL_SCOPES',
322
328
  );
323
329
  const latestBlock = await this.stateMachine.node.getBlockHeader('latest');
324
330
 
@@ -335,29 +341,31 @@ export class TXESession implements TXESessionStateHandler {
335
341
  const taggingIndexCache = new ExecutionTaggingIndexCache();
336
342
 
337
343
  const utilityExecutor = this.utilityExecutorForContractSync(anchorBlock);
338
- this.oracleHandler = new PrivateExecutionOracle(
339
- Fr.ZERO,
340
- new TxContext(this.chainId, this.version, GasSettings.empty()),
341
- new CallContext(AztecAddress.ZERO, contractAddress, FunctionSelector.empty(), false),
342
- anchorBlock!,
344
+ this.oracleHandler = new PrivateExecutionOracle({
345
+ argsHash: Fr.ZERO,
346
+ txContext: new TxContext(this.chainId, this.version, GasSettings.empty()),
347
+ callContext: new CallContext(AztecAddress.ZERO, contractAddress, FunctionSelector.empty(), false),
348
+ anchorBlockHeader: anchorBlock!,
343
349
  utilityExecutor,
344
- [],
345
- [],
346
- new HashedValuesCache(),
350
+ authWitnesses: [],
351
+ capsules: [],
352
+ executionCache: new HashedValuesCache(),
347
353
  noteCache,
348
354
  taggingIndexCache,
349
- this.contractStore,
350
- this.noteStore,
351
- this.keyStore,
352
- this.addressStore,
353
- this.stateMachine.node,
354
- this.senderTaggingStore,
355
- this.recipientTaggingStore,
356
- this.senderAddressBookStore,
357
- this.capsuleStore,
358
- this.privateEventStore,
359
- this.currentJobId,
360
- );
355
+ contractStore: this.contractStore,
356
+ noteStore: this.noteStore,
357
+ keyStore: this.keyStore,
358
+ addressStore: this.addressStore,
359
+ aztecNode: this.stateMachine.node,
360
+ senderTaggingStore: this.senderTaggingStore,
361
+ recipientTaggingStore: this.recipientTaggingStore,
362
+ senderAddressBookStore: this.senderAddressBookStore,
363
+ capsuleStore: this.capsuleStore,
364
+ privateEventStore: this.privateEventStore,
365
+ contractSyncService: this.stateMachine.contractSyncService,
366
+ jobId: this.currentJobId,
367
+ scopes: 'ALL_SCOPES',
368
+ });
361
369
 
362
370
  // We store the note and tagging index caches fed into the PrivateExecutionOracle (along with some other auxiliary
363
371
  // data) in order to refer to it later, mimicking the way this object is used by the ContractFunctionSimulator. The
@@ -409,24 +417,25 @@ export class TXESession implements TXESessionStateHandler {
409
417
  this.stateMachine.node,
410
418
  anchorBlockHeader,
411
419
  this.currentJobId,
412
- ).syncNoteNullifiers(contractAddress);
420
+ ).syncNoteNullifiers(contractAddress, 'ALL_SCOPES');
413
421
 
414
- this.oracleHandler = new UtilityExecutionOracle(
422
+ this.oracleHandler = new UtilityExecutionOracle({
415
423
  contractAddress,
416
- [],
417
- [],
424
+ authWitnesses: [],
425
+ capsules: [],
418
426
  anchorBlockHeader,
419
- this.contractStore,
420
- this.noteStore,
421
- this.keyStore,
422
- this.addressStore,
423
- this.stateMachine.node,
424
- this.recipientTaggingStore,
425
- this.senderAddressBookStore,
426
- this.capsuleStore,
427
- this.privateEventStore,
428
- this.currentJobId,
429
- );
427
+ contractStore: this.contractStore,
428
+ noteStore: this.noteStore,
429
+ keyStore: this.keyStore,
430
+ addressStore: this.addressStore,
431
+ aztecNode: this.stateMachine.node,
432
+ recipientTaggingStore: this.recipientTaggingStore,
433
+ senderAddressBookStore: this.senderAddressBookStore,
434
+ capsuleStore: this.capsuleStore,
435
+ privateEventStore: this.privateEventStore,
436
+ jobId: this.currentJobId,
437
+ scopes: 'ALL_SCOPES',
438
+ });
430
439
 
431
440
  this.state = { name: 'UTILITY' };
432
441
  this.logger.debug(`Entered state ${this.state.name}`);
@@ -494,29 +503,30 @@ export class TXESession implements TXESessionStateHandler {
494
503
  }
495
504
 
496
505
  private utilityExecutorForContractSync(anchorBlock: any) {
497
- return async (call: FunctionCall) => {
506
+ return async (call: FunctionCall, scopes: AccessScopes) => {
498
507
  const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
499
508
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
500
509
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
501
510
  }
502
511
 
503
512
  try {
504
- const oracle = new UtilityExecutionOracle(
505
- call.to,
506
- [],
507
- [],
508
- anchorBlock!,
509
- this.contractStore,
510
- this.noteStore,
511
- this.keyStore,
512
- this.addressStore,
513
- this.stateMachine.node,
514
- this.recipientTaggingStore,
515
- this.senderAddressBookStore,
516
- this.capsuleStore,
517
- this.privateEventStore,
518
- this.currentJobId,
519
- );
513
+ const oracle = new UtilityExecutionOracle({
514
+ contractAddress: call.to,
515
+ authWitnesses: [],
516
+ capsules: [],
517
+ anchorBlockHeader: anchorBlock!,
518
+ contractStore: this.contractStore,
519
+ noteStore: this.noteStore,
520
+ keyStore: this.keyStore,
521
+ addressStore: this.addressStore,
522
+ aztecNode: this.stateMachine.node,
523
+ recipientTaggingStore: this.recipientTaggingStore,
524
+ senderAddressBookStore: this.senderAddressBookStore,
525
+ capsuleStore: this.capsuleStore,
526
+ privateEventStore: this.privateEventStore,
527
+ jobId: this.currentJobId,
528
+ scopes,
529
+ });
520
530
  await new WASMSimulator()
521
531
  .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
522
532
  .catch((err: Error) => {
@@ -87,7 +87,9 @@ export async function makeTXEBlock(
87
87
  const newArchiveInfo = await worldTrees.getTreeInfo(MerkleTreeId.ARCHIVE);
88
88
  const newArchive = new AppendOnlyTreeSnapshot(new Fr(newArchiveInfo.root), Number(newArchiveInfo.size));
89
89
 
90
- // L2Block requires checkpointNumber and indexWithinCheckpoint
90
+ // L2Block requires checkpointNumber and indexWithinCheckpoint.
91
+ // TXE uses 1-block-per-checkpoint for testing simplicity, so we can use block number as checkpoint number.
92
+ // This uses the deprecated fromBlockNumber method intentionally for the TXE testing environment.
91
93
  const checkpointNumber = CheckpointNumber.fromBlockNumber(globalVariables.blockNumber);
92
94
  const indexWithinCheckpoint = IndexWithinCheckpoint(0);
93
95