@aztec/txe 5.0.0-private.20260318 → 5.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/AuthRegistry-CPGFQR26.js +3 -0
- package/dest/AuthRegistry-CPGFQR26.js.map +7 -0
- package/dest/ContractClassRegistry-EHVIHGEK.js +3 -0
- package/dest/ContractClassRegistry-EHVIHGEK.js.map +7 -0
- package/dest/ContractInstanceRegistry-DWZDXHRG.js +3 -0
- package/dest/ContractInstanceRegistry-DWZDXHRG.js.map +7 -0
- package/dest/FeeJuice-MI32ZO7B.js +3 -0
- package/dest/FeeJuice-MI32ZO7B.js.map +7 -0
- package/dest/HandshakeRegistry-3KSP3ITH.js +3 -0
- package/dest/HandshakeRegistry-3KSP3ITH.js.map +7 -0
- package/dest/MultiCallEntrypoint-IU7HYFYE.js +3 -0
- package/dest/MultiCallEntrypoint-IU7HYFYE.js.map +7 -0
- package/dest/SchnorrAccount-6TUE7JX4.js +3 -0
- package/dest/SchnorrAccount-6TUE7JX4.js.map +7 -0
- package/dest/SchnorrInitializerlessAccount-S3DU2DJK.js +3 -0
- package/dest/SchnorrInitializerlessAccount-S3DU2DJK.js.map +7 -0
- package/dest/bin/check_txe_oracle_version.d.ts +2 -0
- package/dest/bin/check_txe_oracle_version.d.ts.map +1 -0
- package/dest/bin/check_txe_oracle_version.js +61 -0
- package/dest/bin/index.js +3 -30
- package/dest/bin/index.js.map +7 -0
- package/dest/bin/oracle_test_server.d.ts +3 -0
- package/dest/bin/oracle_test_server.d.ts.map +1 -0
- package/dest/bin/oracle_test_server.js +41 -0
- package/dest/chunk-5U25VAFR.js +265 -0
- package/dest/chunk-5U25VAFR.js.map +7 -0
- package/dest/chunk-BJVAAXNA.js +3 -0
- package/dest/chunk-BJVAAXNA.js.map +7 -0
- package/dest/chunk-UPW55EJX.js +304 -0
- package/dest/chunk-UPW55EJX.js.map +7 -0
- package/dest/constants.d.ts +5 -1
- package/dest/constants.d.ts.map +1 -1
- package/dest/constants.js +8 -0
- package/dest/dispatcher_pool.d.ts +67 -0
- package/dest/dispatcher_pool.d.ts.map +1 -0
- package/dest/dispatcher_pool.js +286 -0
- package/dest/index.d.ts +51 -7
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +70 -190
- package/dest/metafile.json +38829 -0
- package/dest/msgpackr_fr_extension.d.ts +2 -0
- package/dest/msgpackr_fr_extension.d.ts.map +1 -0
- package/dest/msgpackr_fr_extension.js +21 -0
- package/dest/oracle/interfaces.d.ts +33 -8
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/test-resolver/fixtures.d.ts +43 -0
- package/dest/oracle/test-resolver/fixtures.d.ts.map +1 -0
- package/dest/oracle/test-resolver/fixtures.js +39 -0
- package/dest/oracle/test-resolver/index.d.ts +9 -0
- package/dest/oracle/test-resolver/index.d.ts.map +1 -0
- package/dest/oracle/test-resolver/index.js +33 -0
- package/dest/oracle/test-resolver/resolver.d.ts +34 -0
- package/dest/oracle/test-resolver/resolver.d.ts.map +1 -0
- package/dest/oracle/test-resolver/resolver.js +114 -0
- package/dest/oracle/txe_oracle_public_context.d.ts +26 -2
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +43 -1
- package/dest/oracle/txe_oracle_registry.d.ts +14 -0
- package/dest/oracle/txe_oracle_registry.d.ts.map +1 -0
- package/dest/oracle/txe_oracle_registry.js +562 -0
- package/dest/oracle/txe_oracle_top_level_context.d.ts +32 -18
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +151 -55
- package/dest/oracle/txe_oracle_version.d.ts +17 -0
- package/dest/oracle/txe_oracle_version.d.ts.map +1 -0
- package/dest/oracle/txe_oracle_version.js +14 -0
- package/dest/oracle/txe_private_execution_oracle.d.ts +17 -0
- package/dest/oracle/txe_private_execution_oracle.d.ts.map +1 -0
- package/dest/oracle/txe_private_execution_oracle.js +15 -0
- package/dest/rpc_server.d.ts +14 -0
- package/dest/rpc_server.d.ts.map +1 -0
- package/dest/rpc_server.js +78 -0
- package/dest/rpc_translator.d.ts +103 -230
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +697 -616
- package/dest/server.bundle.js +3 -0
- package/dest/server.bundle.js.map +7 -0
- package/dest/state_machine/archiver.d.ts +4 -3
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +26 -15
- package/dest/state_machine/dummy_p2p_client.d.ts +14 -7
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +19 -4
- package/dest/state_machine/global_variable_builder.d.ts +9 -4
- package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
- package/dest/state_machine/global_variable_builder.js +9 -3
- package/dest/state_machine/index.d.ts +4 -2
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +11 -3
- package/dest/state_machine/mock_epoch_cache.d.ts +16 -3
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +29 -2
- package/dest/state_machine/synchronizer.js +1 -1
- package/dest/txe_session.d.ts +85 -17
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +245 -40
- package/dest/utils/encoding.d.ts +191 -0
- package/dest/utils/encoding.d.ts.map +1 -0
- package/dest/{util → utils}/encoding.js +7 -2
- package/dest/{util → utils}/expected_failure_error.d.ts +1 -1
- package/dest/utils/expected_failure_error.d.ts.map +1 -0
- package/dest/{util → utils}/txe_account_store.d.ts +1 -1
- package/dest/utils/txe_account_store.d.ts.map +1 -0
- package/dest/utils/txe_artifact_resolver.d.ts +37 -0
- package/dest/utils/txe_artifact_resolver.d.ts.map +1 -0
- package/dest/utils/txe_artifact_resolver.js +161 -0
- package/dest/utils/txe_public_contract_data_source.d.ts +20 -0
- package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -0
- package/dest/{util → utils}/txe_public_contract_data_source.js +1 -3
- package/dest/worker.bundle.js +3 -0
- package/dest/worker.bundle.js.map +7 -0
- package/dest/worker.d.ts +2 -0
- package/dest/worker.d.ts.map +1 -0
- package/dest/worker.js +92 -0
- package/package.json +38 -21
- package/src/bin/check_txe_oracle_version.ts +70 -0
- package/src/bin/index.ts +11 -2
- package/src/bin/oracle_test_server.ts +51 -0
- package/src/constants.ts +10 -0
- package/src/dispatcher_pool.ts +317 -0
- package/src/index.ts +97 -227
- package/src/msgpackr_fr_extension.ts +23 -0
- package/src/oracle/interfaces.ts +29 -7
- package/src/oracle/test-resolver/fixtures.ts +84 -0
- package/src/oracle/test-resolver/index.ts +45 -0
- package/src/oracle/test-resolver/resolver.ts +165 -0
- package/src/oracle/txe_oracle_public_context.ts +60 -0
- package/src/oracle/txe_oracle_registry.ts +401 -0
- package/src/oracle/txe_oracle_top_level_context.ts +185 -64
- package/src/oracle/txe_oracle_version.ts +17 -0
- package/src/oracle/txe_private_execution_oracle.ts +30 -0
- package/src/rpc_server.ts +87 -0
- package/src/rpc_translator.ts +767 -892
- package/src/state_machine/archiver.ts +38 -16
- package/src/state_machine/dummy_p2p_client.ts +35 -11
- package/src/state_machine/global_variable_builder.ts +18 -3
- package/src/state_machine/index.ts +17 -5
- package/src/state_machine/mock_epoch_cache.ts +38 -3
- package/src/state_machine/synchronizer.ts +1 -1
- package/src/txe_session.ts +437 -50
- package/src/{util → utils}/encoding.ts +8 -2
- package/src/utils/txe_artifact_resolver.ts +217 -0
- package/src/{util → utils}/txe_public_contract_data_source.ts +0 -2
- package/src/worker.ts +98 -0
- package/dest/util/encoding.d.ts +0 -720
- package/dest/util/encoding.d.ts.map +0 -1
- package/dest/util/expected_failure_error.d.ts.map +0 -1
- package/dest/util/txe_account_store.d.ts.map +0 -1
- package/dest/util/txe_public_contract_data_source.d.ts +0 -20
- package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
- /package/dest/{util → utils}/expected_failure_error.js +0 -0
- /package/dest/{util → utils}/txe_account_store.js +0 -0
- /package/src/{util → utils}/expected_failure_error.ts +0 -0
- /package/src/{util → utils}/txe_account_store.ts +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS,
|
|
1
|
+
import { CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS, MAX_PRIVATE_LOGS_PER_TX, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
|
|
2
2
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
3
3
|
import { Schnorr } from '@aztec/foundation/crypto/schnorr';
|
|
4
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
5
|
import { LogLevels, applyStringFormatting, createLogger } from '@aztec/foundation/log';
|
|
6
6
|
import { TestDateProvider } from '@aztec/foundation/timer';
|
|
7
|
-
import {
|
|
8
|
-
import { ExecutionNoteCache, ExecutionTaggingIndexCache, HashedValuesCache,
|
|
7
|
+
import { CapsuleService, ORACLE_VERSION_MAJOR, composeHooks, enrichPublicSimulationError } from '@aztec/pxe/server';
|
|
8
|
+
import { ExecutionNoteCache, ExecutionTaggingIndexCache, HashedValuesCache, PrivateExecutionOracle, TransientArrayService, UtilityExecutionOracle, buildACIRCallback, executePrivateFunction, generateSimulatedProvingResult } from '@aztec/pxe/simulator';
|
|
9
9
|
import { ExecutionError, WASMSimulator, createSimulationError, extractCallStack, resolveAssertionMessageFromError, toACVMWitness, witnessMapToFields } from '@aztec/simulator/client';
|
|
10
10
|
import { CppPublicTxSimulator, GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor } from '@aztec/simulator/server';
|
|
11
11
|
import { FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
@@ -13,17 +13,18 @@ import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
|
13
13
|
import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
|
|
14
14
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
15
15
|
import { computePartialAddress } from '@aztec/stdlib/contract';
|
|
16
|
-
import { Gas, GasFees
|
|
16
|
+
import { Gas, GasFees } from '@aztec/stdlib/gas';
|
|
17
17
|
import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
|
|
18
18
|
import { PartialPrivateTailPublicInputsForPublic, PrivateKernelTailCircuitPublicInputs, PrivateToPublicAccumulatedData, PublicCallRequest } from '@aztec/stdlib/kernel';
|
|
19
|
+
import { hashPublicKey } from '@aztec/stdlib/keys';
|
|
19
20
|
import { ChonkProof } from '@aztec/stdlib/proofs';
|
|
20
21
|
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
21
22
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
22
23
|
import { CallContext, HashedValues, PrivateExecutionResult, Tx, TxConstantData, TxContext, TxEffect, TxHash, collectNested } from '@aztec/stdlib/tx';
|
|
23
|
-
import { ForkCheckpoint } from '@aztec/world-state';
|
|
24
|
-
import { DEFAULT_ADDRESS } from '../constants.js';
|
|
25
|
-
import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
|
|
24
|
+
import { ForkCheckpoint } from '@aztec/world-state/native';
|
|
25
|
+
import { DEFAULT_ADDRESS, MAX_PRIVATE_EVENTS_PER_TXE_QUERY, MAX_PRIVATE_EVENT_LEN } from '../constants.js';
|
|
26
26
|
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
27
|
+
import { TXEPublicContractDataSource } from '../utils/txe_public_contract_data_source.js';
|
|
27
28
|
export class TXEOracleTopLevelContext {
|
|
28
29
|
stateMachine;
|
|
29
30
|
contractStore;
|
|
@@ -40,10 +41,13 @@ export class TXEOracleTopLevelContext {
|
|
|
40
41
|
version;
|
|
41
42
|
chainId;
|
|
42
43
|
authwits;
|
|
44
|
+
artifactResolver;
|
|
45
|
+
rootPath;
|
|
46
|
+
packageName;
|
|
43
47
|
isMisc;
|
|
44
48
|
isTxe;
|
|
45
49
|
logger;
|
|
46
|
-
constructor(stateMachine, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore, senderAddressBookStore, capsuleStore, privateEventStore, nextBlockTimestamp, version, chainId, authwits){
|
|
50
|
+
constructor(stateMachine, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore, senderAddressBookStore, capsuleStore, privateEventStore, nextBlockTimestamp, version, chainId, authwits, artifactResolver, rootPath, packageName){
|
|
47
51
|
this.stateMachine = stateMachine;
|
|
48
52
|
this.contractStore = contractStore;
|
|
49
53
|
this.noteStore = noteStore;
|
|
@@ -59,15 +63,28 @@ export class TXEOracleTopLevelContext {
|
|
|
59
63
|
this.version = version;
|
|
60
64
|
this.chainId = chainId;
|
|
61
65
|
this.authwits = authwits;
|
|
66
|
+
this.artifactResolver = artifactResolver;
|
|
67
|
+
this.rootPath = rootPath;
|
|
68
|
+
this.packageName = packageName;
|
|
62
69
|
this.isMisc = true;
|
|
63
70
|
this.isTxe = true;
|
|
64
71
|
this.logger = createLogger('txe:top_level_context');
|
|
65
72
|
this.logger.debug('Entering Top Level Context');
|
|
66
73
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
74
|
+
contractOracleVersion;
|
|
75
|
+
assertCompatibleOracleVersion(major, minor) {
|
|
76
|
+
if (major !== ORACLE_VERSION_MAJOR) {
|
|
77
|
+
const hint = major > ORACLE_VERSION_MAJOR ? 'The contract was compiled with a newer version of Aztec.nr than this aztec cli version supports. Upgrade your aztec cli version to a compatible version.' : 'The contract was compiled with an older version of Aztec.nr than this aztec cli version supports. Recompile the contract with a compatible version of Aztec.nr.';
|
|
78
|
+
throw new Error(`Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`);
|
|
70
79
|
}
|
|
80
|
+
this.contractOracleVersion = {
|
|
81
|
+
major,
|
|
82
|
+
minor
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
|
|
86
|
+
nonOracleFunctionGetContractOracleVersion() {
|
|
87
|
+
return this.contractOracleVersion;
|
|
71
88
|
}
|
|
72
89
|
// This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
|
|
73
90
|
// setup.
|
|
@@ -75,7 +92,7 @@ export class TXEOracleTopLevelContext {
|
|
|
75
92
|
return Fr.random();
|
|
76
93
|
}
|
|
77
94
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
78
|
-
log(level, message, fields) {
|
|
95
|
+
log(level, message, _fieldsSize, fields) {
|
|
79
96
|
if (!LogLevels[level]) {
|
|
80
97
|
throw new Error(`Invalid log level: ${level}`);
|
|
81
98
|
}
|
|
@@ -95,20 +112,27 @@ export class TXEOracleTopLevelContext {
|
|
|
95
112
|
return Promise.resolve(this.nextBlockTimestamp);
|
|
96
113
|
}
|
|
97
114
|
async getLastBlockTimestamp() {
|
|
98
|
-
return (await this.stateMachine.node.
|
|
115
|
+
return (await this.stateMachine.node.getBlockData('latest')).header.globalVariables.timestamp;
|
|
99
116
|
}
|
|
100
117
|
async getLastTxEffects() {
|
|
101
118
|
const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
|
|
102
|
-
const block = await this.stateMachine.archiver.getBlock(
|
|
119
|
+
const block = await this.stateMachine.archiver.getBlock({
|
|
120
|
+
number: latestBlockNumber
|
|
121
|
+
});
|
|
103
122
|
if (block.body.txEffects.length != 1) {
|
|
104
123
|
// Note that calls like env.mine() will result in blocks with no transactions, hitting this
|
|
105
124
|
throw new Error(`Expected a single transaction in the last block, found ${block.body.txEffects.length}`);
|
|
106
125
|
}
|
|
107
126
|
const txEffects = block.body.txEffects[0];
|
|
127
|
+
const privateLogs = txEffects.privateLogs;
|
|
128
|
+
if (privateLogs.length > MAX_PRIVATE_LOGS_PER_TX) {
|
|
129
|
+
throw new Error(`${privateLogs.length} private logs exceed max ${MAX_PRIVATE_LOGS_PER_TX}`);
|
|
130
|
+
}
|
|
108
131
|
return {
|
|
109
132
|
txHash: txEffects.txHash,
|
|
110
133
|
noteHashes: txEffects.noteHashes,
|
|
111
|
-
nullifiers: txEffects.nullifiers
|
|
134
|
+
nullifiers: txEffects.nullifiers,
|
|
135
|
+
privateLogs
|
|
112
136
|
};
|
|
113
137
|
}
|
|
114
138
|
async syncContractNonOracleMethod(contractAddress, scope, jobId) {
|
|
@@ -124,7 +148,7 @@ export class TXEOracleTopLevelContext {
|
|
|
124
148
|
]);
|
|
125
149
|
}
|
|
126
150
|
async getPrivateEvents(selector, contractAddress, scope) {
|
|
127
|
-
|
|
151
|
+
const events = (await this.privateEventStore.getPrivateEvents(selector, {
|
|
128
152
|
contractAddress,
|
|
129
153
|
scopes: [
|
|
130
154
|
scope
|
|
@@ -132,6 +156,13 @@ export class TXEOracleTopLevelContext {
|
|
|
132
156
|
fromBlock: 0,
|
|
133
157
|
toBlock: await this.getLastBlockNumber() + 1
|
|
134
158
|
})).map((e)=>e.packedEvent);
|
|
159
|
+
if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
|
|
160
|
+
throw new Error(`Array of length ${events.length} larger than maxLen ${MAX_PRIVATE_EVENTS_PER_TXE_QUERY}`);
|
|
161
|
+
}
|
|
162
|
+
if (events.some((e)=>e.length > MAX_PRIVATE_EVENT_LEN)) {
|
|
163
|
+
throw new Error(`Some private event has length larger than maxLen ${MAX_PRIVATE_EVENT_LEN}`);
|
|
164
|
+
}
|
|
165
|
+
return events;
|
|
135
166
|
}
|
|
136
167
|
async advanceBlocksBy(blocks) {
|
|
137
168
|
this.logger.debug(`time traveling ${blocks} blocks`);
|
|
@@ -143,22 +174,54 @@ export class TXEOracleTopLevelContext {
|
|
|
143
174
|
this.logger.debug(`time traveling ${duration} seconds`);
|
|
144
175
|
this.nextBlockTimestamp += duration;
|
|
145
176
|
}
|
|
146
|
-
|
|
177
|
+
deploymentNullifier(address) {
|
|
178
|
+
return siloNullifier(AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), address.toField());
|
|
179
|
+
}
|
|
180
|
+
async deploy(contractPath, initializer, args, secret, salt, deployer) {
|
|
181
|
+
const { artifact, instance } = await this.artifactResolver.resolveDeployArtifact({
|
|
182
|
+
rootPath: this.rootPath,
|
|
183
|
+
packageName: this.packageName,
|
|
184
|
+
contractPath,
|
|
185
|
+
initializer,
|
|
186
|
+
args,
|
|
187
|
+
secret,
|
|
188
|
+
salt,
|
|
189
|
+
deployer
|
|
190
|
+
});
|
|
147
191
|
// Emit deployment nullifier
|
|
148
192
|
await this.mineBlock({
|
|
149
193
|
nullifiers: [
|
|
150
|
-
await
|
|
194
|
+
await this.deploymentNullifier(instance.address)
|
|
151
195
|
]
|
|
152
196
|
});
|
|
153
197
|
if (!secret.equals(Fr.ZERO)) {
|
|
154
|
-
await this.
|
|
198
|
+
await this.registerContractAndAddAccount(artifact, instance, secret);
|
|
155
199
|
} else {
|
|
156
200
|
await this.contractStore.addContractInstance(instance);
|
|
157
201
|
await this.contractStore.addContractArtifact(artifact);
|
|
158
202
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
159
203
|
}
|
|
204
|
+
return [
|
|
205
|
+
instance.salt,
|
|
206
|
+
instance.deployer.toField(),
|
|
207
|
+
instance.currentContractClassId,
|
|
208
|
+
instance.initializationHash,
|
|
209
|
+
instance.immutablesHash,
|
|
210
|
+
...instance.publicKeys.toFields()
|
|
211
|
+
];
|
|
160
212
|
}
|
|
161
|
-
|
|
213
|
+
/**
|
|
214
|
+
* Mines a single block containing only the deployment nullifiers for the contracts at the given addresses.
|
|
215
|
+
*/ async mineDeploymentNullifiers(addresses) {
|
|
216
|
+
await this.mineBlock({
|
|
217
|
+
nullifiers: await Promise.all(addresses.map((address)=>this.deploymentNullifier(address)))
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
async addAccount(secret) {
|
|
221
|
+
const { artifact, instance } = await this.artifactResolver.resolveAccountArtifact(secret);
|
|
222
|
+
return this.registerContractAndAddAccount(artifact, instance, secret);
|
|
223
|
+
}
|
|
224
|
+
async registerContractAndAddAccount(artifact, instance, secret) {
|
|
162
225
|
const partialAddress = await computePartialAddress(instance);
|
|
163
226
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
164
227
|
await this.contractStore.addContractInstance(instance);
|
|
@@ -179,12 +242,11 @@ export class TXEOracleTopLevelContext {
|
|
|
179
242
|
}
|
|
180
243
|
async addAuthWitness(address, messageHash) {
|
|
181
244
|
const account = await this.accountStore.getAccount(address);
|
|
182
|
-
const
|
|
245
|
+
const ivpkMHash = await hashPublicKey(account.publicKeys.ivpkM);
|
|
246
|
+
const privateKey = await this.keyStore.getMasterSecretKey(ivpkMHash);
|
|
183
247
|
const schnorr = new Schnorr();
|
|
184
|
-
const signature = await schnorr.constructSignature(messageHash
|
|
185
|
-
const authWitness = new AuthWitness(messageHash,
|
|
186
|
-
...signature.toBuffer()
|
|
187
|
-
]);
|
|
248
|
+
const signature = await schnorr.constructSignature(messageHash, privateKey);
|
|
249
|
+
const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
|
|
188
250
|
this.authwits.set(authWitness.requestHash.toString(), authWitness);
|
|
189
251
|
}
|
|
190
252
|
async mineBlock(options = {}) {
|
|
@@ -210,29 +272,26 @@ export class TXEOracleTopLevelContext {
|
|
|
210
272
|
this.logger.info(`Created block ${blockNumber} with timestamp ${block.header.globalVariables.timestamp}`);
|
|
211
273
|
await this.stateMachine.handleL2Block(block);
|
|
212
274
|
}
|
|
213
|
-
async privateCallNewFlow(from, targetContractAddress = AztecAddress.zero(), functionSelector = FunctionSelector.empty(), args, argsHash = Fr.zero(), isStaticCall = false, jobId) {
|
|
275
|
+
async privateCallNewFlow(from, targetContractAddress = AztecAddress.zero(), functionSelector = FunctionSelector.empty(), args, argsHash = Fr.zero(), isStaticCall = false, additionalScopes = [], jobId, authorizedUtilityCallTargets, gasSettings) {
|
|
214
276
|
this.logger.verbose(`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`);
|
|
215
277
|
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
216
278
|
if (!artifact) {
|
|
217
279
|
const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)')) ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.' : 'Function Artifact does not exist';
|
|
218
280
|
throw new Error(message);
|
|
219
281
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
from
|
|
282
|
+
const scopes = from === undefined ? additionalScopes : [
|
|
283
|
+
from,
|
|
284
|
+
...additionalScopes
|
|
224
285
|
];
|
|
225
286
|
// Sync notes before executing private function to discover notes from previous transactions
|
|
226
287
|
const utilityExecutor = async (call, execScopes)=>{
|
|
227
288
|
await this.executeUtilityCall(call, execScopes, jobId);
|
|
228
289
|
};
|
|
229
290
|
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
230
|
-
await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, utilityExecutor, blockHeader, jobId,
|
|
291
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, utilityExecutor, blockHeader, jobId, scopes);
|
|
231
292
|
const blockNumber = await this.getNextBlockNumber();
|
|
232
|
-
const
|
|
233
|
-
const
|
|
234
|
-
const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
|
|
235
|
-
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
293
|
+
const msgSender = from ?? AztecAddress.NULL_MSG_SENDER;
|
|
294
|
+
const callContext = new CallContext(msgSender, targetContractAddress, functionSelector, isStaticCall);
|
|
236
295
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
237
296
|
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
238
297
|
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
@@ -243,6 +302,7 @@ export class TXEOracleTopLevelContext {
|
|
|
243
302
|
await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
244
303
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
245
304
|
const simulator = new WASMSimulator();
|
|
305
|
+
const transientArrayService = new TransientArrayService();
|
|
246
306
|
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
247
307
|
argsHash,
|
|
248
308
|
txContext,
|
|
@@ -264,18 +324,23 @@ export class TXEOracleTopLevelContext {
|
|
|
264
324
|
senderTaggingStore: this.senderTaggingStore,
|
|
265
325
|
recipientTaggingStore: this.recipientTaggingStore,
|
|
266
326
|
senderAddressBookStore: this.senderAddressBookStore,
|
|
267
|
-
|
|
327
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
268
328
|
privateEventStore: this.privateEventStore,
|
|
269
329
|
contractSyncService: this.stateMachine.contractSyncService,
|
|
270
330
|
jobId,
|
|
271
331
|
totalPublicCalldataCount: 0,
|
|
272
332
|
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
273
|
-
scopes
|
|
333
|
+
scopes,
|
|
274
334
|
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
275
335
|
// contract would perform, including setting senderForTags.
|
|
276
336
|
senderForTags: from,
|
|
277
337
|
simulator,
|
|
278
|
-
messageContextService: this.stateMachine.messageContextService
|
|
338
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
339
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
340
|
+
hooks: composeHooks({
|
|
341
|
+
authorizeUtilityCall: this.buildAuthorizeUtilityCallHook(isStaticCall ? 'private view' : 'private', authorizedUtilityCallTargets)
|
|
342
|
+
}),
|
|
343
|
+
transientArrayService
|
|
279
344
|
});
|
|
280
345
|
// Note: This is a slight modification of simulator.run without any of the checks. Maybe we should modify simulator.run with a boolean value to skip checks.
|
|
281
346
|
let result;
|
|
@@ -288,7 +353,7 @@ export class TXEOracleTopLevelContext {
|
|
|
288
353
|
r.publicInputs.publicTeardownCallRequest
|
|
289
354
|
]));
|
|
290
355
|
const publicFunctionsCalldata = await Promise.all(publicCallRequests.map(async (r)=>{
|
|
291
|
-
const calldata = await privateExecutionOracle.
|
|
356
|
+
const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
|
|
292
357
|
return new HashedValues(calldata, r.calldataHash);
|
|
293
358
|
}));
|
|
294
359
|
noteCache.finish();
|
|
@@ -347,10 +412,20 @@ export class TXEOracleTopLevelContext {
|
|
|
347
412
|
throw new Error('Contract execution has reverted');
|
|
348
413
|
}
|
|
349
414
|
}
|
|
415
|
+
// Walk the nested private-call tree and collect every offchain effect the transaction emitted.
|
|
416
|
+
// PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
|
|
417
|
+
// `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
|
|
418
|
+
// we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
|
|
419
|
+
const offchainEffects = collectNested([
|
|
420
|
+
executionResult
|
|
421
|
+
], (r)=>r.offchainEffects.map((e)=>e.data));
|
|
350
422
|
if (isStaticCall) {
|
|
351
423
|
await checkpoint.revert();
|
|
352
424
|
await forkedWorldTrees.close();
|
|
353
|
-
return
|
|
425
|
+
return {
|
|
426
|
+
returnValues: executionResult.returnValues ?? [],
|
|
427
|
+
offchainEffects
|
|
428
|
+
};
|
|
354
429
|
}
|
|
355
430
|
const txEffect = TxEffect.empty();
|
|
356
431
|
txEffect.noteHashes = processedTx.txEffect.noteHashes;
|
|
@@ -366,14 +441,14 @@ export class TXEOracleTopLevelContext {
|
|
|
366
441
|
]);
|
|
367
442
|
await this.stateMachine.handleL2Block(l2Block);
|
|
368
443
|
await forkedWorldTrees.close();
|
|
369
|
-
return
|
|
444
|
+
return {
|
|
445
|
+
returnValues: executionResult.returnValues ?? [],
|
|
446
|
+
offchainEffects
|
|
447
|
+
};
|
|
370
448
|
}
|
|
371
|
-
async publicCallNewFlow(from, targetContractAddress, calldata, isStaticCall) {
|
|
449
|
+
async publicCallNewFlow(from, targetContractAddress, calldata, isStaticCall, gasSettings) {
|
|
372
450
|
this.logger.verbose(`Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`);
|
|
373
451
|
const blockNumber = await this.getNextBlockNumber();
|
|
374
|
-
const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
|
|
375
|
-
const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
|
|
376
|
-
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
377
452
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
378
453
|
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
379
454
|
const calldataHash = await computeCalldataHash(calldata);
|
|
@@ -406,7 +481,7 @@ export class TXEOracleTopLevelContext {
|
|
|
406
481
|
// The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
|
|
407
482
|
// may require producing reverts.
|
|
408
483
|
const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
409
|
-
revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(from, targetContractAddress, isStaticCall, calldataHash);
|
|
484
|
+
revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(from ?? AztecAddress.NULL_MSG_SENDER, targetContractAddress, isStaticCall, calldataHash);
|
|
410
485
|
const inputsForPublic = new PartialPrivateTailPublicInputsForPublic(nonRevertibleAccumulatedData, revertibleAccumulatedData, PublicCallRequest.empty());
|
|
411
486
|
const constantData = new TxConstantData(anchorBlockHeader, txContext, Fr.zero(), Fr.zero());
|
|
412
487
|
const txData = new PrivateKernelTailCircuitPublicInputs(constantData, /*gasUsed=*/ new Gas(0, 0), /*feePayer=*/ AztecAddress.zero(), /*expirationTimestamp=*/ 0n, inputsForPublic, undefined);
|
|
@@ -462,7 +537,7 @@ export class TXEOracleTopLevelContext {
|
|
|
462
537
|
await forkedWorldTrees.close();
|
|
463
538
|
return returnValues ?? [];
|
|
464
539
|
}
|
|
465
|
-
async executeUtilityFunction(targetContractAddress, functionSelector, args, jobId) {
|
|
540
|
+
async executeUtilityFunction(targetContractAddress, functionSelector, args, jobId, authorizedUtilityCallTargets) {
|
|
466
541
|
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
467
542
|
if (!artifact) {
|
|
468
543
|
throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
|
|
@@ -471,7 +546,7 @@ export class TXEOracleTopLevelContext {
|
|
|
471
546
|
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
472
547
|
await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, async (call, execScopes)=>{
|
|
473
548
|
await this.executeUtilityCall(call, execScopes, jobId);
|
|
474
|
-
}, blockHeader, jobId,
|
|
549
|
+
}, blockHeader, jobId, await this.keyStore.getAccounts());
|
|
475
550
|
const call = FunctionCall.from({
|
|
476
551
|
name: artifact.name,
|
|
477
552
|
to: targetContractAddress,
|
|
@@ -482,9 +557,9 @@ export class TXEOracleTopLevelContext {
|
|
|
482
557
|
args,
|
|
483
558
|
returnTypes: []
|
|
484
559
|
});
|
|
485
|
-
return this.executeUtilityCall(call,
|
|
560
|
+
return this.executeUtilityCall(call, await this.keyStore.getAccounts(), jobId, authorizedUtilityCallTargets);
|
|
486
561
|
}
|
|
487
|
-
async executeUtilityCall(call, scopes, jobId) {
|
|
562
|
+
async executeUtilityCall(call, scopes, jobId, authorizedUtilityCallTargets = []) {
|
|
488
563
|
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
489
564
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
490
565
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
@@ -495,6 +570,10 @@ export class TXEOracleTopLevelContext {
|
|
|
495
570
|
});
|
|
496
571
|
try {
|
|
497
572
|
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
573
|
+
const simulator = new WASMSimulator();
|
|
574
|
+
const utilityExecutor = async (syncCall, execScopes)=>{
|
|
575
|
+
await this.executeUtilityCall(syncCall, execScopes, jobId);
|
|
576
|
+
};
|
|
498
577
|
const oracle = new UtilityExecutionOracle({
|
|
499
578
|
contractAddress: call.to,
|
|
500
579
|
authWitnesses: [],
|
|
@@ -507,13 +586,22 @@ export class TXEOracleTopLevelContext {
|
|
|
507
586
|
aztecNode: this.stateMachine.node,
|
|
508
587
|
recipientTaggingStore: this.recipientTaggingStore,
|
|
509
588
|
senderAddressBookStore: this.senderAddressBookStore,
|
|
510
|
-
|
|
589
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
511
590
|
privateEventStore: this.privateEventStore,
|
|
512
591
|
messageContextService: this.stateMachine.messageContextService,
|
|
592
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
593
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
513
594
|
jobId,
|
|
514
|
-
scopes
|
|
595
|
+
scopes,
|
|
596
|
+
simulator,
|
|
597
|
+
hooks: composeHooks({
|
|
598
|
+
authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets)
|
|
599
|
+
}),
|
|
600
|
+
utilityExecutor,
|
|
601
|
+
// Execution-tree root (top-level utility run or contract sync): own store; nested frames inherit it.
|
|
602
|
+
transientArrayService: new TransientArrayService()
|
|
515
603
|
});
|
|
516
|
-
const acirExecutionResult = await
|
|
604
|
+
const acirExecutionResult = await simulator.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, buildACIRCallback(oracle)).catch((err)=>{
|
|
517
605
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
518
606
|
throw new ExecutionError(err.message, {
|
|
519
607
|
contractAddress: call.to,
|
|
@@ -536,7 +624,15 @@ export class TXEOracleTopLevelContext {
|
|
|
536
624
|
];
|
|
537
625
|
}
|
|
538
626
|
async getLastBlockNumber() {
|
|
539
|
-
const
|
|
540
|
-
return
|
|
627
|
+
const block = await this.stateMachine.node.getBlock('latest');
|
|
628
|
+
return block ? block.header.globalVariables.blockNumber : BlockNumber.ZERO;
|
|
629
|
+
}
|
|
630
|
+
buildAuthorizeUtilityCallHook(callerContext, authorizedTargets) {
|
|
631
|
+
if (authorizedTargets.length === 0) {
|
|
632
|
+
return undefined;
|
|
633
|
+
}
|
|
634
|
+
return (req)=>Promise.resolve({
|
|
635
|
+
authorized: req.callerContext === callerContext && authorizedTargets.some((t)=>t.equals(req.target))
|
|
636
|
+
});
|
|
541
637
|
}
|
|
542
638
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The TXE oracle version constants are used to check that the oracle interface used for tests is in sync between
|
|
3
|
+
* TXE and Aztec.nr. This is separate from the contract oracle version in `pxe/src/oracle_version.ts`, which covers
|
|
4
|
+
* oracles used during contract execution by PXE.
|
|
5
|
+
*
|
|
6
|
+
* The Noir counterparts are in `noir-projects/aztec-nr/aztec/src/test/helpers/txe_oracles.nr`.
|
|
7
|
+
*/
|
|
8
|
+
export declare const TXE_ORACLE_VERSION_MAJOR = 1;
|
|
9
|
+
export declare const TXE_ORACLE_VERSION_MINOR = 2;
|
|
10
|
+
/**
|
|
11
|
+
* This hash is computed from the TXE oracle interfaces (IAvmExecutionOracle and ITxeExecutionOracle) and is used to
|
|
12
|
+
* detect when those interfaces change. When it does, bump:
|
|
13
|
+
* - TXE_ORACLE_VERSION_MAJOR (and reset MINOR to 0) for breaking changes, or
|
|
14
|
+
* - TXE_ORACLE_VERSION_MINOR for additive changes (new oracle method added).
|
|
15
|
+
*/
|
|
16
|
+
export declare const TXE_ORACLE_INTERFACE_HASH = "9e5f6ad5fd170d1de5ddd417f19cce47b17382567e08360dc6a783154828e218";
|
|
17
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHhlX29yYWNsZV92ZXJzaW9uLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvb3JhY2xlL3R4ZV9vcmFjbGVfdmVyc2lvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFDSCxlQUFPLE1BQU0sd0JBQXdCLElBQUksQ0FBQztBQUMxQyxlQUFPLE1BQU0sd0JBQXdCLElBQUksQ0FBQztBQUUxQzs7Ozs7R0FLRztBQUNILGVBQU8sTUFBTSx5QkFBeUIscUVBQXFFLENBQUMifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"txe_oracle_version.d.ts","sourceRoot":"","sources":["../../src/oracle/txe_oracle_version.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,qEAAqE,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The TXE oracle version constants are used to check that the oracle interface used for tests is in sync between
|
|
3
|
+
* TXE and Aztec.nr. This is separate from the contract oracle version in `pxe/src/oracle_version.ts`, which covers
|
|
4
|
+
* oracles used during contract execution by PXE.
|
|
5
|
+
*
|
|
6
|
+
* The Noir counterparts are in `noir-projects/aztec-nr/aztec/src/test/helpers/txe_oracles.nr`.
|
|
7
|
+
*/ export const TXE_ORACLE_VERSION_MAJOR = 1;
|
|
8
|
+
export const TXE_ORACLE_VERSION_MINOR = 2;
|
|
9
|
+
/**
|
|
10
|
+
* This hash is computed from the TXE oracle interfaces (IAvmExecutionOracle and ITxeExecutionOracle) and is used to
|
|
11
|
+
* detect when those interfaces change. When it does, bump:
|
|
12
|
+
* - TXE_ORACLE_VERSION_MAJOR (and reset MINOR to 0) for breaking changes, or
|
|
13
|
+
* - TXE_ORACLE_VERSION_MINOR for additive changes (new oracle method added).
|
|
14
|
+
*/ export const TXE_ORACLE_INTERFACE_HASH = '9e5f6ad5fd170d1de5ddd417f19cce47b17382567e08360dc6a783154828e218';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
|
+
import { PrivateExecutionOracle } from '@aztec/pxe/simulator';
|
|
3
|
+
import type { FunctionSelector } from '@aztec/stdlib/abi';
|
|
4
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
5
|
+
/**
|
|
6
|
+
* TXE-specific subclass of PrivateExecutionOracle that forbids operations not supported in
|
|
7
|
+
* TestEnvironment::private_context. TXE uses dedicated oracle flows (e.g. private_call) instead.
|
|
8
|
+
*/
|
|
9
|
+
export declare class TXEPrivateExecutionOracle extends PrivateExecutionOracle {
|
|
10
|
+
callPrivateFunction(_targetContractAddress: AztecAddress, _functionSelector: FunctionSelector, _argsHash: Fr, _sideEffectCounter: number, _isStaticCall: boolean): Promise<{
|
|
11
|
+
endSideEffectCounter: Fr;
|
|
12
|
+
returnsHash: Fr;
|
|
13
|
+
}>;
|
|
14
|
+
assertValidPublicCalldata(_calldataHash: Fr): Promise<void>;
|
|
15
|
+
notifyRevertiblePhaseStart(_minRevertibleSideEffectCounter: number): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHhlX3ByaXZhdGVfZXhlY3V0aW9uX29yYWNsZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL29yYWNsZS90eGVfcHJpdmF0ZV9leGVjdXRpb25fb3JhY2xlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLEVBQUUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3pELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzlELE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDMUQsT0FBTyxLQUFLLEVBQUUsWUFBWSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFaEU7OztHQUdHO0FBQ0gscUJBQWEseUJBQTBCLFNBQVEsc0JBQXNCO0lBQzFELG1CQUFtQixDQUMxQixzQkFBc0IsRUFBRSxZQUFZLEVBQ3BDLGlCQUFpQixFQUFFLGdCQUFnQixFQUNuQyxTQUFTLEVBQUUsRUFBRSxFQUNiLGtCQUFrQixFQUFFLE1BQU0sRUFDMUIsYUFBYSxFQUFFLE9BQU8sR0FDckIsT0FBTyxDQUFDO1FBQUUsb0JBQW9CLEVBQUUsRUFBRSxDQUFDO1FBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQTtLQUFFLENBQUMsQ0FJeEQ7SUFFUSx5QkFBeUIsQ0FBQyxhQUFhLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FFbkU7SUFFUSwwQkFBMEIsQ0FBQywrQkFBK0IsRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUUxRjtDQUNGIn0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"txe_private_execution_oracle.d.ts","sourceRoot":"","sources":["../../src/oracle/txe_private_execution_oracle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;;GAGG;AACH,qBAAa,yBAA0B,SAAQ,sBAAsB;IAC1D,mBAAmB,CAC1B,sBAAsB,EAAE,YAAY,EACpC,iBAAiB,EAAE,gBAAgB,EACnC,SAAS,EAAE,EAAE,EACb,kBAAkB,EAAE,MAAM,EAC1B,aAAa,EAAE,OAAO,GACrB,OAAO,CAAC;QAAE,oBAAoB,EAAE,EAAE,CAAC;QAAC,WAAW,EAAE,EAAE,CAAA;KAAE,CAAC,CAIxD;IAEQ,yBAAyB,CAAC,aAAa,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAEnE;IAEQ,0BAA0B,CAAC,+BAA+B,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1F;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PrivateExecutionOracle } from '@aztec/pxe/simulator';
|
|
2
|
+
/**
|
|
3
|
+
* TXE-specific subclass of PrivateExecutionOracle that forbids operations not supported in
|
|
4
|
+
* TestEnvironment::private_context. TXE uses dedicated oracle flows (e.g. private_call) instead.
|
|
5
|
+
*/ export class TXEPrivateExecutionOracle extends PrivateExecutionOracle {
|
|
6
|
+
callPrivateFunction(_targetContractAddress, _functionSelector, _argsHash, _sideEffectCounter, _isStaticCall) {
|
|
7
|
+
throw new Error('Contract calls are forbidden inside a `TestEnvironment::private_context`, use `private_call` instead');
|
|
8
|
+
}
|
|
9
|
+
assertValidPublicCalldata(_calldataHash) {
|
|
10
|
+
throw new Error('Enqueueing public calls is not supported in TestEnvironment::private_context');
|
|
11
|
+
}
|
|
12
|
+
notifyRevertiblePhaseStart(_minRevertibleSideEffectCounter) {
|
|
13
|
+
throw new Error('Enqueueing public calls is not supported in TestEnvironment::private_context');
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Logger } from '@aztec/foundation/log';
|
|
2
|
+
/**
|
|
3
|
+
* Creates the TXE RPC server. With `TXE_WORKERS=1` oracle calls run on the main thread (no
|
|
4
|
+
* worker_threads, no IPC overhead). With any other value oracle calls are
|
|
5
|
+
* routed to a pool of worker threads sized to that value, sticky by `session_id`.
|
|
6
|
+
*
|
|
7
|
+
* Each incoming TCP socket is tagged with the `session_id` of the first oracle call it carries —
|
|
8
|
+
* nargo uses one HTTP client per test, so the socket-to-session mapping is 1:1. When the socket
|
|
9
|
+
* closes (end of test), the dispatcher disposes the session and frees its world state + LMDB.
|
|
10
|
+
*
|
|
11
|
+
* Lives in its own module so the worker bundle does not pull in the HTTP server stack.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createTXERpcServer(logger: Logger): Promise<import("@aztec/foundation/json-rpc/server").SafeJsonRpcServer>;
|
|
14
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnBjX3NlcnZlci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3JwY19zZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFlcEQ7Ozs7Ozs7Ozs7R0FVRztBQUNILHdCQUFzQixrQkFBa0IsQ0FBQyxNQUFNLEVBQUUsTUFBTSwwRUE0Q3REIn0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc_server.d.ts","sourceRoot":"","sources":["../src/rpc_server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAepD;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,0EA4CtD"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { createSafeJsonRpcServer } from '@aztec/foundation/json-rpc/server';
|
|
2
|
+
import { TXEDispatcherPool, buildSharedContractStore } from './dispatcher_pool.js';
|
|
3
|
+
import { TXEDispatcher, TXEDispatcherApiSchema } from './index.js';
|
|
4
|
+
/**
|
|
5
|
+
* Symbol used to tag an incoming TCP socket with the `session_id` it has been associated with.
|
|
6
|
+
* Hidden under a Symbol so we don't risk colliding with anything koa or http core adds.
|
|
7
|
+
*/ const SESSION_SYMBOL = Symbol('txeSessionId');
|
|
8
|
+
/**
|
|
9
|
+
* Creates the TXE RPC server. With `TXE_WORKERS=1` oracle calls run on the main thread (no
|
|
10
|
+
* worker_threads, no IPC overhead). With any other value oracle calls are
|
|
11
|
+
* routed to a pool of worker threads sized to that value, sticky by `session_id`.
|
|
12
|
+
*
|
|
13
|
+
* Each incoming TCP socket is tagged with the `session_id` of the first oracle call it carries —
|
|
14
|
+
* nargo uses one HTTP client per test, so the socket-to-session mapping is 1:1. When the socket
|
|
15
|
+
* closes (end of test), the dispatcher disposes the session and frees its world state + LMDB.
|
|
16
|
+
*
|
|
17
|
+
* Lives in its own module so the worker bundle does not pull in the HTTP server stack.
|
|
18
|
+
*/ export async function createTXERpcServer(logger) {
|
|
19
|
+
const workerCount = Number(process.env.TXE_WORKERS);
|
|
20
|
+
let dispatcher;
|
|
21
|
+
if (workerCount === 1) {
|
|
22
|
+
const { dataDir, schnorrClassId } = await buildSharedContractStore();
|
|
23
|
+
dispatcher = new TXEDispatcher(logger, {
|
|
24
|
+
contractStoreSourceDir: dataDir,
|
|
25
|
+
schnorrClassId
|
|
26
|
+
});
|
|
27
|
+
} else {
|
|
28
|
+
dispatcher = new TXEDispatcherPool(logger, {
|
|
29
|
+
workers: Number.isFinite(workerCount) && workerCount > 1 ? workerCount : undefined
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
const server = createSafeJsonRpcServer(dispatcher, TXEDispatcherApiSchema, {
|
|
33
|
+
http200OnError: true,
|
|
34
|
+
middlewares: [
|
|
35
|
+
async (ctx, next)=>{
|
|
36
|
+
// The body parser runs further down the chain, so `ctx.request.body` is populated only
|
|
37
|
+
// after `next()` resolves.
|
|
38
|
+
await next();
|
|
39
|
+
const socket = ctx.req.socket;
|
|
40
|
+
if (socket[SESSION_SYMBOL] !== undefined) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const body = ctx.request.body;
|
|
44
|
+
const sessionId = body && typeof body === 'object' && 'params' in body ? extractSessionId(body.params) : undefined;
|
|
45
|
+
if (sessionId === undefined) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
socket[SESSION_SYMBOL] = sessionId;
|
|
49
|
+
logger.debug(`Tagged socket with session`, {
|
|
50
|
+
sessionId,
|
|
51
|
+
remoteAddress: socket.remoteAddress,
|
|
52
|
+
remotePort: socket.remotePort
|
|
53
|
+
});
|
|
54
|
+
socket.once('close', ()=>{
|
|
55
|
+
logger.debug(`Disposing session on socket close`, {
|
|
56
|
+
sessionId
|
|
57
|
+
});
|
|
58
|
+
void dispatcher.disposeSession(sessionId);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
});
|
|
63
|
+
return server;
|
|
64
|
+
}
|
|
65
|
+
// Extracts `session_id` from a JSON-RPC `params` array. Always a `number` because session_id
|
|
66
|
+
// comes off `JSON.parse`, which never produces BigInt; values above MAX_SAFE_INTEGER lose
|
|
67
|
+
// precision but still work as a Map key.
|
|
68
|
+
function extractSessionId(params) {
|
|
69
|
+
if (!Array.isArray(params) || params.length === 0) {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
const first = params[0];
|
|
73
|
+
if (first && typeof first === 'object' && 'session_id' in first) {
|
|
74
|
+
const sid = first.session_id;
|
|
75
|
+
return typeof sid === 'number' ? sid : undefined;
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|