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

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 (49) 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/txe_oracle_public_context.d.ts +3 -3
  5. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  6. package/dest/oracle/txe_oracle_top_level_context.d.ts +4 -2
  7. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  8. package/dest/oracle/txe_oracle_top_level_context.js +36 -22
  9. package/dest/rpc_translator.d.ts +6 -6
  10. package/dest/rpc_translator.d.ts.map +1 -1
  11. package/dest/rpc_translator.js +21 -20
  12. package/dest/state_machine/archiver.d.ts +20 -67
  13. package/dest/state_machine/archiver.d.ts.map +1 -1
  14. package/dest/state_machine/archiver.js +58 -178
  15. package/dest/state_machine/dummy_p2p_client.d.ts +8 -7
  16. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  17. package/dest/state_machine/dummy_p2p_client.js +13 -10
  18. package/dest/state_machine/global_variable_builder.d.ts +2 -2
  19. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  20. package/dest/state_machine/global_variable_builder.js +1 -1
  21. package/dest/state_machine/index.d.ts +3 -3
  22. package/dest/state_machine/index.d.ts.map +1 -1
  23. package/dest/state_machine/index.js +13 -4
  24. package/dest/state_machine/mock_epoch_cache.d.ts +2 -1
  25. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  26. package/dest/state_machine/mock_epoch_cache.js +5 -1
  27. package/dest/txe_session.d.ts +6 -4
  28. package/dest/txe_session.d.ts.map +1 -1
  29. package/dest/txe_session.js +51 -17
  30. package/dest/util/encoding.d.ts +17 -17
  31. package/dest/utils/block_creation.d.ts +7 -7
  32. package/dest/utils/block_creation.d.ts.map +1 -1
  33. package/dest/utils/block_creation.js +18 -7
  34. package/dest/utils/tx_effect_creation.d.ts +2 -3
  35. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  36. package/dest/utils/tx_effect_creation.js +3 -6
  37. package/package.json +16 -16
  38. package/src/constants.ts +3 -0
  39. package/src/oracle/txe_oracle_public_context.ts +2 -2
  40. package/src/oracle/txe_oracle_top_level_context.ts +53 -22
  41. package/src/rpc_translator.ts +21 -23
  42. package/src/state_machine/archiver.ts +55 -219
  43. package/src/state_machine/dummy_p2p_client.ts +18 -13
  44. package/src/state_machine/global_variable_builder.ts +1 -1
  45. package/src/state_machine/index.ts +14 -6
  46. package/src/state_machine/mock_epoch_cache.ts +5 -0
  47. package/src/txe_session.ts +79 -15
  48. package/src/utils/block_creation.ts +20 -19
  49. package/src/utils/tx_effect_creation.ts +3 -11
@@ -7,6 +7,7 @@ import type { ProtocolContract } from '@aztec/protocol-contracts';
7
7
  import {
8
8
  AddressStore,
9
9
  CapsuleStore,
10
+ JobCoordinator,
10
11
  NoteService,
11
12
  NoteStore,
12
13
  PrivateEventStore,
@@ -20,10 +21,19 @@ import {
20
21
  HashedValuesCache,
21
22
  type IPrivateExecutionOracle,
22
23
  type IUtilityExecutionOracle,
24
+ Oracle,
23
25
  PrivateExecutionOracle,
24
26
  UtilityExecutionOracle,
25
27
  } from '@aztec/pxe/simulator';
26
- import { FunctionSelector } from '@aztec/stdlib/abi';
28
+ import {
29
+ ExecutionError,
30
+ WASMSimulator,
31
+ createSimulationError,
32
+ extractCallStack,
33
+ resolveAssertionMessageFromError,
34
+ toACVMWitness,
35
+ } from '@aztec/simulator/client';
36
+ import { FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
27
37
  import type { AuthWitness } from '@aztec/stdlib/auth-witness';
28
38
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
29
39
  import { GasSettings } from '@aztec/stdlib/gas';
@@ -34,6 +44,7 @@ import { CallContext, GlobalVariables, TxContext } from '@aztec/stdlib/tx';
34
44
 
35
45
  import { z } from 'zod';
36
46
 
47
+ import { DEFAULT_ADDRESS } from './constants.js';
37
48
  import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
38
49
  import { TXEOraclePublicContext } from './oracle/txe_oracle_public_context.js';
39
50
  import { TXEOracleTopLevelContext } from './oracle/txe_oracle_top_level_context.js';
@@ -64,7 +75,6 @@ type SessionState =
64
75
  | {
65
76
  name: 'PRIVATE';
66
77
  nextBlockGlobalVariables: GlobalVariables;
67
- protocolNullifier: Fr;
68
78
  noteCache: ExecutionNoteCache;
69
79
  taggingIndexCache: ExecutionTaggingIndexCache;
70
80
  }
@@ -103,8 +113,6 @@ export interface TXESessionStateHandler {
103
113
  enterUtilityState(contractAddress?: AztecAddress): Promise<void>;
104
114
  }
105
115
 
106
- export const DEFAULT_ADDRESS = AztecAddress.fromNumber(42);
107
-
108
116
  /**
109
117
  * A `TXESession` corresponds to a Noir `#[test]` function, and handles all of its oracle calls, stores test-specific
110
118
  * state, etc., independent of all other tests running in parallel.
@@ -131,6 +139,8 @@ export class TXESession implements TXESessionStateHandler {
131
139
  private senderAddressBookStore: SenderAddressBookStore,
132
140
  private capsuleStore: CapsuleStore,
133
141
  private privateEventStore: PrivateEventStore,
142
+ private jobCoordinator: JobCoordinator,
143
+ private currentJobId: string,
134
144
  private chainId: Fr,
135
145
  private version: Fr,
136
146
  private nextBlockTimestamp: bigint,
@@ -150,6 +160,10 @@ export class TXESession implements TXESessionStateHandler {
150
160
  const keyStore = new KeyStore(store);
151
161
  const accountStore = new TXEAccountStore(store);
152
162
 
163
+ // Create job coordinator and register staged stores
164
+ const jobCoordinator = new JobCoordinator(store);
165
+ jobCoordinator.registerStores([capsuleStore, senderTaggingStore, recipientTaggingStore, privateEventStore]);
166
+
153
167
  // Register protocol contracts.
154
168
  for (const { contractClass, instance, artifact } of protocolContracts) {
155
169
  await contractStore.addContractArtifact(contractClass.id, artifact);
@@ -162,6 +176,8 @@ export class TXESession implements TXESessionStateHandler {
162
176
  const version = new Fr(await stateMachine.node.getVersion());
163
177
  const chainId = new Fr(await stateMachine.node.getChainId());
164
178
 
179
+ const initialJobId = jobCoordinator.beginJob();
180
+
165
181
  const topLevelOracleHandler = new TXEOracleTopLevelContext(
166
182
  stateMachine,
167
183
  contractStore,
@@ -174,6 +190,7 @@ export class TXESession implements TXESessionStateHandler {
174
190
  senderAddressBookStore,
175
191
  capsuleStore,
176
192
  privateEventStore,
193
+ initialJobId,
177
194
  nextBlockTimestamp,
178
195
  version,
179
196
  chainId,
@@ -195,6 +212,8 @@ export class TXESession implements TXESessionStateHandler {
195
212
  senderAddressBookStore,
196
213
  capsuleStore,
197
214
  privateEventStore,
215
+ jobCoordinator,
216
+ initialJobId,
198
217
  version,
199
218
  chainId,
200
219
  nextBlockTimestamp,
@@ -254,6 +273,10 @@ export class TXESession implements TXESessionStateHandler {
254
273
  }
255
274
  }
256
275
 
276
+ // Commit all staged stores from the job that was just completed, then begin a new job
277
+ await this.jobCoordinator.commitJob(this.currentJobId);
278
+ this.currentJobId = this.jobCoordinator.beginJob();
279
+
257
280
  this.oracleHandler = new TXEOracleTopLevelContext(
258
281
  this.stateMachine,
259
282
  this.contractStore,
@@ -266,6 +289,7 @@ export class TXESession implements TXESessionStateHandler {
266
289
  this.senderAddressBookStore,
267
290
  this.capsuleStore,
268
291
  this.privateEventStore,
292
+ this.currentJobId,
269
293
  this.nextBlockTimestamp,
270
294
  this.version,
271
295
  this.chainId,
@@ -282,11 +306,6 @@ export class TXESession implements TXESessionStateHandler {
282
306
  ): Promise<PrivateContextInputs> {
283
307
  this.exitTopLevelState();
284
308
 
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
309
  await new NoteService(
291
310
  this.noteStore,
292
311
  this.stateMachine.node,
@@ -311,11 +330,13 @@ export class TXESession implements TXESessionStateHandler {
311
330
  const noteCache = new ExecutionNoteCache(protocolNullifier);
312
331
  const taggingIndexCache = new ExecutionTaggingIndexCache();
313
332
 
333
+ const utilityExecutor = this.utilityExecutorForContractSync(anchorBlock);
314
334
  this.oracleHandler = new PrivateExecutionOracle(
315
335
  Fr.ZERO,
316
336
  new TxContext(this.chainId, this.version, GasSettings.empty()),
317
337
  new CallContext(AztecAddress.ZERO, contractAddress, FunctionSelector.empty(), false),
318
338
  anchorBlock!,
339
+ utilityExecutor,
319
340
  [],
320
341
  [],
321
342
  new HashedValuesCache(),
@@ -332,6 +353,7 @@ export class TXESession implements TXESessionStateHandler {
332
353
  this.senderAddressBookStore,
333
354
  this.capsuleStore,
334
355
  this.privateEventStore,
356
+ this.currentJobId,
335
357
  );
336
358
 
337
359
  // We store the note and tagging index caches fed into the PrivateExecutionOracle (along with some other auxiliary
@@ -339,7 +361,7 @@ export class TXESession implements TXESessionStateHandler {
339
361
  // difference resides in that the simulator has all information needed in order to run the simulation, while ours
340
362
  // will be ongoing as the different oracles will be invoked from the Noir test, until eventually the private
341
363
  // execution finishes.
342
- this.state = { name: 'PRIVATE', nextBlockGlobalVariables, protocolNullifier, noteCache, taggingIndexCache };
364
+ this.state = { name: 'PRIVATE', nextBlockGlobalVariables, noteCache, taggingIndexCache };
343
365
  this.logger.debug(`Entered state ${this.state.name}`);
344
366
 
345
367
  return (this.oracleHandler as PrivateExecutionOracle).getPrivateContextInputs();
@@ -400,6 +422,7 @@ export class TXESession implements TXESessionStateHandler {
400
422
  this.senderAddressBookStore,
401
423
  this.capsuleStore,
402
424
  this.privateEventStore,
425
+ this.currentJobId,
403
426
  );
404
427
 
405
428
  this.state = { name: 'UTILITY' };
@@ -435,11 +458,7 @@ export class TXESession implements TXESessionStateHandler {
435
458
  // We rely on the note cache to determine the effects of the transaction. This is incomplete as it doesn't private
436
459
  // logs (other effects like enqueued public calls don't need to be considered since those are not allowed).
437
460
 
438
- const txEffect = await makeTxEffect(
439
- this.state.noteCache,
440
- this.state.protocolNullifier,
441
- this.state.nextBlockGlobalVariables.blockNumber,
442
- );
461
+ const txEffect = await makeTxEffect(this.state.noteCache, this.state.nextBlockGlobalVariables.blockNumber);
443
462
 
444
463
  // We build a block holding just this transaction
445
464
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
@@ -470,4 +489,49 @@ export class TXESession implements TXESessionStateHandler {
470
489
  throw new Error(`Expected to be in state 'UTILITY', but got '${this.state.name}' instead`);
471
490
  }
472
491
  }
492
+
493
+ private utilityExecutorForContractSync(anchorBlock: any) {
494
+ return async (call: FunctionCall) => {
495
+ const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
496
+ if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
497
+ throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
498
+ }
499
+
500
+ try {
501
+ const oracle = new UtilityExecutionOracle(
502
+ call.to,
503
+ [],
504
+ [],
505
+ anchorBlock!,
506
+ this.contractStore,
507
+ this.noteStore,
508
+ this.keyStore,
509
+ this.addressStore,
510
+ this.stateMachine.node,
511
+ this.stateMachine.anchorBlockStore,
512
+ this.recipientTaggingStore,
513
+ this.senderAddressBookStore,
514
+ this.capsuleStore,
515
+ this.privateEventStore,
516
+ this.currentJobId,
517
+ );
518
+ await new WASMSimulator()
519
+ .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
520
+ .catch((err: Error) => {
521
+ err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
522
+ throw new ExecutionError(
523
+ err.message,
524
+ {
525
+ contractAddress: call.to,
526
+ functionSelector: call.selector,
527
+ },
528
+ extractCallStack(err, entryPointArtifact.debug),
529
+ { cause: err },
530
+ );
531
+ });
532
+ } catch (err) {
533
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error contract data sync'));
534
+ }
535
+ };
536
+ }
473
537
  }
@@ -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, L2BlockNew } 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,24 +46,22 @@ 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
  /**
67
- * Creates an L2Block with proper archive chaining.
64
+ * Creates an L2BlockNew with proper archive chaining.
68
65
  * This function:
69
66
  * 1. Gets the current archive state as lastArchive for the header
70
67
  * 2. Creates the block header
@@ -74,21 +71,25 @@ export async function makeTXEBlockHeader(
74
71
  * @param worldTrees - The world trees to read/write from
75
72
  * @param globalVariables - Global variables for the block
76
73
  * @param txEffects - Transaction effects to include in the block
77
- * @returns The created L2Block with proper archive chaining
74
+ * @returns The created L2BlockNew with proper archive chaining
78
75
  */
79
76
  export async function makeTXEBlock(
80
77
  worldTrees: MerkleTreeWriteOperations,
81
78
  globalVariables: GlobalVariables,
82
79
  txEffects: TxEffect[],
83
- ): Promise<L2Block> {
80
+ ): Promise<L2BlockNew> {
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
+ // L2BlockNew requires checkpointNumber and indexWithinCheckpoint
91
+ const checkpointNumber = CheckpointNumber.fromBlockNumber(globalVariables.blockNumber);
92
+ const indexWithinCheckpoint = IndexWithinCheckpoint(0);
93
+
94
+ return new L2BlockNew(newArchive, header, new Body(txEffects), checkpointNumber, indexWithinCheckpoint);
94
95
  }
@@ -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;