@aztec/txe 5.0.0-private.20260319 → 5.0.0-rc.1
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.
- package/dest/AuthRegistry-CPGFQR26.js +3 -0
- package/dest/AuthRegistry-CPGFQR26.js.map +7 -0
- package/dest/ContractClassRegistry-EHVIHGEK.js +3 -0
- package/dest/ContractClassRegistry-EHVIHGEK.js.map +7 -0
- package/dest/ContractInstanceRegistry-DWZDXHRG.js +3 -0
- package/dest/ContractInstanceRegistry-DWZDXHRG.js.map +7 -0
- package/dest/FeeJuice-MI32ZO7B.js +3 -0
- package/dest/FeeJuice-MI32ZO7B.js.map +7 -0
- package/dest/HandshakeRegistry-3KSP3ITH.js +3 -0
- package/dest/HandshakeRegistry-3KSP3ITH.js.map +7 -0
- package/dest/MultiCallEntrypoint-IU7HYFYE.js +3 -0
- package/dest/MultiCallEntrypoint-IU7HYFYE.js.map +7 -0
- package/dest/SchnorrAccount-6TUE7JX4.js +3 -0
- package/dest/SchnorrAccount-6TUE7JX4.js.map +7 -0
- package/dest/SchnorrInitializerlessAccount-S3DU2DJK.js +3 -0
- package/dest/SchnorrInitializerlessAccount-S3DU2DJK.js.map +7 -0
- package/dest/bin/check_txe_oracle_version.d.ts +2 -0
- package/dest/bin/check_txe_oracle_version.d.ts.map +1 -0
- package/dest/bin/check_txe_oracle_version.js +61 -0
- package/dest/bin/index.js +3 -30
- package/dest/bin/index.js.map +7 -0
- package/dest/bin/oracle_test_server.d.ts +3 -0
- package/dest/bin/oracle_test_server.d.ts.map +1 -0
- package/dest/bin/oracle_test_server.js +41 -0
- package/dest/chunk-5U25VAFR.js +265 -0
- package/dest/chunk-5U25VAFR.js.map +7 -0
- package/dest/chunk-BJVAAXNA.js +3 -0
- package/dest/chunk-BJVAAXNA.js.map +7 -0
- package/dest/chunk-UPW55EJX.js +304 -0
- package/dest/chunk-UPW55EJX.js.map +7 -0
- package/dest/constants.d.ts +5 -1
- package/dest/constants.d.ts.map +1 -1
- package/dest/constants.js +8 -0
- package/dest/dispatcher_pool.d.ts +67 -0
- package/dest/dispatcher_pool.d.ts.map +1 -0
- package/dest/dispatcher_pool.js +286 -0
- package/dest/index.d.ts +51 -7
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +70 -190
- package/dest/metafile.json +38829 -0
- package/dest/msgpackr_fr_extension.d.ts +2 -0
- package/dest/msgpackr_fr_extension.d.ts.map +1 -0
- package/dest/msgpackr_fr_extension.js +21 -0
- package/dest/oracle/interfaces.d.ts +33 -8
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/test-resolver/fixtures.d.ts +43 -0
- package/dest/oracle/test-resolver/fixtures.d.ts.map +1 -0
- package/dest/oracle/test-resolver/fixtures.js +39 -0
- package/dest/oracle/test-resolver/index.d.ts +9 -0
- package/dest/oracle/test-resolver/index.d.ts.map +1 -0
- package/dest/oracle/test-resolver/index.js +33 -0
- package/dest/oracle/test-resolver/resolver.d.ts +34 -0
- package/dest/oracle/test-resolver/resolver.d.ts.map +1 -0
- package/dest/oracle/test-resolver/resolver.js +114 -0
- package/dest/oracle/txe_oracle_public_context.d.ts +26 -2
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +43 -1
- package/dest/oracle/txe_oracle_registry.d.ts +14 -0
- package/dest/oracle/txe_oracle_registry.d.ts.map +1 -0
- package/dest/oracle/txe_oracle_registry.js +562 -0
- package/dest/oracle/txe_oracle_top_level_context.d.ts +33 -20
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +151 -58
- package/dest/oracle/txe_oracle_version.d.ts +17 -0
- package/dest/oracle/txe_oracle_version.d.ts.map +1 -0
- package/dest/oracle/txe_oracle_version.js +14 -0
- package/dest/oracle/txe_private_execution_oracle.d.ts +17 -0
- package/dest/oracle/txe_private_execution_oracle.d.ts.map +1 -0
- package/dest/oracle/txe_private_execution_oracle.js +15 -0
- package/dest/rpc_server.d.ts +14 -0
- package/dest/rpc_server.d.ts.map +1 -0
- package/dest/rpc_server.js +78 -0
- package/dest/rpc_translator.d.ts +103 -233
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +695 -636
- package/dest/server.bundle.js +3 -0
- package/dest/server.bundle.js.map +7 -0
- package/dest/state_machine/archiver.d.ts +4 -3
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +26 -15
- package/dest/state_machine/dummy_p2p_client.d.ts +14 -7
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +19 -4
- package/dest/state_machine/global_variable_builder.d.ts +9 -4
- package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
- package/dest/state_machine/global_variable_builder.js +9 -3
- package/dest/state_machine/index.d.ts +4 -2
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +11 -3
- package/dest/state_machine/mock_epoch_cache.d.ts +1 -2
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +0 -3
- package/dest/state_machine/synchronizer.js +1 -1
- package/dest/txe_session.d.ts +86 -19
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +244 -45
- package/dest/utils/encoding.d.ts +191 -0
- package/dest/utils/encoding.d.ts.map +1 -0
- package/dest/{util → utils}/encoding.js +7 -2
- package/dest/{util → utils}/expected_failure_error.d.ts +1 -1
- package/dest/utils/expected_failure_error.d.ts.map +1 -0
- package/dest/{util → utils}/txe_account_store.d.ts +1 -1
- package/dest/utils/txe_account_store.d.ts.map +1 -0
- package/dest/utils/txe_artifact_resolver.d.ts +37 -0
- package/dest/utils/txe_artifact_resolver.d.ts.map +1 -0
- package/dest/utils/txe_artifact_resolver.js +161 -0
- package/dest/utils/txe_public_contract_data_source.d.ts +20 -0
- package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -0
- package/dest/{util → utils}/txe_public_contract_data_source.js +1 -3
- package/dest/worker.bundle.js +3 -0
- package/dest/worker.bundle.js.map +7 -0
- package/dest/worker.d.ts +2 -0
- package/dest/worker.d.ts.map +1 -0
- package/dest/worker.js +92 -0
- package/package.json +38 -21
- package/src/bin/check_txe_oracle_version.ts +70 -0
- package/src/bin/index.ts +11 -2
- package/src/bin/oracle_test_server.ts +51 -0
- package/src/constants.ts +10 -0
- package/src/dispatcher_pool.ts +317 -0
- package/src/index.ts +97 -227
- package/src/msgpackr_fr_extension.ts +23 -0
- package/src/oracle/interfaces.ts +29 -7
- package/src/oracle/test-resolver/fixtures.ts +84 -0
- package/src/oracle/test-resolver/index.ts +45 -0
- package/src/oracle/test-resolver/resolver.ts +165 -0
- package/src/oracle/txe_oracle_public_context.ts +60 -0
- package/src/oracle/txe_oracle_registry.ts +401 -0
- package/src/oracle/txe_oracle_top_level_context.ts +185 -67
- package/src/oracle/txe_oracle_version.ts +17 -0
- package/src/oracle/txe_private_execution_oracle.ts +30 -0
- package/src/rpc_server.ts +87 -0
- package/src/rpc_translator.ts +765 -913
- package/src/state_machine/archiver.ts +38 -16
- package/src/state_machine/dummy_p2p_client.ts +35 -11
- package/src/state_machine/global_variable_builder.ts +18 -3
- package/src/state_machine/index.ts +17 -5
- package/src/state_machine/mock_epoch_cache.ts +0 -4
- package/src/state_machine/synchronizer.ts +1 -1
- package/src/txe_session.ts +434 -57
- package/src/{util → utils}/encoding.ts +8 -2
- package/src/utils/txe_artifact_resolver.ts +217 -0
- package/src/{util → utils}/txe_public_contract_data_source.ts +0 -2
- package/src/worker.ts +98 -0
- package/dest/util/encoding.d.ts +0 -720
- package/dest/util/encoding.d.ts.map +0 -1
- package/dest/util/expected_failure_error.d.ts.map +0 -1
- package/dest/util/txe_account_store.d.ts.map +0 -1
- package/dest/util/txe_public_contract_data_source.d.ts +0 -20
- package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
- /package/dest/{util → utils}/expected_failure_error.js +0 -0
- /package/dest/{util → utils}/txe_account_store.js +0 -0
- /package/src/{util → utils}/expected_failure_error.ts +0 -0
- /package/src/{util → utils}/txe_account_store.ts +0 -0
package/src/txe_session.ts
CHANGED
|
@@ -2,14 +2,14 @@ import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
|
2
2
|
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
|
-
import {
|
|
6
|
-
import
|
|
5
|
+
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
6
|
+
import { openEphemeralStore } from '@aztec/kv-store/lmdb-v2';
|
|
7
7
|
import {
|
|
8
8
|
AddressStore,
|
|
9
9
|
AnchorBlockStore,
|
|
10
|
+
CapsuleService,
|
|
10
11
|
CapsuleStore,
|
|
11
12
|
ContractStore,
|
|
12
|
-
ContractSyncService,
|
|
13
13
|
JobCoordinator,
|
|
14
14
|
NoteService,
|
|
15
15
|
NoteStore,
|
|
@@ -22,11 +22,13 @@ import {
|
|
|
22
22
|
ExecutionNoteCache,
|
|
23
23
|
ExecutionTaggingIndexCache,
|
|
24
24
|
HashedValuesCache,
|
|
25
|
+
type IMiscOracle,
|
|
25
26
|
type IPrivateExecutionOracle,
|
|
26
27
|
type IUtilityExecutionOracle,
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
Option,
|
|
29
|
+
TransientArrayService,
|
|
29
30
|
UtilityExecutionOracle,
|
|
31
|
+
buildACIRCallback,
|
|
30
32
|
} from '@aztec/pxe/simulator';
|
|
31
33
|
import {
|
|
32
34
|
ExecutionError,
|
|
@@ -36,28 +38,32 @@ import {
|
|
|
36
38
|
resolveAssertionMessageFromError,
|
|
37
39
|
toACVMWitness,
|
|
38
40
|
} from '@aztec/simulator/client';
|
|
39
|
-
import {
|
|
41
|
+
import { STANDARD_AUTH_REGISTRY_ADDRESS } from '@aztec/standard-contracts/auth-registry/constants';
|
|
42
|
+
import { EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
40
43
|
import type { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
41
44
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
42
|
-
import { GasSettings } from '@aztec/stdlib/gas';
|
|
45
|
+
import type { GasSettings } from '@aztec/stdlib/gas';
|
|
43
46
|
import { computeProtocolNullifier } from '@aztec/stdlib/hash';
|
|
44
47
|
import { PrivateContextInputs } from '@aztec/stdlib/kernel';
|
|
45
48
|
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
46
|
-
import { CallContext, GlobalVariables, TxContext } from '@aztec/stdlib/tx';
|
|
49
|
+
import { CallContext, GlobalVariables, OFFCHAIN_MESSAGE_IDENTIFIER, TxContext } from '@aztec/stdlib/tx';
|
|
47
50
|
|
|
48
51
|
import { z } from 'zod';
|
|
49
52
|
|
|
50
|
-
import { DEFAULT_ADDRESS } from './constants.js';
|
|
53
|
+
import { DEFAULT_ADDRESS, MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY, MAX_OFFCHAIN_EFFECT_LEN } from './constants.js';
|
|
51
54
|
import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
|
|
52
55
|
import { TXEOraclePublicContext } from './oracle/txe_oracle_public_context.js';
|
|
53
56
|
import { TXEOracleTopLevelContext } from './oracle/txe_oracle_top_level_context.js';
|
|
54
|
-
import {
|
|
57
|
+
import { TXE_ORACLE_VERSION_MAJOR, TXE_ORACLE_VERSION_MINOR } from './oracle/txe_oracle_version.js';
|
|
58
|
+
import { TXEPrivateExecutionOracle } from './oracle/txe_private_execution_oracle.js';
|
|
59
|
+
import { RPCTranslator, UnavailableOracleError } from './rpc_translator.js';
|
|
55
60
|
import { TXEArchiver } from './state_machine/archiver.js';
|
|
56
61
|
import { TXEStateMachine } from './state_machine/index.js';
|
|
57
|
-
import type { ForeignCallArgs, ForeignCallResult } from './util/encoding.js';
|
|
58
|
-
import { TXEAccountStore } from './util/txe_account_store.js';
|
|
59
62
|
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from './utils/block_creation.js';
|
|
63
|
+
import type { ForeignCallArgs, ForeignCallResult } from './utils/encoding.js';
|
|
60
64
|
import { makeTxEffect } from './utils/tx_effect_creation.js';
|
|
65
|
+
import { TXEAccountStore } from './utils/txe_account_store.js';
|
|
66
|
+
import type { TXEArtifactResolver } from './utils/txe_artifact_resolver.js';
|
|
61
67
|
|
|
62
68
|
/**
|
|
63
69
|
* A TXE Session can be in one of four states, which change as the test progresses and different oracles are called.
|
|
@@ -110,14 +116,110 @@ export type TXEOracleFunctionName = Exclude<
|
|
|
110
116
|
>;
|
|
111
117
|
|
|
112
118
|
export interface TXESessionStateHandler {
|
|
119
|
+
/** Records the TXE oracle version reported by the Noir test code for diagnostics. */
|
|
120
|
+
setTxeOracleVersion(major: number, minor: number): void;
|
|
121
|
+
|
|
113
122
|
enterTopLevelState(): Promise<void>;
|
|
114
|
-
enterPublicState(contractAddress
|
|
115
|
-
enterPrivateState(
|
|
116
|
-
|
|
123
|
+
enterPublicState(contractAddress: Option<AztecAddress>): Promise<void>;
|
|
124
|
+
enterPrivateState(
|
|
125
|
+
contractAddress: Option<AztecAddress>,
|
|
126
|
+
anchorBlockNumber: Option<BlockNumber>,
|
|
127
|
+
gasSettings: GasSettings,
|
|
128
|
+
): Promise<PrivateContextInputs>;
|
|
129
|
+
enterUtilityState(contractAddress: Option<AztecAddress>): Promise<void>;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Executes a top-level private call: runs the private function, drains its offchain effects into the session buffer,
|
|
133
|
+
* commits the job, and (for non-static calls) tags the result with the mined tx hash.
|
|
134
|
+
*/
|
|
135
|
+
executePrivateCall(
|
|
136
|
+
from: Option<AztecAddress>,
|
|
137
|
+
targetContractAddress: AztecAddress,
|
|
138
|
+
functionSelector: FunctionSelector,
|
|
139
|
+
args: Fr[],
|
|
140
|
+
argsHash: Fr,
|
|
141
|
+
isStaticCall: boolean,
|
|
142
|
+
additionalScopes: AztecAddress[],
|
|
143
|
+
authorizedUtilityCallTargets: AztecAddress[],
|
|
144
|
+
gasSettings: GasSettings,
|
|
145
|
+
): Promise<Fr[]>;
|
|
146
|
+
|
|
147
|
+
/** Executes a top-level utility function and commits the job. */
|
|
148
|
+
executeUtilityFunction(
|
|
149
|
+
targetContractAddress: AztecAddress,
|
|
150
|
+
functionSelector: FunctionSelector,
|
|
151
|
+
args: Fr[],
|
|
152
|
+
authorizedUtilityCallTargets: AztecAddress[],
|
|
153
|
+
): Promise<Fr[]>;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Executes a top-level public call, commits the job, and (for non-static calls) tags the result with the mined tx
|
|
157
|
+
* hash.
|
|
158
|
+
*/
|
|
159
|
+
executePublicCall(
|
|
160
|
+
from: Option<AztecAddress>,
|
|
161
|
+
targetContractAddress: AztecAddress,
|
|
162
|
+
calldata: Fr[],
|
|
163
|
+
isStaticCall: boolean,
|
|
164
|
+
gasSettings: GasSettings,
|
|
165
|
+
): Promise<Fr[]>;
|
|
166
|
+
|
|
167
|
+
/** Syncs the target contract and returns the private events it emitted matching the given selector and scope. */
|
|
168
|
+
getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress): Promise<Fr[][]>;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Captures a raw offchain effect payload for consumption from test environment. Called by the `emit_offchain_effect`
|
|
172
|
+
* oracle handler whenever a contract function emits an offchain message, at any call depth.
|
|
173
|
+
*/
|
|
174
|
+
recordOffchainEffect(data: Fr[]): void;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Returns the raw offchain effect payloads emitted by the last top-level call. Each payload follows the protocol
|
|
178
|
+
* convention documented on `OFFCHAIN_MESSAGE_IDENTIFIER`, i.e. `[identifier, recipient, ...ciphertext]`. Decoding into
|
|
179
|
+
* `OffchainMessage` structs happens on the Noir side of the test helper. Marks the buffer as queried so the
|
|
180
|
+
* unqueried-messages warning doesn't fire on the next reset.
|
|
181
|
+
*/
|
|
182
|
+
getLastCallOffchainEffects(): { effects: Fr[][] };
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Returns the context of the last top-level call: its tx hash (`Fr.ZERO` if the call was tx-less) and the anchor
|
|
186
|
+
* block timestamp captured at the start of the call. Does *not* mark the buffer as queried — context reads are
|
|
187
|
+
* metadata, not effect consumption.
|
|
188
|
+
*/
|
|
189
|
+
getLastCallContext(): { txHash: Fr; anchorBlockTimestamp: bigint };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Session state tracking the most recently completed top-level call: the offchain effect buffer it produced, and the
|
|
194
|
+
* call's context (tx hash + anchor block timestamp). The context is refreshed on every top-level call, independently
|
|
195
|
+
* of whether the call produced offchain effects.
|
|
196
|
+
*/
|
|
197
|
+
interface LastCallState {
|
|
198
|
+
/**
|
|
199
|
+
* Raw offchain effect payloads emitted by the currently-executing (or most recently completed) top-level call. Wiped
|
|
200
|
+
* at the start of every top-level entry point, appended to on every `emit_offchain_effect` oracle invocation.
|
|
201
|
+
*/
|
|
202
|
+
offchainEffects: Fr[][];
|
|
203
|
+
/**
|
|
204
|
+
* Tracks whether the test has queried `effects` since the last reset. If a new top-level call clobbers the buffer
|
|
205
|
+
* without it being queried first, any accumulated messages are lost and we emit a warning so tests don't silently
|
|
206
|
+
* drop delivery.
|
|
207
|
+
*/
|
|
208
|
+
queried: boolean;
|
|
209
|
+
/**
|
|
210
|
+
* Tx hash of the most recently completed top-level call, or `Fr.ZERO` if the call was tx-less (context setters,
|
|
211
|
+
* utility execution). Populated by call executor handlers after execution completes.
|
|
212
|
+
*/
|
|
213
|
+
txHash: Fr;
|
|
214
|
+
/**
|
|
215
|
+
* Anchor block timestamp of the most recently completed top-level call, captured from the anchor block header that
|
|
216
|
+
* was active when the call started. Populated by call executor handlers after execution completes.
|
|
217
|
+
*/
|
|
218
|
+
anchorBlockTimestamp: bigint;
|
|
219
|
+
}
|
|
117
220
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
getCurrentJob(): string;
|
|
221
|
+
function emptyLastCallState(): LastCallState {
|
|
222
|
+
return { offchainEffects: [], queried: false, txHash: Fr.ZERO, anchorBlockTimestamp: 0n };
|
|
121
223
|
}
|
|
122
224
|
|
|
123
225
|
/**
|
|
@@ -127,11 +229,17 @@ export interface TXESessionStateHandler {
|
|
|
127
229
|
export class TXESession implements TXESessionStateHandler {
|
|
128
230
|
private state: SessionState = { name: 'TOP_LEVEL' };
|
|
129
231
|
private authwits: Map<string, AuthWitness> = new Map();
|
|
232
|
+
private lastCallInfo: LastCallState = emptyLastCallState();
|
|
233
|
+
private txeOracleVersion: { major: number; minor: number } | undefined;
|
|
234
|
+
|
|
235
|
+
private disposed = false;
|
|
130
236
|
|
|
131
237
|
constructor(
|
|
132
238
|
private logger: Logger,
|
|
239
|
+
private sessionStore: AztecAsyncKVStore,
|
|
133
240
|
private stateMachine: TXEStateMachine,
|
|
134
241
|
private oracleHandler:
|
|
242
|
+
| IMiscOracle
|
|
135
243
|
| IUtilityExecutionOracle
|
|
136
244
|
| IPrivateExecutionOracle
|
|
137
245
|
| IAvmExecutionOracle
|
|
@@ -151,11 +259,43 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
151
259
|
private chainId: Fr,
|
|
152
260
|
private version: Fr,
|
|
153
261
|
private nextBlockTimestamp: bigint,
|
|
154
|
-
private
|
|
262
|
+
private readonly artifactResolver: TXEArtifactResolver,
|
|
263
|
+
private readonly rootPath: string,
|
|
264
|
+
private readonly packageName: string,
|
|
155
265
|
) {}
|
|
156
266
|
|
|
157
|
-
|
|
158
|
-
|
|
267
|
+
/**
|
|
268
|
+
* Closes the per-session `txe-session` LMDB and the `NativeWorldStateService` .
|
|
269
|
+
* Called via IPC when the dispatcher detects the end of a test. Idempotent.
|
|
270
|
+
*/
|
|
271
|
+
async dispose(): Promise<void> {
|
|
272
|
+
if (this.disposed) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
this.disposed = true;
|
|
276
|
+
try {
|
|
277
|
+
await this.stateMachine.synchronizer.nativeWorldStateService.close();
|
|
278
|
+
} catch (err) {
|
|
279
|
+
this.logger.warn(`Error closing native world state during session dispose`, err);
|
|
280
|
+
}
|
|
281
|
+
try {
|
|
282
|
+
await this.sessionStore.close();
|
|
283
|
+
} catch (err) {
|
|
284
|
+
this.logger.warn(`Error closing session LMDB during dispose`, err);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
static async init(
|
|
289
|
+
contractStore: ContractStore,
|
|
290
|
+
artifactResolver: TXEArtifactResolver,
|
|
291
|
+
rootPath: string,
|
|
292
|
+
packageName: string,
|
|
293
|
+
) {
|
|
294
|
+
// Size LMDB's reader slots to the libuv pool (capped to 2 in bin/index.ts via
|
|
295
|
+
// HARDWARE_CONCURRENCY): each native LMDB read needs a libuv worker thread to run, so any
|
|
296
|
+
// slot beyond the pool size would sit idle while still consuming a semaphore + reader-table
|
|
297
|
+
// entry per session.
|
|
298
|
+
const store = await openEphemeralStore('txe-session', undefined, 2);
|
|
159
299
|
|
|
160
300
|
const addressStore = new AddressStore(store);
|
|
161
301
|
const privateEventStore = new PrivateEventStore(store);
|
|
@@ -167,7 +307,6 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
167
307
|
const keyStore = new KeyStore(store);
|
|
168
308
|
const accountStore = new TXEAccountStore(store);
|
|
169
309
|
|
|
170
|
-
// Create job coordinator and register staged stores
|
|
171
310
|
const jobCoordinator = new JobCoordinator(store);
|
|
172
311
|
jobCoordinator.registerStores([
|
|
173
312
|
capsuleStore,
|
|
@@ -188,7 +327,6 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
188
327
|
const initialJobId = jobCoordinator.beginJob();
|
|
189
328
|
|
|
190
329
|
const logger = createLogger('txe:session');
|
|
191
|
-
const contractSyncService = new ContractSyncService(stateMachine.node, contractStore, noteStore, logger);
|
|
192
330
|
|
|
193
331
|
const topLevelOracleHandler = new TXEOracleTopLevelContext(
|
|
194
332
|
stateMachine,
|
|
@@ -206,12 +344,16 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
206
344
|
version,
|
|
207
345
|
chainId,
|
|
208
346
|
new Map(),
|
|
209
|
-
|
|
347
|
+
artifactResolver,
|
|
348
|
+
rootPath,
|
|
349
|
+
packageName,
|
|
210
350
|
);
|
|
211
|
-
|
|
351
|
+
|
|
352
|
+
await topLevelOracleHandler.mineDeploymentNullifiers([STANDARD_AUTH_REGISTRY_ADDRESS]);
|
|
212
353
|
|
|
213
354
|
return new TXESession(
|
|
214
355
|
logger,
|
|
356
|
+
store,
|
|
215
357
|
stateMachine,
|
|
216
358
|
topLevelOracleHandler,
|
|
217
359
|
contractStore,
|
|
@@ -229,7 +371,9 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
229
371
|
version,
|
|
230
372
|
chainId,
|
|
231
373
|
nextBlockTimestamp,
|
|
232
|
-
|
|
374
|
+
artifactResolver,
|
|
375
|
+
rootPath,
|
|
376
|
+
packageName,
|
|
233
377
|
);
|
|
234
378
|
}
|
|
235
379
|
|
|
@@ -251,7 +395,28 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
251
395
|
return translator[validatedFunctionName](...inputs);
|
|
252
396
|
} catch (error) {
|
|
253
397
|
if (error instanceof z.ZodError) {
|
|
254
|
-
|
|
398
|
+
let versionHint: string;
|
|
399
|
+
if (!this.txeOracleVersion) {
|
|
400
|
+
versionHint =
|
|
401
|
+
' The test appears to use an older version of Aztec.nr that does not' +
|
|
402
|
+
' support test environment oracle versioning. Update Aztec.nr to a compatible version.' +
|
|
403
|
+
' See https://docs.aztec.network/errors/12';
|
|
404
|
+
} else if (this.txeOracleVersion.minor > TXE_ORACLE_VERSION_MINOR) {
|
|
405
|
+
versionHint =
|
|
406
|
+
` The test uses Aztec.nr test oracle version` +
|
|
407
|
+
` ${this.txeOracleVersion.major}.${this.txeOracleVersion.minor}, but this test environment` +
|
|
408
|
+
` only supports up to ${TXE_ORACLE_VERSION_MAJOR}.${TXE_ORACLE_VERSION_MINOR}.` +
|
|
409
|
+
` Upgrade the Aztec CLI to a compatible version.` +
|
|
410
|
+
` See https://docs.aztec.network/errors/12`;
|
|
411
|
+
} else {
|
|
412
|
+
versionHint =
|
|
413
|
+
` The test's oracle version (${this.txeOracleVersion.major}.${this.txeOracleVersion.minor})` +
|
|
414
|
+
` is compatible with this test environment` +
|
|
415
|
+
` (${TXE_ORACLE_VERSION_MAJOR}.${TXE_ORACLE_VERSION_MINOR}), so this oracle should be` +
|
|
416
|
+
` available. This is an unexpected error, please report it.` +
|
|
417
|
+
` See https://docs.aztec.network/errors/13`;
|
|
418
|
+
}
|
|
419
|
+
throw new Error(`Unknown oracle '${functionName}'.${versionHint}`);
|
|
255
420
|
} else if (error instanceof Error) {
|
|
256
421
|
throw new Error(
|
|
257
422
|
`Execution error while processing function ${functionName} in state ${this.state.name}: ${error.message}`,
|
|
@@ -264,17 +429,193 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
264
429
|
}
|
|
265
430
|
}
|
|
266
431
|
|
|
267
|
-
getCurrentJob(): string {
|
|
268
|
-
return this.currentJobId;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
432
|
/** Commits the current job and begins a new one. Returns the new job ID. */
|
|
272
|
-
async cycleJob(): Promise<string> {
|
|
433
|
+
private async cycleJob(): Promise<string> {
|
|
273
434
|
await this.jobCoordinator.commitJob(this.currentJobId);
|
|
274
435
|
this.currentJobId = this.jobCoordinator.beginJob();
|
|
275
436
|
return this.currentJobId;
|
|
276
437
|
}
|
|
277
438
|
|
|
439
|
+
private resetLastCall(): void {
|
|
440
|
+
const notQueriedMessageCount = this.lastCallInfo.queried
|
|
441
|
+
? 0
|
|
442
|
+
: this.lastCallInfo.offchainEffects.filter(payload => payload[0]?.equals(OFFCHAIN_MESSAGE_IDENTIFIER)).length;
|
|
443
|
+
if (notQueriedMessageCount > 0) {
|
|
444
|
+
this.logger.warn(
|
|
445
|
+
`Dropping ${notQueriedMessageCount} unqueried offchain message(s) from the previous top-level call. ` +
|
|
446
|
+
`To deliver them, call \`env.offchain_messages()\` and forward the result to the recipient contract's ` +
|
|
447
|
+
`\`offchain_receive\` utility before issuing another top-level call. To intentionally discard, assign ` +
|
|
448
|
+
`to \`let _ = env.offchain_messages()\` to silence this warning.`,
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
this.lastCallInfo = emptyLastCallState();
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
recordOffchainEffect(data: Fr[]): void {
|
|
455
|
+
this.lastCallInfo.offchainEffects.push(data);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
private setLastCallContext(txHash: Fr, anchorBlockTimestamp: bigint): void {
|
|
459
|
+
this.lastCallInfo.txHash = txHash;
|
|
460
|
+
this.lastCallInfo.anchorBlockTimestamp = anchorBlockTimestamp;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
private async withTopLevelCallTracking<T>(work: () => Promise<{ result: T; txHash?: Fr }>): Promise<T> {
|
|
464
|
+
this.resetLastCall();
|
|
465
|
+
// Capture the anchor *before* `work` runs: private/public executor calls mine a new block as a
|
|
466
|
+
// side effect, and that block's timestamp should not be attributed to this call's anchor.
|
|
467
|
+
const anchorBlockTimestamp = (await this.stateMachine.node.getBlockData('latest'))!.header.globalVariables
|
|
468
|
+
.timestamp;
|
|
469
|
+
const { result, txHash } = await work();
|
|
470
|
+
this.setLastCallContext(txHash ?? Fr.ZERO, anchorBlockTimestamp);
|
|
471
|
+
return result;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
getLastCallOffchainEffects(): { effects: Fr[][] } {
|
|
475
|
+
this.lastCallInfo.queried = true;
|
|
476
|
+
const effects = this.lastCallInfo.offchainEffects;
|
|
477
|
+
|
|
478
|
+
if (effects.length > MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY) {
|
|
479
|
+
throw new Error(`${effects.length} offchain effects exceed max ${MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY}`);
|
|
480
|
+
}
|
|
481
|
+
if (effects.some(e => e.length > MAX_OFFCHAIN_EFFECT_LEN)) {
|
|
482
|
+
throw new Error(`Some offchain effect has length larger than max ${MAX_OFFCHAIN_EFFECT_LEN}`);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
return { effects };
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
getLastCallContext(): { txHash: Fr; anchorBlockTimestamp: bigint } {
|
|
489
|
+
const { txHash, anchorBlockTimestamp } = this.lastCallInfo;
|
|
490
|
+
return { txHash, anchorBlockTimestamp };
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
async executePrivateCall(
|
|
494
|
+
from: Option<AztecAddress>,
|
|
495
|
+
targetContractAddress: AztecAddress,
|
|
496
|
+
functionSelector: FunctionSelector,
|
|
497
|
+
args: Fr[],
|
|
498
|
+
argsHash: Fr,
|
|
499
|
+
isStaticCall: boolean,
|
|
500
|
+
additionalScopes: AztecAddress[],
|
|
501
|
+
authorizedUtilityCallTargets: AztecAddress[],
|
|
502
|
+
gasSettings: GasSettings,
|
|
503
|
+
): Promise<Fr[]> {
|
|
504
|
+
const handler = this.handlerAsTxe();
|
|
505
|
+
return await this.withTopLevelCallTracking(async () => {
|
|
506
|
+
const { returnValues, offchainEffects } = await handler.privateCallNewFlow(
|
|
507
|
+
from?.value,
|
|
508
|
+
targetContractAddress,
|
|
509
|
+
functionSelector,
|
|
510
|
+
args,
|
|
511
|
+
argsHash,
|
|
512
|
+
isStaticCall,
|
|
513
|
+
additionalScopes,
|
|
514
|
+
this.currentJobId,
|
|
515
|
+
authorizedUtilityCallTargets,
|
|
516
|
+
gasSettings,
|
|
517
|
+
);
|
|
518
|
+
|
|
519
|
+
// Private execution collects offchain effects inside PXE's PrivateExecutionOracle rather than round-tripping
|
|
520
|
+
// them through `aztec_utl_emitOffchainEffect`, so the session buffer is empty at this point. Drain the effects
|
|
521
|
+
// from the execution tree into the session buffer so the next `env.offchain_messages()` call in the test sees
|
|
522
|
+
// them.
|
|
523
|
+
for (const data of offchainEffects) {
|
|
524
|
+
this.recordOffchainEffect(data);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
await this.cycleJob();
|
|
528
|
+
|
|
529
|
+
if (isStaticCall) {
|
|
530
|
+
// Static calls revert their checkpoint and mine no block, so there is no tx hash to tag offchain effects
|
|
531
|
+
// with. Querying `getLastTxEffects()` here would return an unrelated predecessor tx.
|
|
532
|
+
return { result: returnValues };
|
|
533
|
+
}
|
|
534
|
+
const { txHash } = await handler.getLastTxEffects();
|
|
535
|
+
return { result: returnValues, txHash: txHash.hash };
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
async executeUtilityFunction(
|
|
540
|
+
targetContractAddress: AztecAddress,
|
|
541
|
+
functionSelector: FunctionSelector,
|
|
542
|
+
args: Fr[],
|
|
543
|
+
authorizedUtilityCallTargets: AztecAddress[],
|
|
544
|
+
): Promise<Fr[]> {
|
|
545
|
+
const handler = this.handlerAsTxe();
|
|
546
|
+
return await this.withTopLevelCallTracking(async () => {
|
|
547
|
+
const returnValues = await handler.executeUtilityFunction(
|
|
548
|
+
targetContractAddress,
|
|
549
|
+
functionSelector,
|
|
550
|
+
args,
|
|
551
|
+
this.currentJobId,
|
|
552
|
+
authorizedUtilityCallTargets,
|
|
553
|
+
);
|
|
554
|
+
|
|
555
|
+
await this.cycleJob();
|
|
556
|
+
|
|
557
|
+
return { result: returnValues };
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
async executePublicCall(
|
|
562
|
+
from: Option<AztecAddress>,
|
|
563
|
+
targetContractAddress: AztecAddress,
|
|
564
|
+
calldata: Fr[],
|
|
565
|
+
isStaticCall: boolean,
|
|
566
|
+
gasSettings: GasSettings,
|
|
567
|
+
): Promise<Fr[]> {
|
|
568
|
+
const handler = this.handlerAsTxe();
|
|
569
|
+
return await this.withTopLevelCallTracking(async () => {
|
|
570
|
+
const returnValues = await handler.publicCallNewFlow(
|
|
571
|
+
from?.value,
|
|
572
|
+
targetContractAddress,
|
|
573
|
+
calldata,
|
|
574
|
+
isStaticCall,
|
|
575
|
+
gasSettings,
|
|
576
|
+
);
|
|
577
|
+
|
|
578
|
+
await this.cycleJob();
|
|
579
|
+
|
|
580
|
+
if (isStaticCall) {
|
|
581
|
+
// See the equivalent branch in `executePrivateCall`.
|
|
582
|
+
return { result: returnValues };
|
|
583
|
+
}
|
|
584
|
+
const { txHash } = await handler.getLastTxEffects();
|
|
585
|
+
return { result: returnValues, txHash: txHash.hash };
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress): Promise<Fr[][]> {
|
|
590
|
+
const handler = this.handlerAsTxe();
|
|
591
|
+
await handler.syncContractNonOracleMethod(contractAddress, scope, this.currentJobId);
|
|
592
|
+
// Cycle the job to commit the stores after the contract sync.
|
|
593
|
+
await this.cycleJob();
|
|
594
|
+
return handler.getPrivateEvents(selector, contractAddress, scope);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
private handlerAsTxe(): ITxeExecutionOracle {
|
|
598
|
+
if (!('isTxe' in this.oracleHandler)) {
|
|
599
|
+
throw new UnavailableOracleError('Txe');
|
|
600
|
+
}
|
|
601
|
+
return this.oracleHandler;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
setTxeOracleVersion(major: number, minor: number): void {
|
|
605
|
+
if (major !== TXE_ORACLE_VERSION_MAJOR) {
|
|
606
|
+
const hint =
|
|
607
|
+
major > TXE_ORACLE_VERSION_MAJOR
|
|
608
|
+
? 'The test was compiled with a newer version of Aztec.nr than your test environment supports. Upgrade your test environment to a compatible version.'
|
|
609
|
+
: 'The test was compiled with an older version of Aztec.nr than your test environment supports. Recompile the test with a compatible version of Aztec.nr.';
|
|
610
|
+
throw new Error(
|
|
611
|
+
`Incompatible test environment version: ${hint} See https://docs.aztec.network/errors/12 (expected test oracle major version ${TXE_ORACLE_VERSION_MAJOR}, got ${major})`,
|
|
612
|
+
);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
this.txeOracleVersion = { major, minor };
|
|
616
|
+
this.logger.debug(`Test compiled with test oracle version ${major}.${minor}`);
|
|
617
|
+
}
|
|
618
|
+
|
|
278
619
|
async enterTopLevelState() {
|
|
279
620
|
switch (this.state.name) {
|
|
280
621
|
case 'PRIVATE': {
|
|
@@ -316,7 +657,9 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
316
657
|
this.version,
|
|
317
658
|
this.chainId,
|
|
318
659
|
this.authwits,
|
|
319
|
-
this.
|
|
660
|
+
this.artifactResolver,
|
|
661
|
+
this.rootPath,
|
|
662
|
+
this.packageName,
|
|
320
663
|
);
|
|
321
664
|
|
|
322
665
|
this.state = { name: 'TOP_LEVEL' };
|
|
@@ -324,21 +667,25 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
324
667
|
}
|
|
325
668
|
|
|
326
669
|
async enterPrivateState(
|
|
327
|
-
|
|
328
|
-
|
|
670
|
+
contractAddressOpt: Option<AztecAddress>,
|
|
671
|
+
anchorBlockNumberOpt: Option<BlockNumber>,
|
|
672
|
+
gasSettings: GasSettings,
|
|
329
673
|
): Promise<PrivateContextInputs> {
|
|
674
|
+
const contractAddress = contractAddressOpt?.value ?? DEFAULT_ADDRESS;
|
|
675
|
+
const anchorBlockNumber = anchorBlockNumberOpt?.value;
|
|
330
676
|
this.exitTopLevelState();
|
|
677
|
+
this.resetLastCall();
|
|
331
678
|
|
|
332
679
|
// Private execution has two associated block numbers: the anchor block (i.e. the historical block that is used to
|
|
333
680
|
// build the proof), and the *next* block, i.e. the one we'll create once the execution ends, and which will contain
|
|
334
681
|
// a single transaction with the effects of what was done in the test.
|
|
335
|
-
const anchorBlock = await this.stateMachine.node.
|
|
682
|
+
const anchorBlock = await this.stateMachine.node.getBlock(anchorBlockNumber ?? 'latest').then(b => b?.header);
|
|
336
683
|
|
|
337
684
|
await new NoteService(this.noteStore, this.stateMachine.node, anchorBlock!, this.currentJobId).syncNoteNullifiers(
|
|
338
685
|
contractAddress,
|
|
339
|
-
|
|
686
|
+
await this.keyStore.getAccounts(),
|
|
340
687
|
);
|
|
341
|
-
const latestBlock = await this.stateMachine.node.
|
|
688
|
+
const latestBlock = await this.stateMachine.node.getBlock('latest').then(b => b?.header);
|
|
342
689
|
|
|
343
690
|
const nextBlockGlobalVariables = makeGlobalVariables(undefined, {
|
|
344
691
|
blockNumber: BlockNumber(latestBlock!.globalVariables.blockNumber + 1),
|
|
@@ -353,9 +700,10 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
353
700
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
354
701
|
|
|
355
702
|
const utilityExecutor = this.utilityExecutorForContractSync(anchorBlock);
|
|
356
|
-
|
|
703
|
+
const transientArrayService = new TransientArrayService();
|
|
704
|
+
this.oracleHandler = new TXEPrivateExecutionOracle({
|
|
357
705
|
argsHash: Fr.ZERO,
|
|
358
|
-
txContext: new TxContext(this.chainId, this.version,
|
|
706
|
+
txContext: new TxContext(this.chainId, this.version, gasSettings),
|
|
359
707
|
callContext: new CallContext(AztecAddress.ZERO, contractAddress, FunctionSelector.empty(), false),
|
|
360
708
|
anchorBlockHeader: anchorBlock!,
|
|
361
709
|
utilityExecutor,
|
|
@@ -372,12 +720,15 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
372
720
|
senderTaggingStore: this.senderTaggingStore,
|
|
373
721
|
recipientTaggingStore: this.recipientTaggingStore,
|
|
374
722
|
senderAddressBookStore: this.senderAddressBookStore,
|
|
375
|
-
|
|
723
|
+
capsuleService: new CapsuleService(this.capsuleStore, await this.keyStore.getAccounts()),
|
|
376
724
|
privateEventStore: this.privateEventStore,
|
|
377
725
|
contractSyncService: this.stateMachine.contractSyncService,
|
|
726
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
378
727
|
jobId: this.currentJobId,
|
|
379
|
-
scopes:
|
|
728
|
+
scopes: await this.keyStore.getAccounts(),
|
|
380
729
|
messageContextService: this.stateMachine.messageContextService,
|
|
730
|
+
simulator: new WASMSimulator(),
|
|
731
|
+
transientArrayService,
|
|
381
732
|
});
|
|
382
733
|
|
|
383
734
|
// We store the note and tagging index caches fed into the PrivateExecutionOracle (along with some other auxiliary
|
|
@@ -388,35 +739,47 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
388
739
|
this.state = { name: 'PRIVATE', nextBlockGlobalVariables, noteCache, taggingIndexCache };
|
|
389
740
|
this.logger.debug(`Entered state ${this.state.name}`);
|
|
390
741
|
|
|
391
|
-
|
|
742
|
+
// Record the *resolved* anchor's timestamp — if the caller pinned the anchor to a past block
|
|
743
|
+
// via `anchorBlockNumber`, "latest" would be the wrong anchor for offchain-message semantics.
|
|
744
|
+
this.setLastCallContext(Fr.ZERO, anchorBlock!.globalVariables.timestamp);
|
|
745
|
+
|
|
746
|
+
return (this.oracleHandler as TXEPrivateExecutionOracle).getPrivateContextInputs();
|
|
392
747
|
}
|
|
393
748
|
|
|
394
|
-
async enterPublicState(
|
|
749
|
+
async enterPublicState(contractAddressOpt: Option<AztecAddress>) {
|
|
750
|
+
const contractAddress = contractAddressOpt?.value ?? DEFAULT_ADDRESS;
|
|
395
751
|
this.exitTopLevelState();
|
|
752
|
+
this.resetLastCall();
|
|
396
753
|
|
|
397
754
|
// The PublicContext will create a block with a single transaction in it, containing the effects of what was done in
|
|
398
755
|
// the test. The block therefore gets the *next* block number and timestamp.
|
|
399
|
-
const
|
|
756
|
+
const latestHeader = (await this.stateMachine.node.getBlockData('latest'))!.header;
|
|
400
757
|
const globalVariables = makeGlobalVariables(undefined, {
|
|
401
|
-
blockNumber: BlockNumber(
|
|
758
|
+
blockNumber: BlockNumber(latestHeader.globalVariables.blockNumber + 1),
|
|
402
759
|
timestamp: this.nextBlockTimestamp,
|
|
403
760
|
version: this.version,
|
|
404
761
|
chainId: this.chainId,
|
|
405
762
|
});
|
|
406
763
|
|
|
407
764
|
this.oracleHandler = new TXEOraclePublicContext(
|
|
408
|
-
contractAddress
|
|
765
|
+
contractAddress,
|
|
409
766
|
await this.stateMachine.synchronizer.nativeWorldStateService.fork(),
|
|
410
767
|
getSingleTxBlockRequestHash(globalVariables.blockNumber),
|
|
411
768
|
globalVariables,
|
|
769
|
+
this.contractStore,
|
|
412
770
|
);
|
|
413
771
|
|
|
414
772
|
this.state = { name: 'PUBLIC' };
|
|
415
773
|
this.logger.debug(`Entered state ${this.state.name}`);
|
|
774
|
+
|
|
775
|
+
// Public state is anchored at the latest block.
|
|
776
|
+
this.setLastCallContext(Fr.ZERO, latestHeader.globalVariables.timestamp);
|
|
416
777
|
}
|
|
417
778
|
|
|
418
|
-
async enterUtilityState(
|
|
779
|
+
async enterUtilityState(contractAddressOpt: Option<AztecAddress>) {
|
|
780
|
+
const contractAddress = contractAddressOpt?.value ?? DEFAULT_ADDRESS;
|
|
419
781
|
this.exitTopLevelState();
|
|
782
|
+
this.resetLastCall();
|
|
420
783
|
|
|
421
784
|
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
422
785
|
|
|
@@ -430,7 +793,7 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
430
793
|
this.stateMachine.node,
|
|
431
794
|
anchorBlockHeader,
|
|
432
795
|
this.currentJobId,
|
|
433
|
-
).syncNoteNullifiers(contractAddress,
|
|
796
|
+
).syncNoteNullifiers(contractAddress, await this.keyStore.getAccounts());
|
|
434
797
|
|
|
435
798
|
this.oracleHandler = new UtilityExecutionOracle({
|
|
436
799
|
contractAddress,
|
|
@@ -444,16 +807,24 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
444
807
|
aztecNode: this.stateMachine.node,
|
|
445
808
|
recipientTaggingStore: this.recipientTaggingStore,
|
|
446
809
|
senderAddressBookStore: this.senderAddressBookStore,
|
|
447
|
-
|
|
810
|
+
capsuleService: new CapsuleService(this.capsuleStore, await this.keyStore.getAccounts()),
|
|
448
811
|
privateEventStore: this.privateEventStore,
|
|
449
812
|
messageContextService: this.stateMachine.messageContextService,
|
|
450
|
-
contractSyncService: this.contractSyncService,
|
|
813
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
814
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
451
815
|
jobId: this.currentJobId,
|
|
452
|
-
scopes:
|
|
816
|
+
scopes: await this.keyStore.getAccounts(),
|
|
817
|
+
simulator: new WASMSimulator(),
|
|
818
|
+
utilityExecutor: this.utilityExecutorForContractSync(anchorBlockHeader),
|
|
819
|
+
// Execution-tree root (top-level utility run): own store; nested frames inherit it.
|
|
820
|
+
transientArrayService: new TransientArrayService(),
|
|
453
821
|
});
|
|
454
822
|
|
|
455
823
|
this.state = { name: 'UTILITY' };
|
|
456
824
|
this.logger.debug(`Entered state ${this.state.name}`);
|
|
825
|
+
|
|
826
|
+
// Utility state anchors at whatever the anchor block store is pointing to (tracked as latest).
|
|
827
|
+
this.setLastCallContext(Fr.ZERO, anchorBlockHeader.globalVariables.timestamp);
|
|
457
828
|
}
|
|
458
829
|
|
|
459
830
|
private exitTopLevelState() {
|
|
@@ -518,13 +889,14 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
518
889
|
}
|
|
519
890
|
|
|
520
891
|
private utilityExecutorForContractSync(anchorBlock: any) {
|
|
521
|
-
return async (call: FunctionCall, scopes:
|
|
892
|
+
return async (call: FunctionCall, scopes: AztecAddress[]) => {
|
|
522
893
|
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
523
894
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
524
895
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
525
896
|
}
|
|
526
897
|
|
|
527
898
|
try {
|
|
899
|
+
const simulator = new WASMSimulator();
|
|
528
900
|
const oracle = new UtilityExecutionOracle({
|
|
529
901
|
contractAddress: call.to,
|
|
530
902
|
authWitnesses: [],
|
|
@@ -537,15 +909,20 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
537
909
|
aztecNode: this.stateMachine.node,
|
|
538
910
|
recipientTaggingStore: this.recipientTaggingStore,
|
|
539
911
|
senderAddressBookStore: this.senderAddressBookStore,
|
|
540
|
-
|
|
912
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
541
913
|
privateEventStore: this.privateEventStore,
|
|
542
914
|
messageContextService: this.stateMachine.messageContextService,
|
|
543
|
-
contractSyncService: this.contractSyncService,
|
|
915
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
916
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
544
917
|
jobId: this.currentJobId,
|
|
545
918
|
scopes,
|
|
919
|
+
simulator,
|
|
920
|
+
utilityExecutor: this.utilityExecutorForContractSync(anchorBlock),
|
|
921
|
+
// Top-level utility entrypoint: gets a fresh store. Nested frames inherit it via UtilityExecutionOracle.
|
|
922
|
+
transientArrayService: new TransientArrayService(),
|
|
546
923
|
});
|
|
547
|
-
await
|
|
548
|
-
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact,
|
|
924
|
+
await simulator
|
|
925
|
+
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, buildACIRCallback(oracle))
|
|
549
926
|
.catch((err: Error) => {
|
|
550
927
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
551
928
|
throw new ExecutionError(
|