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