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