@aztec/txe 5.0.0-private.20260319 → 5.0.0-rc.2
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-URXCCPYF.js +3 -0
- package/dest/AuthRegistry-URXCCPYF.js.map +7 -0
- package/dest/ContractClassRegistry-5RDBM6TC.js +3 -0
- package/dest/ContractClassRegistry-5RDBM6TC.js.map +7 -0
- package/dest/ContractInstanceRegistry-GCR4G4D7.js +3 -0
- package/dest/ContractInstanceRegistry-GCR4G4D7.js.map +7 -0
- package/dest/FeeJuice-O3KOSZO5.js +3 -0
- package/dest/FeeJuice-O3KOSZO5.js.map +7 -0
- package/dest/HandshakeRegistry-TXSMHMNY.js +3 -0
- package/dest/HandshakeRegistry-TXSMHMNY.js.map +7 -0
- package/dest/MultiCallEntrypoint-P4FSRXAD.js +3 -0
- package/dest/MultiCallEntrypoint-P4FSRXAD.js.map +7 -0
- package/dest/SchnorrAccount-AQZX7ROU.js +3 -0
- package/dest/SchnorrAccount-AQZX7ROU.js.map +7 -0
- package/dest/SchnorrInitializerlessAccount-KMX2H3J6.js +3 -0
- package/dest/SchnorrInitializerlessAccount-KMX2H3J6.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-BJVAAXNA.js +3 -0
- package/dest/chunk-BJVAAXNA.js.map +7 -0
- package/dest/chunk-I6DL4FT2.js +304 -0
- package/dest/chunk-I6DL4FT2.js.map +7 -0
- package/dest/chunk-IAO54JS2.js +266 -0
- package/dest/chunk-IAO54JS2.js.map +7 -0
- package/dest/constants.d.ts +5 -1
- package/dest/constants.d.ts.map +1 -1
- package/dest/constants.js +9 -1
- 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 +39364 -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 +38 -8
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/test-resolver/default_fixtures.d.ts +9 -0
- package/dest/oracle/test-resolver/default_fixtures.d.ts.map +1 -0
- package/dest/oracle/test-resolver/default_fixtures.js +164 -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 +32 -0
- package/dest/oracle/test-resolver/resolver.d.ts +48 -0
- package/dest/oracle/test-resolver/resolver.d.ts.map +1 -0
- package/dest/oracle/test-resolver/resolver.js +144 -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 +167 -0
- package/dest/oracle/txe_oracle_registry.d.ts.map +1 -0
- package/dest/oracle/txe_oracle_registry.js +715 -0
- package/dest/oracle/txe_oracle_top_level_context.d.ts +42 -17
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +205 -70
- 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 +111 -233
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +759 -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 +24 -14
- package/dest/state_machine/dummy_p2p_client.d.ts +15 -7
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +22 -4
- package/dest/state_machine/global_variable_builder.d.ts +10 -6
- package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
- package/dest/state_machine/global_variable_builder.js +8 -5
- package/dest/state_machine/index.d.ts +9 -6
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +45 -12
- 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.d.ts +3 -2
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/state_machine/synchronizer.js +4 -3
- package/dest/txe_session.d.ts +89 -20
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +289 -64
- package/dest/utils/block_creation.d.ts +2 -2
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +2 -2
- 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 +11 -1
- 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 +35 -7
- package/src/oracle/test-resolver/default_fixtures.ts +226 -0
- package/src/oracle/test-resolver/index.ts +44 -0
- package/src/oracle/test-resolver/resolver.ts +198 -0
- package/src/oracle/txe_oracle_public_context.ts +60 -0
- package/src/oracle/txe_oracle_registry.ts +494 -0
- package/src/oracle/txe_oracle_top_level_context.ts +245 -81
- 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 +845 -905
- package/src/state_machine/archiver.ts +37 -16
- package/src/state_machine/dummy_p2p_client.ts +40 -11
- package/src/state_machine/global_variable_builder.ts +12 -11
- package/src/state_machine/index.ts +44 -30
- package/src/state_machine/mock_epoch_cache.ts +0 -4
- package/src/state_machine/synchronizer.ts +4 -3
- package/src/txe_session.ts +496 -80
- package/src/utils/block_creation.ts +2 -1
- 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,31 +2,37 @@ 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
|
+
FactService,
|
|
14
|
+
FactStore,
|
|
13
15
|
JobCoordinator,
|
|
14
16
|
NoteService,
|
|
15
17
|
NoteStore,
|
|
16
18
|
PrivateEventStore,
|
|
17
19
|
RecipientTaggingStore,
|
|
18
|
-
SenderAddressBookStore,
|
|
19
20
|
SenderTaggingStore,
|
|
21
|
+
TaggingSecretSourcesStore,
|
|
22
|
+
type TaggingSecretStrategy,
|
|
23
|
+
composeHooks,
|
|
20
24
|
} from '@aztec/pxe/server';
|
|
21
25
|
import {
|
|
22
26
|
ExecutionNoteCache,
|
|
23
27
|
ExecutionTaggingIndexCache,
|
|
24
28
|
HashedValuesCache,
|
|
29
|
+
type IMiscOracle,
|
|
25
30
|
type IPrivateExecutionOracle,
|
|
26
31
|
type IUtilityExecutionOracle,
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
Option,
|
|
33
|
+
TransientArrayService,
|
|
29
34
|
UtilityExecutionOracle,
|
|
35
|
+
buildACIRCallback,
|
|
30
36
|
} from '@aztec/pxe/simulator';
|
|
31
37
|
import {
|
|
32
38
|
ExecutionError,
|
|
@@ -36,28 +42,32 @@ import {
|
|
|
36
42
|
resolveAssertionMessageFromError,
|
|
37
43
|
toACVMWitness,
|
|
38
44
|
} from '@aztec/simulator/client';
|
|
39
|
-
import {
|
|
45
|
+
import { STANDARD_AUTH_REGISTRY_ADDRESS } from '@aztec/standard-contracts/auth-registry/constants';
|
|
46
|
+
import { EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
40
47
|
import type { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
41
48
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
42
|
-
import { GasSettings } from '@aztec/stdlib/gas';
|
|
49
|
+
import type { GasSettings } from '@aztec/stdlib/gas';
|
|
43
50
|
import { computeProtocolNullifier } from '@aztec/stdlib/hash';
|
|
44
51
|
import { PrivateContextInputs } from '@aztec/stdlib/kernel';
|
|
45
52
|
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
46
|
-
import { CallContext, GlobalVariables, TxContext } from '@aztec/stdlib/tx';
|
|
53
|
+
import { CallContext, GlobalVariables, OFFCHAIN_MESSAGE_IDENTIFIER, TxContext } from '@aztec/stdlib/tx';
|
|
47
54
|
|
|
48
55
|
import { z } from 'zod';
|
|
49
56
|
|
|
50
|
-
import { DEFAULT_ADDRESS } from './constants.js';
|
|
57
|
+
import { DEFAULT_ADDRESS, MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY, MAX_OFFCHAIN_EFFECT_LEN } from './constants.js';
|
|
51
58
|
import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
|
|
52
59
|
import { TXEOraclePublicContext } from './oracle/txe_oracle_public_context.js';
|
|
53
60
|
import { TXEOracleTopLevelContext } from './oracle/txe_oracle_top_level_context.js';
|
|
54
|
-
import {
|
|
61
|
+
import { TXE_ORACLE_VERSION_MAJOR, TXE_ORACLE_VERSION_MINOR } from './oracle/txe_oracle_version.js';
|
|
62
|
+
import { TXEPrivateExecutionOracle } from './oracle/txe_private_execution_oracle.js';
|
|
63
|
+
import { RPCTranslator, UnavailableOracleError } from './rpc_translator.js';
|
|
55
64
|
import { TXEArchiver } from './state_machine/archiver.js';
|
|
56
65
|
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
66
|
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from './utils/block_creation.js';
|
|
67
|
+
import type { ForeignCallArgs, ForeignCallResult } from './utils/encoding.js';
|
|
60
68
|
import { makeTxEffect } from './utils/tx_effect_creation.js';
|
|
69
|
+
import { TXEAccountStore } from './utils/txe_account_store.js';
|
|
70
|
+
import type { TXEArtifactResolver } from './utils/txe_artifact_resolver.js';
|
|
61
71
|
|
|
62
72
|
/**
|
|
63
73
|
* A TXE Session can be in one of four states, which change as the test progresses and different oracles are called.
|
|
@@ -110,14 +120,111 @@ export type TXEOracleFunctionName = Exclude<
|
|
|
110
120
|
>;
|
|
111
121
|
|
|
112
122
|
export interface TXESessionStateHandler {
|
|
123
|
+
/** Records the TXE oracle version reported by the Noir test code for diagnostics. */
|
|
124
|
+
setTxeOracleVersion(major: number, minor: number): void;
|
|
125
|
+
|
|
113
126
|
enterTopLevelState(): Promise<void>;
|
|
114
|
-
enterPublicState(contractAddress
|
|
115
|
-
enterPrivateState(
|
|
116
|
-
|
|
127
|
+
enterPublicState(contractAddress: Option<AztecAddress>): Promise<void>;
|
|
128
|
+
enterPrivateState(
|
|
129
|
+
contractAddress: Option<AztecAddress>,
|
|
130
|
+
anchorBlockNumber: Option<BlockNumber>,
|
|
131
|
+
gasSettings: GasSettings,
|
|
132
|
+
): Promise<PrivateContextInputs>;
|
|
133
|
+
enterUtilityState(contractAddress: Option<AztecAddress>): Promise<void>;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Executes a top-level private call: runs the private function, drains its offchain effects into the session buffer,
|
|
137
|
+
* commits the job, and (for non-static calls) tags the result with the mined tx hash.
|
|
138
|
+
*/
|
|
139
|
+
executePrivateCall(
|
|
140
|
+
from: Option<AztecAddress>,
|
|
141
|
+
targetContractAddress: AztecAddress,
|
|
142
|
+
functionSelector: FunctionSelector,
|
|
143
|
+
args: Fr[],
|
|
144
|
+
argsHash: Fr,
|
|
145
|
+
isStaticCall: boolean,
|
|
146
|
+
additionalScopes: AztecAddress[],
|
|
147
|
+
authorizedUtilityCallTargets: AztecAddress[],
|
|
148
|
+
gasSettings: GasSettings,
|
|
149
|
+
): Promise<Fr[]>;
|
|
150
|
+
|
|
151
|
+
/** Executes a top-level utility function and commits the job. */
|
|
152
|
+
executeUtilityFunction(
|
|
153
|
+
from: Option<AztecAddress>,
|
|
154
|
+
targetContractAddress: AztecAddress,
|
|
155
|
+
functionSelector: FunctionSelector,
|
|
156
|
+
args: Fr[],
|
|
157
|
+
authorizedUtilityCallTargets: AztecAddress[],
|
|
158
|
+
): Promise<Fr[]>;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Executes a top-level public call, commits the job, and (for non-static calls) tags the result with the mined tx
|
|
162
|
+
* hash.
|
|
163
|
+
*/
|
|
164
|
+
executePublicCall(
|
|
165
|
+
from: Option<AztecAddress>,
|
|
166
|
+
targetContractAddress: AztecAddress,
|
|
167
|
+
calldata: Fr[],
|
|
168
|
+
isStaticCall: boolean,
|
|
169
|
+
gasSettings: GasSettings,
|
|
170
|
+
): Promise<Fr[]>;
|
|
171
|
+
|
|
172
|
+
/** Syncs the target contract and returns the private events it emitted matching the given selector and scope. */
|
|
173
|
+
getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress): Promise<Fr[][]>;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Captures a raw offchain effect payload for consumption from test environment. Called by the `emit_offchain_effect`
|
|
177
|
+
* oracle handler whenever a contract function emits an offchain message, at any call depth.
|
|
178
|
+
*/
|
|
179
|
+
recordOffchainEffect(data: Fr[]): void;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Returns the raw offchain effect payloads emitted by the last top-level call. Each payload follows the protocol
|
|
183
|
+
* convention documented on `OFFCHAIN_MESSAGE_IDENTIFIER`, i.e. `[identifier, recipient, ...ciphertext]`. Decoding into
|
|
184
|
+
* `OffchainMessage` structs happens on the Noir side of the test helper. Marks the buffer as queried so the
|
|
185
|
+
* unqueried-messages warning doesn't fire on the next reset.
|
|
186
|
+
*/
|
|
187
|
+
getLastCallOffchainEffects(): { effects: Fr[][] };
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Returns the context of the last top-level call: its tx hash (`Fr.ZERO` if the call was tx-less) and the anchor
|
|
191
|
+
* block timestamp captured at the start of the call. Does *not* mark the buffer as queried — context reads are
|
|
192
|
+
* metadata, not effect consumption.
|
|
193
|
+
*/
|
|
194
|
+
getLastCallContext(): { txHash: Fr; anchorBlockTimestamp: bigint };
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Session state tracking the most recently completed top-level call: the offchain effect buffer it produced, and the
|
|
199
|
+
* call's context (tx hash + anchor block timestamp). The context is refreshed on every top-level call, independently
|
|
200
|
+
* of whether the call produced offchain effects.
|
|
201
|
+
*/
|
|
202
|
+
interface LastCallState {
|
|
203
|
+
/**
|
|
204
|
+
* Raw offchain effect payloads emitted by the currently-executing (or most recently completed) top-level call. Wiped
|
|
205
|
+
* at the start of every top-level entry point, appended to on every `emit_offchain_effect` oracle invocation.
|
|
206
|
+
*/
|
|
207
|
+
offchainEffects: Fr[][];
|
|
208
|
+
/**
|
|
209
|
+
* Tracks whether the test has queried `effects` since the last reset. If a new top-level call clobbers the buffer
|
|
210
|
+
* without it being queried first, any accumulated messages are lost and we emit a warning so tests don't silently
|
|
211
|
+
* drop delivery.
|
|
212
|
+
*/
|
|
213
|
+
queried: boolean;
|
|
214
|
+
/**
|
|
215
|
+
* Tx hash of the most recently completed top-level call, or `Fr.ZERO` if the call was tx-less (context setters,
|
|
216
|
+
* utility execution). Populated by call executor handlers after execution completes.
|
|
217
|
+
*/
|
|
218
|
+
txHash: Fr;
|
|
219
|
+
/**
|
|
220
|
+
* Anchor block timestamp of the most recently completed top-level call, captured from the anchor block header that
|
|
221
|
+
* was active when the call started. Populated by call executor handlers after execution completes.
|
|
222
|
+
*/
|
|
223
|
+
anchorBlockTimestamp: bigint;
|
|
224
|
+
}
|
|
117
225
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
getCurrentJob(): string;
|
|
226
|
+
function emptyLastCallState(): LastCallState {
|
|
227
|
+
return { offchainEffects: [], queried: false, txHash: Fr.ZERO, anchorBlockTimestamp: 0n };
|
|
121
228
|
}
|
|
122
229
|
|
|
123
230
|
/**
|
|
@@ -127,11 +234,18 @@ export interface TXESessionStateHandler {
|
|
|
127
234
|
export class TXESession implements TXESessionStateHandler {
|
|
128
235
|
private state: SessionState = { name: 'TOP_LEVEL' };
|
|
129
236
|
private authwits: Map<string, AuthWitness> = new Map();
|
|
237
|
+
private taggingSecretStrategy: TaggingSecretStrategy | undefined = undefined;
|
|
238
|
+
private lastCallInfo: LastCallState = emptyLastCallState();
|
|
239
|
+
private txeOracleVersion: { major: number; minor: number } | undefined;
|
|
240
|
+
|
|
241
|
+
private disposed = false;
|
|
130
242
|
|
|
131
243
|
constructor(
|
|
132
244
|
private logger: Logger,
|
|
245
|
+
private sessionStore: AztecAsyncKVStore,
|
|
133
246
|
private stateMachine: TXEStateMachine,
|
|
134
247
|
private oracleHandler:
|
|
248
|
+
| IMiscOracle
|
|
135
249
|
| IUtilityExecutionOracle
|
|
136
250
|
| IPrivateExecutionOracle
|
|
137
251
|
| IAvmExecutionOracle
|
|
@@ -143,34 +257,68 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
143
257
|
private accountStore: TXEAccountStore,
|
|
144
258
|
private senderTaggingStore: SenderTaggingStore,
|
|
145
259
|
private recipientTaggingStore: RecipientTaggingStore,
|
|
146
|
-
private
|
|
260
|
+
private taggingSecretSourcesStore: TaggingSecretSourcesStore,
|
|
147
261
|
private capsuleStore: CapsuleStore,
|
|
262
|
+
private factStore: FactStore,
|
|
148
263
|
private privateEventStore: PrivateEventStore,
|
|
149
264
|
private jobCoordinator: JobCoordinator,
|
|
150
265
|
private currentJobId: string,
|
|
151
266
|
private chainId: Fr,
|
|
152
267
|
private version: Fr,
|
|
153
268
|
private nextBlockTimestamp: bigint,
|
|
154
|
-
private
|
|
269
|
+
private readonly artifactResolver: TXEArtifactResolver,
|
|
270
|
+
private readonly rootPath: string,
|
|
271
|
+
private readonly packageName: string,
|
|
155
272
|
) {}
|
|
156
273
|
|
|
157
|
-
|
|
158
|
-
|
|
274
|
+
/**
|
|
275
|
+
* Closes the per-session `txe-session` LMDB and the `NativeWorldStateService` .
|
|
276
|
+
* Called via IPC when the dispatcher detects the end of a test. Idempotent.
|
|
277
|
+
*/
|
|
278
|
+
async dispose(): Promise<void> {
|
|
279
|
+
if (this.disposed) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
this.disposed = true;
|
|
283
|
+
try {
|
|
284
|
+
await this.stateMachine.synchronizer.nativeWorldStateService.close();
|
|
285
|
+
} catch (err) {
|
|
286
|
+
this.logger.warn(`Error closing native world state during session dispose`, err);
|
|
287
|
+
}
|
|
288
|
+
try {
|
|
289
|
+
await this.sessionStore.close();
|
|
290
|
+
} catch (err) {
|
|
291
|
+
this.logger.warn(`Error closing session LMDB during dispose`, err);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
static async init(
|
|
296
|
+
contractStore: ContractStore,
|
|
297
|
+
artifactResolver: TXEArtifactResolver,
|
|
298
|
+
rootPath: string,
|
|
299
|
+
packageName: string,
|
|
300
|
+
) {
|
|
301
|
+
// Size LMDB's reader slots to the libuv pool (capped to 2 in bin/index.ts via
|
|
302
|
+
// HARDWARE_CONCURRENCY): each native LMDB read needs a libuv worker thread to run, so any
|
|
303
|
+
// slot beyond the pool size would sit idle while still consuming a semaphore + reader-table
|
|
304
|
+
// entry per session.
|
|
305
|
+
const store = await openEphemeralStore('txe-session', undefined, 2);
|
|
159
306
|
|
|
160
307
|
const addressStore = new AddressStore(store);
|
|
161
308
|
const privateEventStore = new PrivateEventStore(store);
|
|
162
309
|
const noteStore = new NoteStore(store);
|
|
163
310
|
const senderTaggingStore = new SenderTaggingStore(store);
|
|
164
311
|
const recipientTaggingStore = new RecipientTaggingStore(store);
|
|
165
|
-
const
|
|
312
|
+
const taggingSecretSourcesStore = new TaggingSecretSourcesStore(store);
|
|
166
313
|
const capsuleStore = new CapsuleStore(store);
|
|
314
|
+
const factStore = new FactStore(store);
|
|
167
315
|
const keyStore = new KeyStore(store);
|
|
168
316
|
const accountStore = new TXEAccountStore(store);
|
|
169
317
|
|
|
170
|
-
// Create job coordinator and register staged stores
|
|
171
318
|
const jobCoordinator = new JobCoordinator(store);
|
|
172
319
|
jobCoordinator.registerStores([
|
|
173
320
|
capsuleStore,
|
|
321
|
+
factStore,
|
|
174
322
|
senderTaggingStore,
|
|
175
323
|
recipientTaggingStore,
|
|
176
324
|
privateEventStore,
|
|
@@ -188,7 +336,6 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
188
336
|
const initialJobId = jobCoordinator.beginJob();
|
|
189
337
|
|
|
190
338
|
const logger = createLogger('txe:session');
|
|
191
|
-
const contractSyncService = new ContractSyncService(stateMachine.node, contractStore, noteStore, logger);
|
|
192
339
|
|
|
193
340
|
const topLevelOracleHandler = new TXEOracleTopLevelContext(
|
|
194
341
|
stateMachine,
|
|
@@ -199,19 +346,25 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
199
346
|
accountStore,
|
|
200
347
|
senderTaggingStore,
|
|
201
348
|
recipientTaggingStore,
|
|
202
|
-
|
|
349
|
+
taggingSecretSourcesStore,
|
|
203
350
|
capsuleStore,
|
|
351
|
+
factStore,
|
|
204
352
|
privateEventStore,
|
|
205
353
|
nextBlockTimestamp,
|
|
206
354
|
version,
|
|
207
355
|
chainId,
|
|
208
356
|
new Map(),
|
|
209
|
-
|
|
357
|
+
undefined,
|
|
358
|
+
artifactResolver,
|
|
359
|
+
rootPath,
|
|
360
|
+
packageName,
|
|
210
361
|
);
|
|
211
|
-
|
|
362
|
+
|
|
363
|
+
await topLevelOracleHandler.mineDeploymentNullifiers([STANDARD_AUTH_REGISTRY_ADDRESS]);
|
|
212
364
|
|
|
213
365
|
return new TXESession(
|
|
214
366
|
logger,
|
|
367
|
+
store,
|
|
215
368
|
stateMachine,
|
|
216
369
|
topLevelOracleHandler,
|
|
217
370
|
contractStore,
|
|
@@ -221,15 +374,18 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
221
374
|
accountStore,
|
|
222
375
|
senderTaggingStore,
|
|
223
376
|
recipientTaggingStore,
|
|
224
|
-
|
|
377
|
+
taggingSecretSourcesStore,
|
|
225
378
|
capsuleStore,
|
|
379
|
+
factStore,
|
|
226
380
|
privateEventStore,
|
|
227
381
|
jobCoordinator,
|
|
228
382
|
initialJobId,
|
|
229
383
|
version,
|
|
230
384
|
chainId,
|
|
231
385
|
nextBlockTimestamp,
|
|
232
|
-
|
|
386
|
+
artifactResolver,
|
|
387
|
+
rootPath,
|
|
388
|
+
packageName,
|
|
233
389
|
);
|
|
234
390
|
}
|
|
235
391
|
|
|
@@ -251,7 +407,28 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
251
407
|
return translator[validatedFunctionName](...inputs);
|
|
252
408
|
} catch (error) {
|
|
253
409
|
if (error instanceof z.ZodError) {
|
|
254
|
-
|
|
410
|
+
let versionHint: string;
|
|
411
|
+
if (!this.txeOracleVersion) {
|
|
412
|
+
versionHint =
|
|
413
|
+
' The test appears to use an older version of Aztec.nr that does not' +
|
|
414
|
+
' support test environment oracle versioning. Update Aztec.nr to a compatible version.' +
|
|
415
|
+
' See https://docs.aztec.network/errors/12';
|
|
416
|
+
} else if (this.txeOracleVersion.minor > TXE_ORACLE_VERSION_MINOR) {
|
|
417
|
+
versionHint =
|
|
418
|
+
` The test uses Aztec.nr test oracle version` +
|
|
419
|
+
` ${this.txeOracleVersion.major}.${this.txeOracleVersion.minor}, but this test environment` +
|
|
420
|
+
` only supports up to ${TXE_ORACLE_VERSION_MAJOR}.${TXE_ORACLE_VERSION_MINOR}.` +
|
|
421
|
+
` Upgrade the Aztec CLI to a compatible version.` +
|
|
422
|
+
` See https://docs.aztec.network/errors/12`;
|
|
423
|
+
} else {
|
|
424
|
+
versionHint =
|
|
425
|
+
` The test's oracle version (${this.txeOracleVersion.major}.${this.txeOracleVersion.minor})` +
|
|
426
|
+
` is compatible with this test environment` +
|
|
427
|
+
` (${TXE_ORACLE_VERSION_MAJOR}.${TXE_ORACLE_VERSION_MINOR}), so this oracle should be` +
|
|
428
|
+
` available. This is an unexpected error, please report it.` +
|
|
429
|
+
` See https://docs.aztec.network/errors/13`;
|
|
430
|
+
}
|
|
431
|
+
throw new Error(`Unknown oracle '${functionName}'.${versionHint}`);
|
|
255
432
|
} else if (error instanceof Error) {
|
|
256
433
|
throw new Error(
|
|
257
434
|
`Execution error while processing function ${functionName} in state ${this.state.name}: ${error.message}`,
|
|
@@ -264,17 +441,195 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
264
441
|
}
|
|
265
442
|
}
|
|
266
443
|
|
|
267
|
-
getCurrentJob(): string {
|
|
268
|
-
return this.currentJobId;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
444
|
/** Commits the current job and begins a new one. Returns the new job ID. */
|
|
272
|
-
async cycleJob(): Promise<string> {
|
|
445
|
+
private async cycleJob(): Promise<string> {
|
|
273
446
|
await this.jobCoordinator.commitJob(this.currentJobId);
|
|
274
447
|
this.currentJobId = this.jobCoordinator.beginJob();
|
|
275
448
|
return this.currentJobId;
|
|
276
449
|
}
|
|
277
450
|
|
|
451
|
+
private resetLastCall(): void {
|
|
452
|
+
const notQueriedMessageCount = this.lastCallInfo.queried
|
|
453
|
+
? 0
|
|
454
|
+
: this.lastCallInfo.offchainEffects.filter(payload => payload[0]?.equals(OFFCHAIN_MESSAGE_IDENTIFIER)).length;
|
|
455
|
+
if (notQueriedMessageCount > 0) {
|
|
456
|
+
this.logger.warn(
|
|
457
|
+
`Dropping ${notQueriedMessageCount} unqueried offchain message(s) from the previous top-level call. ` +
|
|
458
|
+
`To deliver them, call \`env.offchain_messages()\` and forward the result to the recipient contract's ` +
|
|
459
|
+
`\`offchain_receive\` utility before issuing another top-level call. To intentionally discard, assign ` +
|
|
460
|
+
`to \`let _ = env.offchain_messages()\` to silence this warning.`,
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
this.lastCallInfo = emptyLastCallState();
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
recordOffchainEffect(data: Fr[]): void {
|
|
467
|
+
this.lastCallInfo.offchainEffects.push(data);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
private setLastCallContext(txHash: Fr, anchorBlockTimestamp: bigint): void {
|
|
471
|
+
this.lastCallInfo.txHash = txHash;
|
|
472
|
+
this.lastCallInfo.anchorBlockTimestamp = anchorBlockTimestamp;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
private async withTopLevelCallTracking<T>(work: () => Promise<{ result: T; txHash?: Fr }>): Promise<T> {
|
|
476
|
+
this.resetLastCall();
|
|
477
|
+
// Capture the anchor *before* `work` runs: private/public executor calls mine a new block as a
|
|
478
|
+
// side effect, and that block's timestamp should not be attributed to this call's anchor.
|
|
479
|
+
const anchorBlockTimestamp = (await this.stateMachine.node.getBlockData('latest'))!.header.globalVariables
|
|
480
|
+
.timestamp;
|
|
481
|
+
const { result, txHash } = await work();
|
|
482
|
+
this.setLastCallContext(txHash ?? Fr.ZERO, anchorBlockTimestamp);
|
|
483
|
+
return result;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
getLastCallOffchainEffects(): { effects: Fr[][] } {
|
|
487
|
+
this.lastCallInfo.queried = true;
|
|
488
|
+
const effects = this.lastCallInfo.offchainEffects;
|
|
489
|
+
|
|
490
|
+
if (effects.length > MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY) {
|
|
491
|
+
throw new Error(`${effects.length} offchain effects exceed max ${MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY}`);
|
|
492
|
+
}
|
|
493
|
+
if (effects.some(e => e.length > MAX_OFFCHAIN_EFFECT_LEN)) {
|
|
494
|
+
throw new Error(`Some offchain effect has length larger than max ${MAX_OFFCHAIN_EFFECT_LEN}`);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
return { effects };
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
getLastCallContext(): { txHash: Fr; anchorBlockTimestamp: bigint } {
|
|
501
|
+
const { txHash, anchorBlockTimestamp } = this.lastCallInfo;
|
|
502
|
+
return { txHash, anchorBlockTimestamp };
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
async executePrivateCall(
|
|
506
|
+
from: Option<AztecAddress>,
|
|
507
|
+
targetContractAddress: AztecAddress,
|
|
508
|
+
functionSelector: FunctionSelector,
|
|
509
|
+
args: Fr[],
|
|
510
|
+
argsHash: Fr,
|
|
511
|
+
isStaticCall: boolean,
|
|
512
|
+
additionalScopes: AztecAddress[],
|
|
513
|
+
authorizedUtilityCallTargets: AztecAddress[],
|
|
514
|
+
gasSettings: GasSettings,
|
|
515
|
+
): Promise<Fr[]> {
|
|
516
|
+
const handler = this.handlerAsTxe();
|
|
517
|
+
return await this.withTopLevelCallTracking(async () => {
|
|
518
|
+
const { returnValues, offchainEffects } = await handler.privateCallNewFlow(
|
|
519
|
+
from?.value,
|
|
520
|
+
targetContractAddress,
|
|
521
|
+
functionSelector,
|
|
522
|
+
args,
|
|
523
|
+
argsHash,
|
|
524
|
+
isStaticCall,
|
|
525
|
+
additionalScopes,
|
|
526
|
+
this.currentJobId,
|
|
527
|
+
authorizedUtilityCallTargets,
|
|
528
|
+
gasSettings,
|
|
529
|
+
);
|
|
530
|
+
|
|
531
|
+
// Private execution collects offchain effects inside PXE's PrivateExecutionOracle rather than round-tripping
|
|
532
|
+
// them through `aztec_utl_emitOffchainEffect`, so the session buffer is empty at this point. Drain the effects
|
|
533
|
+
// from the execution tree into the session buffer so the next `env.offchain_messages()` call in the test sees
|
|
534
|
+
// them.
|
|
535
|
+
for (const data of offchainEffects) {
|
|
536
|
+
this.recordOffchainEffect(data);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
await this.cycleJob();
|
|
540
|
+
|
|
541
|
+
if (isStaticCall) {
|
|
542
|
+
// Static calls revert their checkpoint and mine no block, so there is no tx hash to tag offchain effects
|
|
543
|
+
// with. Querying `getLastTxEffects()` here would return an unrelated predecessor tx.
|
|
544
|
+
return { result: returnValues };
|
|
545
|
+
}
|
|
546
|
+
const { txHash } = await handler.getLastTxEffects();
|
|
547
|
+
return { result: returnValues, txHash: txHash.hash };
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
async executeUtilityFunction(
|
|
552
|
+
from: Option<AztecAddress>,
|
|
553
|
+
targetContractAddress: AztecAddress,
|
|
554
|
+
functionSelector: FunctionSelector,
|
|
555
|
+
args: Fr[],
|
|
556
|
+
authorizedUtilityCallTargets: AztecAddress[],
|
|
557
|
+
): Promise<Fr[]> {
|
|
558
|
+
const handler = this.handlerAsTxe();
|
|
559
|
+
return await this.withTopLevelCallTracking(async () => {
|
|
560
|
+
const returnValues = await handler.executeUtilityFunction(
|
|
561
|
+
from?.value,
|
|
562
|
+
targetContractAddress,
|
|
563
|
+
functionSelector,
|
|
564
|
+
args,
|
|
565
|
+
this.currentJobId,
|
|
566
|
+
authorizedUtilityCallTargets,
|
|
567
|
+
);
|
|
568
|
+
|
|
569
|
+
await this.cycleJob();
|
|
570
|
+
|
|
571
|
+
return { result: returnValues };
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
async executePublicCall(
|
|
576
|
+
from: Option<AztecAddress>,
|
|
577
|
+
targetContractAddress: AztecAddress,
|
|
578
|
+
calldata: Fr[],
|
|
579
|
+
isStaticCall: boolean,
|
|
580
|
+
gasSettings: GasSettings,
|
|
581
|
+
): Promise<Fr[]> {
|
|
582
|
+
const handler = this.handlerAsTxe();
|
|
583
|
+
return await this.withTopLevelCallTracking(async () => {
|
|
584
|
+
const returnValues = await handler.publicCallNewFlow(
|
|
585
|
+
from?.value,
|
|
586
|
+
targetContractAddress,
|
|
587
|
+
calldata,
|
|
588
|
+
isStaticCall,
|
|
589
|
+
gasSettings,
|
|
590
|
+
);
|
|
591
|
+
|
|
592
|
+
await this.cycleJob();
|
|
593
|
+
|
|
594
|
+
if (isStaticCall) {
|
|
595
|
+
// See the equivalent branch in `executePrivateCall`.
|
|
596
|
+
return { result: returnValues };
|
|
597
|
+
}
|
|
598
|
+
const { txHash } = await handler.getLastTxEffects();
|
|
599
|
+
return { result: returnValues, txHash: txHash.hash };
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress): Promise<Fr[][]> {
|
|
604
|
+
const handler = this.handlerAsTxe();
|
|
605
|
+
await handler.syncContractNonOracleMethod(contractAddress, scope, this.currentJobId);
|
|
606
|
+
// Cycle the job to commit the stores after the contract sync.
|
|
607
|
+
await this.cycleJob();
|
|
608
|
+
return handler.getPrivateEvents(selector, contractAddress, scope);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
private handlerAsTxe(): ITxeExecutionOracle {
|
|
612
|
+
if (!('isTxe' in this.oracleHandler)) {
|
|
613
|
+
throw new UnavailableOracleError('Txe');
|
|
614
|
+
}
|
|
615
|
+
return this.oracleHandler;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
setTxeOracleVersion(major: number, minor: number): void {
|
|
619
|
+
if (major !== TXE_ORACLE_VERSION_MAJOR) {
|
|
620
|
+
const hint =
|
|
621
|
+
major > TXE_ORACLE_VERSION_MAJOR
|
|
622
|
+
? 'The test was compiled with a newer version of Aztec.nr than your test environment supports. Upgrade your test environment to a compatible version.'
|
|
623
|
+
: '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.';
|
|
624
|
+
throw new Error(
|
|
625
|
+
`Incompatible test environment version: ${hint} See https://docs.aztec.network/errors/12 (expected test oracle major version ${TXE_ORACLE_VERSION_MAJOR}, got ${major})`,
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
this.txeOracleVersion = { major, minor };
|
|
630
|
+
this.logger.debug(`Test compiled with test oracle version ${major}.${minor}`);
|
|
631
|
+
}
|
|
632
|
+
|
|
278
633
|
async enterTopLevelState() {
|
|
279
634
|
switch (this.state.name) {
|
|
280
635
|
case 'PRIVATE': {
|
|
@@ -309,14 +664,18 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
309
664
|
this.accountStore,
|
|
310
665
|
this.senderTaggingStore,
|
|
311
666
|
this.recipientTaggingStore,
|
|
312
|
-
this.
|
|
667
|
+
this.taggingSecretSourcesStore,
|
|
313
668
|
this.capsuleStore,
|
|
669
|
+
this.factStore,
|
|
314
670
|
this.privateEventStore,
|
|
315
671
|
this.nextBlockTimestamp,
|
|
316
672
|
this.version,
|
|
317
673
|
this.chainId,
|
|
318
674
|
this.authwits,
|
|
319
|
-
this.
|
|
675
|
+
this.taggingSecretStrategy,
|
|
676
|
+
this.artifactResolver,
|
|
677
|
+
this.rootPath,
|
|
678
|
+
this.packageName,
|
|
320
679
|
);
|
|
321
680
|
|
|
322
681
|
this.state = { name: 'TOP_LEVEL' };
|
|
@@ -324,21 +683,25 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
324
683
|
}
|
|
325
684
|
|
|
326
685
|
async enterPrivateState(
|
|
327
|
-
|
|
328
|
-
|
|
686
|
+
contractAddressOpt: Option<AztecAddress>,
|
|
687
|
+
anchorBlockNumberOpt: Option<BlockNumber>,
|
|
688
|
+
gasSettings: GasSettings,
|
|
329
689
|
): Promise<PrivateContextInputs> {
|
|
690
|
+
const contractAddress = contractAddressOpt?.value ?? DEFAULT_ADDRESS;
|
|
691
|
+
const anchorBlockNumber = anchorBlockNumberOpt?.value;
|
|
330
692
|
this.exitTopLevelState();
|
|
693
|
+
this.resetLastCall();
|
|
331
694
|
|
|
332
695
|
// Private execution has two associated block numbers: the anchor block (i.e. the historical block that is used to
|
|
333
696
|
// build the proof), and the *next* block, i.e. the one we'll create once the execution ends, and which will contain
|
|
334
697
|
// a single transaction with the effects of what was done in the test.
|
|
335
|
-
const anchorBlock = await this.stateMachine.node.
|
|
698
|
+
const anchorBlock = await this.stateMachine.node.getBlock(anchorBlockNumber ?? 'latest').then(b => b?.header);
|
|
336
699
|
|
|
337
700
|
await new NoteService(this.noteStore, this.stateMachine.node, anchorBlock!, this.currentJobId).syncNoteNullifiers(
|
|
338
701
|
contractAddress,
|
|
339
|
-
|
|
702
|
+
await this.keyStore.getAccounts(),
|
|
340
703
|
);
|
|
341
|
-
const latestBlock = await this.stateMachine.node.
|
|
704
|
+
const latestBlock = await this.stateMachine.node.getBlock('latest').then(b => b?.header);
|
|
342
705
|
|
|
343
706
|
const nextBlockGlobalVariables = makeGlobalVariables(undefined, {
|
|
344
707
|
blockNumber: BlockNumber(latestBlock!.globalVariables.blockNumber + 1),
|
|
@@ -353,9 +716,11 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
353
716
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
354
717
|
|
|
355
718
|
const utilityExecutor = this.utilityExecutorForContractSync(anchorBlock);
|
|
356
|
-
|
|
719
|
+
const transientArrayService = new TransientArrayService();
|
|
720
|
+
const taggingSecretStrategy = this.taggingSecretStrategy;
|
|
721
|
+
this.oracleHandler = new TXEPrivateExecutionOracle({
|
|
357
722
|
argsHash: Fr.ZERO,
|
|
358
|
-
txContext: new TxContext(this.chainId, this.version,
|
|
723
|
+
txContext: new TxContext(this.chainId, this.version, gasSettings),
|
|
359
724
|
callContext: new CallContext(AztecAddress.ZERO, contractAddress, FunctionSelector.empty(), false),
|
|
360
725
|
anchorBlockHeader: anchorBlock!,
|
|
361
726
|
utilityExecutor,
|
|
@@ -371,13 +736,20 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
371
736
|
aztecNode: this.stateMachine.node,
|
|
372
737
|
senderTaggingStore: this.senderTaggingStore,
|
|
373
738
|
recipientTaggingStore: this.recipientTaggingStore,
|
|
374
|
-
|
|
375
|
-
|
|
739
|
+
taggingSecretSourcesStore: this.taggingSecretSourcesStore,
|
|
740
|
+
capsuleService: new CapsuleService(this.capsuleStore, await this.keyStore.getAccounts()),
|
|
741
|
+
factService: new FactService(this.factStore, await this.keyStore.getAccounts()),
|
|
376
742
|
privateEventStore: this.privateEventStore,
|
|
377
743
|
contractSyncService: this.stateMachine.contractSyncService,
|
|
744
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
378
745
|
jobId: this.currentJobId,
|
|
379
|
-
scopes:
|
|
380
|
-
|
|
746
|
+
scopes: await this.keyStore.getAccounts(),
|
|
747
|
+
txResolver: this.stateMachine.txResolver,
|
|
748
|
+
simulator: new WASMSimulator(),
|
|
749
|
+
hooks: composeHooks({
|
|
750
|
+
resolveTaggingSecretStrategy: taggingSecretStrategy ? () => Promise.resolve(taggingSecretStrategy) : undefined,
|
|
751
|
+
}),
|
|
752
|
+
transientArrayService,
|
|
381
753
|
});
|
|
382
754
|
|
|
383
755
|
// We store the note and tagging index caches fed into the PrivateExecutionOracle (along with some other auxiliary
|
|
@@ -388,35 +760,47 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
388
760
|
this.state = { name: 'PRIVATE', nextBlockGlobalVariables, noteCache, taggingIndexCache };
|
|
389
761
|
this.logger.debug(`Entered state ${this.state.name}`);
|
|
390
762
|
|
|
391
|
-
|
|
763
|
+
// Record the *resolved* anchor's timestamp — if the caller pinned the anchor to a past block
|
|
764
|
+
// via `anchorBlockNumber`, "latest" would be the wrong anchor for offchain-message semantics.
|
|
765
|
+
this.setLastCallContext(Fr.ZERO, anchorBlock!.globalVariables.timestamp);
|
|
766
|
+
|
|
767
|
+
return (this.oracleHandler as TXEPrivateExecutionOracle).getPrivateContextInputs();
|
|
392
768
|
}
|
|
393
769
|
|
|
394
|
-
async enterPublicState(
|
|
770
|
+
async enterPublicState(contractAddressOpt: Option<AztecAddress>) {
|
|
771
|
+
const contractAddress = contractAddressOpt?.value ?? DEFAULT_ADDRESS;
|
|
395
772
|
this.exitTopLevelState();
|
|
773
|
+
this.resetLastCall();
|
|
396
774
|
|
|
397
775
|
// The PublicContext will create a block with a single transaction in it, containing the effects of what was done in
|
|
398
776
|
// the test. The block therefore gets the *next* block number and timestamp.
|
|
399
|
-
const
|
|
777
|
+
const latestHeader = (await this.stateMachine.node.getBlockData('latest'))!.header;
|
|
400
778
|
const globalVariables = makeGlobalVariables(undefined, {
|
|
401
|
-
blockNumber: BlockNumber(
|
|
779
|
+
blockNumber: BlockNumber(latestHeader.globalVariables.blockNumber + 1),
|
|
402
780
|
timestamp: this.nextBlockTimestamp,
|
|
403
781
|
version: this.version,
|
|
404
782
|
chainId: this.chainId,
|
|
405
783
|
});
|
|
406
784
|
|
|
407
785
|
this.oracleHandler = new TXEOraclePublicContext(
|
|
408
|
-
contractAddress
|
|
786
|
+
contractAddress,
|
|
409
787
|
await this.stateMachine.synchronizer.nativeWorldStateService.fork(),
|
|
410
788
|
getSingleTxBlockRequestHash(globalVariables.blockNumber),
|
|
411
789
|
globalVariables,
|
|
790
|
+
this.contractStore,
|
|
412
791
|
);
|
|
413
792
|
|
|
414
793
|
this.state = { name: 'PUBLIC' };
|
|
415
794
|
this.logger.debug(`Entered state ${this.state.name}`);
|
|
795
|
+
|
|
796
|
+
// Public state is anchored at the latest block.
|
|
797
|
+
this.setLastCallContext(Fr.ZERO, latestHeader.globalVariables.timestamp);
|
|
416
798
|
}
|
|
417
799
|
|
|
418
|
-
async enterUtilityState(
|
|
800
|
+
async enterUtilityState(contractAddressOpt: Option<AztecAddress>) {
|
|
801
|
+
const contractAddress = contractAddressOpt?.value ?? DEFAULT_ADDRESS;
|
|
419
802
|
this.exitTopLevelState();
|
|
803
|
+
this.resetLastCall();
|
|
420
804
|
|
|
421
805
|
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
422
806
|
|
|
@@ -430,10 +814,16 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
430
814
|
this.stateMachine.node,
|
|
431
815
|
anchorBlockHeader,
|
|
432
816
|
this.currentJobId,
|
|
433
|
-
).syncNoteNullifiers(contractAddress,
|
|
817
|
+
).syncNoteNullifiers(contractAddress, await this.keyStore.getAccounts());
|
|
434
818
|
|
|
435
819
|
this.oracleHandler = new UtilityExecutionOracle({
|
|
436
|
-
|
|
820
|
+
callContext: CallContext.from({
|
|
821
|
+
msgSender: AztecAddress.NULL_MSG_SENDER,
|
|
822
|
+
contractAddress,
|
|
823
|
+
// No specific function is being executed in this inlined utility context, hence the empty selector.
|
|
824
|
+
functionSelector: FunctionSelector.empty(),
|
|
825
|
+
isStaticCall: true,
|
|
826
|
+
}),
|
|
437
827
|
authWitnesses: [],
|
|
438
828
|
capsules: [],
|
|
439
829
|
anchorBlockHeader,
|
|
@@ -443,17 +833,26 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
443
833
|
addressStore: this.addressStore,
|
|
444
834
|
aztecNode: this.stateMachine.node,
|
|
445
835
|
recipientTaggingStore: this.recipientTaggingStore,
|
|
446
|
-
|
|
447
|
-
|
|
836
|
+
taggingSecretSourcesStore: this.taggingSecretSourcesStore,
|
|
837
|
+
capsuleService: new CapsuleService(this.capsuleStore, await this.keyStore.getAccounts()),
|
|
838
|
+
factService: new FactService(this.factStore, await this.keyStore.getAccounts()),
|
|
448
839
|
privateEventStore: this.privateEventStore,
|
|
449
|
-
|
|
450
|
-
contractSyncService: this.contractSyncService,
|
|
840
|
+
txResolver: this.stateMachine.txResolver,
|
|
841
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
842
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
451
843
|
jobId: this.currentJobId,
|
|
452
|
-
scopes:
|
|
844
|
+
scopes: await this.keyStore.getAccounts(),
|
|
845
|
+
simulator: new WASMSimulator(),
|
|
846
|
+
utilityExecutor: this.utilityExecutorForContractSync(anchorBlockHeader),
|
|
847
|
+
// Execution-tree root (top-level utility run): own store; nested frames inherit it.
|
|
848
|
+
transientArrayService: new TransientArrayService(),
|
|
453
849
|
});
|
|
454
850
|
|
|
455
851
|
this.state = { name: 'UTILITY' };
|
|
456
852
|
this.logger.debug(`Entered state ${this.state.name}`);
|
|
853
|
+
|
|
854
|
+
// Utility state anchors at whatever the anchor block store is pointing to (tracked as latest).
|
|
855
|
+
this.setLastCallContext(Fr.ZERO, anchorBlockHeader.globalVariables.timestamp);
|
|
457
856
|
}
|
|
458
857
|
|
|
459
858
|
private exitTopLevelState() {
|
|
@@ -462,15 +861,20 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
462
861
|
}
|
|
463
862
|
|
|
464
863
|
// Note that while all public and private contexts do is build a single block that we then process when exiting
|
|
465
|
-
//
|
|
466
|
-
//
|
|
467
|
-
//
|
|
468
|
-
//
|
|
469
|
-
//
|
|
470
|
-
//
|
|
471
|
-
// the
|
|
472
|
-
|
|
473
|
-
|
|
864
|
+
// them, the top level context does most of its work as it goes: it creates empty blocks (via `advanceBlocksBy`
|
|
865
|
+
// and `deploy`), creates blocks with transactions (via `privateCallNewFlow` and `publicCallNewFlow`), adds
|
|
866
|
+
// accounts to PXE (via `addAccount`), etc. This is a slight inconsistency in the working model of this class, but
|
|
867
|
+
// is not too bad. The `close` call below therefore only hands back the session-scoped values that a test
|
|
868
|
+
// sets directly at the top level, outside any contract execution (e.g. via `advanceTimestampBy`,
|
|
869
|
+
// `addAuthWitness`, `setTaggingSecretStrategy`). The oracle handler is discarded on every state transition,
|
|
870
|
+
// so the session must seed these values into the contexts it creates later.
|
|
871
|
+
|
|
872
|
+
// TODO: persisting authwits this way is quite unfortunate: they create a temporary utility context that would
|
|
873
|
+
// otherwise reset them, so we'd not be able to pass more than one per execution. Ideally authwits would be passed
|
|
874
|
+
// alongside a contract call instead of pre-seeded.
|
|
875
|
+
[this.nextBlockTimestamp, this.authwits, this.taggingSecretStrategy] = (
|
|
876
|
+
this.oracleHandler as TXEOracleTopLevelContext
|
|
877
|
+
).close();
|
|
474
878
|
}
|
|
475
879
|
|
|
476
880
|
private async exitPrivateState() {
|
|
@@ -518,15 +922,21 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
518
922
|
}
|
|
519
923
|
|
|
520
924
|
private utilityExecutorForContractSync(anchorBlock: any) {
|
|
521
|
-
return async (call: FunctionCall, scopes:
|
|
925
|
+
return async (call: FunctionCall, scopes: AztecAddress[]) => {
|
|
522
926
|
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
523
927
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
524
928
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
525
929
|
}
|
|
526
930
|
|
|
527
931
|
try {
|
|
932
|
+
const simulator = new WASMSimulator();
|
|
528
933
|
const oracle = new UtilityExecutionOracle({
|
|
529
|
-
|
|
934
|
+
callContext: CallContext.from({
|
|
935
|
+
msgSender: AztecAddress.NULL_MSG_SENDER,
|
|
936
|
+
contractAddress: call.to,
|
|
937
|
+
functionSelector: call.selector,
|
|
938
|
+
isStaticCall: true,
|
|
939
|
+
}),
|
|
530
940
|
authWitnesses: [],
|
|
531
941
|
capsules: [],
|
|
532
942
|
anchorBlockHeader: anchorBlock!,
|
|
@@ -536,16 +946,22 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
536
946
|
addressStore: this.addressStore,
|
|
537
947
|
aztecNode: this.stateMachine.node,
|
|
538
948
|
recipientTaggingStore: this.recipientTaggingStore,
|
|
539
|
-
|
|
540
|
-
|
|
949
|
+
taggingSecretSourcesStore: this.taggingSecretSourcesStore,
|
|
950
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
951
|
+
factService: new FactService(this.factStore, scopes),
|
|
541
952
|
privateEventStore: this.privateEventStore,
|
|
542
|
-
|
|
543
|
-
contractSyncService: this.contractSyncService,
|
|
953
|
+
txResolver: this.stateMachine.txResolver,
|
|
954
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
955
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
544
956
|
jobId: this.currentJobId,
|
|
545
957
|
scopes,
|
|
958
|
+
simulator,
|
|
959
|
+
utilityExecutor: this.utilityExecutorForContractSync(anchorBlock),
|
|
960
|
+
// Top-level utility entrypoint: gets a fresh store. Nested frames inherit it via UtilityExecutionOracle.
|
|
961
|
+
transientArrayService: new TransientArrayService(),
|
|
546
962
|
});
|
|
547
|
-
await
|
|
548
|
-
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact,
|
|
963
|
+
await simulator
|
|
964
|
+
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, buildACIRCallback(oracle))
|
|
549
965
|
.catch((err: Error) => {
|
|
550
966
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
551
967
|
throw new ExecutionError(
|