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

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 (68) 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/index.d.ts +1 -1
  5. package/dest/index.d.ts.map +1 -1
  6. package/dest/index.js +82 -50
  7. package/dest/oracle/interfaces.d.ts +6 -5
  8. package/dest/oracle/interfaces.d.ts.map +1 -1
  9. package/dest/oracle/txe_oracle_public_context.d.ts +3 -3
  10. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  11. package/dest/oracle/txe_oracle_public_context.js +6 -6
  12. package/dest/oracle/txe_oracle_top_level_context.d.ts +8 -7
  13. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  14. package/dest/oracle/txe_oracle_top_level_context.js +123 -38
  15. package/dest/rpc_translator.d.ts +21 -15
  16. package/dest/rpc_translator.d.ts.map +1 -1
  17. package/dest/rpc_translator.js +92 -55
  18. package/dest/state_machine/archiver.d.ts +20 -67
  19. package/dest/state_machine/archiver.d.ts.map +1 -1
  20. package/dest/state_machine/archiver.js +59 -178
  21. package/dest/state_machine/dummy_p2p_client.d.ts +20 -15
  22. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  23. package/dest/state_machine/dummy_p2p_client.js +39 -24
  24. package/dest/state_machine/global_variable_builder.d.ts +2 -2
  25. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  26. package/dest/state_machine/global_variable_builder.js +1 -1
  27. package/dest/state_machine/index.d.ts +5 -5
  28. package/dest/state_machine/index.d.ts.map +1 -1
  29. package/dest/state_machine/index.js +35 -12
  30. package/dest/state_machine/mock_epoch_cache.d.ts +9 -6
  31. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  32. package/dest/state_machine/mock_epoch_cache.js +14 -7
  33. package/dest/state_machine/synchronizer.d.ts +3 -3
  34. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  35. package/dest/txe_session.d.ts +12 -7
  36. package/dest/txe_session.d.ts.map +1 -1
  37. package/dest/txe_session.js +122 -28
  38. package/dest/util/encoding.d.ts +17 -17
  39. package/dest/util/txe_public_contract_data_source.d.ts +2 -3
  40. package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
  41. package/dest/util/txe_public_contract_data_source.js +5 -22
  42. package/dest/utils/block_creation.d.ts +4 -4
  43. package/dest/utils/block_creation.d.ts.map +1 -1
  44. package/dest/utils/block_creation.js +18 -5
  45. package/dest/utils/tx_effect_creation.d.ts +2 -3
  46. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  47. package/dest/utils/tx_effect_creation.js +3 -6
  48. package/package.json +16 -16
  49. package/src/constants.ts +3 -0
  50. package/src/index.ts +83 -49
  51. package/src/oracle/interfaces.ts +8 -3
  52. package/src/oracle/txe_oracle_public_context.ts +6 -8
  53. package/src/oracle/txe_oracle_top_level_context.ts +163 -79
  54. package/src/rpc_translator.ts +97 -56
  55. package/src/state_machine/archiver.ts +54 -220
  56. package/src/state_machine/dummy_p2p_client.ts +55 -32
  57. package/src/state_machine/global_variable_builder.ts +1 -1
  58. package/src/state_machine/index.ts +49 -11
  59. package/src/state_machine/mock_epoch_cache.ts +15 -11
  60. package/src/state_machine/synchronizer.ts +2 -2
  61. package/src/txe_session.ts +151 -71
  62. package/src/util/txe_public_contract_data_source.ts +10 -36
  63. package/src/utils/block_creation.ts +19 -16
  64. package/src/utils/tx_effect_creation.ts +3 -11
  65. package/dest/util/txe_contract_store.d.ts +0 -12
  66. package/dest/util/txe_contract_store.d.ts.map +0 -1
  67. package/dest/util/txe_contract_store.js +0 -22
  68. package/src/util/txe_contract_store.ts +0 -36
@@ -3,10 +3,13 @@ import { Fr } from '@aztec/foundation/curves/bn254';
3
3
  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
- import type { ProtocolContract } from '@aztec/protocol-contracts';
6
+ import type { AccessScopes } from '@aztec/pxe/client/lazy';
7
7
  import {
8
8
  AddressStore,
9
+ AnchorBlockStore,
9
10
  CapsuleStore,
11
+ ContractStore,
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,14 +46,15 @@ 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';
44
- import { TXEContractStore } from './util/txe_contract_store.js';
45
58
  import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from './utils/block_creation.js';
46
59
  import { makeTxEffect } from './utils/tx_effect_creation.js';
47
60
 
@@ -64,7 +77,6 @@ type SessionState =
64
77
  | {
65
78
  name: 'PRIVATE';
66
79
  nextBlockGlobalVariables: GlobalVariables;
67
- protocolNullifier: Fr;
68
80
  noteCache: ExecutionNoteCache;
69
81
  taggingIndexCache: ExecutionTaggingIndexCache;
70
82
  }
@@ -101,9 +113,11 @@ export interface TXESessionStateHandler {
101
113
  enterPublicState(contractAddress?: AztecAddress): Promise<void>;
102
114
  enterPrivateState(contractAddress?: AztecAddress, anchorBlockNumber?: BlockNumber): Promise<PrivateContextInputs>;
103
115
  enterUtilityState(contractAddress?: AztecAddress): Promise<void>;
104
- }
105
116
 
106
- export const DEFAULT_ADDRESS = AztecAddress.fromNumber(42);
117
+ // TODO(F-335): Exposing the job info is abstraction breakage - drop the following 2 functions.
118
+ cycleJob(): Promise<string>;
119
+ getCurrentJob(): string;
120
+ }
107
121
 
108
122
  /**
109
123
  * A `TXESession` corresponds to a Noir `#[test]` function, and handles all of its oracle calls, stores test-specific
@@ -121,7 +135,7 @@ export class TXESession implements TXESessionStateHandler {
121
135
  | IPrivateExecutionOracle
122
136
  | IAvmExecutionOracle
123
137
  | ITxeExecutionOracle,
124
- private contractStore: TXEContractStore,
138
+ private contractStore: ContractStore,
125
139
  private noteStore: NoteStore,
126
140
  private keyStore: KeyStore,
127
141
  private addressStore: AddressStore,
@@ -131,18 +145,19 @@ export class TXESession implements TXESessionStateHandler {
131
145
  private senderAddressBookStore: SenderAddressBookStore,
132
146
  private capsuleStore: CapsuleStore,
133
147
  private privateEventStore: PrivateEventStore,
148
+ private jobCoordinator: JobCoordinator,
149
+ private currentJobId: string,
134
150
  private chainId: Fr,
135
151
  private version: Fr,
136
152
  private nextBlockTimestamp: bigint,
137
153
  ) {}
138
154
 
139
- static async init(protocolContracts: ProtocolContract[]) {
155
+ static async init(contractStore: ContractStore) {
140
156
  const store = await openTmpStore('txe-session');
141
157
 
142
158
  const addressStore = new AddressStore(store);
143
159
  const privateEventStore = new PrivateEventStore(store);
144
- const contractStore = new TXEContractStore(store);
145
- const noteStore = await NoteStore.create(store);
160
+ const noteStore = new NoteStore(store);
146
161
  const senderTaggingStore = new SenderTaggingStore(store);
147
162
  const recipientTaggingStore = new RecipientTaggingStore(store);
148
163
  const senderAddressBookStore = new SenderAddressBookStore(store);
@@ -150,18 +165,26 @@ export class TXESession implements TXESessionStateHandler {
150
165
  const keyStore = new KeyStore(store);
151
166
  const accountStore = new TXEAccountStore(store);
152
167
 
153
- // Register protocol contracts.
154
- for (const { contractClass, instance, artifact } of protocolContracts) {
155
- await contractStore.addContractArtifact(contractClass.id, artifact);
156
- await contractStore.addContractInstance(instance);
157
- }
168
+ // Create job coordinator and register staged stores
169
+ const jobCoordinator = new JobCoordinator(store);
170
+ jobCoordinator.registerStores([
171
+ capsuleStore,
172
+ senderTaggingStore,
173
+ recipientTaggingStore,
174
+ privateEventStore,
175
+ noteStore,
176
+ ]);
158
177
 
159
- const stateMachine = await TXEStateMachine.create(store);
178
+ const archiver = new TXEArchiver(store);
179
+ const anchorBlockStore = new AnchorBlockStore(store);
180
+ const stateMachine = await TXEStateMachine.create(archiver, anchorBlockStore, contractStore, noteStore);
160
181
 
161
182
  const nextBlockTimestamp = BigInt(Math.floor(new Date().getTime() / 1000));
162
183
  const version = new Fr(await stateMachine.node.getVersion());
163
184
  const chainId = new Fr(await stateMachine.node.getChainId());
164
185
 
186
+ const initialJobId = jobCoordinator.beginJob();
187
+
165
188
  const topLevelOracleHandler = new TXEOracleTopLevelContext(
166
189
  stateMachine,
167
190
  contractStore,
@@ -195,6 +218,8 @@ export class TXESession implements TXESessionStateHandler {
195
218
  senderAddressBookStore,
196
219
  capsuleStore,
197
220
  privateEventStore,
221
+ jobCoordinator,
222
+ initialJobId,
198
223
  version,
199
224
  chainId,
200
225
  nextBlockTimestamp,
@@ -232,6 +257,17 @@ export class TXESession implements TXESessionStateHandler {
232
257
  }
233
258
  }
234
259
 
260
+ getCurrentJob(): string {
261
+ return this.currentJobId;
262
+ }
263
+
264
+ /** Commits the current job and begins a new one. Returns the new job ID. */
265
+ async cycleJob(): Promise<string> {
266
+ await this.jobCoordinator.commitJob(this.currentJobId);
267
+ this.currentJobId = this.jobCoordinator.beginJob();
268
+ return this.currentJobId;
269
+ }
270
+
235
271
  async enterTopLevelState() {
236
272
  switch (this.state.name) {
237
273
  case 'PRIVATE': {
@@ -254,6 +290,9 @@ export class TXESession implements TXESessionStateHandler {
254
290
  }
255
291
  }
256
292
 
293
+ // Commit all staged stores from the job that was just completed, then begin a new job
294
+ await this.cycleJob();
295
+
257
296
  this.oracleHandler = new TXEOracleTopLevelContext(
258
297
  this.stateMachine,
259
298
  this.contractStore,
@@ -282,21 +321,15 @@ export class TXESession implements TXESessionStateHandler {
282
321
  ): Promise<PrivateContextInputs> {
283
322
  this.exitTopLevelState();
284
323
 
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
324
  // Private execution has two associated block numbers: the anchor block (i.e. the historical block that is used to
297
325
  // build the proof), and the *next* block, i.e. the one we'll create once the execution ends, and which will contain
298
326
  // a single transaction with the effects of what was done in the test.
299
327
  const anchorBlock = await this.stateMachine.node.getBlockHeader(anchorBlockNumber ?? 'latest');
328
+
329
+ await new NoteService(this.noteStore, this.stateMachine.node, anchorBlock!, this.currentJobId).syncNoteNullifiers(
330
+ contractAddress,
331
+ 'ALL_SCOPES',
332
+ );
300
333
  const latestBlock = await this.stateMachine.node.getBlockHeader('latest');
301
334
 
302
335
  const nextBlockGlobalVariables = makeGlobalVariables(undefined, {
@@ -311,35 +344,39 @@ export class TXESession implements TXESessionStateHandler {
311
344
  const noteCache = new ExecutionNoteCache(protocolNullifier);
312
345
  const taggingIndexCache = new ExecutionTaggingIndexCache();
313
346
 
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(),
347
+ const utilityExecutor = this.utilityExecutorForContractSync(anchorBlock);
348
+ this.oracleHandler = new PrivateExecutionOracle({
349
+ argsHash: Fr.ZERO,
350
+ txContext: new TxContext(this.chainId, this.version, GasSettings.empty()),
351
+ callContext: new CallContext(AztecAddress.ZERO, contractAddress, FunctionSelector.empty(), false),
352
+ anchorBlockHeader: anchorBlock!,
353
+ utilityExecutor,
354
+ authWitnesses: [],
355
+ capsules: [],
356
+ executionCache: new HashedValuesCache(),
322
357
  noteCache,
323
358
  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
- );
359
+ contractStore: this.contractStore,
360
+ noteStore: this.noteStore,
361
+ keyStore: this.keyStore,
362
+ addressStore: this.addressStore,
363
+ aztecNode: this.stateMachine.node,
364
+ senderTaggingStore: this.senderTaggingStore,
365
+ recipientTaggingStore: this.recipientTaggingStore,
366
+ senderAddressBookStore: this.senderAddressBookStore,
367
+ capsuleStore: this.capsuleStore,
368
+ privateEventStore: this.privateEventStore,
369
+ contractSyncService: this.stateMachine.contractSyncService,
370
+ jobId: this.currentJobId,
371
+ scopes: 'ALL_SCOPES',
372
+ });
336
373
 
337
374
  // We store the note and tagging index caches fed into the PrivateExecutionOracle (along with some other auxiliary
338
375
  // data) in order to refer to it later, mimicking the way this object is used by the ContractFunctionSimulator. The
339
376
  // difference resides in that the simulator has all information needed in order to run the simulation, while ours
340
377
  // will be ongoing as the different oracles will be invoked from the Noir test, until eventually the private
341
378
  // execution finishes.
342
- this.state = { name: 'PRIVATE', nextBlockGlobalVariables, protocolNullifier, noteCache, taggingIndexCache };
379
+ this.state = { name: 'PRIVATE', nextBlockGlobalVariables, noteCache, taggingIndexCache };
343
380
  this.logger.debug(`Entered state ${this.state.name}`);
344
381
 
345
382
  return (this.oracleHandler as PrivateExecutionOracle).getPrivateContextInputs();
@@ -372,6 +409,8 @@ export class TXESession implements TXESessionStateHandler {
372
409
  async enterUtilityState(contractAddress: AztecAddress = DEFAULT_ADDRESS) {
373
410
  this.exitTopLevelState();
374
411
 
412
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
413
+
375
414
  // There is no automatic message discovery and contract-driven syncing process in inlined private or utility
376
415
  // contexts, which means that known nullifiers are also not searched for, since it is during the tagging sync that
377
416
  // we perform this. We therefore search for known nullifiers now, as otherwise notes that were nullified would not
@@ -380,27 +419,27 @@ export class TXESession implements TXESessionStateHandler {
380
419
  await new NoteService(
381
420
  this.noteStore,
382
421
  this.stateMachine.node,
383
- this.stateMachine.anchorBlockStore,
384
- ).syncNoteNullifiers(contractAddress);
385
-
386
- const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
422
+ anchorBlockHeader,
423
+ this.currentJobId,
424
+ ).syncNoteNullifiers(contractAddress, 'ALL_SCOPES');
387
425
 
388
- this.oracleHandler = new UtilityExecutionOracle(
426
+ this.oracleHandler = new UtilityExecutionOracle({
389
427
  contractAddress,
390
- [],
391
- [],
428
+ authWitnesses: [],
429
+ capsules: [],
392
430
  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
- );
431
+ contractStore: this.contractStore,
432
+ noteStore: this.noteStore,
433
+ keyStore: this.keyStore,
434
+ addressStore: this.addressStore,
435
+ aztecNode: this.stateMachine.node,
436
+ recipientTaggingStore: this.recipientTaggingStore,
437
+ senderAddressBookStore: this.senderAddressBookStore,
438
+ capsuleStore: this.capsuleStore,
439
+ privateEventStore: this.privateEventStore,
440
+ jobId: this.currentJobId,
441
+ scopes: 'ALL_SCOPES',
442
+ });
404
443
 
405
444
  this.state = { name: 'UTILITY' };
406
445
  this.logger.debug(`Entered state ${this.state.name}`);
@@ -435,11 +474,7 @@ export class TXESession implements TXESessionStateHandler {
435
474
  // We rely on the note cache to determine the effects of the transaction. This is incomplete as it doesn't private
436
475
  // logs (other effects like enqueued public calls don't need to be considered since those are not allowed).
437
476
 
438
- const txEffect = await makeTxEffect(
439
- this.state.noteCache,
440
- this.state.protocolNullifier,
441
- this.state.nextBlockGlobalVariables.blockNumber,
442
- );
477
+ const txEffect = await makeTxEffect(this.state.noteCache, this.state.nextBlockGlobalVariables.blockNumber);
443
478
 
444
479
  // We build a block holding just this transaction
445
480
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
@@ -470,4 +505,49 @@ export class TXESession implements TXESessionStateHandler {
470
505
  throw new Error(`Expected to be in state 'UTILITY', but got '${this.state.name}' instead`);
471
506
  }
472
507
  }
508
+
509
+ private utilityExecutorForContractSync(anchorBlock: any) {
510
+ return async (call: FunctionCall, scopes: AccessScopes) => {
511
+ const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
512
+ if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
513
+ throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
514
+ }
515
+
516
+ try {
517
+ const oracle = new UtilityExecutionOracle({
518
+ contractAddress: call.to,
519
+ authWitnesses: [],
520
+ capsules: [],
521
+ anchorBlockHeader: anchorBlock!,
522
+ contractStore: this.contractStore,
523
+ noteStore: this.noteStore,
524
+ keyStore: this.keyStore,
525
+ addressStore: this.addressStore,
526
+ aztecNode: this.stateMachine.node,
527
+ recipientTaggingStore: this.recipientTaggingStore,
528
+ senderAddressBookStore: this.senderAddressBookStore,
529
+ capsuleStore: this.capsuleStore,
530
+ privateEventStore: this.privateEventStore,
531
+ jobId: this.currentJobId,
532
+ scopes,
533
+ });
534
+ await new WASMSimulator()
535
+ .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
536
+ .catch((err: Error) => {
537
+ err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
538
+ throw new ExecutionError(
539
+ err.message,
540
+ {
541
+ contractAddress: call.to,
542
+ functionSelector: call.selector,
543
+ },
544
+ extractCallStack(err, entryPointArtifact.debug),
545
+ { cause: err },
546
+ );
547
+ });
548
+ } catch (err) {
549
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error contract data sync'));
550
+ }
551
+ };
552
+ }
473
553
  }
@@ -1,19 +1,11 @@
1
1
  import { BlockNumber } from '@aztec/foundation/branded-types';
2
2
  import { Fr } from '@aztec/foundation/curves/bn254';
3
3
  import type { ContractStore } from '@aztec/pxe/server';
4
- import { type ContractArtifact, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
4
+ import { type ContractArtifact, FunctionSelector } from '@aztec/stdlib/abi';
5
5
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
6
- import {
7
- type ContractClassPublic,
8
- type ContractDataSource,
9
- type ContractInstanceWithAddress,
10
- computePrivateFunctionsRoot,
11
- computePublicBytecodeCommitment,
12
- getContractClassPrivateFunctionFromArtifact,
13
- } from '@aztec/stdlib/contract';
6
+ import type { ContractClassPublic, ContractDataSource, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
14
7
 
15
8
  export class TXEPublicContractDataSource implements ContractDataSource {
16
- #privateFunctionsRoot: Map<string, Buffer> = new Map();
17
9
  constructor(
18
10
  private blockNumber: BlockNumber,
19
11
  private contractStore: ContractStore,
@@ -24,42 +16,24 @@ export class TXEPublicContractDataSource implements ContractDataSource {
24
16
  }
25
17
 
26
18
  async getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
27
- const contractClass = await this.contractStore.getContractClass(id);
19
+ const contractClass = await this.contractStore.getContractClassWithPreimage(id);
28
20
  if (!contractClass) {
29
21
  return;
30
22
  }
31
- const artifact = await this.contractStore.getContractArtifact(id);
32
- if (!artifact) {
33
- return;
34
- }
35
-
36
- let privateFunctionsRoot;
37
- if (!this.#privateFunctionsRoot.has(id.toString())) {
38
- const privateFunctions = await Promise.all(
39
- artifact.functions
40
- .filter(fn => fn.functionType === FunctionType.PRIVATE)
41
- .map(fn => getContractClassPrivateFunctionFromArtifact(fn)),
42
- );
43
- privateFunctionsRoot = await computePrivateFunctionsRoot(privateFunctions);
44
- this.#privateFunctionsRoot.set(id.toString(), privateFunctionsRoot.toBuffer());
45
- } else {
46
- privateFunctionsRoot = Fr.fromBuffer(this.#privateFunctionsRoot.get(id.toString())!);
47
- }
48
-
49
23
  return {
50
- id,
51
- artifactHash: contractClass!.artifactHash,
52
- packedBytecode: contractClass!.packedBytecode,
53
- privateFunctionsRoot,
54
- version: contractClass!.version,
24
+ id: contractClass.id,
25
+ artifactHash: contractClass.artifactHash,
26
+ packedBytecode: contractClass.packedBytecode,
27
+ privateFunctionsRoot: contractClass.privateFunctionsRoot,
28
+ version: contractClass.version,
55
29
  privateFunctions: [],
56
30
  utilityFunctions: [],
57
31
  };
58
32
  }
59
33
 
60
34
  async getBytecodeCommitment(id: Fr): Promise<Fr | undefined> {
61
- const contractClass = await this.contractStore.getContractClass(id);
62
- return contractClass && computePublicBytecodeCommitment(contractClass.packedBytecode);
35
+ const contractClass = await this.contractStore.getContractClassWithPreimage(id);
36
+ return contractClass?.publicBytecodeCommitment;
63
37
  }
64
38
 
65
39
  async getContract(address: AztecAddress): Promise<ContractInstanceWithAddress | undefined> {
@@ -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;
@@ -1,12 +0,0 @@
1
- import type { ContractArtifact } from '@aztec/aztec.js/abi';
2
- import { Fr } from '@aztec/aztec.js/fields';
3
- import { ContractStore } from '@aztec/pxe/server';
4
- export type ContractArtifactWithHash = ContractArtifact & {
5
- artifactHash: Fr;
6
- };
7
- export declare class TXEContractStore extends ContractStore {
8
- #private;
9
- addContractArtifact(id: Fr, artifact: ContractArtifact | ContractArtifactWithHash): Promise<void>;
10
- getContractArtifact(contractClassId: Fr): Promise<ContractArtifact | ContractArtifactWithHash | undefined>;
11
- }
12
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHhlX2NvbnRyYWN0X3N0b3JlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbC90eGVfY29udHJhY3Rfc3RvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDNUMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRWxELE1BQU0sTUFBTSx3QkFBd0IsR0FBRyxnQkFBZ0IsR0FBRztJQUFFLFlBQVksRUFBRSxFQUFFLENBQUE7Q0FBRSxDQUFDO0FBTy9FLHFCQUFhLGdCQUFpQixTQUFRLGFBQWE7O0lBRzNCLG1CQUFtQixDQUN2QyxFQUFFLEVBQUUsRUFBRSxFQUNOLFFBQVEsRUFBRSxnQkFBZ0IsR0FBRyx3QkFBd0IsR0FDcEQsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUtmO0lBRXFCLG1CQUFtQixDQUN2QyxlQUFlLEVBQUUsRUFBRSxHQUNsQixPQUFPLENBQUMsZ0JBQWdCLEdBQUcsd0JBQXdCLEdBQUcsU0FBUyxDQUFDLENBUWxFO0NBQ0YifQ==
@@ -1 +0,0 @@
1
- {"version":3,"file":"txe_contract_store.d.ts","sourceRoot":"","sources":["../../src/util/txe_contract_store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,EAAE,EAAE,MAAM,wBAAwB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,MAAM,wBAAwB,GAAG,gBAAgB,GAAG;IAAE,YAAY,EAAE,EAAE,CAAA;CAAE,CAAC;AAO/E,qBAAa,gBAAiB,SAAQ,aAAa;;IAG3B,mBAAmB,CACvC,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,gBAAgB,GAAG,wBAAwB,GACpD,OAAO,CAAC,IAAI,CAAC,CAKf;IAEqB,mBAAmB,CACvC,eAAe,EAAE,EAAE,GAClB,OAAO,CAAC,gBAAgB,GAAG,wBAAwB,GAAG,SAAS,CAAC,CAQlE;CACF"}
@@ -1,22 +0,0 @@
1
- import { Fr } from '@aztec/aztec.js/fields';
2
- import { ContractStore } from '@aztec/pxe/server';
3
- /*
4
- * A contract store that stores contract artifacts with their hashes. Since
5
- * TXE typically deploys the same contract again and again for multiple tests, caching
6
- * the *very* expensive artifact hash computation improves testing speed significantly.
7
- */ export class TXEContractStore extends ContractStore {
8
- #artifactHashes = new Map();
9
- async addContractArtifact(id, artifact) {
10
- if ('artifactHash' in artifact) {
11
- this.#artifactHashes.set(id.toString(), artifact.artifactHash.toBuffer());
12
- }
13
- await super.addContractArtifact(id, artifact);
14
- }
15
- async getContractArtifact(contractClassId) {
16
- const artifact = await super.getContractArtifact(contractClassId);
17
- if (artifact && this.#artifactHashes.has(contractClassId.toString())) {
18
- artifact.artifactHash = Fr.fromBuffer(this.#artifactHashes.get(contractClassId.toString()));
19
- }
20
- return artifact;
21
- }
22
- }
@@ -1,36 +0,0 @@
1
- import type { ContractArtifact } from '@aztec/aztec.js/abi';
2
- import { Fr } from '@aztec/aztec.js/fields';
3
- import { ContractStore } from '@aztec/pxe/server';
4
-
5
- export type ContractArtifactWithHash = ContractArtifact & { artifactHash: Fr };
6
-
7
- /*
8
- * A contract store that stores contract artifacts with their hashes. Since
9
- * TXE typically deploys the same contract again and again for multiple tests, caching
10
- * the *very* expensive artifact hash computation improves testing speed significantly.
11
- */
12
- export class TXEContractStore extends ContractStore {
13
- #artifactHashes: Map<string, Buffer> = new Map();
14
-
15
- public override async addContractArtifact(
16
- id: Fr,
17
- artifact: ContractArtifact | ContractArtifactWithHash,
18
- ): Promise<void> {
19
- if ('artifactHash' in artifact) {
20
- this.#artifactHashes.set(id.toString(), artifact.artifactHash.toBuffer());
21
- }
22
- await super.addContractArtifact(id, artifact);
23
- }
24
-
25
- public override async getContractArtifact(
26
- contractClassId: Fr,
27
- ): Promise<ContractArtifact | ContractArtifactWithHash | undefined> {
28
- const artifact = await super.getContractArtifact(contractClassId);
29
- if (artifact && this.#artifactHashes.has(contractClassId.toString())) {
30
- (artifact as ContractArtifactWithHash).artifactHash = Fr.fromBuffer(
31
- this.#artifactHashes.get(contractClassId.toString())!,
32
- );
33
- }
34
- return artifact;
35
- }
36
- }