@aztec/txe 5.0.0-private.20260318 → 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 +32 -18
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +151 -55
- 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 -230
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +697 -616
- 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 +16 -3
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +29 -2
- package/dest/state_machine/synchronizer.js +1 -1
- package/dest/txe_session.d.ts +85 -17
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +245 -40
- 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 -64
- 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 +767 -892
- 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 +38 -3
- package/src/state_machine/synchronizer.ts +1 -1
- package/src/txe_session.ts +437 -50
- 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,11 +2,12 @@ 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
13
|
JobCoordinator,
|
|
@@ -21,11 +22,13 @@ import {
|
|
|
21
22
|
ExecutionNoteCache,
|
|
22
23
|
ExecutionTaggingIndexCache,
|
|
23
24
|
HashedValuesCache,
|
|
25
|
+
type IMiscOracle,
|
|
24
26
|
type IPrivateExecutionOracle,
|
|
25
27
|
type IUtilityExecutionOracle,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
Option,
|
|
29
|
+
TransientArrayService,
|
|
28
30
|
UtilityExecutionOracle,
|
|
31
|
+
buildACIRCallback,
|
|
29
32
|
} from '@aztec/pxe/simulator';
|
|
30
33
|
import {
|
|
31
34
|
ExecutionError,
|
|
@@ -35,28 +38,32 @@ import {
|
|
|
35
38
|
resolveAssertionMessageFromError,
|
|
36
39
|
toACVMWitness,
|
|
37
40
|
} from '@aztec/simulator/client';
|
|
38
|
-
import {
|
|
41
|
+
import { STANDARD_AUTH_REGISTRY_ADDRESS } from '@aztec/standard-contracts/auth-registry/constants';
|
|
42
|
+
import { EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
39
43
|
import type { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
40
44
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
41
|
-
import { GasSettings } from '@aztec/stdlib/gas';
|
|
45
|
+
import type { GasSettings } from '@aztec/stdlib/gas';
|
|
42
46
|
import { computeProtocolNullifier } from '@aztec/stdlib/hash';
|
|
43
47
|
import { PrivateContextInputs } from '@aztec/stdlib/kernel';
|
|
44
48
|
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
45
|
-
import { CallContext, GlobalVariables, TxContext } from '@aztec/stdlib/tx';
|
|
49
|
+
import { CallContext, GlobalVariables, OFFCHAIN_MESSAGE_IDENTIFIER, TxContext } from '@aztec/stdlib/tx';
|
|
46
50
|
|
|
47
51
|
import { z } from 'zod';
|
|
48
52
|
|
|
49
|
-
import { DEFAULT_ADDRESS } from './constants.js';
|
|
53
|
+
import { DEFAULT_ADDRESS, MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY, MAX_OFFCHAIN_EFFECT_LEN } from './constants.js';
|
|
50
54
|
import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
|
|
51
55
|
import { TXEOraclePublicContext } from './oracle/txe_oracle_public_context.js';
|
|
52
56
|
import { TXEOracleTopLevelContext } from './oracle/txe_oracle_top_level_context.js';
|
|
53
|
-
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';
|
|
54
60
|
import { TXEArchiver } from './state_machine/archiver.js';
|
|
55
61
|
import { TXEStateMachine } from './state_machine/index.js';
|
|
56
|
-
import type { ForeignCallArgs, ForeignCallResult } from './util/encoding.js';
|
|
57
|
-
import { TXEAccountStore } from './util/txe_account_store.js';
|
|
58
62
|
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from './utils/block_creation.js';
|
|
63
|
+
import type { ForeignCallArgs, ForeignCallResult } from './utils/encoding.js';
|
|
59
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';
|
|
60
67
|
|
|
61
68
|
/**
|
|
62
69
|
* A TXE Session can be in one of four states, which change as the test progresses and different oracles are called.
|
|
@@ -109,14 +116,110 @@ export type TXEOracleFunctionName = Exclude<
|
|
|
109
116
|
>;
|
|
110
117
|
|
|
111
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
|
+
|
|
112
122
|
enterTopLevelState(): Promise<void>;
|
|
113
|
-
enterPublicState(contractAddress
|
|
114
|
-
enterPrivateState(
|
|
115
|
-
|
|
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
|
+
}
|
|
116
220
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
getCurrentJob(): string;
|
|
221
|
+
function emptyLastCallState(): LastCallState {
|
|
222
|
+
return { offchainEffects: [], queried: false, txHash: Fr.ZERO, anchorBlockTimestamp: 0n };
|
|
120
223
|
}
|
|
121
224
|
|
|
122
225
|
/**
|
|
@@ -126,11 +229,17 @@ export interface TXESessionStateHandler {
|
|
|
126
229
|
export class TXESession implements TXESessionStateHandler {
|
|
127
230
|
private state: SessionState = { name: 'TOP_LEVEL' };
|
|
128
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;
|
|
129
236
|
|
|
130
237
|
constructor(
|
|
131
238
|
private logger: Logger,
|
|
239
|
+
private sessionStore: AztecAsyncKVStore,
|
|
132
240
|
private stateMachine: TXEStateMachine,
|
|
133
241
|
private oracleHandler:
|
|
242
|
+
| IMiscOracle
|
|
134
243
|
| IUtilityExecutionOracle
|
|
135
244
|
| IPrivateExecutionOracle
|
|
136
245
|
| IAvmExecutionOracle
|
|
@@ -150,10 +259,43 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
150
259
|
private chainId: Fr,
|
|
151
260
|
private version: Fr,
|
|
152
261
|
private nextBlockTimestamp: bigint,
|
|
262
|
+
private readonly artifactResolver: TXEArtifactResolver,
|
|
263
|
+
private readonly rootPath: string,
|
|
264
|
+
private readonly packageName: string,
|
|
153
265
|
) {}
|
|
154
266
|
|
|
155
|
-
|
|
156
|
-
|
|
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);
|
|
157
299
|
|
|
158
300
|
const addressStore = new AddressStore(store);
|
|
159
301
|
const privateEventStore = new PrivateEventStore(store);
|
|
@@ -165,7 +307,6 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
165
307
|
const keyStore = new KeyStore(store);
|
|
166
308
|
const accountStore = new TXEAccountStore(store);
|
|
167
309
|
|
|
168
|
-
// Create job coordinator and register staged stores
|
|
169
310
|
const jobCoordinator = new JobCoordinator(store);
|
|
170
311
|
jobCoordinator.registerStores([
|
|
171
312
|
capsuleStore,
|
|
@@ -185,6 +326,8 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
185
326
|
|
|
186
327
|
const initialJobId = jobCoordinator.beginJob();
|
|
187
328
|
|
|
329
|
+
const logger = createLogger('txe:session');
|
|
330
|
+
|
|
188
331
|
const topLevelOracleHandler = new TXEOracleTopLevelContext(
|
|
189
332
|
stateMachine,
|
|
190
333
|
contractStore,
|
|
@@ -201,11 +344,16 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
201
344
|
version,
|
|
202
345
|
chainId,
|
|
203
346
|
new Map(),
|
|
347
|
+
artifactResolver,
|
|
348
|
+
rootPath,
|
|
349
|
+
packageName,
|
|
204
350
|
);
|
|
205
|
-
|
|
351
|
+
|
|
352
|
+
await topLevelOracleHandler.mineDeploymentNullifiers([STANDARD_AUTH_REGISTRY_ADDRESS]);
|
|
206
353
|
|
|
207
354
|
return new TXESession(
|
|
208
|
-
|
|
355
|
+
logger,
|
|
356
|
+
store,
|
|
209
357
|
stateMachine,
|
|
210
358
|
topLevelOracleHandler,
|
|
211
359
|
contractStore,
|
|
@@ -223,6 +371,9 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
223
371
|
version,
|
|
224
372
|
chainId,
|
|
225
373
|
nextBlockTimestamp,
|
|
374
|
+
artifactResolver,
|
|
375
|
+
rootPath,
|
|
376
|
+
packageName,
|
|
226
377
|
);
|
|
227
378
|
}
|
|
228
379
|
|
|
@@ -244,7 +395,28 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
244
395
|
return translator[validatedFunctionName](...inputs);
|
|
245
396
|
} catch (error) {
|
|
246
397
|
if (error instanceof z.ZodError) {
|
|
247
|
-
|
|
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}`);
|
|
248
420
|
} else if (error instanceof Error) {
|
|
249
421
|
throw new Error(
|
|
250
422
|
`Execution error while processing function ${functionName} in state ${this.state.name}: ${error.message}`,
|
|
@@ -257,17 +429,193 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
257
429
|
}
|
|
258
430
|
}
|
|
259
431
|
|
|
260
|
-
getCurrentJob(): string {
|
|
261
|
-
return this.currentJobId;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
432
|
/** Commits the current job and begins a new one. Returns the new job ID. */
|
|
265
|
-
async cycleJob(): Promise<string> {
|
|
433
|
+
private async cycleJob(): Promise<string> {
|
|
266
434
|
await this.jobCoordinator.commitJob(this.currentJobId);
|
|
267
435
|
this.currentJobId = this.jobCoordinator.beginJob();
|
|
268
436
|
return this.currentJobId;
|
|
269
437
|
}
|
|
270
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
|
+
|
|
271
619
|
async enterTopLevelState() {
|
|
272
620
|
switch (this.state.name) {
|
|
273
621
|
case 'PRIVATE': {
|
|
@@ -309,6 +657,9 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
309
657
|
this.version,
|
|
310
658
|
this.chainId,
|
|
311
659
|
this.authwits,
|
|
660
|
+
this.artifactResolver,
|
|
661
|
+
this.rootPath,
|
|
662
|
+
this.packageName,
|
|
312
663
|
);
|
|
313
664
|
|
|
314
665
|
this.state = { name: 'TOP_LEVEL' };
|
|
@@ -316,21 +667,25 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
316
667
|
}
|
|
317
668
|
|
|
318
669
|
async enterPrivateState(
|
|
319
|
-
|
|
320
|
-
|
|
670
|
+
contractAddressOpt: Option<AztecAddress>,
|
|
671
|
+
anchorBlockNumberOpt: Option<BlockNumber>,
|
|
672
|
+
gasSettings: GasSettings,
|
|
321
673
|
): Promise<PrivateContextInputs> {
|
|
674
|
+
const contractAddress = contractAddressOpt?.value ?? DEFAULT_ADDRESS;
|
|
675
|
+
const anchorBlockNumber = anchorBlockNumberOpt?.value;
|
|
322
676
|
this.exitTopLevelState();
|
|
677
|
+
this.resetLastCall();
|
|
323
678
|
|
|
324
679
|
// Private execution has two associated block numbers: the anchor block (i.e. the historical block that is used to
|
|
325
680
|
// build the proof), and the *next* block, i.e. the one we'll create once the execution ends, and which will contain
|
|
326
681
|
// a single transaction with the effects of what was done in the test.
|
|
327
|
-
const anchorBlock = await this.stateMachine.node.
|
|
682
|
+
const anchorBlock = await this.stateMachine.node.getBlock(anchorBlockNumber ?? 'latest').then(b => b?.header);
|
|
328
683
|
|
|
329
684
|
await new NoteService(this.noteStore, this.stateMachine.node, anchorBlock!, this.currentJobId).syncNoteNullifiers(
|
|
330
685
|
contractAddress,
|
|
331
|
-
|
|
686
|
+
await this.keyStore.getAccounts(),
|
|
332
687
|
);
|
|
333
|
-
const latestBlock = await this.stateMachine.node.
|
|
688
|
+
const latestBlock = await this.stateMachine.node.getBlock('latest').then(b => b?.header);
|
|
334
689
|
|
|
335
690
|
const nextBlockGlobalVariables = makeGlobalVariables(undefined, {
|
|
336
691
|
blockNumber: BlockNumber(latestBlock!.globalVariables.blockNumber + 1),
|
|
@@ -345,9 +700,10 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
345
700
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
346
701
|
|
|
347
702
|
const utilityExecutor = this.utilityExecutorForContractSync(anchorBlock);
|
|
348
|
-
|
|
703
|
+
const transientArrayService = new TransientArrayService();
|
|
704
|
+
this.oracleHandler = new TXEPrivateExecutionOracle({
|
|
349
705
|
argsHash: Fr.ZERO,
|
|
350
|
-
txContext: new TxContext(this.chainId, this.version,
|
|
706
|
+
txContext: new TxContext(this.chainId, this.version, gasSettings),
|
|
351
707
|
callContext: new CallContext(AztecAddress.ZERO, contractAddress, FunctionSelector.empty(), false),
|
|
352
708
|
anchorBlockHeader: anchorBlock!,
|
|
353
709
|
utilityExecutor,
|
|
@@ -364,12 +720,15 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
364
720
|
senderTaggingStore: this.senderTaggingStore,
|
|
365
721
|
recipientTaggingStore: this.recipientTaggingStore,
|
|
366
722
|
senderAddressBookStore: this.senderAddressBookStore,
|
|
367
|
-
|
|
723
|
+
capsuleService: new CapsuleService(this.capsuleStore, await this.keyStore.getAccounts()),
|
|
368
724
|
privateEventStore: this.privateEventStore,
|
|
369
725
|
contractSyncService: this.stateMachine.contractSyncService,
|
|
726
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
370
727
|
jobId: this.currentJobId,
|
|
371
|
-
scopes:
|
|
728
|
+
scopes: await this.keyStore.getAccounts(),
|
|
372
729
|
messageContextService: this.stateMachine.messageContextService,
|
|
730
|
+
simulator: new WASMSimulator(),
|
|
731
|
+
transientArrayService,
|
|
373
732
|
});
|
|
374
733
|
|
|
375
734
|
// We store the note and tagging index caches fed into the PrivateExecutionOracle (along with some other auxiliary
|
|
@@ -380,35 +739,47 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
380
739
|
this.state = { name: 'PRIVATE', nextBlockGlobalVariables, noteCache, taggingIndexCache };
|
|
381
740
|
this.logger.debug(`Entered state ${this.state.name}`);
|
|
382
741
|
|
|
383
|
-
|
|
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();
|
|
384
747
|
}
|
|
385
748
|
|
|
386
|
-
async enterPublicState(
|
|
749
|
+
async enterPublicState(contractAddressOpt: Option<AztecAddress>) {
|
|
750
|
+
const contractAddress = contractAddressOpt?.value ?? DEFAULT_ADDRESS;
|
|
387
751
|
this.exitTopLevelState();
|
|
752
|
+
this.resetLastCall();
|
|
388
753
|
|
|
389
754
|
// The PublicContext will create a block with a single transaction in it, containing the effects of what was done in
|
|
390
755
|
// the test. The block therefore gets the *next* block number and timestamp.
|
|
391
|
-
const
|
|
756
|
+
const latestHeader = (await this.stateMachine.node.getBlockData('latest'))!.header;
|
|
392
757
|
const globalVariables = makeGlobalVariables(undefined, {
|
|
393
|
-
blockNumber: BlockNumber(
|
|
758
|
+
blockNumber: BlockNumber(latestHeader.globalVariables.blockNumber + 1),
|
|
394
759
|
timestamp: this.nextBlockTimestamp,
|
|
395
760
|
version: this.version,
|
|
396
761
|
chainId: this.chainId,
|
|
397
762
|
});
|
|
398
763
|
|
|
399
764
|
this.oracleHandler = new TXEOraclePublicContext(
|
|
400
|
-
contractAddress
|
|
765
|
+
contractAddress,
|
|
401
766
|
await this.stateMachine.synchronizer.nativeWorldStateService.fork(),
|
|
402
767
|
getSingleTxBlockRequestHash(globalVariables.blockNumber),
|
|
403
768
|
globalVariables,
|
|
769
|
+
this.contractStore,
|
|
404
770
|
);
|
|
405
771
|
|
|
406
772
|
this.state = { name: 'PUBLIC' };
|
|
407
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);
|
|
408
777
|
}
|
|
409
778
|
|
|
410
|
-
async enterUtilityState(
|
|
779
|
+
async enterUtilityState(contractAddressOpt: Option<AztecAddress>) {
|
|
780
|
+
const contractAddress = contractAddressOpt?.value ?? DEFAULT_ADDRESS;
|
|
411
781
|
this.exitTopLevelState();
|
|
782
|
+
this.resetLastCall();
|
|
412
783
|
|
|
413
784
|
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
414
785
|
|
|
@@ -422,7 +793,7 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
422
793
|
this.stateMachine.node,
|
|
423
794
|
anchorBlockHeader,
|
|
424
795
|
this.currentJobId,
|
|
425
|
-
).syncNoteNullifiers(contractAddress,
|
|
796
|
+
).syncNoteNullifiers(contractAddress, await this.keyStore.getAccounts());
|
|
426
797
|
|
|
427
798
|
this.oracleHandler = new UtilityExecutionOracle({
|
|
428
799
|
contractAddress,
|
|
@@ -436,15 +807,24 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
436
807
|
aztecNode: this.stateMachine.node,
|
|
437
808
|
recipientTaggingStore: this.recipientTaggingStore,
|
|
438
809
|
senderAddressBookStore: this.senderAddressBookStore,
|
|
439
|
-
|
|
810
|
+
capsuleService: new CapsuleService(this.capsuleStore, await this.keyStore.getAccounts()),
|
|
440
811
|
privateEventStore: this.privateEventStore,
|
|
441
812
|
messageContextService: this.stateMachine.messageContextService,
|
|
813
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
814
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
442
815
|
jobId: this.currentJobId,
|
|
443
|
-
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(),
|
|
444
821
|
});
|
|
445
822
|
|
|
446
823
|
this.state = { name: 'UTILITY' };
|
|
447
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);
|
|
448
828
|
}
|
|
449
829
|
|
|
450
830
|
private exitTopLevelState() {
|
|
@@ -509,13 +889,14 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
509
889
|
}
|
|
510
890
|
|
|
511
891
|
private utilityExecutorForContractSync(anchorBlock: any) {
|
|
512
|
-
return async (call: FunctionCall, scopes:
|
|
892
|
+
return async (call: FunctionCall, scopes: AztecAddress[]) => {
|
|
513
893
|
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
514
894
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
515
895
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
516
896
|
}
|
|
517
897
|
|
|
518
898
|
try {
|
|
899
|
+
const simulator = new WASMSimulator();
|
|
519
900
|
const oracle = new UtilityExecutionOracle({
|
|
520
901
|
contractAddress: call.to,
|
|
521
902
|
authWitnesses: [],
|
|
@@ -528,14 +909,20 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
528
909
|
aztecNode: this.stateMachine.node,
|
|
529
910
|
recipientTaggingStore: this.recipientTaggingStore,
|
|
530
911
|
senderAddressBookStore: this.senderAddressBookStore,
|
|
531
|
-
|
|
912
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
532
913
|
privateEventStore: this.privateEventStore,
|
|
533
914
|
messageContextService: this.stateMachine.messageContextService,
|
|
915
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
916
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
534
917
|
jobId: this.currentJobId,
|
|
535
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(),
|
|
536
923
|
});
|
|
537
|
-
await
|
|
538
|
-
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact,
|
|
924
|
+
await simulator
|
|
925
|
+
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, buildACIRCallback(oracle))
|
|
539
926
|
.catch((err: Error) => {
|
|
540
927
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
541
928
|
throw new ExecutionError(
|