@aztec/txe 0.0.1-commit.fce3e4f → 0.0.1-commit.ff7989d6c
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 +3 -0
- package/dest/constants.d.ts.map +1 -0
- package/dest/constants.js +2 -0
- package/dest/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +85 -52
- package/dest/oracle/interfaces.d.ts +12 -9
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.d.ts +7 -7
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +10 -12
- package/dest/oracle/txe_oracle_top_level_context.d.ts +23 -14
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +177 -79
- package/dest/rpc_translator.d.ts +30 -18
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +127 -60
- package/dest/state_machine/archiver.d.ts +21 -52
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +63 -94
- package/dest/state_machine/dummy_p2p_client.d.ts +19 -14
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +41 -24
- package/dest/state_machine/global_variable_builder.d.ts +6 -5
- package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
- package/dest/state_machine/global_variable_builder.js +13 -1
- package/dest/state_machine/index.d.ts +7 -7
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +40 -23
- package/dest/state_machine/mock_epoch_cache.d.ts +9 -6
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +14 -7
- package/dest/state_machine/synchronizer.d.ts +3 -2
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/state_machine/synchronizer.js +5 -4
- package/dest/txe_session.d.ts +21 -15
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +151 -52
- package/dest/util/encoding.d.ts +618 -19
- package/dest/util/encoding.d.ts.map +1 -1
- package/dest/util/encoding.js +1 -1
- package/dest/util/txe_account_store.d.ts +10 -0
- package/dest/util/txe_account_store.d.ts.map +1 -0
- package/dest/util/{txe_account_data_provider.js → txe_account_store.js} +1 -1
- package/dest/util/txe_public_contract_data_source.d.ts +8 -8
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +12 -29
- package/dest/utils/block_creation.d.ts +21 -6
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +38 -4
- package/dest/utils/tx_effect_creation.d.ts +3 -3
- package/dest/utils/tx_effect_creation.d.ts.map +1 -1
- package/dest/utils/tx_effect_creation.js +4 -7
- package/package.json +18 -18
- package/src/constants.ts +3 -0
- package/src/index.ts +97 -60
- package/src/oracle/interfaces.ts +11 -8
- package/src/oracle/txe_oracle_public_context.ts +12 -19
- package/src/oracle/txe_oracle_top_level_context.ts +213 -124
- package/src/rpc_translator.ts +156 -60
- package/src/state_machine/archiver.ts +59 -114
- package/src/state_machine/dummy_p2p_client.ts +57 -32
- package/src/state_machine/global_variable_builder.ts +21 -4
- package/src/state_machine/index.ts +60 -21
- package/src/state_machine/mock_epoch_cache.ts +15 -11
- package/src/state_machine/synchronizer.ts +6 -5
- package/src/txe_session.ts +207 -100
- package/src/util/encoding.ts +1 -1
- package/src/util/{txe_account_data_provider.ts → txe_account_store.ts} +1 -1
- package/src/util/txe_public_contract_data_source.ts +20 -45
- package/src/utils/block_creation.ts +49 -15
- package/src/utils/tx_effect_creation.ts +5 -12
- package/dest/util/txe_account_data_provider.d.ts +0 -10
- package/dest/util/txe_account_data_provider.d.ts.map +0 -1
- package/dest/util/txe_contract_data_provider.d.ts +0 -12
- package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
- package/dest/util/txe_contract_data_provider.js +0 -22
- package/src/util/txe_contract_data_provider.ts +0 -36
|
@@ -6,15 +6,23 @@ import {
|
|
|
6
6
|
DEFAULT_TEARDOWN_L2_GAS_LIMIT,
|
|
7
7
|
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
8
8
|
} from '@aztec/constants';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
10
|
+
import { Schnorr } from '@aztec/foundation/crypto/schnorr';
|
|
11
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
11
12
|
import { LogLevels, type Logger, applyStringFormatting, createLogger } from '@aztec/foundation/log';
|
|
12
13
|
import { TestDateProvider } from '@aztec/foundation/timer';
|
|
13
14
|
import type { KeyStore } from '@aztec/key-store';
|
|
15
|
+
import type { AccessScopes } from '@aztec/pxe/client/lazy';
|
|
14
16
|
import {
|
|
15
|
-
|
|
17
|
+
AddressStore,
|
|
18
|
+
CapsuleStore,
|
|
19
|
+
type ContractStore,
|
|
20
|
+
NoteStore,
|
|
16
21
|
ORACLE_VERSION,
|
|
17
|
-
|
|
22
|
+
PrivateEventStore,
|
|
23
|
+
RecipientTaggingStore,
|
|
24
|
+
SenderAddressBookStore,
|
|
25
|
+
SenderTaggingStore,
|
|
18
26
|
enrichPublicSimulationError,
|
|
19
27
|
} from '@aztec/pxe/server';
|
|
20
28
|
import {
|
|
@@ -38,16 +46,15 @@ import {
|
|
|
38
46
|
witnessMapToFields,
|
|
39
47
|
} from '@aztec/simulator/client';
|
|
40
48
|
import {
|
|
49
|
+
CppPublicTxSimulator,
|
|
41
50
|
GuardedMerkleTreeOperations,
|
|
42
51
|
PublicContractsDB,
|
|
43
52
|
PublicProcessor,
|
|
44
|
-
PublicTxSimulator,
|
|
45
53
|
} from '@aztec/simulator/server';
|
|
46
|
-
import { type ContractArtifact, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
54
|
+
import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
47
55
|
import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
48
56
|
import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
|
|
49
57
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
50
|
-
import { Body, L2Block } from '@aztec/stdlib/block';
|
|
51
58
|
import { type ContractInstanceWithAddress, computePartialAddress } from '@aztec/stdlib/contract';
|
|
52
59
|
import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
|
|
53
60
|
import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
|
|
@@ -58,7 +65,7 @@ import {
|
|
|
58
65
|
PublicCallRequest,
|
|
59
66
|
} from '@aztec/stdlib/kernel';
|
|
60
67
|
import { ChonkProof } from '@aztec/stdlib/proofs';
|
|
61
|
-
import {
|
|
68
|
+
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
62
69
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
63
70
|
import {
|
|
64
71
|
CallContext,
|
|
@@ -75,15 +82,11 @@ import {
|
|
|
75
82
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
76
83
|
import { ForkCheckpoint } from '@aztec/world-state';
|
|
77
84
|
|
|
85
|
+
import { DEFAULT_ADDRESS } from '../constants.js';
|
|
78
86
|
import type { TXEStateMachine } from '../state_machine/index.js';
|
|
79
|
-
import type {
|
|
80
|
-
import type { TXEContractDataProvider } from '../util/txe_contract_data_provider.js';
|
|
87
|
+
import type { TXEAccountStore } from '../util/txe_account_store.js';
|
|
81
88
|
import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
|
|
82
|
-
import {
|
|
83
|
-
getSingleTxBlockRequestHash,
|
|
84
|
-
insertTxEffectIntoWorldTrees,
|
|
85
|
-
makeTXEBlockHeader,
|
|
86
|
-
} from '../utils/block_creation.js';
|
|
89
|
+
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
87
90
|
import type { ITxeExecutionOracle } from './interfaces.js';
|
|
88
91
|
|
|
89
92
|
export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracle {
|
|
@@ -94,11 +97,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
94
97
|
|
|
95
98
|
constructor(
|
|
96
99
|
private stateMachine: TXEStateMachine,
|
|
97
|
-
private
|
|
100
|
+
private contractStore: ContractStore,
|
|
101
|
+
private noteStore: NoteStore,
|
|
98
102
|
private keyStore: KeyStore,
|
|
99
|
-
private
|
|
100
|
-
private
|
|
101
|
-
private
|
|
103
|
+
private addressStore: AddressStore,
|
|
104
|
+
private accountStore: TXEAccountStore,
|
|
105
|
+
private senderTaggingStore: SenderTaggingStore,
|
|
106
|
+
private recipientTaggingStore: RecipientTaggingStore,
|
|
107
|
+
private senderAddressBookStore: SenderAddressBookStore,
|
|
108
|
+
private capsuleStore: CapsuleStore,
|
|
109
|
+
private privateEventStore: PrivateEventStore,
|
|
110
|
+
private jobId: string,
|
|
102
111
|
private nextBlockTimestamp: bigint,
|
|
103
112
|
private version: Fr,
|
|
104
113
|
private chainId: Fr,
|
|
@@ -123,17 +132,22 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
123
132
|
}
|
|
124
133
|
|
|
125
134
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
126
|
-
|
|
135
|
+
utilityLog(level: number, message: string, fields: Fr[]): Promise<void> {
|
|
127
136
|
if (!LogLevels[level]) {
|
|
128
|
-
throw new Error(`Invalid
|
|
137
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
129
138
|
}
|
|
130
139
|
const levelName = LogLevels[level];
|
|
131
140
|
|
|
132
141
|
this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
|
|
142
|
+
return Promise.resolve();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
txeGetDefaultAddress(): AztecAddress {
|
|
146
|
+
return DEFAULT_ADDRESS;
|
|
133
147
|
}
|
|
134
148
|
|
|
135
|
-
async txeGetNextBlockNumber(): Promise<
|
|
136
|
-
return (await this.getLastBlockNumber()) + 1;
|
|
149
|
+
async txeGetNextBlockNumber(): Promise<BlockNumber> {
|
|
150
|
+
return BlockNumber((await this.getLastBlockNumber()) + 1);
|
|
137
151
|
}
|
|
138
152
|
|
|
139
153
|
txeGetNextBlockTimestamp(): Promise<bigint> {
|
|
@@ -145,7 +159,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
145
159
|
}
|
|
146
160
|
|
|
147
161
|
async txeGetLastTxEffects() {
|
|
148
|
-
const
|
|
162
|
+
const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
|
|
163
|
+
const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
|
|
149
164
|
|
|
150
165
|
if (block!.body.txEffects.length != 1) {
|
|
151
166
|
// Note that calls like env.mine() will result in blocks with no transactions, hitting this
|
|
@@ -157,6 +172,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
157
172
|
return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
|
|
158
173
|
}
|
|
159
174
|
|
|
175
|
+
async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
|
|
176
|
+
return (
|
|
177
|
+
await this.privateEventStore.getPrivateEvents(selector, {
|
|
178
|
+
contractAddress,
|
|
179
|
+
scopes: [scope],
|
|
180
|
+
fromBlock: 0,
|
|
181
|
+
toBlock: (await this.getLastBlockNumber()) + 1,
|
|
182
|
+
})
|
|
183
|
+
).map(e => e.packedEvent);
|
|
184
|
+
}
|
|
185
|
+
|
|
160
186
|
async txeAdvanceBlocksBy(blocks: number) {
|
|
161
187
|
this.logger.debug(`time traveling ${blocks} blocks`);
|
|
162
188
|
|
|
@@ -184,8 +210,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
184
210
|
if (!secret.equals(Fr.ZERO)) {
|
|
185
211
|
await this.txeAddAccount(artifact, instance, secret);
|
|
186
212
|
} else {
|
|
187
|
-
await this.
|
|
188
|
-
await this.
|
|
213
|
+
await this.contractStore.addContractInstance(instance);
|
|
214
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
189
215
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
190
216
|
}
|
|
191
217
|
}
|
|
@@ -194,29 +220,29 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
194
220
|
const partialAddress = await computePartialAddress(instance);
|
|
195
221
|
|
|
196
222
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
197
|
-
await this.
|
|
198
|
-
await this.
|
|
223
|
+
await this.contractStore.addContractInstance(instance);
|
|
224
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
199
225
|
|
|
200
226
|
const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
|
|
201
|
-
await this.
|
|
202
|
-
await this.
|
|
227
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
228
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
203
229
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
204
230
|
|
|
205
231
|
return completeAddress;
|
|
206
232
|
}
|
|
207
233
|
|
|
208
234
|
async txeCreateAccount(secret: Fr) {
|
|
209
|
-
// This is a
|
|
235
|
+
// This is a foot gun !
|
|
210
236
|
const completeAddress = await this.keyStore.addAccount(secret, secret);
|
|
211
|
-
await this.
|
|
212
|
-
await this.
|
|
237
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
238
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
213
239
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
214
240
|
|
|
215
241
|
return completeAddress;
|
|
216
242
|
}
|
|
217
243
|
|
|
218
244
|
async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
|
|
219
|
-
const account = await this.
|
|
245
|
+
const account = await this.accountStore.getAccount(address);
|
|
220
246
|
const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
|
|
221
247
|
|
|
222
248
|
const schnorr = new Schnorr();
|
|
@@ -237,19 +263,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
237
263
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
238
264
|
await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
|
|
239
265
|
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
version: this.version,
|
|
248
|
-
chainId: this.chainId,
|
|
249
|
-
}),
|
|
250
|
-
),
|
|
251
|
-
new Body([txEffect]),
|
|
252
|
-
);
|
|
266
|
+
const globals = makeGlobalVariables(undefined, {
|
|
267
|
+
blockNumber,
|
|
268
|
+
timestamp: this.nextBlockTimestamp,
|
|
269
|
+
version: this.version,
|
|
270
|
+
chainId: this.chainId,
|
|
271
|
+
});
|
|
272
|
+
const block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
253
273
|
|
|
254
274
|
await forkedWorldTrees.close();
|
|
255
275
|
|
|
@@ -267,10 +287,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
267
287
|
isStaticCall: boolean = false,
|
|
268
288
|
) {
|
|
269
289
|
this.logger.verbose(
|
|
270
|
-
`Executing external function ${await this.
|
|
290
|
+
`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
271
291
|
);
|
|
272
292
|
|
|
273
|
-
const artifact = await this.
|
|
293
|
+
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
274
294
|
if (!artifact) {
|
|
275
295
|
const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
|
|
276
296
|
? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
|
|
@@ -278,51 +298,77 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
278
298
|
throw new Error(message);
|
|
279
299
|
}
|
|
280
300
|
|
|
301
|
+
// When `from` is the zero address (e.g. when deploying a new account contract), we return an
|
|
302
|
+
// empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
|
|
303
|
+
const effectiveScopes = from.isZero() ? [] : [from];
|
|
304
|
+
|
|
305
|
+
// Sync notes before executing private function to discover notes from previous transactions
|
|
306
|
+
const utilityExecutor = async (call: FunctionCall, execScopes: AccessScopes) => {
|
|
307
|
+
await this.executeUtilityCall(call, execScopes);
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
311
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
312
|
+
targetContractAddress,
|
|
313
|
+
functionSelector,
|
|
314
|
+
utilityExecutor,
|
|
315
|
+
blockHeader,
|
|
316
|
+
this.jobId,
|
|
317
|
+
effectiveScopes,
|
|
318
|
+
);
|
|
319
|
+
|
|
281
320
|
const blockNumber = await this.txeGetNextBlockNumber();
|
|
282
321
|
|
|
283
322
|
const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
|
|
284
323
|
|
|
285
324
|
const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
|
|
286
|
-
|
|
287
325
|
const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
|
|
288
|
-
|
|
289
326
|
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
290
327
|
|
|
291
328
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
292
329
|
|
|
293
|
-
const blockHeader = await this.pxeOracleInterface.getAnchorBlockHeader();
|
|
294
|
-
|
|
295
330
|
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
296
331
|
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
332
|
+
// In production, the account contract sets the min revertible counter before calling the app function.
|
|
333
|
+
// Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
|
|
334
|
+
// marking all side effects as revertible.
|
|
335
|
+
const minRevertibleSideEffectCounter = 1;
|
|
336
|
+
await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
297
337
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
298
338
|
|
|
299
339
|
const simulator = new WASMSimulator();
|
|
300
340
|
|
|
301
|
-
const privateExecutionOracle = new PrivateExecutionOracle(
|
|
341
|
+
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
302
342
|
argsHash,
|
|
303
343
|
txContext,
|
|
304
344
|
callContext,
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
[],
|
|
311
|
-
HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
345
|
+
anchorBlockHeader: blockHeader,
|
|
346
|
+
utilityExecutor,
|
|
347
|
+
authWitnesses: Array.from(this.authwits.values()),
|
|
348
|
+
capsules: [],
|
|
349
|
+
executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
312
350
|
noteCache,
|
|
313
351
|
taggingIndexCache,
|
|
314
|
-
this.
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
352
|
+
contractStore: this.contractStore,
|
|
353
|
+
noteStore: this.noteStore,
|
|
354
|
+
keyStore: this.keyStore,
|
|
355
|
+
addressStore: this.addressStore,
|
|
356
|
+
aztecNode: this.stateMachine.node,
|
|
357
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
358
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
359
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
360
|
+
capsuleStore: this.capsuleStore,
|
|
361
|
+
privateEventStore: this.privateEventStore,
|
|
362
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
363
|
+
jobId: this.jobId,
|
|
364
|
+
totalPublicCalldataCount: 0,
|
|
365
|
+
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
366
|
+
scopes: effectiveScopes,
|
|
367
|
+
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
368
|
+
// contract would perform, including setting senderForTags.
|
|
369
|
+
senderForTags: from,
|
|
324
370
|
simulator,
|
|
325
|
-
);
|
|
371
|
+
});
|
|
326
372
|
|
|
327
373
|
// 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.
|
|
328
374
|
let result: PrivateExecutionResult;
|
|
@@ -349,19 +395,22 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
349
395
|
}),
|
|
350
396
|
);
|
|
351
397
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
|
|
398
|
+
noteCache.finish();
|
|
399
|
+
const nonceGenerator = noteCache.getNonceGenerator();
|
|
400
|
+
result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
|
|
356
401
|
} catch (err) {
|
|
357
402
|
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
358
403
|
}
|
|
359
404
|
|
|
360
|
-
// According to the protocol rules,
|
|
361
|
-
//
|
|
362
|
-
//
|
|
363
|
-
const
|
|
364
|
-
|
|
405
|
+
// According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
|
|
406
|
+
// the nonce generator for the note hashes.
|
|
407
|
+
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
408
|
+
const { publicInputs } = await generateSimulatedProvingResult(
|
|
409
|
+
result,
|
|
410
|
+
(addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
|
|
411
|
+
this.stateMachine.node,
|
|
412
|
+
minRevertibleSideEffectCounter,
|
|
413
|
+
);
|
|
365
414
|
|
|
366
415
|
const globals = makeGlobalVariables();
|
|
367
416
|
globals.blockNumber = blockNumber;
|
|
@@ -372,7 +421,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
372
421
|
|
|
373
422
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
374
423
|
|
|
375
|
-
const
|
|
424
|
+
const bindings = this.logger.getBindings();
|
|
425
|
+
const contractsDB = new PublicContractsDB(
|
|
426
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
427
|
+
bindings,
|
|
428
|
+
);
|
|
376
429
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
377
430
|
const config = PublicSimulatorConfig.from({
|
|
378
431
|
skipFeeEnforcement: true,
|
|
@@ -385,8 +438,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
385
438
|
globals,
|
|
386
439
|
guardedMerkleTrees,
|
|
387
440
|
contractsDB,
|
|
388
|
-
new
|
|
441
|
+
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
|
|
389
442
|
new TestDateProvider(),
|
|
443
|
+
undefined,
|
|
444
|
+
createLogger('simulator:public-processor', bindings),
|
|
390
445
|
);
|
|
391
446
|
|
|
392
447
|
const tx = await Tx.create({
|
|
@@ -411,7 +466,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
411
466
|
} else if (!processedTx.revertCode.isOK()) {
|
|
412
467
|
if (processedTx.revertReason) {
|
|
413
468
|
try {
|
|
414
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.
|
|
469
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
415
470
|
// eslint-disable-next-line no-empty
|
|
416
471
|
} catch {}
|
|
417
472
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -440,13 +495,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
440
495
|
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
441
496
|
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
442
497
|
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
const l2Block = new L2Block(
|
|
446
|
-
makeAppendOnlyTreeSnapshot(),
|
|
447
|
-
await makeTXEBlockHeader(forkedWorldTrees, globals),
|
|
448
|
-
body,
|
|
449
|
-
);
|
|
498
|
+
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
450
499
|
|
|
451
500
|
await this.stateMachine.handleL2Block(l2Block);
|
|
452
501
|
|
|
@@ -462,7 +511,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
462
511
|
isStaticCall: boolean,
|
|
463
512
|
) {
|
|
464
513
|
this.logger.verbose(
|
|
465
|
-
`Executing public function ${await this.
|
|
514
|
+
`Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
466
515
|
);
|
|
467
516
|
|
|
468
517
|
const blockNumber = await this.txeGetNextBlockNumber();
|
|
@@ -475,7 +524,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
475
524
|
|
|
476
525
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
477
526
|
|
|
478
|
-
const anchorBlockHeader = await this.
|
|
527
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
479
528
|
|
|
480
529
|
const calldataHash = await computeCalldataHash(calldata);
|
|
481
530
|
const calldataHashedValues = new HashedValues(calldata, calldataHash);
|
|
@@ -489,7 +538,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
489
538
|
|
|
490
539
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
491
540
|
|
|
492
|
-
const
|
|
541
|
+
const bindings2 = this.logger.getBindings();
|
|
542
|
+
const contractsDB = new PublicContractsDB(
|
|
543
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
544
|
+
bindings2,
|
|
545
|
+
);
|
|
493
546
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
494
547
|
const config = PublicSimulatorConfig.from({
|
|
495
548
|
skipFeeEnforcement: true,
|
|
@@ -498,17 +551,23 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
498
551
|
collectStatistics: false,
|
|
499
552
|
collectCallMetadata: true,
|
|
500
553
|
});
|
|
501
|
-
const simulator = new
|
|
502
|
-
const processor = new PublicProcessor(
|
|
554
|
+
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
|
|
555
|
+
const processor = new PublicProcessor(
|
|
556
|
+
globals,
|
|
557
|
+
guardedMerkleTrees,
|
|
558
|
+
contractsDB,
|
|
559
|
+
simulator,
|
|
560
|
+
new TestDateProvider(),
|
|
561
|
+
undefined,
|
|
562
|
+
createLogger('simulator:public-processor', bindings2),
|
|
563
|
+
);
|
|
503
564
|
|
|
504
565
|
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
505
566
|
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
506
567
|
// side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
|
|
507
568
|
// unique.
|
|
508
569
|
const nonRevertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
509
|
-
|
|
510
|
-
nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
|
|
511
|
-
}
|
|
570
|
+
nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
|
|
512
571
|
|
|
513
572
|
// The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
|
|
514
573
|
// may require producing reverts.
|
|
@@ -532,7 +591,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
532
591
|
constantData,
|
|
533
592
|
/*gasUsed=*/ new Gas(0, 0),
|
|
534
593
|
/*feePayer=*/ AztecAddress.zero(),
|
|
535
|
-
/*
|
|
594
|
+
/*expirationTimestamp=*/ 0n,
|
|
536
595
|
inputsForPublic,
|
|
537
596
|
undefined,
|
|
538
597
|
);
|
|
@@ -559,7 +618,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
559
618
|
} else if (!processedTx.revertCode.isOK()) {
|
|
560
619
|
if (processedTx.revertReason) {
|
|
561
620
|
try {
|
|
562
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.
|
|
621
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
563
622
|
// eslint-disable-next-line no-empty
|
|
564
623
|
} catch {}
|
|
565
624
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -591,13 +650,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
591
650
|
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
592
651
|
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
593
652
|
|
|
594
|
-
const
|
|
595
|
-
|
|
596
|
-
const l2Block = new L2Block(
|
|
597
|
-
makeAppendOnlyTreeSnapshot(),
|
|
598
|
-
await makeTXEBlockHeader(forkedWorldTrees, globals),
|
|
599
|
-
body,
|
|
600
|
-
);
|
|
653
|
+
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
601
654
|
|
|
602
655
|
await this.stateMachine.handleL2Block(l2Block);
|
|
603
656
|
|
|
@@ -606,23 +659,41 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
606
659
|
return returnValues ?? [];
|
|
607
660
|
}
|
|
608
661
|
|
|
609
|
-
async
|
|
610
|
-
targetContractAddress
|
|
611
|
-
functionSelector: FunctionSelector,
|
|
612
|
-
args: Fr[],
|
|
613
|
-
) {
|
|
614
|
-
const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
662
|
+
async txeExecuteUtilityFunction(targetContractAddress: AztecAddress, functionSelector: FunctionSelector, args: Fr[]) {
|
|
663
|
+
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
615
664
|
if (!artifact) {
|
|
616
665
|
throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
|
|
617
666
|
}
|
|
618
667
|
|
|
619
|
-
|
|
668
|
+
// Sync notes before executing utility function to discover notes from previous transactions
|
|
669
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
670
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
671
|
+
targetContractAddress,
|
|
672
|
+
functionSelector,
|
|
673
|
+
async (call, execScopes) => {
|
|
674
|
+
await this.executeUtilityCall(call, execScopes);
|
|
675
|
+
},
|
|
676
|
+
blockHeader,
|
|
677
|
+
this.jobId,
|
|
678
|
+
'ALL_SCOPES',
|
|
679
|
+
);
|
|
680
|
+
|
|
681
|
+
const call = FunctionCall.from({
|
|
620
682
|
name: artifact.name,
|
|
621
|
-
selector: functionSelector,
|
|
622
683
|
to: targetContractAddress,
|
|
623
|
-
|
|
684
|
+
selector: functionSelector,
|
|
685
|
+
type: FunctionType.UTILITY,
|
|
686
|
+
hideMsgSender: false,
|
|
687
|
+
isStatic: false,
|
|
688
|
+
args,
|
|
689
|
+
returnTypes: [],
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
return this.executeUtilityCall(call, 'ALL_SCOPES');
|
|
693
|
+
}
|
|
624
694
|
|
|
625
|
-
|
|
695
|
+
private async executeUtilityCall(call: FunctionCall, scopes: AccessScopes): Promise<Fr[]> {
|
|
696
|
+
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
626
697
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
627
698
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
628
699
|
}
|
|
@@ -633,9 +704,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
633
704
|
});
|
|
634
705
|
|
|
635
706
|
try {
|
|
636
|
-
const
|
|
707
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
708
|
+
const oracle = new UtilityExecutionOracle({
|
|
709
|
+
contractAddress: call.to,
|
|
710
|
+
authWitnesses: [],
|
|
711
|
+
capsules: [],
|
|
712
|
+
anchorBlockHeader,
|
|
713
|
+
contractStore: this.contractStore,
|
|
714
|
+
noteStore: this.noteStore,
|
|
715
|
+
keyStore: this.keyStore,
|
|
716
|
+
addressStore: this.addressStore,
|
|
717
|
+
aztecNode: this.stateMachine.node,
|
|
718
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
719
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
720
|
+
capsuleStore: this.capsuleStore,
|
|
721
|
+
privateEventStore: this.privateEventStore,
|
|
722
|
+
jobId: this.jobId,
|
|
723
|
+
scopes,
|
|
724
|
+
});
|
|
637
725
|
const acirExecutionResult = await new WASMSimulator()
|
|
638
|
-
.executeUserCircuit(toACVMWitness(0, args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
726
|
+
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
639
727
|
.catch((err: Error) => {
|
|
640
728
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
641
729
|
throw new ExecutionError(
|
|
@@ -649,10 +737,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
649
737
|
);
|
|
650
738
|
});
|
|
651
739
|
|
|
652
|
-
this.logger.verbose(`Utility
|
|
740
|
+
this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
|
|
653
741
|
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
654
742
|
} catch (err) {
|
|
655
|
-
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility
|
|
743
|
+
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
|
|
656
744
|
}
|
|
657
745
|
}
|
|
658
746
|
|
|
@@ -661,7 +749,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
661
749
|
return [this.nextBlockTimestamp, this.authwits];
|
|
662
750
|
}
|
|
663
751
|
|
|
664
|
-
private async getLastBlockNumber(): Promise<
|
|
665
|
-
|
|
752
|
+
private async getLastBlockNumber(): Promise<BlockNumber> {
|
|
753
|
+
const header = await this.stateMachine.node.getBlockHeader('latest');
|
|
754
|
+
return header ? header.globalVariables.blockNumber : BlockNumber.ZERO;
|
|
666
755
|
}
|
|
667
756
|
}
|