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