@aztec/txe 0.0.1-commit.b655e406 → 0.0.1-commit.c31f2472
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 +3 -2
- package/dest/oracle/interfaces.d.ts +11 -8
- 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 +22 -12
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +128 -80
- package/dest/rpc_translator.d.ts +31 -16
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +113 -51
- 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 +61 -94
- package/dest/state_machine/dummy_p2p_client.d.ts +9 -6
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +16 -8
- 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 +5 -5
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +31 -19
- package/dest/state_machine/mock_epoch_cache.d.ts +12 -10
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +17 -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 +21 -13
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +97 -48
- 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_contract_store.d.ts +12 -0
- package/dest/util/txe_contract_store.d.ts.map +1 -0
- package/dest/util/{txe_contract_data_provider.js → txe_contract_store.js} +3 -3
- package/dest/util/txe_public_contract_data_source.d.ts +7 -6
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +11 -11
- 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 +36 -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 +15 -12
- package/src/oracle/interfaces.ts +10 -7
- package/src/oracle/txe_oracle_public_context.ts +12 -19
- package/src/oracle/txe_oracle_top_level_context.ts +194 -106
- package/src/rpc_translator.ts +139 -62
- package/src/state_machine/archiver.ts +61 -117
- package/src/state_machine/dummy_p2p_client.ts +22 -10
- package/src/state_machine/global_variable_builder.ts +22 -4
- package/src/state_machine/index.ts +40 -17
- package/src/state_machine/mock_epoch_cache.ts +20 -20
- package/src/state_machine/synchronizer.ts +6 -5
- package/src/txe_session.ts +195 -82
- 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_contract_data_provider.ts → txe_contract_store.ts} +3 -3
- package/src/util/txe_public_contract_data_source.ts +13 -12
- package/src/utils/block_creation.ts +47 -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
|
@@ -6,16 +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';
|
|
14
15
|
import {
|
|
15
|
-
|
|
16
|
+
AddressStore,
|
|
17
|
+
CapsuleStore,
|
|
18
|
+
NoteStore,
|
|
16
19
|
ORACLE_VERSION,
|
|
17
|
-
|
|
20
|
+
PrivateEventStore,
|
|
21
|
+
RecipientTaggingStore,
|
|
22
|
+
SenderAddressBookStore,
|
|
23
|
+
SenderTaggingStore,
|
|
18
24
|
enrichPublicSimulationError,
|
|
25
|
+
syncState,
|
|
19
26
|
} from '@aztec/pxe/server';
|
|
20
27
|
import {
|
|
21
28
|
ExecutionNoteCache,
|
|
@@ -38,18 +45,18 @@ import {
|
|
|
38
45
|
witnessMapToFields,
|
|
39
46
|
} from '@aztec/simulator/client';
|
|
40
47
|
import {
|
|
48
|
+
CppPublicTxSimulator,
|
|
41
49
|
GuardedMerkleTreeOperations,
|
|
42
50
|
PublicContractsDB,
|
|
43
51
|
PublicProcessor,
|
|
44
|
-
PublicTxSimulator,
|
|
45
52
|
} from '@aztec/simulator/server';
|
|
46
|
-
import { type ContractArtifact, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
53
|
+
import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
47
54
|
import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
55
|
+
import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
|
|
48
56
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
49
|
-
import { Body, L2Block } from '@aztec/stdlib/block';
|
|
50
57
|
import { type ContractInstanceWithAddress, computePartialAddress } from '@aztec/stdlib/contract';
|
|
51
58
|
import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
|
|
52
|
-
import { computeCalldataHash, siloNullifier } from '@aztec/stdlib/hash';
|
|
59
|
+
import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
|
|
53
60
|
import {
|
|
54
61
|
PartialPrivateTailPublicInputsForPublic,
|
|
55
62
|
PrivateKernelTailCircuitPublicInputs,
|
|
@@ -57,7 +64,7 @@ import {
|
|
|
57
64
|
PublicCallRequest,
|
|
58
65
|
} from '@aztec/stdlib/kernel';
|
|
59
66
|
import { ChonkProof } from '@aztec/stdlib/proofs';
|
|
60
|
-
import {
|
|
67
|
+
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
61
68
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
62
69
|
import {
|
|
63
70
|
CallContext,
|
|
@@ -74,15 +81,12 @@ import {
|
|
|
74
81
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
75
82
|
import { ForkCheckpoint } from '@aztec/world-state';
|
|
76
83
|
|
|
84
|
+
import { DEFAULT_ADDRESS } from '../constants.js';
|
|
77
85
|
import type { TXEStateMachine } from '../state_machine/index.js';
|
|
78
|
-
import type {
|
|
79
|
-
import type {
|
|
86
|
+
import type { TXEAccountStore } from '../util/txe_account_store.js';
|
|
87
|
+
import type { TXEContractStore } from '../util/txe_contract_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,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
93
97
|
|
|
94
98
|
constructor(
|
|
95
99
|
private stateMachine: TXEStateMachine,
|
|
96
|
-
private
|
|
100
|
+
private contractStore: TXEContractStore,
|
|
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,
|
|
110
|
+
private jobId: string,
|
|
101
111
|
private nextBlockTimestamp: bigint,
|
|
102
112
|
private version: Fr,
|
|
103
113
|
private chainId: Fr,
|
|
@@ -131,8 +141,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
131
141
|
this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
|
|
132
142
|
}
|
|
133
143
|
|
|
134
|
-
|
|
135
|
-
return
|
|
144
|
+
txeGetDefaultAddress(): AztecAddress {
|
|
145
|
+
return DEFAULT_ADDRESS;
|
|
146
|
+
}
|
|
147
|
+
|
|
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,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
156
171
|
return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
|
|
157
172
|
}
|
|
158
173
|
|
|
174
|
+
async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
|
|
175
|
+
return (
|
|
176
|
+
await this.privateEventStore.getPrivateEvents(selector, {
|
|
177
|
+
contractAddress,
|
|
178
|
+
scopes: [scope],
|
|
179
|
+
fromBlock: 0,
|
|
180
|
+
toBlock: (await this.getLastBlockNumber()) + 1,
|
|
181
|
+
})
|
|
182
|
+
).map(e => e.packedEvent);
|
|
183
|
+
}
|
|
184
|
+
|
|
159
185
|
async txeAdvanceBlocksBy(blocks: number) {
|
|
160
186
|
this.logger.debug(`time traveling ${blocks} blocks`);
|
|
161
187
|
|
|
@@ -183,8 +209,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
183
209
|
if (!secret.equals(Fr.ZERO)) {
|
|
184
210
|
await this.txeAddAccount(artifact, instance, secret);
|
|
185
211
|
} else {
|
|
186
|
-
await this.
|
|
187
|
-
await this.
|
|
212
|
+
await this.contractStore.addContractInstance(instance);
|
|
213
|
+
await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
|
|
188
214
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
189
215
|
}
|
|
190
216
|
}
|
|
@@ -193,29 +219,29 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
193
219
|
const partialAddress = await computePartialAddress(instance);
|
|
194
220
|
|
|
195
221
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
196
|
-
await this.
|
|
197
|
-
await this.
|
|
222
|
+
await this.contractStore.addContractInstance(instance);
|
|
223
|
+
await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
|
|
198
224
|
|
|
199
225
|
const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
|
|
200
|
-
await this.
|
|
201
|
-
await this.
|
|
226
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
227
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
202
228
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
203
229
|
|
|
204
230
|
return completeAddress;
|
|
205
231
|
}
|
|
206
232
|
|
|
207
233
|
async txeCreateAccount(secret: Fr) {
|
|
208
|
-
// This is a
|
|
234
|
+
// This is a foot gun !
|
|
209
235
|
const completeAddress = await this.keyStore.addAccount(secret, secret);
|
|
210
|
-
await this.
|
|
211
|
-
await this.
|
|
236
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
237
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
212
238
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
213
239
|
|
|
214
240
|
return completeAddress;
|
|
215
241
|
}
|
|
216
242
|
|
|
217
243
|
async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
|
|
218
|
-
const account = await this.
|
|
244
|
+
const account = await this.accountStore.getAccount(address);
|
|
219
245
|
const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
|
|
220
246
|
|
|
221
247
|
const schnorr = new Schnorr();
|
|
@@ -236,19 +262,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
236
262
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
237
263
|
await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
|
|
238
264
|
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
version: this.version,
|
|
247
|
-
chainId: this.chainId,
|
|
248
|
-
}),
|
|
249
|
-
),
|
|
250
|
-
new Body([txEffect]),
|
|
251
|
-
);
|
|
265
|
+
const globals = makeGlobalVariables(undefined, {
|
|
266
|
+
blockNumber,
|
|
267
|
+
timestamp: this.nextBlockTimestamp,
|
|
268
|
+
version: this.version,
|
|
269
|
+
chainId: this.chainId,
|
|
270
|
+
});
|
|
271
|
+
const block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
252
272
|
|
|
253
273
|
await forkedWorldTrees.close();
|
|
254
274
|
|
|
@@ -266,10 +286,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
266
286
|
isStaticCall: boolean = false,
|
|
267
287
|
) {
|
|
268
288
|
this.logger.verbose(
|
|
269
|
-
`Executing external function ${await this.
|
|
289
|
+
`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
270
290
|
);
|
|
271
291
|
|
|
272
|
-
const artifact = await this.
|
|
292
|
+
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
273
293
|
if (!artifact) {
|
|
274
294
|
const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
|
|
275
295
|
? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
|
|
@@ -277,22 +297,32 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
277
297
|
throw new Error(message);
|
|
278
298
|
}
|
|
279
299
|
|
|
300
|
+
// Sync notes before executing private function to discover notes from previous transactions
|
|
301
|
+
const utilityExecutor = async (call: FunctionCall) => {
|
|
302
|
+
await this.executeUtilityCall(call);
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
await syncState(targetContractAddress, this.contractStore, functionSelector, utilityExecutor);
|
|
306
|
+
|
|
280
307
|
const blockNumber = await this.txeGetNextBlockNumber();
|
|
281
308
|
|
|
282
309
|
const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
|
|
283
310
|
|
|
284
311
|
const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
|
|
285
|
-
|
|
286
312
|
const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
|
|
287
|
-
|
|
288
313
|
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
289
314
|
|
|
290
315
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
291
316
|
|
|
292
|
-
const blockHeader = await this.
|
|
317
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
293
318
|
|
|
294
|
-
const
|
|
295
|
-
const noteCache = new ExecutionNoteCache(
|
|
319
|
+
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
320
|
+
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
321
|
+
// In production, the account contract sets the min revertible counter before calling the app function.
|
|
322
|
+
// Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
|
|
323
|
+
// marking all side effects as revertible.
|
|
324
|
+
const minRevertibleSideEffectCounter = 1;
|
|
325
|
+
await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
296
326
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
297
327
|
|
|
298
328
|
const simulator = new WASMSimulator();
|
|
@@ -303,6 +333,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
303
333
|
callContext,
|
|
304
334
|
/** Header of a block whose state is used during private execution (not the block the transaction is included in). */
|
|
305
335
|
blockHeader,
|
|
336
|
+
utilityExecutor,
|
|
306
337
|
/** List of transient auth witnesses to be used during this simulation */
|
|
307
338
|
Array.from(this.authwits.values()),
|
|
308
339
|
/** List of transient auth witnesses to be used during this simulation */
|
|
@@ -310,9 +341,20 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
310
341
|
HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
311
342
|
noteCache,
|
|
312
343
|
taggingIndexCache,
|
|
313
|
-
this.
|
|
314
|
-
|
|
315
|
-
|
|
344
|
+
this.contractStore,
|
|
345
|
+
this.noteStore,
|
|
346
|
+
this.keyStore,
|
|
347
|
+
this.addressStore,
|
|
348
|
+
this.stateMachine.node,
|
|
349
|
+
this.stateMachine.anchorBlockStore,
|
|
350
|
+
this.senderTaggingStore,
|
|
351
|
+
this.recipientTaggingStore,
|
|
352
|
+
this.senderAddressBookStore,
|
|
353
|
+
this.capsuleStore,
|
|
354
|
+
this.privateEventStore,
|
|
355
|
+
this.jobId,
|
|
356
|
+
0, // totalPublicArgsCount
|
|
357
|
+
minRevertibleSideEffectCounter, // (start) sideEffectCounter
|
|
316
358
|
undefined, // log
|
|
317
359
|
undefined, // scopes
|
|
318
360
|
/**
|
|
@@ -348,19 +390,21 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
348
390
|
}),
|
|
349
391
|
);
|
|
350
392
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
|
|
393
|
+
noteCache.finish();
|
|
394
|
+
const nonceGenerator = noteCache.getNonceGenerator();
|
|
395
|
+
result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
|
|
355
396
|
} catch (err) {
|
|
356
397
|
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
357
398
|
}
|
|
358
399
|
|
|
359
|
-
// According to the protocol rules,
|
|
360
|
-
//
|
|
361
|
-
//
|
|
362
|
-
const
|
|
363
|
-
|
|
400
|
+
// According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
|
|
401
|
+
// the nonce generator for the note hashes.
|
|
402
|
+
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
403
|
+
const { publicInputs } = await generateSimulatedProvingResult(
|
|
404
|
+
result,
|
|
405
|
+
this.contractStore,
|
|
406
|
+
minRevertibleSideEffectCounter,
|
|
407
|
+
);
|
|
364
408
|
|
|
365
409
|
const globals = makeGlobalVariables();
|
|
366
410
|
globals.blockNumber = blockNumber;
|
|
@@ -371,17 +415,27 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
371
415
|
|
|
372
416
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
373
417
|
|
|
374
|
-
const
|
|
418
|
+
const bindings = this.logger.getBindings();
|
|
419
|
+
const contractsDB = new PublicContractsDB(
|
|
420
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
421
|
+
bindings,
|
|
422
|
+
);
|
|
375
423
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
424
|
+
const config = PublicSimulatorConfig.from({
|
|
425
|
+
skipFeeEnforcement: true,
|
|
426
|
+
collectDebugLogs: true,
|
|
427
|
+
collectHints: false,
|
|
428
|
+
collectStatistics: false,
|
|
429
|
+
collectCallMetadata: true,
|
|
430
|
+
});
|
|
376
431
|
const processor = new PublicProcessor(
|
|
377
432
|
globals,
|
|
378
433
|
guardedMerkleTrees,
|
|
379
434
|
contractsDB,
|
|
380
|
-
new
|
|
381
|
-
doMerkleOperations: true,
|
|
382
|
-
skipFeeEnforcement: true,
|
|
383
|
-
}),
|
|
435
|
+
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
|
|
384
436
|
new TestDateProvider(),
|
|
437
|
+
undefined,
|
|
438
|
+
createLogger('simulator:public-processor', bindings),
|
|
385
439
|
);
|
|
386
440
|
|
|
387
441
|
const tx = await Tx.create({
|
|
@@ -406,7 +460,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
406
460
|
} else if (!processedTx.revertCode.isOK()) {
|
|
407
461
|
if (processedTx.revertReason) {
|
|
408
462
|
try {
|
|
409
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.
|
|
463
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
410
464
|
// eslint-disable-next-line no-empty
|
|
411
465
|
} catch {}
|
|
412
466
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -435,13 +489,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
435
489
|
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
436
490
|
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
437
491
|
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
const l2Block = new L2Block(
|
|
441
|
-
makeAppendOnlyTreeSnapshot(),
|
|
442
|
-
await makeTXEBlockHeader(forkedWorldTrees, globals),
|
|
443
|
-
body,
|
|
444
|
-
);
|
|
492
|
+
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
445
493
|
|
|
446
494
|
await this.stateMachine.handleL2Block(l2Block);
|
|
447
495
|
|
|
@@ -457,7 +505,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
457
505
|
isStaticCall: boolean,
|
|
458
506
|
) {
|
|
459
507
|
this.logger.verbose(
|
|
460
|
-
`Executing public function ${await this.
|
|
508
|
+
`Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
461
509
|
);
|
|
462
510
|
|
|
463
511
|
const blockNumber = await this.txeGetNextBlockNumber();
|
|
@@ -470,7 +518,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
470
518
|
|
|
471
519
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
472
520
|
|
|
473
|
-
const anchorBlockHeader = await this.
|
|
521
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
474
522
|
|
|
475
523
|
const calldataHash = await computeCalldataHash(calldata);
|
|
476
524
|
const calldataHashedValues = new HashedValues(calldata, calldataHash);
|
|
@@ -484,22 +532,36 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
484
532
|
|
|
485
533
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
486
534
|
|
|
487
|
-
const
|
|
535
|
+
const bindings2 = this.logger.getBindings();
|
|
536
|
+
const contractsDB = new PublicContractsDB(
|
|
537
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
538
|
+
bindings2,
|
|
539
|
+
);
|
|
488
540
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
489
|
-
const
|
|
490
|
-
doMerkleOperations: true,
|
|
541
|
+
const config = PublicSimulatorConfig.from({
|
|
491
542
|
skipFeeEnforcement: true,
|
|
543
|
+
collectDebugLogs: true,
|
|
544
|
+
collectHints: false,
|
|
545
|
+
collectStatistics: false,
|
|
546
|
+
collectCallMetadata: true,
|
|
492
547
|
});
|
|
493
|
-
const
|
|
548
|
+
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
|
|
549
|
+
const processor = new PublicProcessor(
|
|
550
|
+
globals,
|
|
551
|
+
guardedMerkleTrees,
|
|
552
|
+
contractsDB,
|
|
553
|
+
simulator,
|
|
554
|
+
new TestDateProvider(),
|
|
555
|
+
undefined,
|
|
556
|
+
createLogger('simulator:public-processor', bindings2),
|
|
557
|
+
);
|
|
494
558
|
|
|
495
559
|
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
496
560
|
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
497
561
|
// side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
|
|
498
562
|
// unique.
|
|
499
563
|
const nonRevertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
500
|
-
|
|
501
|
-
nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
|
|
502
|
-
}
|
|
564
|
+
nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
|
|
503
565
|
|
|
504
566
|
// The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
|
|
505
567
|
// may require producing reverts.
|
|
@@ -550,7 +612,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
550
612
|
} else if (!processedTx.revertCode.isOK()) {
|
|
551
613
|
if (processedTx.revertReason) {
|
|
552
614
|
try {
|
|
553
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.
|
|
615
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
554
616
|
// eslint-disable-next-line no-empty
|
|
555
617
|
} catch {}
|
|
556
618
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -582,13 +644,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
582
644
|
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
583
645
|
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
584
646
|
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
const l2Block = new L2Block(
|
|
588
|
-
makeAppendOnlyTreeSnapshot(),
|
|
589
|
-
await makeTXEBlockHeader(forkedWorldTrees, globals),
|
|
590
|
-
body,
|
|
591
|
-
);
|
|
647
|
+
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
592
648
|
|
|
593
649
|
await this.stateMachine.handleL2Block(l2Block);
|
|
594
650
|
|
|
@@ -602,18 +658,32 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
602
658
|
functionSelector: FunctionSelector,
|
|
603
659
|
args: Fr[],
|
|
604
660
|
) {
|
|
605
|
-
const artifact = await this.
|
|
661
|
+
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
606
662
|
if (!artifact) {
|
|
607
663
|
throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
|
|
608
664
|
}
|
|
609
665
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
666
|
+
// Sync notes before executing utility function to discover notes from previous transactions
|
|
667
|
+
await syncState(targetContractAddress, this.contractStore, functionSelector, async call => {
|
|
668
|
+
await this.executeUtilityCall(call);
|
|
669
|
+
});
|
|
670
|
+
|
|
671
|
+
const call = new FunctionCall(
|
|
672
|
+
artifact.name,
|
|
673
|
+
targetContractAddress,
|
|
674
|
+
functionSelector,
|
|
675
|
+
FunctionType.UTILITY,
|
|
676
|
+
false,
|
|
677
|
+
false,
|
|
678
|
+
args,
|
|
679
|
+
[],
|
|
680
|
+
);
|
|
615
681
|
|
|
616
|
-
|
|
682
|
+
return this.executeUtilityCall(call);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
private async executeUtilityCall(call: FunctionCall): Promise<Fr[]> {
|
|
686
|
+
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
617
687
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
618
688
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
619
689
|
}
|
|
@@ -624,9 +694,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
624
694
|
});
|
|
625
695
|
|
|
626
696
|
try {
|
|
627
|
-
const
|
|
697
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
698
|
+
const oracle = new UtilityExecutionOracle(
|
|
699
|
+
call.to,
|
|
700
|
+
[],
|
|
701
|
+
[],
|
|
702
|
+
anchorBlockHeader,
|
|
703
|
+
this.contractStore,
|
|
704
|
+
this.noteStore,
|
|
705
|
+
this.keyStore,
|
|
706
|
+
this.addressStore,
|
|
707
|
+
this.stateMachine.node,
|
|
708
|
+
this.stateMachine.anchorBlockStore,
|
|
709
|
+
this.recipientTaggingStore,
|
|
710
|
+
this.senderAddressBookStore,
|
|
711
|
+
this.capsuleStore,
|
|
712
|
+
this.privateEventStore,
|
|
713
|
+
this.jobId,
|
|
714
|
+
);
|
|
628
715
|
const acirExecutionResult = await new WASMSimulator()
|
|
629
|
-
.executeUserCircuit(toACVMWitness(0, args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
716
|
+
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
630
717
|
.catch((err: Error) => {
|
|
631
718
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
632
719
|
throw new ExecutionError(
|
|
@@ -652,7 +739,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
652
739
|
return [this.nextBlockTimestamp, this.authwits];
|
|
653
740
|
}
|
|
654
741
|
|
|
655
|
-
private async getLastBlockNumber(): Promise<
|
|
656
|
-
|
|
742
|
+
private async getLastBlockNumber(): Promise<BlockNumber> {
|
|
743
|
+
const header = await this.stateMachine.node.getBlockHeader('latest');
|
|
744
|
+
return header ? header.globalVariables.blockNumber : BlockNumber.ZERO;
|
|
657
745
|
}
|
|
658
746
|
}
|