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

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 (56) hide show
  1. package/dest/constants.d.ts +3 -0
  2. package/dest/constants.d.ts.map +1 -0
  3. package/dest/constants.js +2 -0
  4. package/dest/oracle/interfaces.d.ts +3 -3
  5. package/dest/oracle/interfaces.d.ts.map +1 -1
  6. package/dest/oracle/txe_oracle_public_context.d.ts +3 -3
  7. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  8. package/dest/oracle/txe_oracle_public_context.js +6 -6
  9. package/dest/oracle/txe_oracle_top_level_context.d.ts +5 -3
  10. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  11. package/dest/oracle/txe_oracle_top_level_context.js +108 -33
  12. package/dest/rpc_translator.d.ts +20 -14
  13. package/dest/rpc_translator.d.ts.map +1 -1
  14. package/dest/rpc_translator.js +76 -51
  15. package/dest/state_machine/archiver.d.ts +20 -67
  16. package/dest/state_machine/archiver.d.ts.map +1 -1
  17. package/dest/state_machine/archiver.js +59 -178
  18. package/dest/state_machine/dummy_p2p_client.d.ts +18 -14
  19. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  20. package/dest/state_machine/dummy_p2p_client.js +35 -23
  21. package/dest/state_machine/global_variable_builder.d.ts +2 -2
  22. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  23. package/dest/state_machine/global_variable_builder.js +1 -1
  24. package/dest/state_machine/index.d.ts +5 -5
  25. package/dest/state_machine/index.d.ts.map +1 -1
  26. package/dest/state_machine/index.js +35 -12
  27. package/dest/state_machine/mock_epoch_cache.d.ts +9 -6
  28. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  29. package/dest/state_machine/mock_epoch_cache.js +14 -7
  30. package/dest/state_machine/synchronizer.d.ts +3 -3
  31. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  32. package/dest/txe_session.d.ts +6 -4
  33. package/dest/txe_session.d.ts.map +1 -1
  34. package/dest/txe_session.js +116 -22
  35. package/dest/util/encoding.d.ts +17 -17
  36. package/dest/utils/block_creation.d.ts +4 -4
  37. package/dest/utils/block_creation.d.ts.map +1 -1
  38. package/dest/utils/block_creation.js +18 -5
  39. package/dest/utils/tx_effect_creation.d.ts +2 -3
  40. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  41. package/dest/utils/tx_effect_creation.js +3 -6
  42. package/package.json +16 -16
  43. package/src/constants.ts +3 -0
  44. package/src/oracle/interfaces.ts +2 -2
  45. package/src/oracle/txe_oracle_public_context.ts +6 -8
  46. package/src/oracle/txe_oracle_top_level_context.ts +136 -72
  47. package/src/rpc_translator.ts +79 -53
  48. package/src/state_machine/archiver.ts +54 -220
  49. package/src/state_machine/dummy_p2p_client.ts +50 -31
  50. package/src/state_machine/global_variable_builder.ts +1 -1
  51. package/src/state_machine/index.ts +49 -11
  52. package/src/state_machine/mock_epoch_cache.ts +15 -11
  53. package/src/state_machine/synchronizer.ts +2 -2
  54. package/src/txe_session.ts +137 -61
  55. package/src/utils/block_creation.ts +19 -16
  56. package/src/utils/tx_effect_creation.ts +3 -11
@@ -4,9 +4,12 @@ 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,
12
+ JobCoordinator,
10
13
  NoteService,
11
14
  NoteStore,
12
15
  PrivateEventStore,
@@ -20,10 +23,19 @@ import {
20
23
  HashedValuesCache,
21
24
  type IPrivateExecutionOracle,
22
25
  type IUtilityExecutionOracle,
26
+ Oracle,
23
27
  PrivateExecutionOracle,
24
28
  UtilityExecutionOracle,
25
29
  } from '@aztec/pxe/simulator';
26
- import { FunctionSelector } from '@aztec/stdlib/abi';
30
+ import {
31
+ ExecutionError,
32
+ WASMSimulator,
33
+ createSimulationError,
34
+ extractCallStack,
35
+ resolveAssertionMessageFromError,
36
+ toACVMWitness,
37
+ } from '@aztec/simulator/client';
38
+ import { FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
27
39
  import type { AuthWitness } from '@aztec/stdlib/auth-witness';
28
40
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
29
41
  import { GasSettings } from '@aztec/stdlib/gas';
@@ -34,10 +46,12 @@ import { CallContext, GlobalVariables, TxContext } from '@aztec/stdlib/tx';
34
46
 
35
47
  import { z } from 'zod';
36
48
 
49
+ import { DEFAULT_ADDRESS } from './constants.js';
37
50
  import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
38
51
  import { TXEOraclePublicContext } from './oracle/txe_oracle_public_context.js';
39
52
  import { TXEOracleTopLevelContext } from './oracle/txe_oracle_top_level_context.js';
40
53
  import { RPCTranslator } from './rpc_translator.js';
54
+ import { TXEArchiver } from './state_machine/archiver.js';
41
55
  import { TXEStateMachine } from './state_machine/index.js';
42
56
  import type { ForeignCallArgs, ForeignCallResult } from './util/encoding.js';
43
57
  import { TXEAccountStore } from './util/txe_account_store.js';
@@ -64,7 +78,6 @@ type SessionState =
64
78
  | {
65
79
  name: 'PRIVATE';
66
80
  nextBlockGlobalVariables: GlobalVariables;
67
- protocolNullifier: Fr;
68
81
  noteCache: ExecutionNoteCache;
69
82
  taggingIndexCache: ExecutionTaggingIndexCache;
70
83
  }
@@ -103,8 +116,6 @@ export interface TXESessionStateHandler {
103
116
  enterUtilityState(contractAddress?: AztecAddress): Promise<void>;
104
117
  }
105
118
 
106
- export const DEFAULT_ADDRESS = AztecAddress.fromNumber(42);
107
-
108
119
  /**
109
120
  * A `TXESession` corresponds to a Noir `#[test]` function, and handles all of its oracle calls, stores test-specific
110
121
  * state, etc., independent of all other tests running in parallel.
@@ -131,6 +142,8 @@ export class TXESession implements TXESessionStateHandler {
131
142
  private senderAddressBookStore: SenderAddressBookStore,
132
143
  private capsuleStore: CapsuleStore,
133
144
  private privateEventStore: PrivateEventStore,
145
+ private jobCoordinator: JobCoordinator,
146
+ private currentJobId: string,
134
147
  private chainId: Fr,
135
148
  private version: Fr,
136
149
  private nextBlockTimestamp: bigint,
@@ -142,7 +155,7 @@ export class TXESession implements TXESessionStateHandler {
142
155
  const addressStore = new AddressStore(store);
143
156
  const privateEventStore = new PrivateEventStore(store);
144
157
  const contractStore = new TXEContractStore(store);
145
- const noteStore = await NoteStore.create(store);
158
+ const noteStore = new NoteStore(store);
146
159
  const senderTaggingStore = new SenderTaggingStore(store);
147
160
  const recipientTaggingStore = new RecipientTaggingStore(store);
148
161
  const senderAddressBookStore = new SenderAddressBookStore(store);
@@ -150,18 +163,32 @@ export class TXESession implements TXESessionStateHandler {
150
163
  const keyStore = new KeyStore(store);
151
164
  const accountStore = new TXEAccountStore(store);
152
165
 
166
+ // Create job coordinator and register staged stores
167
+ const jobCoordinator = new JobCoordinator(store);
168
+ jobCoordinator.registerStores([
169
+ capsuleStore,
170
+ senderTaggingStore,
171
+ recipientTaggingStore,
172
+ privateEventStore,
173
+ noteStore,
174
+ ]);
175
+
153
176
  // Register protocol contracts.
154
177
  for (const { contractClass, instance, artifact } of protocolContracts) {
155
178
  await contractStore.addContractArtifact(contractClass.id, artifact);
156
179
  await contractStore.addContractInstance(instance);
157
180
  }
158
181
 
159
- 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);
160
185
 
161
186
  const nextBlockTimestamp = BigInt(Math.floor(new Date().getTime() / 1000));
162
187
  const version = new Fr(await stateMachine.node.getVersion());
163
188
  const chainId = new Fr(await stateMachine.node.getChainId());
164
189
 
190
+ const initialJobId = jobCoordinator.beginJob();
191
+
165
192
  const topLevelOracleHandler = new TXEOracleTopLevelContext(
166
193
  stateMachine,
167
194
  contractStore,
@@ -174,6 +201,7 @@ export class TXESession implements TXESessionStateHandler {
174
201
  senderAddressBookStore,
175
202
  capsuleStore,
176
203
  privateEventStore,
204
+ initialJobId,
177
205
  nextBlockTimestamp,
178
206
  version,
179
207
  chainId,
@@ -195,6 +223,8 @@ export class TXESession implements TXESessionStateHandler {
195
223
  senderAddressBookStore,
196
224
  capsuleStore,
197
225
  privateEventStore,
226
+ jobCoordinator,
227
+ initialJobId,
198
228
  version,
199
229
  chainId,
200
230
  nextBlockTimestamp,
@@ -254,6 +284,10 @@ export class TXESession implements TXESessionStateHandler {
254
284
  }
255
285
  }
256
286
 
287
+ // Commit all staged stores from the job that was just completed, then begin a new job
288
+ await this.jobCoordinator.commitJob(this.currentJobId);
289
+ this.currentJobId = this.jobCoordinator.beginJob();
290
+
257
291
  this.oracleHandler = new TXEOracleTopLevelContext(
258
292
  this.stateMachine,
259
293
  this.contractStore,
@@ -266,6 +300,7 @@ export class TXESession implements TXESessionStateHandler {
266
300
  this.senderAddressBookStore,
267
301
  this.capsuleStore,
268
302
  this.privateEventStore,
303
+ this.currentJobId,
269
304
  this.nextBlockTimestamp,
270
305
  this.version,
271
306
  this.chainId,
@@ -282,21 +317,15 @@ export class TXESession implements TXESessionStateHandler {
282
317
  ): Promise<PrivateContextInputs> {
283
318
  this.exitTopLevelState();
284
319
 
285
- // There is no automatic message discovery and contract-driven syncing process in inlined private or utility
286
- // contexts, which means that known nullifiers are also not searched for, since it is during the tagging sync that
287
- // we perform this. We therefore search for known nullifiers now, as otherwise notes that were nullified would not
288
- // be removed from the database.
289
- // TODO(#12553): make the synchronizer sync here instead and remove this
290
- await new NoteService(
291
- this.noteStore,
292
- this.stateMachine.node,
293
- this.stateMachine.anchorBlockStore,
294
- ).syncNoteNullifiers(contractAddress);
295
-
296
320
  // Private execution has two associated block numbers: the anchor block (i.e. the historical block that is used to
297
321
  // build the proof), and the *next* block, i.e. the one we'll create once the execution ends, and which will contain
298
322
  // a single transaction with the effects of what was done in the test.
299
323
  const anchorBlock = await this.stateMachine.node.getBlockHeader(anchorBlockNumber ?? 'latest');
324
+
325
+ await new NoteService(this.noteStore, this.stateMachine.node, anchorBlock!, this.currentJobId).syncNoteNullifiers(
326
+ contractAddress,
327
+ 'ALL_SCOPES',
328
+ );
300
329
  const latestBlock = await this.stateMachine.node.getBlockHeader('latest');
301
330
 
302
331
  const nextBlockGlobalVariables = makeGlobalVariables(undefined, {
@@ -311,35 +340,39 @@ export class TXESession implements TXESessionStateHandler {
311
340
  const noteCache = new ExecutionNoteCache(protocolNullifier);
312
341
  const taggingIndexCache = new ExecutionTaggingIndexCache();
313
342
 
314
- this.oracleHandler = new PrivateExecutionOracle(
315
- Fr.ZERO,
316
- new TxContext(this.chainId, this.version, GasSettings.empty()),
317
- new CallContext(AztecAddress.ZERO, contractAddress, FunctionSelector.empty(), false),
318
- anchorBlock!,
319
- [],
320
- [],
321
- new HashedValuesCache(),
343
+ const utilityExecutor = this.utilityExecutorForContractSync(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!,
349
+ utilityExecutor,
350
+ authWitnesses: [],
351
+ capsules: [],
352
+ executionCache: new HashedValuesCache(),
322
353
  noteCache,
323
354
  taggingIndexCache,
324
- this.contractStore,
325
- this.noteStore,
326
- this.keyStore,
327
- this.addressStore,
328
- this.stateMachine.node,
329
- this.stateMachine.anchorBlockStore,
330
- this.senderTaggingStore,
331
- this.recipientTaggingStore,
332
- this.senderAddressBookStore,
333
- this.capsuleStore,
334
- this.privateEventStore,
335
- );
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
+ });
336
369
 
337
370
  // We store the note and tagging index caches fed into the PrivateExecutionOracle (along with some other auxiliary
338
371
  // data) in order to refer to it later, mimicking the way this object is used by the ContractFunctionSimulator. The
339
372
  // difference resides in that the simulator has all information needed in order to run the simulation, while ours
340
373
  // will be ongoing as the different oracles will be invoked from the Noir test, until eventually the private
341
374
  // execution finishes.
342
- this.state = { name: 'PRIVATE', nextBlockGlobalVariables, protocolNullifier, noteCache, taggingIndexCache };
375
+ this.state = { name: 'PRIVATE', nextBlockGlobalVariables, noteCache, taggingIndexCache };
343
376
  this.logger.debug(`Entered state ${this.state.name}`);
344
377
 
345
378
  return (this.oracleHandler as PrivateExecutionOracle).getPrivateContextInputs();
@@ -372,6 +405,8 @@ export class TXESession implements TXESessionStateHandler {
372
405
  async enterUtilityState(contractAddress: AztecAddress = DEFAULT_ADDRESS) {
373
406
  this.exitTopLevelState();
374
407
 
408
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
409
+
375
410
  // There is no automatic message discovery and contract-driven syncing process in inlined private or utility
376
411
  // contexts, which means that known nullifiers are also not searched for, since it is during the tagging sync that
377
412
  // we perform this. We therefore search for known nullifiers now, as otherwise notes that were nullified would not
@@ -380,27 +415,27 @@ export class TXESession implements TXESessionStateHandler {
380
415
  await new NoteService(
381
416
  this.noteStore,
382
417
  this.stateMachine.node,
383
- this.stateMachine.anchorBlockStore,
384
- ).syncNoteNullifiers(contractAddress);
385
-
386
- const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
418
+ anchorBlockHeader,
419
+ this.currentJobId,
420
+ ).syncNoteNullifiers(contractAddress, 'ALL_SCOPES');
387
421
 
388
- this.oracleHandler = new UtilityExecutionOracle(
422
+ this.oracleHandler = new UtilityExecutionOracle({
389
423
  contractAddress,
390
- [],
391
- [],
424
+ authWitnesses: [],
425
+ capsules: [],
392
426
  anchorBlockHeader,
393
- this.contractStore,
394
- this.noteStore,
395
- this.keyStore,
396
- this.addressStore,
397
- this.stateMachine.node,
398
- this.stateMachine.anchorBlockStore,
399
- this.recipientTaggingStore,
400
- this.senderAddressBookStore,
401
- this.capsuleStore,
402
- this.privateEventStore,
403
- );
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
+ });
404
439
 
405
440
  this.state = { name: 'UTILITY' };
406
441
  this.logger.debug(`Entered state ${this.state.name}`);
@@ -435,11 +470,7 @@ export class TXESession implements TXESessionStateHandler {
435
470
  // We rely on the note cache to determine the effects of the transaction. This is incomplete as it doesn't private
436
471
  // logs (other effects like enqueued public calls don't need to be considered since those are not allowed).
437
472
 
438
- const txEffect = await makeTxEffect(
439
- this.state.noteCache,
440
- this.state.protocolNullifier,
441
- this.state.nextBlockGlobalVariables.blockNumber,
442
- );
473
+ const txEffect = await makeTxEffect(this.state.noteCache, this.state.nextBlockGlobalVariables.blockNumber);
443
474
 
444
475
  // We build a block holding just this transaction
445
476
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
@@ -470,4 +501,49 @@ export class TXESession implements TXESessionStateHandler {
470
501
  throw new Error(`Expected to be in state 'UTILITY', but got '${this.state.name}' instead`);
471
502
  }
472
503
  }
504
+
505
+ private utilityExecutorForContractSync(anchorBlock: any) {
506
+ return async (call: FunctionCall, scopes: AccessScopes) => {
507
+ const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
508
+ if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
509
+ throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
510
+ }
511
+
512
+ try {
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
+ });
530
+ await new WASMSimulator()
531
+ .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
532
+ .catch((err: Error) => {
533
+ err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
534
+ throw new ExecutionError(
535
+ err.message,
536
+ {
537
+ contractAddress: call.to,
538
+ functionSelector: call.selector,
539
+ },
540
+ extractCallStack(err, entryPointArtifact.debug),
541
+ { cause: err },
542
+ );
543
+ });
544
+ } catch (err) {
545
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error contract data sync'));
546
+ }
547
+ };
548
+ }
473
549
  }
@@ -4,13 +4,12 @@ import {
4
4
  NULLIFIER_SUBTREE_HEIGHT,
5
5
  NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
6
6
  } from '@aztec/constants';
7
- import { BlockNumber } from '@aztec/foundation/branded-types';
7
+ import { BlockNumber, CheckpointNumber, IndexWithinCheckpoint } from '@aztec/foundation/branded-types';
8
8
  import { padArrayEnd } from '@aztec/foundation/collection';
9
9
  import { Fr } from '@aztec/foundation/curves/bn254';
10
- import { Body, L2Block, L2BlockHeader } from '@aztec/stdlib/block';
11
- import { makeContentCommitment } from '@aztec/stdlib/testing';
10
+ import { Body, L2Block } from '@aztec/stdlib/block';
12
11
  import { AppendOnlyTreeSnapshot, MerkleTreeId, type MerkleTreeWriteOperations } from '@aztec/stdlib/trees';
13
- import { GlobalVariables, TxEffect } from '@aztec/stdlib/tx';
12
+ import { BlockHeader, GlobalVariables, TxEffect } from '@aztec/stdlib/tx';
14
13
 
15
14
  /**
16
15
  * Returns a transaction request hash that is valid for transactions that are the only ones in a block.
@@ -47,20 +46,18 @@ export async function insertTxEffectIntoWorldTrees(
47
46
  export async function makeTXEBlockHeader(
48
47
  worldTrees: MerkleTreeWriteOperations,
49
48
  globalVariables: GlobalVariables,
50
- ): Promise<L2BlockHeader> {
49
+ ): Promise<BlockHeader> {
51
50
  const stateReference = await worldTrees.getStateReference();
52
51
  const archiveInfo = await worldTrees.getTreeInfo(MerkleTreeId.ARCHIVE);
53
52
 
54
- return new L2BlockHeader(
55
- new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)),
56
- makeContentCommitment(),
57
- stateReference,
53
+ return BlockHeader.from({
54
+ lastArchive: new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)),
55
+ spongeBlobHash: Fr.ZERO,
56
+ state: stateReference,
58
57
  globalVariables,
59
- Fr.ZERO,
60
- Fr.ZERO,
61
- Fr.ZERO,
62
- Fr.ZERO,
63
- );
58
+ totalFees: Fr.ZERO,
59
+ totalManaUsed: Fr.ZERO,
60
+ });
64
61
  }
65
62
 
66
63
  /**
@@ -84,11 +81,17 @@ export async function makeTXEBlock(
84
81
  const header = await makeTXEBlockHeader(worldTrees, globalVariables);
85
82
 
86
83
  // Update the archive tree with this block's header hash
87
- await worldTrees.updateArchive(header.toBlockHeader());
84
+ await worldTrees.updateArchive(header);
88
85
 
89
86
  // Get the new archive state after updating
90
87
  const newArchiveInfo = await worldTrees.getTreeInfo(MerkleTreeId.ARCHIVE);
91
88
  const newArchive = new AppendOnlyTreeSnapshot(new Fr(newArchiveInfo.root), Number(newArchiveInfo.size));
92
89
 
93
- return new L2Block(newArchive, header, new Body(txEffects));
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.
93
+ const checkpointNumber = CheckpointNumber.fromBlockNumber(globalVariables.blockNumber);
94
+ const indexWithinCheckpoint = IndexWithinCheckpoint(0);
95
+
96
+ return new L2Block(newArchive, header, new Body(txEffects), checkpointNumber, indexWithinCheckpoint);
94
97
  }
@@ -4,16 +4,12 @@ import type { ExecutionNoteCache } from '@aztec/pxe/simulator';
4
4
  import { computeNoteHashNonce, computeUniqueNoteHash, siloNoteHash } from '@aztec/stdlib/hash';
5
5
  import { TxEffect, TxHash } from '@aztec/stdlib/tx';
6
6
 
7
- export async function makeTxEffect(
8
- noteCache: ExecutionNoteCache,
9
- protocolNullifier: Fr,
10
- txBlockNumber: BlockNumber,
11
- ): Promise<TxEffect> {
7
+ export async function makeTxEffect(noteCache: ExecutionNoteCache, txBlockNumber: BlockNumber): Promise<TxEffect> {
12
8
  const txEffect = TxEffect.empty();
13
9
 
14
- const { usedProtocolNullifierForNonces } = noteCache.finish();
15
- const nonceGenerator = usedProtocolNullifierForNonces ? protocolNullifier : noteCache.getAllNullifiers()[0];
10
+ noteCache.finish();
16
11
 
12
+ const nonceGenerator = noteCache.getNonceGenerator();
17
13
  txEffect.noteHashes = await Promise.all(
18
14
  noteCache
19
15
  .getAllNotes()
@@ -28,10 +24,6 @@ export async function makeTxEffect(
28
24
  // Nullifiers are already siloed
29
25
  txEffect.nullifiers = noteCache.getAllNullifiers();
30
26
 
31
- if (usedProtocolNullifierForNonces) {
32
- txEffect.nullifiers.unshift(protocolNullifier);
33
- }
34
-
35
27
  txEffect.txHash = new TxHash(new Fr(txBlockNumber));
36
28
 
37
29
  return txEffect;