@aztec/txe 0.0.1-commit.2448fdb → 0.0.1-commit.2606882
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/ContractClassRegistry-PII7Q556.js +3 -0
- package/dest/ContractClassRegistry-PII7Q556.js.map +7 -0
- package/dest/ContractInstanceRegistry-3MHLGFNZ.js +3 -0
- package/dest/ContractInstanceRegistry-3MHLGFNZ.js.map +7 -0
- package/dest/FeeJuice-TQV5AQK7.js +3 -0
- package/dest/FeeJuice-TQV5AQK7.js.map +7 -0
- package/dest/MultiCallEntrypoint-SBJUIJY7.js +3 -0
- package/dest/MultiCallEntrypoint-SBJUIJY7.js.map +7 -0
- package/dest/SchnorrAccount-MQXPIZ44.js +3 -0
- package/dest/SchnorrAccount-MQXPIZ44.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-3VX4QA7B.js +265 -0
- package/dest/chunk-3VX4QA7B.js.map +7 -0
- package/dest/chunk-BJVAAXNA.js +3 -0
- package/dest/chunk-BJVAAXNA.js.map +7 -0
- package/dest/chunk-FU3LBVE4.js +304 -0
- package/dest/chunk-FU3LBVE4.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 +284 -0
- package/dest/index.d.ts +185 -7
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +70 -190
- package/dest/metafile.json +38352 -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 +147 -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 +27 -13
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +129 -52
- 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 +96 -266
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +699 -731
- 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 +13 -7
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +16 -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 +17 -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 +75 -14
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +164 -38
- 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 +316 -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 +157 -62
- 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 +774 -1043
- package/src/state_machine/archiver.ts +38 -16
- package/src/state_machine/dummy_p2p_client.ts +31 -11
- package/src/state_machine/global_variable_builder.ts +18 -3
- package/src/state_machine/index.ts +20 -5
- package/src/state_machine/mock_epoch_cache.ts +38 -3
- package/src/state_machine/synchronizer.ts +1 -1
- package/src/txe_session.ts +269 -39
- 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 -719
- 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,10 +1,10 @@
|
|
|
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 { CapsuleService, ORACLE_VERSION_MAJOR, enrichPublicSimulationError } from '@aztec/pxe/server';
|
|
7
|
+
import { CapsuleService, ORACLE_VERSION_MAJOR, composeHooks, enrichPublicSimulationError } from '@aztec/pxe/server';
|
|
8
8
|
import { ExecutionNoteCache, ExecutionTaggingIndexCache, HashedValuesCache, Oracle, PrivateExecutionOracle, UtilityExecutionOracle, 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';
|
|
@@ -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 {
|
|
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,11 +41,13 @@ export class TXEOracleTopLevelContext {
|
|
|
40
41
|
version;
|
|
41
42
|
chainId;
|
|
42
43
|
authwits;
|
|
43
|
-
|
|
44
|
+
artifactResolver;
|
|
45
|
+
rootPath;
|
|
46
|
+
packageName;
|
|
44
47
|
isMisc;
|
|
45
48
|
isTxe;
|
|
46
49
|
logger;
|
|
47
|
-
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){
|
|
48
51
|
this.stateMachine = stateMachine;
|
|
49
52
|
this.contractStore = contractStore;
|
|
50
53
|
this.noteStore = noteStore;
|
|
@@ -60,7 +63,9 @@ export class TXEOracleTopLevelContext {
|
|
|
60
63
|
this.version = version;
|
|
61
64
|
this.chainId = chainId;
|
|
62
65
|
this.authwits = authwits;
|
|
63
|
-
this.
|
|
66
|
+
this.artifactResolver = artifactResolver;
|
|
67
|
+
this.rootPath = rootPath;
|
|
68
|
+
this.packageName = packageName;
|
|
64
69
|
this.isMisc = true;
|
|
65
70
|
this.isTxe = true;
|
|
66
71
|
this.logger = createLogger('txe:top_level_context');
|
|
@@ -87,7 +92,7 @@ export class TXEOracleTopLevelContext {
|
|
|
87
92
|
return Fr.random();
|
|
88
93
|
}
|
|
89
94
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
90
|
-
log(level, message, fields) {
|
|
95
|
+
log(level, message, _fieldsSize, fields) {
|
|
91
96
|
if (!LogLevels[level]) {
|
|
92
97
|
throw new Error(`Invalid log level: ${level}`);
|
|
93
98
|
}
|
|
@@ -107,20 +112,27 @@ export class TXEOracleTopLevelContext {
|
|
|
107
112
|
return Promise.resolve(this.nextBlockTimestamp);
|
|
108
113
|
}
|
|
109
114
|
async getLastBlockTimestamp() {
|
|
110
|
-
return (await this.stateMachine.node.
|
|
115
|
+
return (await this.stateMachine.node.getBlockData('latest')).header.globalVariables.timestamp;
|
|
111
116
|
}
|
|
112
117
|
async getLastTxEffects() {
|
|
113
118
|
const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
|
|
114
|
-
const block = await this.stateMachine.archiver.getBlock(
|
|
119
|
+
const block = await this.stateMachine.archiver.getBlock({
|
|
120
|
+
number: latestBlockNumber
|
|
121
|
+
});
|
|
115
122
|
if (block.body.txEffects.length != 1) {
|
|
116
123
|
// Note that calls like env.mine() will result in blocks with no transactions, hitting this
|
|
117
124
|
throw new Error(`Expected a single transaction in the last block, found ${block.body.txEffects.length}`);
|
|
118
125
|
}
|
|
119
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
|
+
}
|
|
120
131
|
return {
|
|
121
132
|
txHash: txEffects.txHash,
|
|
122
133
|
noteHashes: txEffects.noteHashes,
|
|
123
|
-
nullifiers: txEffects.nullifiers
|
|
134
|
+
nullifiers: txEffects.nullifiers,
|
|
135
|
+
privateLogs
|
|
124
136
|
};
|
|
125
137
|
}
|
|
126
138
|
async syncContractNonOracleMethod(contractAddress, scope, jobId) {
|
|
@@ -136,7 +148,7 @@ export class TXEOracleTopLevelContext {
|
|
|
136
148
|
]);
|
|
137
149
|
}
|
|
138
150
|
async getPrivateEvents(selector, contractAddress, scope) {
|
|
139
|
-
|
|
151
|
+
const events = (await this.privateEventStore.getPrivateEvents(selector, {
|
|
140
152
|
contractAddress,
|
|
141
153
|
scopes: [
|
|
142
154
|
scope
|
|
@@ -144,6 +156,13 @@ export class TXEOracleTopLevelContext {
|
|
|
144
156
|
fromBlock: 0,
|
|
145
157
|
toBlock: await this.getLastBlockNumber() + 1
|
|
146
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;
|
|
147
166
|
}
|
|
148
167
|
async advanceBlocksBy(blocks) {
|
|
149
168
|
this.logger.debug(`time traveling ${blocks} blocks`);
|
|
@@ -155,22 +174,54 @@ export class TXEOracleTopLevelContext {
|
|
|
155
174
|
this.logger.debug(`time traveling ${duration} seconds`);
|
|
156
175
|
this.nextBlockTimestamp += duration;
|
|
157
176
|
}
|
|
158
|
-
|
|
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
|
+
});
|
|
159
191
|
// Emit deployment nullifier
|
|
160
192
|
await this.mineBlock({
|
|
161
193
|
nullifiers: [
|
|
162
|
-
await
|
|
194
|
+
await this.deploymentNullifier(instance.address)
|
|
163
195
|
]
|
|
164
196
|
});
|
|
165
197
|
if (!secret.equals(Fr.ZERO)) {
|
|
166
|
-
await this.
|
|
198
|
+
await this.registerContractAndAddAccount(artifact, instance, secret);
|
|
167
199
|
} else {
|
|
168
200
|
await this.contractStore.addContractInstance(instance);
|
|
169
201
|
await this.contractStore.addContractArtifact(artifact);
|
|
170
202
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
171
203
|
}
|
|
204
|
+
return [
|
|
205
|
+
instance.salt,
|
|
206
|
+
instance.deployer.toField(),
|
|
207
|
+
instance.currentContractClassId,
|
|
208
|
+
instance.initializationHash,
|
|
209
|
+
instance.immutablesHash,
|
|
210
|
+
...instance.publicKeys.toFields()
|
|
211
|
+
];
|
|
172
212
|
}
|
|
173
|
-
|
|
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) {
|
|
174
225
|
const partialAddress = await computePartialAddress(instance);
|
|
175
226
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
176
227
|
await this.contractStore.addContractInstance(instance);
|
|
@@ -191,12 +242,11 @@ export class TXEOracleTopLevelContext {
|
|
|
191
242
|
}
|
|
192
243
|
async addAuthWitness(address, messageHash) {
|
|
193
244
|
const account = await this.accountStore.getAccount(address);
|
|
194
|
-
const
|
|
245
|
+
const ivpkMHash = await hashPublicKey(account.publicKeys.ivpkM);
|
|
246
|
+
const privateKey = await this.keyStore.getMasterSecretKey(ivpkMHash);
|
|
195
247
|
const schnorr = new Schnorr();
|
|
196
|
-
const signature = await schnorr.constructSignature(messageHash
|
|
197
|
-
const authWitness = new AuthWitness(messageHash,
|
|
198
|
-
...signature.toBuffer()
|
|
199
|
-
]);
|
|
248
|
+
const signature = await schnorr.constructSignature(messageHash, privateKey);
|
|
249
|
+
const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
|
|
200
250
|
this.authwits.set(authWitness.requestHash.toString(), authWitness);
|
|
201
251
|
}
|
|
202
252
|
async mineBlock(options = {}) {
|
|
@@ -222,29 +272,26 @@ export class TXEOracleTopLevelContext {
|
|
|
222
272
|
this.logger.info(`Created block ${blockNumber} with timestamp ${block.header.globalVariables.timestamp}`);
|
|
223
273
|
await this.stateMachine.handleL2Block(block);
|
|
224
274
|
}
|
|
225
|
-
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) {
|
|
226
276
|
this.logger.verbose(`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`);
|
|
227
277
|
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
228
278
|
if (!artifact) {
|
|
229
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';
|
|
230
280
|
throw new Error(message);
|
|
231
281
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
from
|
|
282
|
+
const scopes = from === undefined ? additionalScopes : [
|
|
283
|
+
from,
|
|
284
|
+
...additionalScopes
|
|
236
285
|
];
|
|
237
286
|
// Sync notes before executing private function to discover notes from previous transactions
|
|
238
287
|
const utilityExecutor = async (call, execScopes)=>{
|
|
239
288
|
await this.executeUtilityCall(call, execScopes, jobId);
|
|
240
289
|
};
|
|
241
290
|
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
242
|
-
await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, utilityExecutor, blockHeader, jobId,
|
|
291
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, utilityExecutor, blockHeader, jobId, scopes);
|
|
243
292
|
const blockNumber = await this.getNextBlockNumber();
|
|
244
|
-
const
|
|
245
|
-
const
|
|
246
|
-
const teardownGasLimits = new Gas(FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT);
|
|
247
|
-
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);
|
|
248
295
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
249
296
|
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
250
297
|
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
@@ -276,19 +323,22 @@ export class TXEOracleTopLevelContext {
|
|
|
276
323
|
senderTaggingStore: this.senderTaggingStore,
|
|
277
324
|
recipientTaggingStore: this.recipientTaggingStore,
|
|
278
325
|
senderAddressBookStore: this.senderAddressBookStore,
|
|
279
|
-
capsuleService: new CapsuleService(this.capsuleStore,
|
|
326
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
280
327
|
privateEventStore: this.privateEventStore,
|
|
281
328
|
contractSyncService: this.stateMachine.contractSyncService,
|
|
282
329
|
jobId,
|
|
283
330
|
totalPublicCalldataCount: 0,
|
|
284
331
|
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
285
|
-
scopes
|
|
332
|
+
scopes,
|
|
286
333
|
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
287
334
|
// contract would perform, including setting senderForTags.
|
|
288
335
|
senderForTags: from,
|
|
289
336
|
simulator,
|
|
290
337
|
messageContextService: this.stateMachine.messageContextService,
|
|
291
|
-
l2TipsStore: this.stateMachine.
|
|
338
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
339
|
+
hooks: composeHooks({
|
|
340
|
+
authorizeUtilityCall: this.buildAuthorizeUtilityCallHook(isStaticCall ? 'private view' : 'private', authorizedUtilityCallTargets)
|
|
341
|
+
})
|
|
292
342
|
});
|
|
293
343
|
// 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.
|
|
294
344
|
let result;
|
|
@@ -360,10 +410,20 @@ export class TXEOracleTopLevelContext {
|
|
|
360
410
|
throw new Error('Contract execution has reverted');
|
|
361
411
|
}
|
|
362
412
|
}
|
|
413
|
+
// Walk the nested private-call tree and collect every offchain effect the transaction emitted.
|
|
414
|
+
// PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
|
|
415
|
+
// `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
|
|
416
|
+
// we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
|
|
417
|
+
const offchainEffects = collectNested([
|
|
418
|
+
executionResult
|
|
419
|
+
], (r)=>r.offchainEffects.map((e)=>e.data));
|
|
363
420
|
if (isStaticCall) {
|
|
364
421
|
await checkpoint.revert();
|
|
365
422
|
await forkedWorldTrees.close();
|
|
366
|
-
return
|
|
423
|
+
return {
|
|
424
|
+
returnValues: executionResult.returnValues ?? [],
|
|
425
|
+
offchainEffects
|
|
426
|
+
};
|
|
367
427
|
}
|
|
368
428
|
const txEffect = TxEffect.empty();
|
|
369
429
|
txEffect.noteHashes = processedTx.txEffect.noteHashes;
|
|
@@ -379,14 +439,14 @@ export class TXEOracleTopLevelContext {
|
|
|
379
439
|
]);
|
|
380
440
|
await this.stateMachine.handleL2Block(l2Block);
|
|
381
441
|
await forkedWorldTrees.close();
|
|
382
|
-
return
|
|
442
|
+
return {
|
|
443
|
+
returnValues: executionResult.returnValues ?? [],
|
|
444
|
+
offchainEffects
|
|
445
|
+
};
|
|
383
446
|
}
|
|
384
|
-
async publicCallNewFlow(from, targetContractAddress, calldata, isStaticCall) {
|
|
447
|
+
async publicCallNewFlow(from, targetContractAddress, calldata, isStaticCall, gasSettings) {
|
|
385
448
|
this.logger.verbose(`Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`);
|
|
386
449
|
const blockNumber = await this.getNextBlockNumber();
|
|
387
|
-
const gasLimits = new Gas(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, MAX_PROCESSABLE_L2_GAS);
|
|
388
|
-
const teardownGasLimits = new Gas(FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT);
|
|
389
|
-
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
390
450
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
391
451
|
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
392
452
|
const calldataHash = await computeCalldataHash(calldata);
|
|
@@ -419,7 +479,7 @@ export class TXEOracleTopLevelContext {
|
|
|
419
479
|
// The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
|
|
420
480
|
// may require producing reverts.
|
|
421
481
|
const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
422
|
-
revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(from, targetContractAddress, isStaticCall, calldataHash);
|
|
482
|
+
revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(from ?? AztecAddress.NULL_MSG_SENDER, targetContractAddress, isStaticCall, calldataHash);
|
|
423
483
|
const inputsForPublic = new PartialPrivateTailPublicInputsForPublic(nonRevertibleAccumulatedData, revertibleAccumulatedData, PublicCallRequest.empty());
|
|
424
484
|
const constantData = new TxConstantData(anchorBlockHeader, txContext, Fr.zero(), Fr.zero());
|
|
425
485
|
const txData = new PrivateKernelTailCircuitPublicInputs(constantData, /*gasUsed=*/ new Gas(0, 0), /*feePayer=*/ AztecAddress.zero(), /*expirationTimestamp=*/ 0n, inputsForPublic, undefined);
|
|
@@ -475,7 +535,7 @@ export class TXEOracleTopLevelContext {
|
|
|
475
535
|
await forkedWorldTrees.close();
|
|
476
536
|
return returnValues ?? [];
|
|
477
537
|
}
|
|
478
|
-
async executeUtilityFunction(targetContractAddress, functionSelector, args, jobId) {
|
|
538
|
+
async executeUtilityFunction(targetContractAddress, functionSelector, args, jobId, authorizedUtilityCallTargets) {
|
|
479
539
|
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
480
540
|
if (!artifact) {
|
|
481
541
|
throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
|
|
@@ -495,9 +555,9 @@ export class TXEOracleTopLevelContext {
|
|
|
495
555
|
args,
|
|
496
556
|
returnTypes: []
|
|
497
557
|
});
|
|
498
|
-
return this.executeUtilityCall(call, await this.keyStore.getAccounts(), jobId);
|
|
558
|
+
return this.executeUtilityCall(call, await this.keyStore.getAccounts(), jobId, authorizedUtilityCallTargets);
|
|
499
559
|
}
|
|
500
|
-
async executeUtilityCall(call, scopes, jobId) {
|
|
560
|
+
async executeUtilityCall(call, scopes, jobId, authorizedUtilityCallTargets = []) {
|
|
501
561
|
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
502
562
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
503
563
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
@@ -508,6 +568,10 @@ export class TXEOracleTopLevelContext {
|
|
|
508
568
|
});
|
|
509
569
|
try {
|
|
510
570
|
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
571
|
+
const simulator = new WASMSimulator();
|
|
572
|
+
const utilityExecutor = async (syncCall, execScopes)=>{
|
|
573
|
+
await this.executeUtilityCall(syncCall, execScopes, jobId);
|
|
574
|
+
};
|
|
511
575
|
const oracle = new UtilityExecutionOracle({
|
|
512
576
|
contractAddress: call.to,
|
|
513
577
|
authWitnesses: [],
|
|
@@ -523,12 +587,17 @@ export class TXEOracleTopLevelContext {
|
|
|
523
587
|
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
524
588
|
privateEventStore: this.privateEventStore,
|
|
525
589
|
messageContextService: this.stateMachine.messageContextService,
|
|
526
|
-
contractSyncService: this.contractSyncService,
|
|
527
|
-
l2TipsStore: this.stateMachine.
|
|
590
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
591
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
528
592
|
jobId,
|
|
529
|
-
scopes
|
|
593
|
+
scopes,
|
|
594
|
+
simulator,
|
|
595
|
+
hooks: composeHooks({
|
|
596
|
+
authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets)
|
|
597
|
+
}),
|
|
598
|
+
utilityExecutor
|
|
530
599
|
});
|
|
531
|
-
const acirExecutionResult = await
|
|
600
|
+
const acirExecutionResult = await simulator.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback()).catch((err)=>{
|
|
532
601
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
533
602
|
throw new ExecutionError(err.message, {
|
|
534
603
|
contractAddress: call.to,
|
|
@@ -551,7 +620,15 @@ export class TXEOracleTopLevelContext {
|
|
|
551
620
|
];
|
|
552
621
|
}
|
|
553
622
|
async getLastBlockNumber() {
|
|
554
|
-
const
|
|
555
|
-
return
|
|
623
|
+
const block = await this.stateMachine.node.getBlock('latest');
|
|
624
|
+
return block ? block.header.globalVariables.blockNumber : BlockNumber.ZERO;
|
|
625
|
+
}
|
|
626
|
+
buildAuthorizeUtilityCallHook(callerContext, authorizedTargets) {
|
|
627
|
+
if (authorizedTargets.length === 0) {
|
|
628
|
+
return undefined;
|
|
629
|
+
}
|
|
630
|
+
return (req)=>Promise.resolve({
|
|
631
|
+
authorized: req.callerContext === callerContext && authorizedTargets.some((t)=>t.equals(req.target))
|
|
632
|
+
});
|
|
556
633
|
}
|
|
557
634
|
}
|
|
@@ -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
|
+
}
|