@aztec/txe 0.0.1-commit.fffb133c → 0.0.1-dev
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/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +88 -54
- package/dest/oracle/interfaces.d.ts +35 -28
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.d.ts +13 -13
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +14 -15
- package/dest/oracle/txe_oracle_top_level_context.d.ts +33 -23
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +185 -71
- package/dest/rpc_translator.d.ts +135 -83
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +540 -178
- package/dest/state_machine/archiver.d.ts +3 -3
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +7 -7
- package/dest/state_machine/dummy_p2p_client.d.ts +16 -12
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +28 -16
- package/dest/state_machine/index.d.ts +7 -5
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +19 -10
- package/dest/state_machine/mock_epoch_cache.d.ts +3 -1
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +4 -0
- package/dest/state_machine/synchronizer.d.ts +5 -5
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/state_machine/synchronizer.js +3 -3
- package/dest/txe_oracle_version.d.ts +10 -0
- package/dest/txe_oracle_version.d.ts.map +1 -0
- package/dest/txe_oracle_version.js +8 -0
- package/dest/txe_session.d.ts +67 -8
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +175 -32
- package/dest/util/encoding.d.ts +43 -41
- package/dest/util/encoding.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.d.ts +2 -3
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +5 -22
- package/dest/utils/block_creation.d.ts +1 -1
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +3 -1
- package/package.json +15 -15
- package/src/index.ts +89 -52
- package/src/oracle/interfaces.ts +43 -34
- package/src/oracle/txe_oracle_public_context.ts +14 -16
- package/src/oracle/txe_oracle_top_level_context.ts +231 -132
- package/src/rpc_translator.ts +673 -208
- package/src/state_machine/archiver.ts +7 -5
- package/src/state_machine/dummy_p2p_client.ts +40 -22
- package/src/state_machine/index.ts +30 -10
- package/src/state_machine/mock_epoch_cache.ts +5 -0
- package/src/state_machine/synchronizer.ts +4 -4
- package/src/txe_oracle_version.ts +9 -0
- package/src/txe_session.ts +270 -93
- package/src/util/txe_public_contract_data_source.ts +10 -36
- package/src/utils/block_creation.ts +3 -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/src/util/txe_contract_store.ts +0 -36
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS,
|
|
3
|
-
DEFAULT_DA_GAS_LIMIT,
|
|
4
|
-
DEFAULT_L2_GAS_LIMIT,
|
|
5
|
-
DEFAULT_TEARDOWN_DA_GAS_LIMIT,
|
|
6
|
-
DEFAULT_TEARDOWN_L2_GAS_LIMIT,
|
|
7
|
-
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
8
|
-
} from '@aztec/constants';
|
|
1
|
+
import { CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
|
|
9
2
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
10
3
|
import { Schnorr } from '@aztec/foundation/crypto/schnorr';
|
|
11
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
@@ -14,15 +7,18 @@ import { TestDateProvider } from '@aztec/foundation/timer';
|
|
|
14
7
|
import type { KeyStore } from '@aztec/key-store';
|
|
15
8
|
import {
|
|
16
9
|
AddressStore,
|
|
10
|
+
CapsuleService,
|
|
17
11
|
CapsuleStore,
|
|
12
|
+
type ContractStore,
|
|
13
|
+
type ExecutionHooks,
|
|
18
14
|
NoteStore,
|
|
19
|
-
|
|
15
|
+
ORACLE_VERSION_MAJOR,
|
|
20
16
|
PrivateEventStore,
|
|
21
17
|
RecipientTaggingStore,
|
|
22
18
|
SenderAddressBookStore,
|
|
23
19
|
SenderTaggingStore,
|
|
20
|
+
composeHooks,
|
|
24
21
|
enrichPublicSimulationError,
|
|
25
|
-
syncState,
|
|
26
22
|
} from '@aztec/pxe/server';
|
|
27
23
|
import {
|
|
28
24
|
ExecutionNoteCache,
|
|
@@ -84,7 +80,6 @@ import { ForkCheckpoint } from '@aztec/world-state';
|
|
|
84
80
|
import { DEFAULT_ADDRESS } from '../constants.js';
|
|
85
81
|
import type { TXEStateMachine } from '../state_machine/index.js';
|
|
86
82
|
import type { TXEAccountStore } from '../util/txe_account_store.js';
|
|
87
|
-
import type { TXEContractStore } from '../util/txe_contract_store.js';
|
|
88
83
|
import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
|
|
89
84
|
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
90
85
|
import type { ITxeExecutionOracle } from './interfaces.js';
|
|
@@ -97,7 +92,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
97
92
|
|
|
98
93
|
constructor(
|
|
99
94
|
private stateMachine: TXEStateMachine,
|
|
100
|
-
private contractStore:
|
|
95
|
+
private contractStore: ContractStore,
|
|
101
96
|
private noteStore: NoteStore,
|
|
102
97
|
private keyStore: KeyStore,
|
|
103
98
|
private addressStore: AddressStore,
|
|
@@ -107,7 +102,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
107
102
|
private senderAddressBookStore: SenderAddressBookStore,
|
|
108
103
|
private capsuleStore: CapsuleStore,
|
|
109
104
|
private privateEventStore: PrivateEventStore,
|
|
110
|
-
private jobId: string,
|
|
111
105
|
private nextBlockTimestamp: bigint,
|
|
112
106
|
private version: Fr,
|
|
113
107
|
private chainId: Fr,
|
|
@@ -117,47 +111,60 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
117
111
|
this.logger.debug('Entering Top Level Context');
|
|
118
112
|
}
|
|
119
113
|
|
|
120
|
-
|
|
121
|
-
|
|
114
|
+
private contractOracleVersion: { major: number; minor: number } | undefined;
|
|
115
|
+
|
|
116
|
+
assertCompatibleOracleVersion(major: number, minor: number): void {
|
|
117
|
+
if (major !== ORACLE_VERSION_MAJOR) {
|
|
118
|
+
const hint =
|
|
119
|
+
major > ORACLE_VERSION_MAJOR
|
|
120
|
+
? '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.'
|
|
121
|
+
: '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.';
|
|
122
122
|
throw new Error(
|
|
123
|
-
`Incompatible
|
|
123
|
+
`Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
|
|
124
124
|
);
|
|
125
125
|
}
|
|
126
|
+
this.contractOracleVersion = { major, minor };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
|
|
130
|
+
nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined {
|
|
131
|
+
return this.contractOracleVersion;
|
|
126
132
|
}
|
|
127
133
|
|
|
128
134
|
// This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
|
|
129
135
|
// setup.
|
|
130
|
-
|
|
136
|
+
getRandomField(): Fr {
|
|
131
137
|
return Fr.random();
|
|
132
138
|
}
|
|
133
139
|
|
|
134
140
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
135
|
-
|
|
141
|
+
log(level: number, message: string, fields: Fr[]): Promise<void> {
|
|
136
142
|
if (!LogLevels[level]) {
|
|
137
|
-
throw new Error(`Invalid
|
|
143
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
138
144
|
}
|
|
139
145
|
const levelName = LogLevels[level];
|
|
140
146
|
|
|
141
147
|
this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
|
|
148
|
+
return Promise.resolve();
|
|
142
149
|
}
|
|
143
150
|
|
|
144
|
-
|
|
151
|
+
getDefaultAddress(): AztecAddress {
|
|
145
152
|
return DEFAULT_ADDRESS;
|
|
146
153
|
}
|
|
147
154
|
|
|
148
|
-
async
|
|
155
|
+
async getNextBlockNumber(): Promise<BlockNumber> {
|
|
149
156
|
return BlockNumber((await this.getLastBlockNumber()) + 1);
|
|
150
157
|
}
|
|
151
158
|
|
|
152
|
-
|
|
159
|
+
getNextBlockTimestamp(): Promise<bigint> {
|
|
153
160
|
return Promise.resolve(this.nextBlockTimestamp);
|
|
154
161
|
}
|
|
155
162
|
|
|
156
|
-
async
|
|
163
|
+
async getLastBlockTimestamp() {
|
|
157
164
|
return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
|
|
158
165
|
}
|
|
159
166
|
|
|
160
|
-
async
|
|
167
|
+
async getLastTxEffects() {
|
|
161
168
|
const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
|
|
162
169
|
const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
|
|
163
170
|
|
|
@@ -168,10 +175,34 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
168
175
|
|
|
169
176
|
const txEffects = block!.body.txEffects[0];
|
|
170
177
|
|
|
171
|
-
return {
|
|
178
|
+
return {
|
|
179
|
+
txHash: txEffects.txHash,
|
|
180
|
+
noteHashes: txEffects.noteHashes,
|
|
181
|
+
nullifiers: txEffects.nullifiers,
|
|
182
|
+
privateLogs: txEffects.privateLogs,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
|
|
187
|
+
if (contractAddress.equals(DEFAULT_ADDRESS)) {
|
|
188
|
+
this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
193
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
194
|
+
contractAddress,
|
|
195
|
+
null,
|
|
196
|
+
async (call, execScopes) => {
|
|
197
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
198
|
+
},
|
|
199
|
+
blockHeader,
|
|
200
|
+
jobId,
|
|
201
|
+
[scope],
|
|
202
|
+
);
|
|
172
203
|
}
|
|
173
204
|
|
|
174
|
-
async
|
|
205
|
+
async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
|
|
175
206
|
return (
|
|
176
207
|
await this.privateEventStore.getPrivateEvents(selector, {
|
|
177
208
|
contractAddress,
|
|
@@ -182,7 +213,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
182
213
|
).map(e => e.packedEvent);
|
|
183
214
|
}
|
|
184
215
|
|
|
185
|
-
async
|
|
216
|
+
async advanceBlocksBy(blocks: number) {
|
|
186
217
|
this.logger.debug(`time traveling ${blocks} blocks`);
|
|
187
218
|
|
|
188
219
|
for (let i = 0; i < blocks; i++) {
|
|
@@ -190,12 +221,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
190
221
|
}
|
|
191
222
|
}
|
|
192
223
|
|
|
193
|
-
|
|
224
|
+
advanceTimestampBy(duration: UInt64) {
|
|
194
225
|
this.logger.debug(`time traveling ${duration} seconds`);
|
|
195
226
|
this.nextBlockTimestamp += duration;
|
|
196
227
|
}
|
|
197
228
|
|
|
198
|
-
async
|
|
229
|
+
async deploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
|
|
199
230
|
// Emit deployment nullifier
|
|
200
231
|
await this.mineBlock({
|
|
201
232
|
nullifiers: [
|
|
@@ -207,20 +238,20 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
207
238
|
});
|
|
208
239
|
|
|
209
240
|
if (!secret.equals(Fr.ZERO)) {
|
|
210
|
-
await this.
|
|
241
|
+
await this.addAccount(artifact, instance, secret);
|
|
211
242
|
} else {
|
|
212
243
|
await this.contractStore.addContractInstance(instance);
|
|
213
|
-
await this.contractStore.addContractArtifact(
|
|
244
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
214
245
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
215
246
|
}
|
|
216
247
|
}
|
|
217
248
|
|
|
218
|
-
async
|
|
249
|
+
async addAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
|
|
219
250
|
const partialAddress = await computePartialAddress(instance);
|
|
220
251
|
|
|
221
252
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
222
253
|
await this.contractStore.addContractInstance(instance);
|
|
223
|
-
await this.contractStore.addContractArtifact(
|
|
254
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
224
255
|
|
|
225
256
|
const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
|
|
226
257
|
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
@@ -230,7 +261,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
230
261
|
return completeAddress;
|
|
231
262
|
}
|
|
232
263
|
|
|
233
|
-
async
|
|
264
|
+
async createAccount(secret: Fr) {
|
|
234
265
|
// This is a foot gun !
|
|
235
266
|
const completeAddress = await this.keyStore.addAccount(secret, secret);
|
|
236
267
|
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
@@ -240,7 +271,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
240
271
|
return completeAddress;
|
|
241
272
|
}
|
|
242
273
|
|
|
243
|
-
async
|
|
274
|
+
async addAuthWitness(address: AztecAddress, messageHash: Fr) {
|
|
244
275
|
const account = await this.accountStore.getAccount(address);
|
|
245
276
|
const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
|
|
246
277
|
|
|
@@ -253,7 +284,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
253
284
|
}
|
|
254
285
|
|
|
255
286
|
async mineBlock(options: { nullifiers?: Fr[] } = {}) {
|
|
256
|
-
const blockNumber = await this.
|
|
287
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
257
288
|
|
|
258
289
|
const txEffect = TxEffect.empty();
|
|
259
290
|
txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
|
|
@@ -277,13 +308,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
277
308
|
await this.stateMachine.handleL2Block(block);
|
|
278
309
|
}
|
|
279
310
|
|
|
280
|
-
async
|
|
281
|
-
from: AztecAddress,
|
|
311
|
+
async privateCallNewFlow(
|
|
312
|
+
from: AztecAddress | undefined,
|
|
282
313
|
targetContractAddress: AztecAddress = AztecAddress.zero(),
|
|
283
314
|
functionSelector: FunctionSelector = FunctionSelector.empty(),
|
|
284
315
|
args: Fr[],
|
|
285
316
|
argsHash: Fr = Fr.zero(),
|
|
286
317
|
isStaticCall: boolean = false,
|
|
318
|
+
additionalScopes: AztecAddress[] = [],
|
|
319
|
+
jobId: string,
|
|
320
|
+
authorizedUtilityCallTargets: AztecAddress[],
|
|
321
|
+
gasSettings: GasSettings,
|
|
287
322
|
) {
|
|
288
323
|
this.logger.verbose(
|
|
289
324
|
`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
@@ -297,25 +332,30 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
297
332
|
throw new Error(message);
|
|
298
333
|
}
|
|
299
334
|
|
|
335
|
+
const scopes = from === undefined ? additionalScopes : [from, ...additionalScopes];
|
|
336
|
+
|
|
300
337
|
// Sync notes before executing private function to discover notes from previous transactions
|
|
301
|
-
const utilityExecutor = async (call: FunctionCall) => {
|
|
302
|
-
await this.executeUtilityCall(call);
|
|
338
|
+
const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
|
|
339
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
303
340
|
};
|
|
304
341
|
|
|
305
|
-
await
|
|
306
|
-
|
|
307
|
-
|
|
342
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
343
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
344
|
+
targetContractAddress,
|
|
345
|
+
functionSelector,
|
|
346
|
+
utilityExecutor,
|
|
347
|
+
blockHeader,
|
|
348
|
+
jobId,
|
|
349
|
+
scopes,
|
|
350
|
+
);
|
|
308
351
|
|
|
309
|
-
const
|
|
352
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
310
353
|
|
|
311
|
-
const
|
|
312
|
-
const
|
|
313
|
-
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
354
|
+
const msgSender = from ?? AztecAddress.NULL_MSG_SENDER;
|
|
355
|
+
const callContext = new CallContext(msgSender, targetContractAddress, functionSelector, isStaticCall);
|
|
314
356
|
|
|
315
357
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
316
358
|
|
|
317
|
-
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
318
|
-
|
|
319
359
|
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
320
360
|
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
321
361
|
// In production, the account contract sets the min revertible counter before calling the app function.
|
|
@@ -327,43 +367,42 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
327
367
|
|
|
328
368
|
const simulator = new WASMSimulator();
|
|
329
369
|
|
|
330
|
-
const privateExecutionOracle = new PrivateExecutionOracle(
|
|
370
|
+
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
331
371
|
argsHash,
|
|
332
372
|
txContext,
|
|
333
373
|
callContext,
|
|
334
|
-
|
|
335
|
-
blockHeader,
|
|
374
|
+
anchorBlockHeader: blockHeader,
|
|
336
375
|
utilityExecutor,
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
[],
|
|
341
|
-
HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
376
|
+
authWitnesses: Array.from(this.authwits.values()),
|
|
377
|
+
capsules: [],
|
|
378
|
+
executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
342
379
|
noteCache,
|
|
343
380
|
taggingIndexCache,
|
|
344
|
-
this.contractStore,
|
|
345
|
-
this.noteStore,
|
|
346
|
-
this.keyStore,
|
|
347
|
-
this.addressStore,
|
|
348
|
-
this.stateMachine.node,
|
|
349
|
-
this.
|
|
350
|
-
this.
|
|
351
|
-
this.
|
|
352
|
-
this.
|
|
353
|
-
this.
|
|
354
|
-
this.
|
|
355
|
-
|
|
356
|
-
0,
|
|
357
|
-
minRevertibleSideEffectCounter,
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
* contract would perform, including setting senderForTags.
|
|
363
|
-
*/
|
|
364
|
-
from,
|
|
381
|
+
contractStore: this.contractStore,
|
|
382
|
+
noteStore: this.noteStore,
|
|
383
|
+
keyStore: this.keyStore,
|
|
384
|
+
addressStore: this.addressStore,
|
|
385
|
+
aztecNode: this.stateMachine.node,
|
|
386
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
387
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
388
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
389
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
390
|
+
privateEventStore: this.privateEventStore,
|
|
391
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
392
|
+
jobId,
|
|
393
|
+
totalPublicCalldataCount: 0,
|
|
394
|
+
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
395
|
+
scopes,
|
|
396
|
+
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
397
|
+
// contract would perform, including setting senderForTags.
|
|
398
|
+
senderForTags: from,
|
|
365
399
|
simulator,
|
|
366
|
-
|
|
400
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
401
|
+
l2TipsStore: this.stateMachine.node,
|
|
402
|
+
hooks: composeHooks({
|
|
403
|
+
authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('private', authorizedUtilityCallTargets),
|
|
404
|
+
}),
|
|
405
|
+
});
|
|
367
406
|
|
|
368
407
|
// 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.
|
|
369
408
|
let result: PrivateExecutionResult;
|
|
@@ -385,7 +424,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
385
424
|
);
|
|
386
425
|
const publicFunctionsCalldata = await Promise.all(
|
|
387
426
|
publicCallRequests.map(async r => {
|
|
388
|
-
const calldata = await privateExecutionOracle.
|
|
427
|
+
const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
|
|
389
428
|
return new HashedValues(calldata, r.calldataHash);
|
|
390
429
|
}),
|
|
391
430
|
);
|
|
@@ -402,7 +441,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
402
441
|
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
403
442
|
const { publicInputs } = await generateSimulatedProvingResult(
|
|
404
443
|
result,
|
|
405
|
-
this.contractStore,
|
|
444
|
+
(addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
|
|
445
|
+
this.stateMachine.node,
|
|
406
446
|
minRevertibleSideEffectCounter,
|
|
407
447
|
);
|
|
408
448
|
|
|
@@ -415,7 +455,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
415
455
|
|
|
416
456
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
417
457
|
|
|
418
|
-
const
|
|
458
|
+
const bindings = this.logger.getBindings();
|
|
459
|
+
const contractsDB = new PublicContractsDB(
|
|
460
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
461
|
+
bindings,
|
|
462
|
+
);
|
|
419
463
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
420
464
|
const config = PublicSimulatorConfig.from({
|
|
421
465
|
skipFeeEnforcement: true,
|
|
@@ -428,8 +472,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
428
472
|
globals,
|
|
429
473
|
guardedMerkleTrees,
|
|
430
474
|
contractsDB,
|
|
431
|
-
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config),
|
|
475
|
+
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
|
|
432
476
|
new TestDateProvider(),
|
|
477
|
+
undefined,
|
|
478
|
+
createLogger('simulator:public-processor', bindings),
|
|
433
479
|
);
|
|
434
480
|
|
|
435
481
|
const tx = await Tx.create({
|
|
@@ -463,11 +509,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
463
509
|
}
|
|
464
510
|
}
|
|
465
511
|
|
|
512
|
+
// Walk the nested private-call tree and collect every offchain effect the transaction emitted.
|
|
513
|
+
// PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
|
|
514
|
+
// `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
|
|
515
|
+
// we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
|
|
516
|
+
const offchainEffects = collectNested([executionResult], r => r.offchainEffects.map(e => e.data));
|
|
517
|
+
|
|
466
518
|
if (isStaticCall) {
|
|
467
519
|
await checkpoint!.revert();
|
|
468
520
|
|
|
469
521
|
await forkedWorldTrees.close();
|
|
470
|
-
return executionResult.returnValues ?? [];
|
|
522
|
+
return { returnValues: executionResult.returnValues ?? [], offchainEffects };
|
|
471
523
|
}
|
|
472
524
|
|
|
473
525
|
const txEffect = TxEffect.empty();
|
|
@@ -489,26 +541,21 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
489
541
|
|
|
490
542
|
await forkedWorldTrees.close();
|
|
491
543
|
|
|
492
|
-
return executionResult.returnValues ?? [];
|
|
544
|
+
return { returnValues: executionResult.returnValues ?? [], offchainEffects };
|
|
493
545
|
}
|
|
494
546
|
|
|
495
|
-
async
|
|
496
|
-
from: AztecAddress,
|
|
547
|
+
async publicCallNewFlow(
|
|
548
|
+
from: AztecAddress | undefined,
|
|
497
549
|
targetContractAddress: AztecAddress,
|
|
498
550
|
calldata: Fr[],
|
|
499
551
|
isStaticCall: boolean,
|
|
552
|
+
gasSettings: GasSettings,
|
|
500
553
|
) {
|
|
501
554
|
this.logger.verbose(
|
|
502
555
|
`Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
503
556
|
);
|
|
504
557
|
|
|
505
|
-
const blockNumber = await this.
|
|
506
|
-
|
|
507
|
-
const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
|
|
508
|
-
|
|
509
|
-
const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
|
|
510
|
-
|
|
511
|
-
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
558
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
512
559
|
|
|
513
560
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
514
561
|
|
|
@@ -526,7 +573,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
526
573
|
|
|
527
574
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
528
575
|
|
|
529
|
-
const
|
|
576
|
+
const bindings2 = this.logger.getBindings();
|
|
577
|
+
const contractsDB = new PublicContractsDB(
|
|
578
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
579
|
+
bindings2,
|
|
580
|
+
);
|
|
530
581
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
531
582
|
const config = PublicSimulatorConfig.from({
|
|
532
583
|
skipFeeEnforcement: true,
|
|
@@ -535,8 +586,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
535
586
|
collectStatistics: false,
|
|
536
587
|
collectCallMetadata: true,
|
|
537
588
|
});
|
|
538
|
-
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
|
|
539
|
-
const processor = new PublicProcessor(
|
|
589
|
+
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
|
|
590
|
+
const processor = new PublicProcessor(
|
|
591
|
+
globals,
|
|
592
|
+
guardedMerkleTrees,
|
|
593
|
+
contractsDB,
|
|
594
|
+
simulator,
|
|
595
|
+
new TestDateProvider(),
|
|
596
|
+
undefined,
|
|
597
|
+
createLogger('simulator:public-processor', bindings2),
|
|
598
|
+
);
|
|
540
599
|
|
|
541
600
|
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
542
601
|
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
@@ -549,7 +608,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
549
608
|
// may require producing reverts.
|
|
550
609
|
const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
551
610
|
revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(
|
|
552
|
-
from,
|
|
611
|
+
from ?? AztecAddress.NULL_MSG_SENDER,
|
|
553
612
|
targetContractAddress,
|
|
554
613
|
isStaticCall,
|
|
555
614
|
calldataHash,
|
|
@@ -567,7 +626,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
567
626
|
constantData,
|
|
568
627
|
/*gasUsed=*/ new Gas(0, 0),
|
|
569
628
|
/*feePayer=*/ AztecAddress.zero(),
|
|
570
|
-
/*
|
|
629
|
+
/*expirationTimestamp=*/ 0n,
|
|
571
630
|
inputsForPublic,
|
|
572
631
|
undefined,
|
|
573
632
|
);
|
|
@@ -635,10 +694,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
635
694
|
return returnValues ?? [];
|
|
636
695
|
}
|
|
637
696
|
|
|
638
|
-
async
|
|
697
|
+
async executeUtilityFunction(
|
|
639
698
|
targetContractAddress: AztecAddress,
|
|
640
699
|
functionSelector: FunctionSelector,
|
|
641
700
|
args: Fr[],
|
|
701
|
+
jobId: string,
|
|
702
|
+
authorizedUtilityCallTargets: AztecAddress[],
|
|
642
703
|
) {
|
|
643
704
|
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
644
705
|
if (!artifact) {
|
|
@@ -646,25 +707,38 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
646
707
|
}
|
|
647
708
|
|
|
648
709
|
// Sync notes before executing utility function to discover notes from previous transactions
|
|
649
|
-
await
|
|
650
|
-
|
|
651
|
-
});
|
|
652
|
-
|
|
653
|
-
const call = new FunctionCall(
|
|
654
|
-
artifact.name,
|
|
710
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
711
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
655
712
|
targetContractAddress,
|
|
656
713
|
functionSelector,
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
714
|
+
async (call, execScopes) => {
|
|
715
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
716
|
+
},
|
|
717
|
+
blockHeader,
|
|
718
|
+
jobId,
|
|
719
|
+
await this.keyStore.getAccounts(),
|
|
662
720
|
);
|
|
663
721
|
|
|
664
|
-
|
|
722
|
+
const call = FunctionCall.from({
|
|
723
|
+
name: artifact.name,
|
|
724
|
+
to: targetContractAddress,
|
|
725
|
+
selector: functionSelector,
|
|
726
|
+
type: FunctionType.UTILITY,
|
|
727
|
+
hideMsgSender: false,
|
|
728
|
+
isStatic: false,
|
|
729
|
+
args,
|
|
730
|
+
returnTypes: [],
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
return this.executeUtilityCall(call, await this.keyStore.getAccounts(), jobId, authorizedUtilityCallTargets);
|
|
665
734
|
}
|
|
666
735
|
|
|
667
|
-
private async executeUtilityCall(
|
|
736
|
+
private async executeUtilityCall(
|
|
737
|
+
call: FunctionCall,
|
|
738
|
+
scopes: AztecAddress[],
|
|
739
|
+
jobId: string,
|
|
740
|
+
authorizedUtilityCallTargets: AztecAddress[] = [],
|
|
741
|
+
): Promise<Fr[]> {
|
|
668
742
|
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
669
743
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
670
744
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
@@ -677,24 +751,36 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
677
751
|
|
|
678
752
|
try {
|
|
679
753
|
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
680
|
-
const
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
754
|
+
const simulator = new WASMSimulator();
|
|
755
|
+
const utilityExecutor = async (syncCall: FunctionCall, execScopes: AztecAddress[]) => {
|
|
756
|
+
await this.executeUtilityCall(syncCall, execScopes, jobId);
|
|
757
|
+
};
|
|
758
|
+
const oracle = new UtilityExecutionOracle({
|
|
759
|
+
contractAddress: call.to,
|
|
760
|
+
authWitnesses: [],
|
|
761
|
+
capsules: [],
|
|
684
762
|
anchorBlockHeader,
|
|
685
|
-
this.contractStore,
|
|
686
|
-
this.noteStore,
|
|
687
|
-
this.keyStore,
|
|
688
|
-
this.addressStore,
|
|
689
|
-
this.stateMachine.node,
|
|
690
|
-
this.
|
|
691
|
-
this.
|
|
692
|
-
this.
|
|
693
|
-
this.
|
|
694
|
-
this.
|
|
695
|
-
this.
|
|
696
|
-
|
|
697
|
-
|
|
763
|
+
contractStore: this.contractStore,
|
|
764
|
+
noteStore: this.noteStore,
|
|
765
|
+
keyStore: this.keyStore,
|
|
766
|
+
addressStore: this.addressStore,
|
|
767
|
+
aztecNode: this.stateMachine.node,
|
|
768
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
769
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
770
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
771
|
+
privateEventStore: this.privateEventStore,
|
|
772
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
773
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
774
|
+
l2TipsStore: this.stateMachine.node,
|
|
775
|
+
jobId,
|
|
776
|
+
scopes,
|
|
777
|
+
simulator,
|
|
778
|
+
hooks: composeHooks({
|
|
779
|
+
authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets),
|
|
780
|
+
}),
|
|
781
|
+
utilityExecutor,
|
|
782
|
+
});
|
|
783
|
+
const acirExecutionResult = await simulator
|
|
698
784
|
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
699
785
|
.catch((err: Error) => {
|
|
700
786
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
@@ -709,10 +795,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
709
795
|
);
|
|
710
796
|
});
|
|
711
797
|
|
|
712
|
-
this.logger.verbose(`Utility
|
|
798
|
+
this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
|
|
713
799
|
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
714
800
|
} catch (err) {
|
|
715
|
-
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility
|
|
801
|
+
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
|
|
716
802
|
}
|
|
717
803
|
}
|
|
718
804
|
|
|
@@ -725,4 +811,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
725
811
|
const header = await this.stateMachine.node.getBlockHeader('latest');
|
|
726
812
|
return header ? header.globalVariables.blockNumber : BlockNumber.ZERO;
|
|
727
813
|
}
|
|
814
|
+
|
|
815
|
+
private buildAuthorizeUtilityCallHook(
|
|
816
|
+
callerContext: 'private' | 'utility',
|
|
817
|
+
authorizedTargets: AztecAddress[],
|
|
818
|
+
): ExecutionHooks['authorizeUtilityCall'] | undefined {
|
|
819
|
+
if (authorizedTargets.length === 0) {
|
|
820
|
+
return undefined;
|
|
821
|
+
}
|
|
822
|
+
return req =>
|
|
823
|
+
Promise.resolve({
|
|
824
|
+
authorized: req.callerContext === callerContext && authorizedTargets.some(t => t.equals(req.target)),
|
|
825
|
+
});
|
|
826
|
+
}
|
|
728
827
|
}
|