@aztec/txe 0.0.1-commit.6d3c34e → 0.0.1-commit.7035c9bd6
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/constants.d.ts +1 -2
- package/dest/constants.d.ts.map +1 -1
- package/dest/constants.js +0 -1
- 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 +29 -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 +16 -16
- package/dest/oracle/txe_oracle_top_level_context.d.ts +23 -22
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +144 -62
- package/dest/rpc_translator.d.ts +92 -81
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +323 -176
- package/dest/state_machine/archiver.d.ts +20 -69
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +34 -178
- 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 +39 -12
- package/dest/state_machine/mock_epoch_cache.d.ts +24 -8
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +43 -9
- package/dest/state_machine/synchronizer.d.ts +6 -6
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/state_machine/synchronizer.js +3 -3
- package/dest/txe_session.d.ts +12 -6
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +112 -28
- package/dest/util/encoding.d.ts +17 -17
- 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 +4 -4
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +18 -4
- package/dest/utils/tx_effect_creation.d.ts +2 -3
- package/dest/utils/tx_effect_creation.d.ts.map +1 -1
- package/dest/utils/tx_effect_creation.js +3 -6
- package/package.json +16 -16
- package/src/constants.ts +0 -1
- package/src/index.ts +89 -52
- package/src/oracle/interfaces.ts +32 -31
- package/src/oracle/txe_oracle_public_context.ts +16 -18
- package/src/oracle/txe_oracle_top_level_context.ts +178 -111
- package/src/rpc_translator.ts +360 -202
- package/src/state_machine/archiver.ts +37 -234
- package/src/state_machine/dummy_p2p_client.ts +40 -22
- package/src/state_machine/index.ts +53 -11
- package/src/state_machine/mock_epoch_cache.ts +53 -14
- package/src/state_machine/synchronizer.ts +5 -5
- package/src/txe_session.ts +129 -88
- package/src/util/txe_public_contract_data_source.ts +10 -36
- package/src/utils/block_creation.ts +19 -16
- package/src/utils/tx_effect_creation.ts +3 -11
- 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
|
@@ -12,9 +12,12 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
12
12
|
import { LogLevels, type Logger, applyStringFormatting, createLogger } from '@aztec/foundation/log';
|
|
13
13
|
import { TestDateProvider } from '@aztec/foundation/timer';
|
|
14
14
|
import type { KeyStore } from '@aztec/key-store';
|
|
15
|
+
import type { AccessScopes } from '@aztec/pxe/client/lazy';
|
|
15
16
|
import {
|
|
16
17
|
AddressStore,
|
|
17
18
|
CapsuleStore,
|
|
19
|
+
type ContractStore,
|
|
20
|
+
type ContractSyncService,
|
|
18
21
|
NoteStore,
|
|
19
22
|
ORACLE_VERSION,
|
|
20
23
|
PrivateEventStore,
|
|
@@ -80,10 +83,9 @@ import {
|
|
|
80
83
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
81
84
|
import { ForkCheckpoint } from '@aztec/world-state';
|
|
82
85
|
|
|
83
|
-
import { DEFAULT_ADDRESS
|
|
86
|
+
import { DEFAULT_ADDRESS } from '../constants.js';
|
|
84
87
|
import type { TXEStateMachine } from '../state_machine/index.js';
|
|
85
88
|
import type { TXEAccountStore } from '../util/txe_account_store.js';
|
|
86
|
-
import type { TXEContractStore } from '../util/txe_contract_store.js';
|
|
87
89
|
import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
|
|
88
90
|
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
89
91
|
import type { ITxeExecutionOracle } from './interfaces.js';
|
|
@@ -96,7 +98,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
96
98
|
|
|
97
99
|
constructor(
|
|
98
100
|
private stateMachine: TXEStateMachine,
|
|
99
|
-
private contractStore:
|
|
101
|
+
private contractStore: ContractStore,
|
|
100
102
|
private noteStore: NoteStore,
|
|
101
103
|
private keyStore: KeyStore,
|
|
102
104
|
private addressStore: AddressStore,
|
|
@@ -110,12 +112,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
110
112
|
private version: Fr,
|
|
111
113
|
private chainId: Fr,
|
|
112
114
|
private authwits: Map<string, AuthWitness>,
|
|
115
|
+
private readonly contractSyncService: ContractSyncService,
|
|
113
116
|
) {
|
|
114
117
|
this.logger = createLogger('txe:top_level_context');
|
|
115
118
|
this.logger.debug('Entering Top Level Context');
|
|
116
119
|
}
|
|
117
120
|
|
|
118
|
-
|
|
121
|
+
assertCompatibleOracleVersion(version: number): void {
|
|
119
122
|
if (version !== ORACLE_VERSION) {
|
|
120
123
|
throw new Error(
|
|
121
124
|
`Incompatible oracle version. TXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`,
|
|
@@ -125,38 +128,40 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
125
128
|
|
|
126
129
|
// This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
|
|
127
130
|
// setup.
|
|
128
|
-
|
|
131
|
+
getRandomField(): Fr {
|
|
129
132
|
return Fr.random();
|
|
130
133
|
}
|
|
131
134
|
|
|
132
135
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
133
|
-
|
|
136
|
+
log(level: number, message: string, fields: Fr[]): Promise<void> {
|
|
134
137
|
if (!LogLevels[level]) {
|
|
135
|
-
throw new Error(`Invalid
|
|
138
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
136
139
|
}
|
|
137
140
|
const levelName = LogLevels[level];
|
|
138
141
|
|
|
139
142
|
this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
|
|
143
|
+
return Promise.resolve();
|
|
140
144
|
}
|
|
141
145
|
|
|
142
|
-
|
|
146
|
+
getDefaultAddress(): AztecAddress {
|
|
143
147
|
return DEFAULT_ADDRESS;
|
|
144
148
|
}
|
|
145
149
|
|
|
146
|
-
async
|
|
150
|
+
async getNextBlockNumber(): Promise<BlockNumber> {
|
|
147
151
|
return BlockNumber((await this.getLastBlockNumber()) + 1);
|
|
148
152
|
}
|
|
149
153
|
|
|
150
|
-
|
|
154
|
+
getNextBlockTimestamp(): Promise<bigint> {
|
|
151
155
|
return Promise.resolve(this.nextBlockTimestamp);
|
|
152
156
|
}
|
|
153
157
|
|
|
154
|
-
async
|
|
158
|
+
async getLastBlockTimestamp() {
|
|
155
159
|
return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
|
|
156
160
|
}
|
|
157
161
|
|
|
158
|
-
async
|
|
159
|
-
const
|
|
162
|
+
async getLastTxEffects() {
|
|
163
|
+
const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
|
|
164
|
+
const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
|
|
160
165
|
|
|
161
166
|
if (block!.body.txEffects.length != 1) {
|
|
162
167
|
// Note that calls like env.mine() will result in blocks with no transactions, hitting this
|
|
@@ -168,7 +173,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
168
173
|
return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
|
|
169
174
|
}
|
|
170
175
|
|
|
171
|
-
async
|
|
176
|
+
async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
|
|
177
|
+
if (contractAddress.equals(DEFAULT_ADDRESS)) {
|
|
178
|
+
this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
183
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
184
|
+
contractAddress,
|
|
185
|
+
null,
|
|
186
|
+
async (call, execScopes) => {
|
|
187
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
188
|
+
},
|
|
189
|
+
blockHeader,
|
|
190
|
+
jobId,
|
|
191
|
+
[scope],
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
|
|
172
196
|
return (
|
|
173
197
|
await this.privateEventStore.getPrivateEvents(selector, {
|
|
174
198
|
contractAddress,
|
|
@@ -179,7 +203,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
179
203
|
).map(e => e.packedEvent);
|
|
180
204
|
}
|
|
181
205
|
|
|
182
|
-
async
|
|
206
|
+
async advanceBlocksBy(blocks: number) {
|
|
183
207
|
this.logger.debug(`time traveling ${blocks} blocks`);
|
|
184
208
|
|
|
185
209
|
for (let i = 0; i < blocks; i++) {
|
|
@@ -187,12 +211,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
187
211
|
}
|
|
188
212
|
}
|
|
189
213
|
|
|
190
|
-
|
|
214
|
+
advanceTimestampBy(duration: UInt64) {
|
|
191
215
|
this.logger.debug(`time traveling ${duration} seconds`);
|
|
192
216
|
this.nextBlockTimestamp += duration;
|
|
193
217
|
}
|
|
194
218
|
|
|
195
|
-
async
|
|
219
|
+
async deploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
|
|
196
220
|
// Emit deployment nullifier
|
|
197
221
|
await this.mineBlock({
|
|
198
222
|
nullifiers: [
|
|
@@ -204,20 +228,20 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
204
228
|
});
|
|
205
229
|
|
|
206
230
|
if (!secret.equals(Fr.ZERO)) {
|
|
207
|
-
await this.
|
|
231
|
+
await this.addAccount(artifact, instance, secret);
|
|
208
232
|
} else {
|
|
209
233
|
await this.contractStore.addContractInstance(instance);
|
|
210
|
-
await this.contractStore.addContractArtifact(
|
|
234
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
211
235
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
212
236
|
}
|
|
213
237
|
}
|
|
214
238
|
|
|
215
|
-
async
|
|
239
|
+
async addAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
|
|
216
240
|
const partialAddress = await computePartialAddress(instance);
|
|
217
241
|
|
|
218
242
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
219
243
|
await this.contractStore.addContractInstance(instance);
|
|
220
|
-
await this.contractStore.addContractArtifact(
|
|
244
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
221
245
|
|
|
222
246
|
const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
|
|
223
247
|
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
@@ -227,7 +251,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
227
251
|
return completeAddress;
|
|
228
252
|
}
|
|
229
253
|
|
|
230
|
-
async
|
|
254
|
+
async createAccount(secret: Fr) {
|
|
231
255
|
// This is a foot gun !
|
|
232
256
|
const completeAddress = await this.keyStore.addAccount(secret, secret);
|
|
233
257
|
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
@@ -237,7 +261,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
237
261
|
return completeAddress;
|
|
238
262
|
}
|
|
239
263
|
|
|
240
|
-
async
|
|
264
|
+
async addAuthWitness(address: AztecAddress, messageHash: Fr) {
|
|
241
265
|
const account = await this.accountStore.getAccount(address);
|
|
242
266
|
const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
|
|
243
267
|
|
|
@@ -250,7 +274,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
250
274
|
}
|
|
251
275
|
|
|
252
276
|
async mineBlock(options: { nullifiers?: Fr[] } = {}) {
|
|
253
|
-
const blockNumber = await this.
|
|
277
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
254
278
|
|
|
255
279
|
const txEffect = TxEffect.empty();
|
|
256
280
|
txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
|
|
@@ -274,13 +298,14 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
274
298
|
await this.stateMachine.handleL2Block(block);
|
|
275
299
|
}
|
|
276
300
|
|
|
277
|
-
async
|
|
301
|
+
async privateCallNewFlow(
|
|
278
302
|
from: AztecAddress,
|
|
279
303
|
targetContractAddress: AztecAddress = AztecAddress.zero(),
|
|
280
304
|
functionSelector: FunctionSelector = FunctionSelector.empty(),
|
|
281
305
|
args: Fr[],
|
|
282
306
|
argsHash: Fr = Fr.zero(),
|
|
283
307
|
isStaticCall: boolean = false,
|
|
308
|
+
jobId: string,
|
|
284
309
|
) {
|
|
285
310
|
this.logger.verbose(
|
|
286
311
|
`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
@@ -294,14 +319,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
294
319
|
throw new Error(message);
|
|
295
320
|
}
|
|
296
321
|
|
|
322
|
+
// When `from` is the zero address (e.g. when deploying a new account contract), we return an
|
|
323
|
+
// empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
|
|
324
|
+
const effectiveScopes = from.isZero() ? [] : [from];
|
|
325
|
+
|
|
297
326
|
// Sync notes before executing private function to discover notes from previous transactions
|
|
298
|
-
const utilityExecutor = async (call: FunctionCall) => {
|
|
299
|
-
await this.executeUtilityCall(call);
|
|
327
|
+
const utilityExecutor = async (call: FunctionCall, execScopes: AccessScopes) => {
|
|
328
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
300
329
|
};
|
|
301
330
|
|
|
302
|
-
await this.
|
|
331
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
332
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
333
|
+
targetContractAddress,
|
|
334
|
+
functionSelector,
|
|
335
|
+
utilityExecutor,
|
|
336
|
+
blockHeader,
|
|
337
|
+
jobId,
|
|
338
|
+
effectiveScopes,
|
|
339
|
+
);
|
|
303
340
|
|
|
304
|
-
const blockNumber = await this.
|
|
341
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
305
342
|
|
|
306
343
|
const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
|
|
307
344
|
|
|
@@ -311,51 +348,49 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
311
348
|
|
|
312
349
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
313
350
|
|
|
314
|
-
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
315
|
-
|
|
316
351
|
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
317
352
|
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
353
|
+
// In production, the account contract sets the min revertible counter before calling the app function.
|
|
354
|
+
// Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
|
|
355
|
+
// marking all side effects as revertible.
|
|
356
|
+
const minRevertibleSideEffectCounter = 1;
|
|
357
|
+
await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
318
358
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
319
359
|
|
|
320
360
|
const simulator = new WASMSimulator();
|
|
321
361
|
|
|
322
|
-
const privateExecutionOracle = new PrivateExecutionOracle(
|
|
362
|
+
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
323
363
|
argsHash,
|
|
324
364
|
txContext,
|
|
325
365
|
callContext,
|
|
326
|
-
|
|
327
|
-
blockHeader,
|
|
366
|
+
anchorBlockHeader: blockHeader,
|
|
328
367
|
utilityExecutor,
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
[],
|
|
333
|
-
HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
368
|
+
authWitnesses: Array.from(this.authwits.values()),
|
|
369
|
+
capsules: [],
|
|
370
|
+
executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
334
371
|
noteCache,
|
|
335
372
|
taggingIndexCache,
|
|
336
|
-
this.contractStore,
|
|
337
|
-
this.noteStore,
|
|
338
|
-
this.keyStore,
|
|
339
|
-
this.addressStore,
|
|
340
|
-
this.stateMachine.node,
|
|
341
|
-
this.
|
|
342
|
-
this.
|
|
343
|
-
this.
|
|
344
|
-
this.
|
|
345
|
-
this.
|
|
346
|
-
this.
|
|
347
|
-
|
|
348
|
-
0,
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
* contract would perform, including setting senderForTags.
|
|
355
|
-
*/
|
|
356
|
-
from,
|
|
373
|
+
contractStore: this.contractStore,
|
|
374
|
+
noteStore: this.noteStore,
|
|
375
|
+
keyStore: this.keyStore,
|
|
376
|
+
addressStore: this.addressStore,
|
|
377
|
+
aztecNode: this.stateMachine.node,
|
|
378
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
379
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
380
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
381
|
+
capsuleStore: this.capsuleStore,
|
|
382
|
+
privateEventStore: this.privateEventStore,
|
|
383
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
384
|
+
jobId,
|
|
385
|
+
totalPublicCalldataCount: 0,
|
|
386
|
+
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
387
|
+
scopes: effectiveScopes,
|
|
388
|
+
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
389
|
+
// contract would perform, including setting senderForTags.
|
|
390
|
+
senderForTags: from,
|
|
357
391
|
simulator,
|
|
358
|
-
|
|
392
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
393
|
+
});
|
|
359
394
|
|
|
360
395
|
// 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.
|
|
361
396
|
let result: PrivateExecutionResult;
|
|
@@ -377,24 +412,27 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
377
412
|
);
|
|
378
413
|
const publicFunctionsCalldata = await Promise.all(
|
|
379
414
|
publicCallRequests.map(async r => {
|
|
380
|
-
const calldata = await privateExecutionOracle.
|
|
415
|
+
const calldata = await privateExecutionOracle.loadFromExecutionCache(r.calldataHash);
|
|
381
416
|
return new HashedValues(calldata, r.calldataHash);
|
|
382
417
|
}),
|
|
383
418
|
);
|
|
384
419
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
|
|
420
|
+
noteCache.finish();
|
|
421
|
+
const nonceGenerator = noteCache.getNonceGenerator();
|
|
422
|
+
result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
|
|
389
423
|
} catch (err) {
|
|
390
424
|
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
391
425
|
}
|
|
392
426
|
|
|
393
|
-
// According to the protocol rules,
|
|
394
|
-
//
|
|
395
|
-
//
|
|
396
|
-
const
|
|
397
|
-
|
|
427
|
+
// According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
|
|
428
|
+
// the nonce generator for the note hashes.
|
|
429
|
+
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
430
|
+
const { publicInputs } = await generateSimulatedProvingResult(
|
|
431
|
+
result,
|
|
432
|
+
(addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
|
|
433
|
+
this.stateMachine.node,
|
|
434
|
+
minRevertibleSideEffectCounter,
|
|
435
|
+
);
|
|
398
436
|
|
|
399
437
|
const globals = makeGlobalVariables();
|
|
400
438
|
globals.blockNumber = blockNumber;
|
|
@@ -405,7 +443,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
405
443
|
|
|
406
444
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
407
445
|
|
|
408
|
-
const
|
|
446
|
+
const bindings = this.logger.getBindings();
|
|
447
|
+
const contractsDB = new PublicContractsDB(
|
|
448
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
449
|
+
bindings,
|
|
450
|
+
);
|
|
409
451
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
410
452
|
const config = PublicSimulatorConfig.from({
|
|
411
453
|
skipFeeEnforcement: true,
|
|
@@ -418,8 +460,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
418
460
|
globals,
|
|
419
461
|
guardedMerkleTrees,
|
|
420
462
|
contractsDB,
|
|
421
|
-
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config),
|
|
463
|
+
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
|
|
422
464
|
new TestDateProvider(),
|
|
465
|
+
undefined,
|
|
466
|
+
createLogger('simulator:public-processor', bindings),
|
|
423
467
|
);
|
|
424
468
|
|
|
425
469
|
const tx = await Tx.create({
|
|
@@ -482,7 +526,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
482
526
|
return executionResult.returnValues ?? [];
|
|
483
527
|
}
|
|
484
528
|
|
|
485
|
-
async
|
|
529
|
+
async publicCallNewFlow(
|
|
486
530
|
from: AztecAddress,
|
|
487
531
|
targetContractAddress: AztecAddress,
|
|
488
532
|
calldata: Fr[],
|
|
@@ -492,7 +536,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
492
536
|
`Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
493
537
|
);
|
|
494
538
|
|
|
495
|
-
const blockNumber = await this.
|
|
539
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
496
540
|
|
|
497
541
|
const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
|
|
498
542
|
|
|
@@ -516,7 +560,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
516
560
|
|
|
517
561
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
518
562
|
|
|
519
|
-
const
|
|
563
|
+
const bindings2 = this.logger.getBindings();
|
|
564
|
+
const contractsDB = new PublicContractsDB(
|
|
565
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
566
|
+
bindings2,
|
|
567
|
+
);
|
|
520
568
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
521
569
|
const config = PublicSimulatorConfig.from({
|
|
522
570
|
skipFeeEnforcement: true,
|
|
@@ -525,8 +573,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
525
573
|
collectStatistics: false,
|
|
526
574
|
collectCallMetadata: true,
|
|
527
575
|
});
|
|
528
|
-
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
|
|
529
|
-
const processor = new PublicProcessor(
|
|
576
|
+
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
|
|
577
|
+
const processor = new PublicProcessor(
|
|
578
|
+
globals,
|
|
579
|
+
guardedMerkleTrees,
|
|
580
|
+
contractsDB,
|
|
581
|
+
simulator,
|
|
582
|
+
new TestDateProvider(),
|
|
583
|
+
undefined,
|
|
584
|
+
createLogger('simulator:public-processor', bindings2),
|
|
585
|
+
);
|
|
530
586
|
|
|
531
587
|
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
532
588
|
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
@@ -557,7 +613,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
557
613
|
constantData,
|
|
558
614
|
/*gasUsed=*/ new Gas(0, 0),
|
|
559
615
|
/*feePayer=*/ AztecAddress.zero(),
|
|
560
|
-
/*
|
|
616
|
+
/*expirationTimestamp=*/ 0n,
|
|
561
617
|
inputsForPublic,
|
|
562
618
|
undefined,
|
|
563
619
|
);
|
|
@@ -625,10 +681,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
625
681
|
return returnValues ?? [];
|
|
626
682
|
}
|
|
627
683
|
|
|
628
|
-
async
|
|
684
|
+
async executeUtilityFunction(
|
|
629
685
|
targetContractAddress: AztecAddress,
|
|
630
686
|
functionSelector: FunctionSelector,
|
|
631
687
|
args: Fr[],
|
|
688
|
+
jobId: string,
|
|
632
689
|
) {
|
|
633
690
|
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
634
691
|
if (!artifact) {
|
|
@@ -636,25 +693,33 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
636
693
|
}
|
|
637
694
|
|
|
638
695
|
// Sync notes before executing utility function to discover notes from previous transactions
|
|
639
|
-
await this.
|
|
640
|
-
|
|
641
|
-
});
|
|
642
|
-
|
|
643
|
-
const call = new FunctionCall(
|
|
644
|
-
artifact.name,
|
|
696
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
697
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
645
698
|
targetContractAddress,
|
|
646
699
|
functionSelector,
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
700
|
+
async (call, execScopes) => {
|
|
701
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
702
|
+
},
|
|
703
|
+
blockHeader,
|
|
704
|
+
jobId,
|
|
705
|
+
'ALL_SCOPES',
|
|
652
706
|
);
|
|
653
707
|
|
|
654
|
-
|
|
708
|
+
const call = FunctionCall.from({
|
|
709
|
+
name: artifact.name,
|
|
710
|
+
to: targetContractAddress,
|
|
711
|
+
selector: functionSelector,
|
|
712
|
+
type: FunctionType.UTILITY,
|
|
713
|
+
hideMsgSender: false,
|
|
714
|
+
isStatic: false,
|
|
715
|
+
args,
|
|
716
|
+
returnTypes: [],
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
return this.executeUtilityCall(call, 'ALL_SCOPES', jobId);
|
|
655
720
|
}
|
|
656
721
|
|
|
657
|
-
private async executeUtilityCall(call: FunctionCall): Promise<Fr[]> {
|
|
722
|
+
private async executeUtilityCall(call: FunctionCall, scopes: AccessScopes, jobId: string): Promise<Fr[]> {
|
|
658
723
|
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
659
724
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
660
725
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
@@ -667,23 +732,25 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
667
732
|
|
|
668
733
|
try {
|
|
669
734
|
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
670
|
-
const oracle = new UtilityExecutionOracle(
|
|
671
|
-
call.to,
|
|
672
|
-
[],
|
|
673
|
-
[],
|
|
735
|
+
const oracle = new UtilityExecutionOracle({
|
|
736
|
+
contractAddress: call.to,
|
|
737
|
+
authWitnesses: [],
|
|
738
|
+
capsules: [],
|
|
674
739
|
anchorBlockHeader,
|
|
675
|
-
this.contractStore,
|
|
676
|
-
this.noteStore,
|
|
677
|
-
this.keyStore,
|
|
678
|
-
this.addressStore,
|
|
679
|
-
this.stateMachine.node,
|
|
680
|
-
this.
|
|
681
|
-
this.
|
|
682
|
-
this.
|
|
683
|
-
this.
|
|
684
|
-
this.
|
|
685
|
-
|
|
686
|
-
|
|
740
|
+
contractStore: this.contractStore,
|
|
741
|
+
noteStore: this.noteStore,
|
|
742
|
+
keyStore: this.keyStore,
|
|
743
|
+
addressStore: this.addressStore,
|
|
744
|
+
aztecNode: this.stateMachine.node,
|
|
745
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
746
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
747
|
+
capsuleStore: this.capsuleStore,
|
|
748
|
+
privateEventStore: this.privateEventStore,
|
|
749
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
750
|
+
contractSyncService: this.contractSyncService,
|
|
751
|
+
jobId,
|
|
752
|
+
scopes,
|
|
753
|
+
});
|
|
687
754
|
const acirExecutionResult = await new WASMSimulator()
|
|
688
755
|
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
689
756
|
.catch((err: Error) => {
|
|
@@ -699,10 +766,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
699
766
|
);
|
|
700
767
|
});
|
|
701
768
|
|
|
702
|
-
this.logger.verbose(`Utility
|
|
769
|
+
this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
|
|
703
770
|
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
704
771
|
} catch (err) {
|
|
705
|
-
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility
|
|
772
|
+
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
|
|
706
773
|
}
|
|
707
774
|
}
|
|
708
775
|
|