@aztec/txe 0.0.1-commit.023c3e5 → 0.0.1-commit.033589e

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 (52) hide show
  1. package/dest/index.d.ts +1 -1
  2. package/dest/index.d.ts.map +1 -1
  3. package/dest/index.js +88 -54
  4. package/dest/oracle/interfaces.d.ts +29 -28
  5. package/dest/oracle/interfaces.d.ts.map +1 -1
  6. package/dest/oracle/txe_oracle_public_context.d.ts +13 -13
  7. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  8. package/dest/oracle/txe_oracle_public_context.js +12 -12
  9. package/dest/oracle/txe_oracle_top_level_context.d.ts +22 -23
  10. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  11. package/dest/oracle/txe_oracle_top_level_context.js +119 -50
  12. package/dest/rpc_translator.d.ts +83 -83
  13. package/dest/rpc_translator.d.ts.map +1 -1
  14. package/dest/rpc_translator.js +259 -154
  15. package/dest/state_machine/archiver.d.ts +1 -1
  16. package/dest/state_machine/archiver.d.ts.map +1 -1
  17. package/dest/state_machine/archiver.js +2 -0
  18. package/dest/state_machine/dummy_p2p_client.d.ts +16 -12
  19. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  20. package/dest/state_machine/dummy_p2p_client.js +28 -16
  21. package/dest/state_machine/index.d.ts +5 -5
  22. package/dest/state_machine/index.d.ts.map +1 -1
  23. package/dest/state_machine/index.js +15 -10
  24. package/dest/state_machine/mock_epoch_cache.d.ts +3 -1
  25. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  26. package/dest/state_machine/mock_epoch_cache.js +4 -0
  27. package/dest/txe_session.d.ts +9 -6
  28. package/dest/txe_session.d.ts.map +1 -1
  29. package/dest/txe_session.js +82 -23
  30. package/dest/util/txe_public_contract_data_source.d.ts +2 -3
  31. package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
  32. package/dest/util/txe_public_contract_data_source.js +5 -22
  33. package/dest/utils/block_creation.d.ts +1 -1
  34. package/dest/utils/block_creation.d.ts.map +1 -1
  35. package/dest/utils/block_creation.js +3 -1
  36. package/package.json +15 -15
  37. package/src/index.ts +89 -52
  38. package/src/oracle/interfaces.ts +32 -31
  39. package/src/oracle/txe_oracle_public_context.ts +12 -12
  40. package/src/oracle/txe_oracle_top_level_context.ts +132 -96
  41. package/src/rpc_translator.ts +266 -157
  42. package/src/state_machine/archiver.ts +2 -0
  43. package/src/state_machine/dummy_p2p_client.ts +40 -22
  44. package/src/state_machine/index.ts +25 -9
  45. package/src/state_machine/mock_epoch_cache.ts +5 -0
  46. package/src/txe_session.ts +85 -71
  47. package/src/util/txe_public_contract_data_source.ts +10 -36
  48. package/src/utils/block_creation.ts +3 -1
  49. package/dest/util/txe_contract_store.d.ts +0 -12
  50. package/dest/util/txe_contract_store.d.ts.map +0 -1
  51. package/dest/util/txe_contract_store.js +0 -22
  52. package/src/util/txe_contract_store.ts +0 -36
@@ -24,18 +24,18 @@ import type { UInt64 } from '@aztec/stdlib/types';
24
24
  export interface IAvmExecutionOracle {
25
25
  isAvm: true;
26
26
 
27
- avmOpcodeAddress(): Promise<AztecAddress>;
28
- avmOpcodeSender(): Promise<AztecAddress>;
29
- avmOpcodeBlockNumber(): Promise<BlockNumber>;
30
- avmOpcodeTimestamp(): Promise<bigint>;
31
- avmOpcodeIsStaticCall(): Promise<boolean>;
32
- avmOpcodeChainId(): Promise<Fr>;
33
- avmOpcodeVersion(): Promise<Fr>;
34
- avmOpcodeEmitNullifier(nullifier: Fr): Promise<void>;
35
- avmOpcodeEmitNoteHash(noteHash: Fr): Promise<void>;
36
- avmOpcodeNullifierExists(siloedNullifier: Fr): Promise<boolean>;
37
- avmOpcodeStorageWrite(slot: Fr, value: Fr): Promise<void>;
38
- avmOpcodeStorageRead(slot: Fr, contractAddress: AztecAddress): Promise<Fr>;
27
+ address(): Promise<AztecAddress>;
28
+ sender(): Promise<AztecAddress>;
29
+ blockNumber(): Promise<BlockNumber>;
30
+ timestamp(): Promise<bigint>;
31
+ isStaticCall(): Promise<boolean>;
32
+ chainId(): Promise<Fr>;
33
+ version(): Promise<Fr>;
34
+ emitNullifier(nullifier: Fr): Promise<void>;
35
+ emitNoteHash(noteHash: Fr): Promise<void>;
36
+ nullifierExists(siloedNullifier: Fr): Promise<boolean>;
37
+ storageWrite(slot: Fr, value: Fr): Promise<void>;
38
+ storageRead(slot: Fr, contractAddress: AztecAddress): Promise<Fr>;
39
39
  }
40
40
 
41
41
  /**
@@ -44,43 +44,44 @@ export interface IAvmExecutionOracle {
44
44
  export interface ITxeExecutionOracle {
45
45
  isTxe: true;
46
46
 
47
- txeGetDefaultAddress(): AztecAddress;
48
- txeGetNextBlockNumber(): Promise<BlockNumber>;
49
- txeGetNextBlockTimestamp(): Promise<UInt64>;
50
- txeAdvanceBlocksBy(blocks: number): Promise<void>;
51
- txeAdvanceTimestampBy(duration: UInt64): void;
52
- txeDeploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, foreignSecret: Fr): Promise<void>;
53
- txeCreateAccount(secret: Fr): Promise<CompleteAddress>;
54
- txeAddAccount(
55
- artifact: ContractArtifact,
56
- instance: ContractInstanceWithAddress,
57
- secret: Fr,
58
- ): Promise<CompleteAddress>;
59
- txeAddAuthWitness(address: AztecAddress, messageHash: Fr): Promise<void>;
60
- txeGetLastBlockTimestamp(): Promise<bigint>;
61
- txeGetLastTxEffects(): Promise<{
47
+ getDefaultAddress(): AztecAddress;
48
+ getNextBlockNumber(): Promise<BlockNumber>;
49
+ getNextBlockTimestamp(): Promise<UInt64>;
50
+ advanceBlocksBy(blocks: number): Promise<void>;
51
+ advanceTimestampBy(duration: UInt64): void;
52
+ deploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, foreignSecret: Fr): Promise<void>;
53
+ createAccount(secret: Fr): Promise<CompleteAddress>;
54
+ addAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr): Promise<CompleteAddress>;
55
+ addAuthWitness(address: AztecAddress, messageHash: Fr): Promise<void>;
56
+ getLastBlockTimestamp(): Promise<bigint>;
57
+ getLastTxEffects(): Promise<{
62
58
  txHash: TxHash;
63
59
  noteHashes: Fr[];
64
60
  nullifiers: Fr[];
65
61
  }>;
66
- txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress): Promise<Fr[][]>;
67
- txePrivateCallNewFlow(
62
+ getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress): Promise<Fr[][]>;
63
+ privateCallNewFlow(
68
64
  from: AztecAddress,
69
65
  targetContractAddress: AztecAddress,
70
66
  functionSelector: FunctionSelector,
71
67
  args: Fr[],
72
68
  argsHash: Fr,
73
69
  isStaticCall: boolean,
70
+ jobId: string,
74
71
  ): Promise<Fr[]>;
75
- txeSimulateUtilityFunction(
72
+ executeUtilityFunction(
76
73
  targetContractAddress: AztecAddress,
77
74
  functionSelector: FunctionSelector,
78
75
  args: Fr[],
76
+ jobId: string,
79
77
  ): Promise<Fr[]>;
80
- txePublicCallNewFlow(
78
+ publicCallNewFlow(
81
79
  from: AztecAddress,
82
80
  targetContractAddress: AztecAddress,
83
81
  calldata: Fr[],
84
82
  isStaticCall: boolean,
85
83
  ): Promise<Fr[]>;
84
+ // TODO(F-335): Drop this from here as it's not a real oracle handler - it's only called from
85
+ // RPCTranslator::txeGetPrivateEvents and never from Noir.
86
+ syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string): Promise<void>;
86
87
  }
@@ -39,46 +39,46 @@ export class TXEOraclePublicContext implements IAvmExecutionOracle {
39
39
  });
40
40
  }
41
41
 
42
- avmOpcodeAddress(): Promise<AztecAddress> {
42
+ address(): Promise<AztecAddress> {
43
43
  return Promise.resolve(this.contractAddress);
44
44
  }
45
45
 
46
- avmOpcodeSender(): Promise<AztecAddress> {
46
+ sender(): Promise<AztecAddress> {
47
47
  return Promise.resolve(AztecAddress.ZERO); // todo: change?
48
48
  }
49
49
 
50
- avmOpcodeBlockNumber(): Promise<BlockNumber> {
50
+ blockNumber(): Promise<BlockNumber> {
51
51
  return Promise.resolve(this.globalVariables.blockNumber);
52
52
  }
53
53
 
54
- avmOpcodeTimestamp(): Promise<bigint> {
54
+ timestamp(): Promise<bigint> {
55
55
  return Promise.resolve(this.globalVariables.timestamp);
56
56
  }
57
57
 
58
- avmOpcodeIsStaticCall(): Promise<boolean> {
58
+ isStaticCall(): Promise<boolean> {
59
59
  return Promise.resolve(false);
60
60
  }
61
61
 
62
- avmOpcodeChainId(): Promise<Fr> {
62
+ chainId(): Promise<Fr> {
63
63
  return Promise.resolve(this.globalVariables.chainId);
64
64
  }
65
65
 
66
- avmOpcodeVersion(): Promise<Fr> {
66
+ version(): Promise<Fr> {
67
67
  return Promise.resolve(this.globalVariables.version);
68
68
  }
69
69
 
70
- async avmOpcodeEmitNullifier(nullifier: Fr) {
70
+ async emitNullifier(nullifier: Fr) {
71
71
  const siloedNullifier = await siloNullifier(this.contractAddress, nullifier);
72
72
  this.transientSiloedNullifiers.push(siloedNullifier);
73
73
  }
74
74
 
75
- async avmOpcodeEmitNoteHash(noteHash: Fr) {
75
+ async emitNoteHash(noteHash: Fr) {
76
76
  const siloedNoteHash = await siloNoteHash(this.contractAddress, noteHash);
77
77
  // TODO: make the note hash unique - they are only siloed right now
78
78
  this.transientUniqueNoteHashes.push(siloedNoteHash);
79
79
  }
80
80
 
81
- async avmOpcodeNullifierExists(siloedNullifier: Fr): Promise<boolean> {
81
+ async nullifierExists(siloedNullifier: Fr): Promise<boolean> {
82
82
  const treeIndex = (
83
83
  await this.forkedWorldTrees.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [siloedNullifier.toBuffer()])
84
84
  )[0];
@@ -87,7 +87,7 @@ export class TXEOraclePublicContext implements IAvmExecutionOracle {
87
87
  return treeIndex !== undefined || transientIndex !== undefined;
88
88
  }
89
89
 
90
- async avmOpcodeStorageWrite(slot: Fr, value: Fr) {
90
+ async storageWrite(slot: Fr, value: Fr) {
91
91
  this.logger.debug('AVM storage write', { slot, value });
92
92
 
93
93
  const dataWrite = new PublicDataWrite(await computePublicDataTreeLeafSlot(this.contractAddress, slot), value);
@@ -99,7 +99,7 @@ export class TXEOraclePublicContext implements IAvmExecutionOracle {
99
99
  ]);
100
100
  }
101
101
 
102
- async avmOpcodeStorageRead(slot: Fr, contractAddress: AztecAddress): Promise<Fr> {
102
+ async storageRead(slot: Fr, contractAddress: AztecAddress): Promise<Fr> {
103
103
  const leafSlot = await computePublicDataTreeLeafSlot(contractAddress, slot);
104
104
 
105
105
  const lowLeafResult = await this.forkedWorldTrees.getPreviousValueIndex(
@@ -12,9 +12,11 @@ import { Fr } from '@aztec/foundation/curves/bn254';
12
12
  import { LogLevels, type Logger, applyStringFormatting, createLogger } from '@aztec/foundation/log';
13
13
  import { TestDateProvider } from '@aztec/foundation/timer';
14
14
  import type { KeyStore } from '@aztec/key-store';
15
+ import type { AccessScopes } from '@aztec/pxe/client/lazy';
15
16
  import {
16
17
  AddressStore,
17
18
  CapsuleStore,
19
+ type ContractStore,
18
20
  NoteStore,
19
21
  ORACLE_VERSION,
20
22
  PrivateEventStore,
@@ -22,7 +24,6 @@ import {
22
24
  SenderAddressBookStore,
23
25
  SenderTaggingStore,
24
26
  enrichPublicSimulationError,
25
- syncState,
26
27
  } from '@aztec/pxe/server';
27
28
  import {
28
29
  ExecutionNoteCache,
@@ -84,7 +85,6 @@ import { ForkCheckpoint } from '@aztec/world-state';
84
85
  import { DEFAULT_ADDRESS } from '../constants.js';
85
86
  import type { TXEStateMachine } from '../state_machine/index.js';
86
87
  import type { TXEAccountStore } from '../util/txe_account_store.js';
87
- import type { TXEContractStore } from '../util/txe_contract_store.js';
88
88
  import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
89
89
  import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
90
90
  import type { ITxeExecutionOracle } from './interfaces.js';
@@ -97,7 +97,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
97
97
 
98
98
  constructor(
99
99
  private stateMachine: TXEStateMachine,
100
- private contractStore: TXEContractStore,
100
+ private contractStore: ContractStore,
101
101
  private noteStore: NoteStore,
102
102
  private keyStore: KeyStore,
103
103
  private addressStore: AddressStore,
@@ -107,7 +107,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
107
107
  private senderAddressBookStore: SenderAddressBookStore,
108
108
  private capsuleStore: CapsuleStore,
109
109
  private privateEventStore: PrivateEventStore,
110
- private jobId: string,
111
110
  private nextBlockTimestamp: bigint,
112
111
  private version: Fr,
113
112
  private chainId: Fr,
@@ -117,7 +116,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
117
116
  this.logger.debug('Entering Top Level Context');
118
117
  }
119
118
 
120
- utilityAssertCompatibleOracleVersion(version: number): void {
119
+ assertCompatibleOracleVersion(version: number): void {
121
120
  if (version !== ORACLE_VERSION) {
122
121
  throw new Error(
123
122
  `Incompatible oracle version. TXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`,
@@ -127,37 +126,38 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
127
126
 
128
127
  // This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
129
128
  // setup.
130
- utilityGetRandomField(): Fr {
129
+ getRandomField(): Fr {
131
130
  return Fr.random();
132
131
  }
133
132
 
134
133
  // We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
135
- utilityDebugLog(level: number, message: string, fields: Fr[]): void {
134
+ log(level: number, message: string, fields: Fr[]): Promise<void> {
136
135
  if (!LogLevels[level]) {
137
- throw new Error(`Invalid debug log level: ${level}`);
136
+ throw new Error(`Invalid log level: ${level}`);
138
137
  }
139
138
  const levelName = LogLevels[level];
140
139
 
141
140
  this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
141
+ return Promise.resolve();
142
142
  }
143
143
 
144
- txeGetDefaultAddress(): AztecAddress {
144
+ getDefaultAddress(): AztecAddress {
145
145
  return DEFAULT_ADDRESS;
146
146
  }
147
147
 
148
- async txeGetNextBlockNumber(): Promise<BlockNumber> {
148
+ async getNextBlockNumber(): Promise<BlockNumber> {
149
149
  return BlockNumber((await this.getLastBlockNumber()) + 1);
150
150
  }
151
151
 
152
- txeGetNextBlockTimestamp(): Promise<bigint> {
152
+ getNextBlockTimestamp(): Promise<bigint> {
153
153
  return Promise.resolve(this.nextBlockTimestamp);
154
154
  }
155
155
 
156
- async txeGetLastBlockTimestamp() {
156
+ async getLastBlockTimestamp() {
157
157
  return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
158
158
  }
159
159
 
160
- async txeGetLastTxEffects() {
160
+ async getLastTxEffects() {
161
161
  const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
162
162
  const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
163
163
 
@@ -171,7 +171,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
171
171
  return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
172
172
  }
173
173
 
174
- async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
174
+ async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
175
+ if (contractAddress.equals(DEFAULT_ADDRESS)) {
176
+ this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
177
+ return;
178
+ }
179
+
180
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
181
+ await this.stateMachine.contractSyncService.ensureContractSynced(
182
+ contractAddress,
183
+ null,
184
+ async (call, execScopes) => {
185
+ await this.executeUtilityCall(call, execScopes, jobId);
186
+ },
187
+ blockHeader,
188
+ jobId,
189
+ [scope],
190
+ );
191
+ }
192
+
193
+ async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
175
194
  return (
176
195
  await this.privateEventStore.getPrivateEvents(selector, {
177
196
  contractAddress,
@@ -182,7 +201,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
182
201
  ).map(e => e.packedEvent);
183
202
  }
184
203
 
185
- async txeAdvanceBlocksBy(blocks: number) {
204
+ async advanceBlocksBy(blocks: number) {
186
205
  this.logger.debug(`time traveling ${blocks} blocks`);
187
206
 
188
207
  for (let i = 0; i < blocks; i++) {
@@ -190,12 +209,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
190
209
  }
191
210
  }
192
211
 
193
- txeAdvanceTimestampBy(duration: UInt64) {
212
+ advanceTimestampBy(duration: UInt64) {
194
213
  this.logger.debug(`time traveling ${duration} seconds`);
195
214
  this.nextBlockTimestamp += duration;
196
215
  }
197
216
 
198
- async txeDeploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
217
+ async deploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
199
218
  // Emit deployment nullifier
200
219
  await this.mineBlock({
201
220
  nullifiers: [
@@ -207,20 +226,20 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
207
226
  });
208
227
 
209
228
  if (!secret.equals(Fr.ZERO)) {
210
- await this.txeAddAccount(artifact, instance, secret);
229
+ await this.addAccount(artifact, instance, secret);
211
230
  } else {
212
231
  await this.contractStore.addContractInstance(instance);
213
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
232
+ await this.contractStore.addContractArtifact(artifact);
214
233
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
215
234
  }
216
235
  }
217
236
 
218
- async txeAddAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
237
+ async addAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
219
238
  const partialAddress = await computePartialAddress(instance);
220
239
 
221
240
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
222
241
  await this.contractStore.addContractInstance(instance);
223
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
242
+ await this.contractStore.addContractArtifact(artifact);
224
243
 
225
244
  const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
226
245
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
@@ -230,7 +249,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
230
249
  return completeAddress;
231
250
  }
232
251
 
233
- async txeCreateAccount(secret: Fr) {
252
+ async createAccount(secret: Fr) {
234
253
  // This is a foot gun !
235
254
  const completeAddress = await this.keyStore.addAccount(secret, secret);
236
255
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
@@ -240,7 +259,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
240
259
  return completeAddress;
241
260
  }
242
261
 
243
- async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
262
+ async addAuthWitness(address: AztecAddress, messageHash: Fr) {
244
263
  const account = await this.accountStore.getAccount(address);
245
264
  const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
246
265
 
@@ -253,7 +272,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
253
272
  }
254
273
 
255
274
  async mineBlock(options: { nullifiers?: Fr[] } = {}) {
256
- const blockNumber = await this.txeGetNextBlockNumber();
275
+ const blockNumber = await this.getNextBlockNumber();
257
276
 
258
277
  const txEffect = TxEffect.empty();
259
278
  txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
@@ -277,13 +296,14 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
277
296
  await this.stateMachine.handleL2Block(block);
278
297
  }
279
298
 
280
- async txePrivateCallNewFlow(
299
+ async privateCallNewFlow(
281
300
  from: AztecAddress,
282
301
  targetContractAddress: AztecAddress = AztecAddress.zero(),
283
302
  functionSelector: FunctionSelector = FunctionSelector.empty(),
284
303
  args: Fr[],
285
304
  argsHash: Fr = Fr.zero(),
286
305
  isStaticCall: boolean = false,
306
+ jobId: string,
287
307
  ) {
288
308
  this.logger.verbose(
289
309
  `Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
@@ -297,14 +317,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
297
317
  throw new Error(message);
298
318
  }
299
319
 
320
+ // When `from` is the zero address (e.g. when deploying a new account contract), we return an
321
+ // empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
322
+ const effectiveScopes = from.isZero() ? [] : [from];
323
+
300
324
  // Sync notes before executing private function to discover notes from previous transactions
301
- const utilityExecutor = async (call: FunctionCall) => {
302
- await this.executeUtilityCall(call);
325
+ const utilityExecutor = async (call: FunctionCall, execScopes: AccessScopes) => {
326
+ await this.executeUtilityCall(call, execScopes, jobId);
303
327
  };
304
328
 
305
- await syncState(targetContractAddress, this.contractStore, functionSelector, utilityExecutor);
329
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
330
+ await this.stateMachine.contractSyncService.ensureContractSynced(
331
+ targetContractAddress,
332
+ functionSelector,
333
+ utilityExecutor,
334
+ blockHeader,
335
+ jobId,
336
+ effectiveScopes,
337
+ );
306
338
 
307
- const blockNumber = await this.txeGetNextBlockNumber();
339
+ const blockNumber = await this.getNextBlockNumber();
308
340
 
309
341
  const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
310
342
 
@@ -314,8 +346,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
314
346
 
315
347
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
316
348
 
317
- const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
318
-
319
349
  const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
320
350
  const noteCache = new ExecutionNoteCache(protocolNullifier);
321
351
  // In production, the account contract sets the min revertible counter before calling the app function.
@@ -327,42 +357,37 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
327
357
 
328
358
  const simulator = new WASMSimulator();
329
359
 
330
- const privateExecutionOracle = new PrivateExecutionOracle(
360
+ const privateExecutionOracle = new PrivateExecutionOracle({
331
361
  argsHash,
332
362
  txContext,
333
363
  callContext,
334
- /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
335
- blockHeader,
364
+ anchorBlockHeader: blockHeader,
336
365
  utilityExecutor,
337
- /** List of transient auth witnesses to be used during this simulation */
338
- Array.from(this.authwits.values()),
339
- /** List of transient auth witnesses to be used during this simulation */
340
- [],
341
- HashedValuesCache.create([new HashedValues(args, argsHash)]),
366
+ authWitnesses: Array.from(this.authwits.values()),
367
+ capsules: [],
368
+ executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
342
369
  noteCache,
343
370
  taggingIndexCache,
344
- this.contractStore,
345
- this.noteStore,
346
- this.keyStore,
347
- this.addressStore,
348
- this.stateMachine.node,
349
- this.senderTaggingStore,
350
- this.recipientTaggingStore,
351
- this.senderAddressBookStore,
352
- this.capsuleStore,
353
- this.privateEventStore,
354
- this.jobId,
355
- 0, // totalPublicArgsCount
356
- minRevertibleSideEffectCounter, // (start) sideEffectCounter
357
- undefined, // log
358
- undefined, // scopes
359
- /**
360
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
361
- * contract would perform, including setting senderForTags.
362
- */
363
- from,
371
+ contractStore: this.contractStore,
372
+ noteStore: this.noteStore,
373
+ keyStore: this.keyStore,
374
+ addressStore: this.addressStore,
375
+ aztecNode: this.stateMachine.node,
376
+ senderTaggingStore: this.senderTaggingStore,
377
+ recipientTaggingStore: this.recipientTaggingStore,
378
+ senderAddressBookStore: this.senderAddressBookStore,
379
+ capsuleStore: this.capsuleStore,
380
+ privateEventStore: this.privateEventStore,
381
+ contractSyncService: this.stateMachine.contractSyncService,
382
+ jobId,
383
+ totalPublicCalldataCount: 0,
384
+ sideEffectCounter: minRevertibleSideEffectCounter,
385
+ scopes: effectiveScopes,
386
+ // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
387
+ // contract would perform, including setting senderForTags.
388
+ senderForTags: from,
364
389
  simulator,
365
- );
390
+ });
366
391
 
367
392
  // Note: This is a slight modification of simulator.run without any of the checks. Maybe we should modify simulator.run with a boolean value to skip checks.
368
393
  let result: PrivateExecutionResult;
@@ -384,7 +409,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
384
409
  );
385
410
  const publicFunctionsCalldata = await Promise.all(
386
411
  publicCallRequests.map(async r => {
387
- const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
412
+ const calldata = await privateExecutionOracle.loadFromExecutionCache(r.calldataHash);
388
413
  return new HashedValues(calldata, r.calldataHash);
389
414
  }),
390
415
  );
@@ -401,7 +426,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
401
426
  // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
402
427
  const { publicInputs } = await generateSimulatedProvingResult(
403
428
  result,
404
- this.contractStore,
429
+ (addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
430
+ this.stateMachine.node,
405
431
  minRevertibleSideEffectCounter,
406
432
  );
407
433
 
@@ -497,7 +523,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
497
523
  return executionResult.returnValues ?? [];
498
524
  }
499
525
 
500
- async txePublicCallNewFlow(
526
+ async publicCallNewFlow(
501
527
  from: AztecAddress,
502
528
  targetContractAddress: AztecAddress,
503
529
  calldata: Fr[],
@@ -507,7 +533,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
507
533
  `Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
508
534
  );
509
535
 
510
- const blockNumber = await this.txeGetNextBlockNumber();
536
+ const blockNumber = await this.getNextBlockNumber();
511
537
 
512
538
  const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
513
539
 
@@ -584,7 +610,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
584
610
  constantData,
585
611
  /*gasUsed=*/ new Gas(0, 0),
586
612
  /*feePayer=*/ AztecAddress.zero(),
587
- /*includeByTimestamp=*/ 0n,
613
+ /*expirationTimestamp=*/ 0n,
588
614
  inputsForPublic,
589
615
  undefined,
590
616
  );
@@ -652,10 +678,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
652
678
  return returnValues ?? [];
653
679
  }
654
680
 
655
- async txeSimulateUtilityFunction(
681
+ async executeUtilityFunction(
656
682
  targetContractAddress: AztecAddress,
657
683
  functionSelector: FunctionSelector,
658
684
  args: Fr[],
685
+ jobId: string,
659
686
  ) {
660
687
  const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
661
688
  if (!artifact) {
@@ -663,25 +690,33 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
663
690
  }
664
691
 
665
692
  // Sync notes before executing utility function to discover notes from previous transactions
666
- await syncState(targetContractAddress, this.contractStore, functionSelector, async call => {
667
- await this.executeUtilityCall(call);
668
- });
669
-
670
- const call = new FunctionCall(
671
- artifact.name,
693
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
694
+ await this.stateMachine.contractSyncService.ensureContractSynced(
672
695
  targetContractAddress,
673
696
  functionSelector,
674
- FunctionType.UTILITY,
675
- false,
676
- false,
677
- args,
678
- [],
697
+ async (call, execScopes) => {
698
+ await this.executeUtilityCall(call, execScopes, jobId);
699
+ },
700
+ blockHeader,
701
+ jobId,
702
+ 'ALL_SCOPES',
679
703
  );
680
704
 
681
- return this.executeUtilityCall(call);
705
+ const call = FunctionCall.from({
706
+ name: artifact.name,
707
+ to: targetContractAddress,
708
+ selector: functionSelector,
709
+ type: FunctionType.UTILITY,
710
+ hideMsgSender: false,
711
+ isStatic: false,
712
+ args,
713
+ returnTypes: [],
714
+ });
715
+
716
+ return this.executeUtilityCall(call, 'ALL_SCOPES', jobId);
682
717
  }
683
718
 
684
- private async executeUtilityCall(call: FunctionCall): Promise<Fr[]> {
719
+ private async executeUtilityCall(call: FunctionCall, scopes: AccessScopes, jobId: string): Promise<Fr[]> {
685
720
  const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
686
721
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
687
722
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
@@ -694,22 +729,23 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
694
729
 
695
730
  try {
696
731
  const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
697
- const oracle = new UtilityExecutionOracle(
698
- call.to,
699
- [],
700
- [],
732
+ const oracle = new UtilityExecutionOracle({
733
+ contractAddress: call.to,
734
+ authWitnesses: [],
735
+ capsules: [],
701
736
  anchorBlockHeader,
702
- this.contractStore,
703
- this.noteStore,
704
- this.keyStore,
705
- this.addressStore,
706
- this.stateMachine.node,
707
- this.recipientTaggingStore,
708
- this.senderAddressBookStore,
709
- this.capsuleStore,
710
- this.privateEventStore,
711
- this.jobId,
712
- );
737
+ contractStore: this.contractStore,
738
+ noteStore: this.noteStore,
739
+ keyStore: this.keyStore,
740
+ addressStore: this.addressStore,
741
+ aztecNode: this.stateMachine.node,
742
+ recipientTaggingStore: this.recipientTaggingStore,
743
+ senderAddressBookStore: this.senderAddressBookStore,
744
+ capsuleStore: this.capsuleStore,
745
+ privateEventStore: this.privateEventStore,
746
+ jobId,
747
+ scopes,
748
+ });
713
749
  const acirExecutionResult = await new WASMSimulator()
714
750
  .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
715
751
  .catch((err: Error) => {
@@ -725,10 +761,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
725
761
  );
726
762
  });
727
763
 
728
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
764
+ this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
729
765
  return witnessMapToFields(acirExecutionResult.returnWitness);
730
766
  } catch (err) {
731
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility simulation'));
767
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
732
768
  }
733
769
  }
734
770