@aztec/txe 0.0.1-commit.5daedc8 → 0.0.1-commit.6201a7b05
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 +91 -56
- package/dest/oracle/interfaces.d.ts +36 -29
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.d.ts +16 -16
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +20 -22
- package/dest/oracle/txe_oracle_top_level_context.d.ts +44 -27
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +245 -109
- package/dest/rpc_translator.d.ts +136 -78
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +545 -178
- 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 +67 -99
- package/dest/state_machine/dummy_p2p_client.d.ts +21 -15
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +45 -25
- package/dest/state_machine/global_variable_builder.d.ts +11 -5
- package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
- package/dest/state_machine/global_variable_builder.js +21 -3
- package/dest/state_machine/index.d.ts +9 -7
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +45 -24
- package/dest/state_machine/mock_epoch_cache.d.ts +26 -8
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +49 -9
- package/dest/state_machine/synchronizer.d.ts +6 -5
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/state_machine/synchronizer.js +8 -7
- package/dest/txe_session.d.ts +71 -15
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +228 -57
- package/dest/util/encoding.d.ts +688 -19
- package/dest/util/encoding.d.ts.map +1 -1
- package/dest/util/encoding.js +5 -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 +13 -32
- 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 +103 -63
- package/src/oracle/interfaces.ts +37 -33
- package/src/oracle/txe_oracle_public_context.ts +21 -28
- package/src/oracle/txe_oracle_top_level_context.ts +291 -151
- package/src/rpc_translator.ts +645 -206
- package/src/state_machine/archiver.ts +63 -117
- package/src/state_machine/dummy_p2p_client.ts +62 -33
- package/src/state_machine/global_variable_builder.ts +38 -6
- package/src/state_machine/index.ts +68 -22
- package/src/state_machine/mock_epoch_cache.ts +61 -14
- package/src/state_machine/synchronizer.ts +9 -8
- package/src/txe_session.ts +351 -105
- package/src/util/encoding.ts +6 -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 -47
- 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
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
DEFAULT_TEARDOWN_DA_GAS_LIMIT,
|
|
6
|
-
DEFAULT_TEARDOWN_L2_GAS_LIMIT,
|
|
3
|
+
MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT,
|
|
4
|
+
MAX_PROCESSABLE_L2_GAS,
|
|
7
5
|
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
8
6
|
} from '@aztec/constants';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
7
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
8
|
+
import { Schnorr } from '@aztec/foundation/crypto/schnorr';
|
|
9
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
11
10
|
import { LogLevels, type Logger, applyStringFormatting, createLogger } from '@aztec/foundation/log';
|
|
12
11
|
import { TestDateProvider } from '@aztec/foundation/timer';
|
|
13
12
|
import type { KeyStore } from '@aztec/key-store';
|
|
14
13
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
AddressStore,
|
|
15
|
+
CapsuleService,
|
|
16
|
+
CapsuleStore,
|
|
17
|
+
type ContractStore,
|
|
18
|
+
NoteStore,
|
|
19
|
+
ORACLE_VERSION_MAJOR,
|
|
20
|
+
PrivateEventStore,
|
|
21
|
+
RecipientTaggingStore,
|
|
22
|
+
SenderAddressBookStore,
|
|
23
|
+
SenderTaggingStore,
|
|
18
24
|
enrichPublicSimulationError,
|
|
19
25
|
} from '@aztec/pxe/server';
|
|
20
26
|
import {
|
|
@@ -38,18 +44,23 @@ import {
|
|
|
38
44
|
witnessMapToFields,
|
|
39
45
|
} from '@aztec/simulator/client';
|
|
40
46
|
import {
|
|
47
|
+
CppPublicTxSimulator,
|
|
41
48
|
GuardedMerkleTreeOperations,
|
|
42
49
|
PublicContractsDB,
|
|
43
50
|
PublicProcessor,
|
|
44
|
-
PublicTxSimulator,
|
|
45
51
|
} from '@aztec/simulator/server';
|
|
46
|
-
import { type ContractArtifact, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
52
|
+
import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
47
53
|
import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
48
54
|
import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
|
|
49
55
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
50
|
-
import { Body, L2Block } from '@aztec/stdlib/block';
|
|
51
56
|
import { type ContractInstanceWithAddress, computePartialAddress } from '@aztec/stdlib/contract';
|
|
52
|
-
import {
|
|
57
|
+
import {
|
|
58
|
+
FALLBACK_TEARDOWN_DA_GAS_LIMIT,
|
|
59
|
+
FALLBACK_TEARDOWN_L2_GAS_LIMIT,
|
|
60
|
+
Gas,
|
|
61
|
+
GasFees,
|
|
62
|
+
GasSettings,
|
|
63
|
+
} from '@aztec/stdlib/gas';
|
|
53
64
|
import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
|
|
54
65
|
import {
|
|
55
66
|
PartialPrivateTailPublicInputsForPublic,
|
|
@@ -58,7 +69,7 @@ import {
|
|
|
58
69
|
PublicCallRequest,
|
|
59
70
|
} from '@aztec/stdlib/kernel';
|
|
60
71
|
import { ChonkProof } from '@aztec/stdlib/proofs';
|
|
61
|
-
import {
|
|
72
|
+
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
62
73
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
63
74
|
import {
|
|
64
75
|
CallContext,
|
|
@@ -75,15 +86,11 @@ import {
|
|
|
75
86
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
76
87
|
import { ForkCheckpoint } from '@aztec/world-state';
|
|
77
88
|
|
|
89
|
+
import { DEFAULT_ADDRESS } from '../constants.js';
|
|
78
90
|
import type { TXEStateMachine } from '../state_machine/index.js';
|
|
79
|
-
import type {
|
|
80
|
-
import type { TXEContractDataProvider } from '../util/txe_contract_data_provider.js';
|
|
91
|
+
import type { TXEAccountStore } from '../util/txe_account_store.js';
|
|
81
92
|
import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
|
|
82
|
-
import {
|
|
83
|
-
getSingleTxBlockRequestHash,
|
|
84
|
-
insertTxEffectIntoWorldTrees,
|
|
85
|
-
makeTXEBlockHeader,
|
|
86
|
-
} from '../utils/block_creation.js';
|
|
93
|
+
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
87
94
|
import type { ITxeExecutionOracle } from './interfaces.js';
|
|
88
95
|
|
|
89
96
|
export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracle {
|
|
@@ -94,11 +101,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
94
101
|
|
|
95
102
|
constructor(
|
|
96
103
|
private stateMachine: TXEStateMachine,
|
|
97
|
-
private
|
|
104
|
+
private contractStore: ContractStore,
|
|
105
|
+
private noteStore: NoteStore,
|
|
98
106
|
private keyStore: KeyStore,
|
|
99
|
-
private
|
|
100
|
-
private
|
|
101
|
-
private
|
|
107
|
+
private addressStore: AddressStore,
|
|
108
|
+
private accountStore: TXEAccountStore,
|
|
109
|
+
private senderTaggingStore: SenderTaggingStore,
|
|
110
|
+
private recipientTaggingStore: RecipientTaggingStore,
|
|
111
|
+
private senderAddressBookStore: SenderAddressBookStore,
|
|
112
|
+
private capsuleStore: CapsuleStore,
|
|
113
|
+
private privateEventStore: PrivateEventStore,
|
|
102
114
|
private nextBlockTimestamp: bigint,
|
|
103
115
|
private version: Fr,
|
|
104
116
|
private chainId: Fr,
|
|
@@ -108,44 +120,62 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
108
120
|
this.logger.debug('Entering Top Level Context');
|
|
109
121
|
}
|
|
110
122
|
|
|
111
|
-
|
|
112
|
-
|
|
123
|
+
private contractOracleVersion: { major: number; minor: number } | undefined;
|
|
124
|
+
|
|
125
|
+
assertCompatibleOracleVersion(major: number, minor: number): void {
|
|
126
|
+
if (major !== ORACLE_VERSION_MAJOR) {
|
|
127
|
+
const hint =
|
|
128
|
+
major > ORACLE_VERSION_MAJOR
|
|
129
|
+
? 'The contract was compiled with a newer version of Aztec.nr than this aztec cli version supports. Upgrade your aztec cli version to a compatible version.'
|
|
130
|
+
: 'The contract was compiled with an older version of Aztec.nr than this aztec cli version supports. Recompile the contract with a compatible version of Aztec.nr.';
|
|
113
131
|
throw new Error(
|
|
114
|
-
`Incompatible
|
|
132
|
+
`Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
|
|
115
133
|
);
|
|
116
134
|
}
|
|
135
|
+
this.contractOracleVersion = { major, minor };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
|
|
139
|
+
nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined {
|
|
140
|
+
return this.contractOracleVersion;
|
|
117
141
|
}
|
|
118
142
|
|
|
119
143
|
// This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
|
|
120
144
|
// setup.
|
|
121
|
-
|
|
145
|
+
getRandomField(): Fr {
|
|
122
146
|
return Fr.random();
|
|
123
147
|
}
|
|
124
148
|
|
|
125
149
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
126
|
-
|
|
150
|
+
log(level: number, message: string, fields: Fr[]): Promise<void> {
|
|
127
151
|
if (!LogLevels[level]) {
|
|
128
|
-
throw new Error(`Invalid
|
|
152
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
129
153
|
}
|
|
130
154
|
const levelName = LogLevels[level];
|
|
131
155
|
|
|
132
156
|
this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
|
|
157
|
+
return Promise.resolve();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
getDefaultAddress(): AztecAddress {
|
|
161
|
+
return DEFAULT_ADDRESS;
|
|
133
162
|
}
|
|
134
163
|
|
|
135
|
-
async
|
|
136
|
-
return (await this.getLastBlockNumber()) + 1;
|
|
164
|
+
async getNextBlockNumber(): Promise<BlockNumber> {
|
|
165
|
+
return BlockNumber((await this.getLastBlockNumber()) + 1);
|
|
137
166
|
}
|
|
138
167
|
|
|
139
|
-
|
|
168
|
+
getNextBlockTimestamp(): Promise<bigint> {
|
|
140
169
|
return Promise.resolve(this.nextBlockTimestamp);
|
|
141
170
|
}
|
|
142
171
|
|
|
143
|
-
async
|
|
172
|
+
async getLastBlockTimestamp() {
|
|
144
173
|
return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
|
|
145
174
|
}
|
|
146
175
|
|
|
147
|
-
async
|
|
148
|
-
const
|
|
176
|
+
async getLastTxEffects() {
|
|
177
|
+
const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
|
|
178
|
+
const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
|
|
149
179
|
|
|
150
180
|
if (block!.body.txEffects.length != 1) {
|
|
151
181
|
// Note that calls like env.mine() will result in blocks with no transactions, hitting this
|
|
@@ -157,7 +187,37 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
157
187
|
return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
|
|
158
188
|
}
|
|
159
189
|
|
|
160
|
-
async
|
|
190
|
+
async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
|
|
191
|
+
if (contractAddress.equals(DEFAULT_ADDRESS)) {
|
|
192
|
+
this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
197
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
198
|
+
contractAddress,
|
|
199
|
+
null,
|
|
200
|
+
async (call, execScopes) => {
|
|
201
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
202
|
+
},
|
|
203
|
+
blockHeader,
|
|
204
|
+
jobId,
|
|
205
|
+
[scope],
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
|
|
210
|
+
return (
|
|
211
|
+
await this.privateEventStore.getPrivateEvents(selector, {
|
|
212
|
+
contractAddress,
|
|
213
|
+
scopes: [scope],
|
|
214
|
+
fromBlock: 0,
|
|
215
|
+
toBlock: (await this.getLastBlockNumber()) + 1,
|
|
216
|
+
})
|
|
217
|
+
).map(e => e.packedEvent);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async advanceBlocksBy(blocks: number) {
|
|
161
221
|
this.logger.debug(`time traveling ${blocks} blocks`);
|
|
162
222
|
|
|
163
223
|
for (let i = 0; i < blocks; i++) {
|
|
@@ -165,12 +225,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
165
225
|
}
|
|
166
226
|
}
|
|
167
227
|
|
|
168
|
-
|
|
228
|
+
advanceTimestampBy(duration: UInt64) {
|
|
169
229
|
this.logger.debug(`time traveling ${duration} seconds`);
|
|
170
230
|
this.nextBlockTimestamp += duration;
|
|
171
231
|
}
|
|
172
232
|
|
|
173
|
-
async
|
|
233
|
+
async deploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
|
|
174
234
|
// Emit deployment nullifier
|
|
175
235
|
await this.mineBlock({
|
|
176
236
|
nullifiers: [
|
|
@@ -182,41 +242,41 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
182
242
|
});
|
|
183
243
|
|
|
184
244
|
if (!secret.equals(Fr.ZERO)) {
|
|
185
|
-
await this.
|
|
245
|
+
await this.addAccount(artifact, instance, secret);
|
|
186
246
|
} else {
|
|
187
|
-
await this.
|
|
188
|
-
await this.
|
|
247
|
+
await this.contractStore.addContractInstance(instance);
|
|
248
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
189
249
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
190
250
|
}
|
|
191
251
|
}
|
|
192
252
|
|
|
193
|
-
async
|
|
253
|
+
async addAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
|
|
194
254
|
const partialAddress = await computePartialAddress(instance);
|
|
195
255
|
|
|
196
256
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
197
|
-
await this.
|
|
198
|
-
await this.
|
|
257
|
+
await this.contractStore.addContractInstance(instance);
|
|
258
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
199
259
|
|
|
200
260
|
const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
|
|
201
|
-
await this.
|
|
202
|
-
await this.
|
|
261
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
262
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
203
263
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
204
264
|
|
|
205
265
|
return completeAddress;
|
|
206
266
|
}
|
|
207
267
|
|
|
208
|
-
async
|
|
209
|
-
// This is a
|
|
268
|
+
async createAccount(secret: Fr) {
|
|
269
|
+
// This is a foot gun !
|
|
210
270
|
const completeAddress = await this.keyStore.addAccount(secret, secret);
|
|
211
|
-
await this.
|
|
212
|
-
await this.
|
|
271
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
272
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
213
273
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
214
274
|
|
|
215
275
|
return completeAddress;
|
|
216
276
|
}
|
|
217
277
|
|
|
218
|
-
async
|
|
219
|
-
const account = await this.
|
|
278
|
+
async addAuthWitness(address: AztecAddress, messageHash: Fr) {
|
|
279
|
+
const account = await this.accountStore.getAccount(address);
|
|
220
280
|
const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
|
|
221
281
|
|
|
222
282
|
const schnorr = new Schnorr();
|
|
@@ -228,7 +288,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
228
288
|
}
|
|
229
289
|
|
|
230
290
|
async mineBlock(options: { nullifiers?: Fr[] } = {}) {
|
|
231
|
-
const blockNumber = await this.
|
|
291
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
232
292
|
|
|
233
293
|
const txEffect = TxEffect.empty();
|
|
234
294
|
txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
|
|
@@ -237,19 +297,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
237
297
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
238
298
|
await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
|
|
239
299
|
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
version: this.version,
|
|
248
|
-
chainId: this.chainId,
|
|
249
|
-
}),
|
|
250
|
-
),
|
|
251
|
-
new Body([txEffect]),
|
|
252
|
-
);
|
|
300
|
+
const globals = makeGlobalVariables(undefined, {
|
|
301
|
+
blockNumber,
|
|
302
|
+
timestamp: this.nextBlockTimestamp,
|
|
303
|
+
version: this.version,
|
|
304
|
+
chainId: this.chainId,
|
|
305
|
+
});
|
|
306
|
+
const block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
253
307
|
|
|
254
308
|
await forkedWorldTrees.close();
|
|
255
309
|
|
|
@@ -258,19 +312,20 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
258
312
|
await this.stateMachine.handleL2Block(block);
|
|
259
313
|
}
|
|
260
314
|
|
|
261
|
-
async
|
|
315
|
+
async privateCallNewFlow(
|
|
262
316
|
from: AztecAddress,
|
|
263
317
|
targetContractAddress: AztecAddress = AztecAddress.zero(),
|
|
264
318
|
functionSelector: FunctionSelector = FunctionSelector.empty(),
|
|
265
319
|
args: Fr[],
|
|
266
320
|
argsHash: Fr = Fr.zero(),
|
|
267
321
|
isStaticCall: boolean = false,
|
|
322
|
+
jobId: string,
|
|
268
323
|
) {
|
|
269
324
|
this.logger.verbose(
|
|
270
|
-
`Executing external function ${await this.
|
|
325
|
+
`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
271
326
|
);
|
|
272
327
|
|
|
273
|
-
const artifact = await this.
|
|
328
|
+
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
274
329
|
if (!artifact) {
|
|
275
330
|
const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
|
|
276
331
|
? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
|
|
@@ -278,51 +333,79 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
278
333
|
throw new Error(message);
|
|
279
334
|
}
|
|
280
335
|
|
|
281
|
-
|
|
336
|
+
// When `from` is the zero address (e.g. when deploying a new account contract), we return an
|
|
337
|
+
// empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
|
|
338
|
+
const effectiveScopes = from.isZero() ? [] : [from];
|
|
282
339
|
|
|
283
|
-
|
|
340
|
+
// Sync notes before executing private function to discover notes from previous transactions
|
|
341
|
+
const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
|
|
342
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
346
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
347
|
+
targetContractAddress,
|
|
348
|
+
functionSelector,
|
|
349
|
+
utilityExecutor,
|
|
350
|
+
blockHeader,
|
|
351
|
+
jobId,
|
|
352
|
+
effectiveScopes,
|
|
353
|
+
);
|
|
284
354
|
|
|
285
|
-
const
|
|
355
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
286
356
|
|
|
287
|
-
const
|
|
357
|
+
const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
|
|
288
358
|
|
|
359
|
+
const gasLimits = new Gas(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, MAX_PROCESSABLE_L2_GAS);
|
|
360
|
+
const teardownGasLimits = new Gas(FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT);
|
|
289
361
|
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
290
362
|
|
|
291
363
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
292
364
|
|
|
293
|
-
const blockHeader = await this.pxeOracleInterface.getAnchorBlockHeader();
|
|
294
|
-
|
|
295
365
|
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
296
366
|
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
367
|
+
// In production, the account contract sets the min revertible counter before calling the app function.
|
|
368
|
+
// Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
|
|
369
|
+
// marking all side effects as revertible.
|
|
370
|
+
const minRevertibleSideEffectCounter = 1;
|
|
371
|
+
await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
297
372
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
298
373
|
|
|
299
374
|
const simulator = new WASMSimulator();
|
|
300
375
|
|
|
301
|
-
const privateExecutionOracle = new PrivateExecutionOracle(
|
|
376
|
+
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
302
377
|
argsHash,
|
|
303
378
|
txContext,
|
|
304
379
|
callContext,
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
[],
|
|
311
|
-
HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
380
|
+
anchorBlockHeader: blockHeader,
|
|
381
|
+
utilityExecutor,
|
|
382
|
+
authWitnesses: Array.from(this.authwits.values()),
|
|
383
|
+
capsules: [],
|
|
384
|
+
executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
312
385
|
noteCache,
|
|
313
386
|
taggingIndexCache,
|
|
314
|
-
this.
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
387
|
+
contractStore: this.contractStore,
|
|
388
|
+
noteStore: this.noteStore,
|
|
389
|
+
keyStore: this.keyStore,
|
|
390
|
+
addressStore: this.addressStore,
|
|
391
|
+
aztecNode: this.stateMachine.node,
|
|
392
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
393
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
394
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
395
|
+
capsuleService: new CapsuleService(this.capsuleStore, effectiveScopes),
|
|
396
|
+
privateEventStore: this.privateEventStore,
|
|
397
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
398
|
+
jobId,
|
|
399
|
+
totalPublicCalldataCount: 0,
|
|
400
|
+
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
401
|
+
scopes: effectiveScopes,
|
|
402
|
+
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
403
|
+
// contract would perform, including setting senderForTags.
|
|
404
|
+
senderForTags: from,
|
|
324
405
|
simulator,
|
|
325
|
-
|
|
406
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
407
|
+
l2TipsStore: this.stateMachine.node,
|
|
408
|
+
});
|
|
326
409
|
|
|
327
410
|
// 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
411
|
let result: PrivateExecutionResult;
|
|
@@ -344,24 +427,27 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
344
427
|
);
|
|
345
428
|
const publicFunctionsCalldata = await Promise.all(
|
|
346
429
|
publicCallRequests.map(async r => {
|
|
347
|
-
const calldata = await privateExecutionOracle.
|
|
430
|
+
const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
|
|
348
431
|
return new HashedValues(calldata, r.calldataHash);
|
|
349
432
|
}),
|
|
350
433
|
);
|
|
351
434
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
|
|
435
|
+
noteCache.finish();
|
|
436
|
+
const nonceGenerator = noteCache.getNonceGenerator();
|
|
437
|
+
result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
|
|
356
438
|
} catch (err) {
|
|
357
439
|
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
358
440
|
}
|
|
359
441
|
|
|
360
|
-
// According to the protocol rules,
|
|
361
|
-
//
|
|
362
|
-
//
|
|
363
|
-
const
|
|
364
|
-
|
|
442
|
+
// According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
|
|
443
|
+
// the nonce generator for the note hashes.
|
|
444
|
+
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
445
|
+
const { publicInputs } = await generateSimulatedProvingResult(
|
|
446
|
+
result,
|
|
447
|
+
(addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
|
|
448
|
+
this.stateMachine.node,
|
|
449
|
+
minRevertibleSideEffectCounter,
|
|
450
|
+
);
|
|
365
451
|
|
|
366
452
|
const globals = makeGlobalVariables();
|
|
367
453
|
globals.blockNumber = blockNumber;
|
|
@@ -372,7 +458,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
372
458
|
|
|
373
459
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
374
460
|
|
|
375
|
-
const
|
|
461
|
+
const bindings = this.logger.getBindings();
|
|
462
|
+
const contractsDB = new PublicContractsDB(
|
|
463
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
464
|
+
bindings,
|
|
465
|
+
);
|
|
376
466
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
377
467
|
const config = PublicSimulatorConfig.from({
|
|
378
468
|
skipFeeEnforcement: true,
|
|
@@ -385,8 +475,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
385
475
|
globals,
|
|
386
476
|
guardedMerkleTrees,
|
|
387
477
|
contractsDB,
|
|
388
|
-
new
|
|
478
|
+
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
|
|
389
479
|
new TestDateProvider(),
|
|
480
|
+
undefined,
|
|
481
|
+
createLogger('simulator:public-processor', bindings),
|
|
390
482
|
);
|
|
391
483
|
|
|
392
484
|
const tx = await Tx.create({
|
|
@@ -411,7 +503,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
411
503
|
} else if (!processedTx.revertCode.isOK()) {
|
|
412
504
|
if (processedTx.revertReason) {
|
|
413
505
|
try {
|
|
414
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.
|
|
506
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
415
507
|
// eslint-disable-next-line no-empty
|
|
416
508
|
} catch {}
|
|
417
509
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -420,11 +512,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
420
512
|
}
|
|
421
513
|
}
|
|
422
514
|
|
|
515
|
+
// Walk the nested private-call tree and collect every offchain effect the transaction emitted.
|
|
516
|
+
// PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
|
|
517
|
+
// `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
|
|
518
|
+
// we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
|
|
519
|
+
const offchainEffects = collectNested([executionResult], r => r.offchainEffects.map(e => e.data));
|
|
520
|
+
|
|
423
521
|
if (isStaticCall) {
|
|
424
522
|
await checkpoint!.revert();
|
|
425
523
|
|
|
426
524
|
await forkedWorldTrees.close();
|
|
427
|
-
return executionResult.returnValues ?? [];
|
|
525
|
+
return { returnValues: executionResult.returnValues ?? [], offchainEffects };
|
|
428
526
|
}
|
|
429
527
|
|
|
430
528
|
const txEffect = TxEffect.empty();
|
|
@@ -440,42 +538,36 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
440
538
|
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
441
539
|
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
442
540
|
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
const l2Block = new L2Block(
|
|
446
|
-
makeAppendOnlyTreeSnapshot(),
|
|
447
|
-
await makeTXEBlockHeader(forkedWorldTrees, globals),
|
|
448
|
-
body,
|
|
449
|
-
);
|
|
541
|
+
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
450
542
|
|
|
451
543
|
await this.stateMachine.handleL2Block(l2Block);
|
|
452
544
|
|
|
453
545
|
await forkedWorldTrees.close();
|
|
454
546
|
|
|
455
|
-
return executionResult.returnValues ?? [];
|
|
547
|
+
return { returnValues: executionResult.returnValues ?? [], offchainEffects };
|
|
456
548
|
}
|
|
457
549
|
|
|
458
|
-
async
|
|
550
|
+
async publicCallNewFlow(
|
|
459
551
|
from: AztecAddress,
|
|
460
552
|
targetContractAddress: AztecAddress,
|
|
461
553
|
calldata: Fr[],
|
|
462
554
|
isStaticCall: boolean,
|
|
463
555
|
) {
|
|
464
556
|
this.logger.verbose(
|
|
465
|
-
`Executing public function ${await this.
|
|
557
|
+
`Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
466
558
|
);
|
|
467
559
|
|
|
468
|
-
const blockNumber = await this.
|
|
560
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
469
561
|
|
|
470
|
-
const gasLimits = new Gas(
|
|
562
|
+
const gasLimits = new Gas(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, MAX_PROCESSABLE_L2_GAS);
|
|
471
563
|
|
|
472
|
-
const teardownGasLimits = new Gas(
|
|
564
|
+
const teardownGasLimits = new Gas(FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT);
|
|
473
565
|
|
|
474
566
|
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
475
567
|
|
|
476
568
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
477
569
|
|
|
478
|
-
const anchorBlockHeader = await this.
|
|
570
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
479
571
|
|
|
480
572
|
const calldataHash = await computeCalldataHash(calldata);
|
|
481
573
|
const calldataHashedValues = new HashedValues(calldata, calldataHash);
|
|
@@ -489,7 +581,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
489
581
|
|
|
490
582
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
491
583
|
|
|
492
|
-
const
|
|
584
|
+
const bindings2 = this.logger.getBindings();
|
|
585
|
+
const contractsDB = new PublicContractsDB(
|
|
586
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
587
|
+
bindings2,
|
|
588
|
+
);
|
|
493
589
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
494
590
|
const config = PublicSimulatorConfig.from({
|
|
495
591
|
skipFeeEnforcement: true,
|
|
@@ -498,17 +594,23 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
498
594
|
collectStatistics: false,
|
|
499
595
|
collectCallMetadata: true,
|
|
500
596
|
});
|
|
501
|
-
const simulator = new
|
|
502
|
-
const processor = new PublicProcessor(
|
|
597
|
+
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
|
|
598
|
+
const processor = new PublicProcessor(
|
|
599
|
+
globals,
|
|
600
|
+
guardedMerkleTrees,
|
|
601
|
+
contractsDB,
|
|
602
|
+
simulator,
|
|
603
|
+
new TestDateProvider(),
|
|
604
|
+
undefined,
|
|
605
|
+
createLogger('simulator:public-processor', bindings2),
|
|
606
|
+
);
|
|
503
607
|
|
|
504
608
|
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
505
609
|
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
506
610
|
// side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
|
|
507
611
|
// unique.
|
|
508
612
|
const nonRevertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
509
|
-
|
|
510
|
-
nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
|
|
511
|
-
}
|
|
613
|
+
nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
|
|
512
614
|
|
|
513
615
|
// The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
|
|
514
616
|
// may require producing reverts.
|
|
@@ -532,7 +634,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
532
634
|
constantData,
|
|
533
635
|
/*gasUsed=*/ new Gas(0, 0),
|
|
534
636
|
/*feePayer=*/ AztecAddress.zero(),
|
|
535
|
-
/*
|
|
637
|
+
/*expirationTimestamp=*/ 0n,
|
|
536
638
|
inputsForPublic,
|
|
537
639
|
undefined,
|
|
538
640
|
);
|
|
@@ -559,7 +661,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
559
661
|
} else if (!processedTx.revertCode.isOK()) {
|
|
560
662
|
if (processedTx.revertReason) {
|
|
561
663
|
try {
|
|
562
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.
|
|
664
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
563
665
|
// eslint-disable-next-line no-empty
|
|
564
666
|
} catch {}
|
|
565
667
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -591,13 +693,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
591
693
|
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
592
694
|
await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
593
695
|
|
|
594
|
-
const
|
|
595
|
-
|
|
596
|
-
const l2Block = new L2Block(
|
|
597
|
-
makeAppendOnlyTreeSnapshot(),
|
|
598
|
-
await makeTXEBlockHeader(forkedWorldTrees, globals),
|
|
599
|
-
body,
|
|
600
|
-
);
|
|
696
|
+
const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
|
|
601
697
|
|
|
602
698
|
await this.stateMachine.handleL2Block(l2Block);
|
|
603
699
|
|
|
@@ -606,23 +702,46 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
606
702
|
return returnValues ?? [];
|
|
607
703
|
}
|
|
608
704
|
|
|
609
|
-
async
|
|
705
|
+
async executeUtilityFunction(
|
|
610
706
|
targetContractAddress: AztecAddress,
|
|
611
707
|
functionSelector: FunctionSelector,
|
|
612
708
|
args: Fr[],
|
|
709
|
+
jobId: string,
|
|
613
710
|
) {
|
|
614
|
-
const artifact = await this.
|
|
711
|
+
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
615
712
|
if (!artifact) {
|
|
616
713
|
throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
|
|
617
714
|
}
|
|
618
715
|
|
|
619
|
-
|
|
716
|
+
// Sync notes before executing utility function to discover notes from previous transactions
|
|
717
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
718
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
719
|
+
targetContractAddress,
|
|
720
|
+
functionSelector,
|
|
721
|
+
async (call, execScopes) => {
|
|
722
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
723
|
+
},
|
|
724
|
+
blockHeader,
|
|
725
|
+
jobId,
|
|
726
|
+
await this.keyStore.getAccounts(),
|
|
727
|
+
);
|
|
728
|
+
|
|
729
|
+
const call = FunctionCall.from({
|
|
620
730
|
name: artifact.name,
|
|
621
|
-
selector: functionSelector,
|
|
622
731
|
to: targetContractAddress,
|
|
623
|
-
|
|
732
|
+
selector: functionSelector,
|
|
733
|
+
type: FunctionType.UTILITY,
|
|
734
|
+
hideMsgSender: false,
|
|
735
|
+
isStatic: false,
|
|
736
|
+
args,
|
|
737
|
+
returnTypes: [],
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
return this.executeUtilityCall(call, await this.keyStore.getAccounts(), jobId);
|
|
741
|
+
}
|
|
624
742
|
|
|
625
|
-
|
|
743
|
+
private async executeUtilityCall(call: FunctionCall, scopes: AztecAddress[], jobId: string): Promise<Fr[]> {
|
|
744
|
+
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
626
745
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
627
746
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
628
747
|
}
|
|
@@ -633,9 +752,29 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
633
752
|
});
|
|
634
753
|
|
|
635
754
|
try {
|
|
636
|
-
const
|
|
755
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
756
|
+
const oracle = new UtilityExecutionOracle({
|
|
757
|
+
contractAddress: call.to,
|
|
758
|
+
authWitnesses: [],
|
|
759
|
+
capsules: [],
|
|
760
|
+
anchorBlockHeader,
|
|
761
|
+
contractStore: this.contractStore,
|
|
762
|
+
noteStore: this.noteStore,
|
|
763
|
+
keyStore: this.keyStore,
|
|
764
|
+
addressStore: this.addressStore,
|
|
765
|
+
aztecNode: this.stateMachine.node,
|
|
766
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
767
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
768
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
769
|
+
privateEventStore: this.privateEventStore,
|
|
770
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
771
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
772
|
+
l2TipsStore: this.stateMachine.node,
|
|
773
|
+
jobId,
|
|
774
|
+
scopes,
|
|
775
|
+
});
|
|
637
776
|
const acirExecutionResult = await new WASMSimulator()
|
|
638
|
-
.executeUserCircuit(toACVMWitness(0, args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
777
|
+
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
639
778
|
.catch((err: Error) => {
|
|
640
779
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
641
780
|
throw new ExecutionError(
|
|
@@ -649,10 +788,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
649
788
|
);
|
|
650
789
|
});
|
|
651
790
|
|
|
652
|
-
this.logger.verbose(`Utility
|
|
791
|
+
this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
|
|
653
792
|
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
654
793
|
} catch (err) {
|
|
655
|
-
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility
|
|
794
|
+
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
|
|
656
795
|
}
|
|
657
796
|
}
|
|
658
797
|
|
|
@@ -661,7 +800,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
661
800
|
return [this.nextBlockTimestamp, this.authwits];
|
|
662
801
|
}
|
|
663
802
|
|
|
664
|
-
private async getLastBlockNumber(): Promise<
|
|
665
|
-
|
|
803
|
+
private async getLastBlockNumber(): Promise<BlockNumber> {
|
|
804
|
+
const header = await this.stateMachine.node.getBlockHeader('latest');
|
|
805
|
+
return header ? header.globalVariables.blockNumber : BlockNumber.ZERO;
|
|
666
806
|
}
|
|
667
807
|
}
|