@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
package/src/txe_session.ts
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
3
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
3
4
|
import { KeyStore } from '@aztec/key-store';
|
|
4
5
|
import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
|
|
5
|
-
import type {
|
|
6
|
+
import type { AccessScopes } from '@aztec/pxe/client/lazy';
|
|
6
7
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
AddressStore,
|
|
9
|
+
AnchorBlockStore,
|
|
10
|
+
CapsuleStore,
|
|
11
|
+
ContractStore,
|
|
12
|
+
ContractSyncService,
|
|
13
|
+
JobCoordinator,
|
|
14
|
+
NoteService,
|
|
15
|
+
NoteStore,
|
|
16
|
+
PrivateEventStore,
|
|
17
|
+
RecipientTaggingStore,
|
|
18
|
+
SenderAddressBookStore,
|
|
19
|
+
SenderTaggingStore,
|
|
13
20
|
} from '@aztec/pxe/server';
|
|
14
21
|
import {
|
|
15
22
|
ExecutionNoteCache,
|
|
@@ -17,34 +24,39 @@ import {
|
|
|
17
24
|
HashedValuesCache,
|
|
18
25
|
type IPrivateExecutionOracle,
|
|
19
26
|
type IUtilityExecutionOracle,
|
|
27
|
+
Oracle,
|
|
20
28
|
PrivateExecutionOracle,
|
|
21
29
|
UtilityExecutionOracle,
|
|
22
30
|
} from '@aztec/pxe/simulator';
|
|
23
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
ExecutionError,
|
|
33
|
+
WASMSimulator,
|
|
34
|
+
createSimulationError,
|
|
35
|
+
extractCallStack,
|
|
36
|
+
resolveAssertionMessageFromError,
|
|
37
|
+
toACVMWitness,
|
|
38
|
+
} from '@aztec/simulator/client';
|
|
39
|
+
import { FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
24
40
|
import type { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
25
41
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
26
|
-
import { Body, L2Block } from '@aztec/stdlib/block';
|
|
27
42
|
import { GasSettings } from '@aztec/stdlib/gas';
|
|
43
|
+
import { computeProtocolNullifier } from '@aztec/stdlib/hash';
|
|
28
44
|
import { PrivateContextInputs } from '@aztec/stdlib/kernel';
|
|
29
|
-
import {
|
|
45
|
+
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
30
46
|
import { CallContext, GlobalVariables, TxContext } from '@aztec/stdlib/tx';
|
|
31
|
-
import type { UInt32 } from '@aztec/stdlib/types';
|
|
32
47
|
|
|
33
48
|
import { z } from 'zod';
|
|
34
49
|
|
|
50
|
+
import { DEFAULT_ADDRESS } from './constants.js';
|
|
35
51
|
import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
|
|
36
52
|
import { TXEOraclePublicContext } from './oracle/txe_oracle_public_context.js';
|
|
37
53
|
import { TXEOracleTopLevelContext } from './oracle/txe_oracle_top_level_context.js';
|
|
38
54
|
import { RPCTranslator } from './rpc_translator.js';
|
|
55
|
+
import { TXEArchiver } from './state_machine/archiver.js';
|
|
39
56
|
import { TXEStateMachine } from './state_machine/index.js';
|
|
40
57
|
import type { ForeignCallArgs, ForeignCallResult } from './util/encoding.js';
|
|
41
|
-
import {
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
44
|
-
getSingleTxBlockRequestHash,
|
|
45
|
-
insertTxEffectIntoWorldTrees,
|
|
46
|
-
makeTXEBlockHeader,
|
|
47
|
-
} from './utils/block_creation.js';
|
|
58
|
+
import { TXEAccountStore } from './util/txe_account_store.js';
|
|
59
|
+
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from './utils/block_creation.js';
|
|
48
60
|
import { makeTxEffect } from './utils/tx_effect_creation.js';
|
|
49
61
|
|
|
50
62
|
/**
|
|
@@ -66,7 +78,6 @@ type SessionState =
|
|
|
66
78
|
| {
|
|
67
79
|
name: 'PRIVATE';
|
|
68
80
|
nextBlockGlobalVariables: GlobalVariables;
|
|
69
|
-
txRequestHash: Fr;
|
|
70
81
|
noteCache: ExecutionNoteCache;
|
|
71
82
|
taggingIndexCache: ExecutionTaggingIndexCache;
|
|
72
83
|
}
|
|
@@ -101,11 +112,13 @@ export type TXEOracleFunctionName = Exclude<
|
|
|
101
112
|
export interface TXESessionStateHandler {
|
|
102
113
|
enterTopLevelState(): Promise<void>;
|
|
103
114
|
enterPublicState(contractAddress?: AztecAddress): Promise<void>;
|
|
104
|
-
enterPrivateState(contractAddress?: AztecAddress, anchorBlockNumber?:
|
|
115
|
+
enterPrivateState(contractAddress?: AztecAddress, anchorBlockNumber?: BlockNumber): Promise<PrivateContextInputs>;
|
|
105
116
|
enterUtilityState(contractAddress?: AztecAddress): Promise<void>;
|
|
106
|
-
}
|
|
107
117
|
|
|
108
|
-
|
|
118
|
+
// TODO(F-335): Exposing the job info is abstraction breakage - drop the following 2 functions.
|
|
119
|
+
cycleJob(): Promise<string>;
|
|
120
|
+
getCurrentJob(): string;
|
|
121
|
+
}
|
|
109
122
|
|
|
110
123
|
/**
|
|
111
124
|
* A `TXESession` corresponds to a Noir `#[test]` function, and handles all of its oracle calls, stores test-specific
|
|
@@ -123,78 +136,100 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
123
136
|
| IPrivateExecutionOracle
|
|
124
137
|
| IAvmExecutionOracle
|
|
125
138
|
| ITxeExecutionOracle,
|
|
126
|
-
private
|
|
139
|
+
private contractStore: ContractStore,
|
|
140
|
+
private noteStore: NoteStore,
|
|
127
141
|
private keyStore: KeyStore,
|
|
128
|
-
private
|
|
129
|
-
private
|
|
142
|
+
private addressStore: AddressStore,
|
|
143
|
+
private accountStore: TXEAccountStore,
|
|
144
|
+
private senderTaggingStore: SenderTaggingStore,
|
|
145
|
+
private recipientTaggingStore: RecipientTaggingStore,
|
|
146
|
+
private senderAddressBookStore: SenderAddressBookStore,
|
|
147
|
+
private capsuleStore: CapsuleStore,
|
|
148
|
+
private privateEventStore: PrivateEventStore,
|
|
149
|
+
private jobCoordinator: JobCoordinator,
|
|
150
|
+
private currentJobId: string,
|
|
130
151
|
private chainId: Fr,
|
|
131
152
|
private version: Fr,
|
|
132
153
|
private nextBlockTimestamp: bigint,
|
|
133
|
-
private
|
|
154
|
+
private contractSyncService: ContractSyncService,
|
|
134
155
|
) {}
|
|
135
156
|
|
|
136
|
-
static async init(
|
|
157
|
+
static async init(contractStore: ContractStore) {
|
|
137
158
|
const store = await openTmpStore('txe-session');
|
|
138
159
|
|
|
139
|
-
const
|
|
140
|
-
const
|
|
141
|
-
const
|
|
142
|
-
const
|
|
143
|
-
const
|
|
144
|
-
const
|
|
160
|
+
const addressStore = new AddressStore(store);
|
|
161
|
+
const privateEventStore = new PrivateEventStore(store);
|
|
162
|
+
const noteStore = new NoteStore(store);
|
|
163
|
+
const senderTaggingStore = new SenderTaggingStore(store);
|
|
164
|
+
const recipientTaggingStore = new RecipientTaggingStore(store);
|
|
165
|
+
const senderAddressBookStore = new SenderAddressBookStore(store);
|
|
166
|
+
const capsuleStore = new CapsuleStore(store);
|
|
145
167
|
const keyStore = new KeyStore(store);
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
//
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
168
|
+
const accountStore = new TXEAccountStore(store);
|
|
169
|
+
|
|
170
|
+
// Create job coordinator and register staged stores
|
|
171
|
+
const jobCoordinator = new JobCoordinator(store);
|
|
172
|
+
jobCoordinator.registerStores([
|
|
173
|
+
capsuleStore,
|
|
174
|
+
senderTaggingStore,
|
|
175
|
+
recipientTaggingStore,
|
|
176
|
+
privateEventStore,
|
|
177
|
+
noteStore,
|
|
178
|
+
]);
|
|
179
|
+
|
|
180
|
+
const archiver = new TXEArchiver(store);
|
|
181
|
+
const anchorBlockStore = new AnchorBlockStore(store);
|
|
182
|
+
const stateMachine = await TXEStateMachine.create(archiver, anchorBlockStore, contractStore, noteStore);
|
|
155
183
|
|
|
156
184
|
const nextBlockTimestamp = BigInt(Math.floor(new Date().getTime() / 1000));
|
|
157
185
|
const version = new Fr(await stateMachine.node.getVersion());
|
|
158
186
|
const chainId = new Fr(await stateMachine.node.getChainId());
|
|
159
187
|
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
noteDataProvider,
|
|
165
|
-
capsuleDataProvider,
|
|
166
|
-
stateMachine.syncDataProvider,
|
|
167
|
-
taggingDataProvider,
|
|
168
|
-
addressDataProvider,
|
|
169
|
-
privateEventDataProvider,
|
|
170
|
-
);
|
|
188
|
+
const initialJobId = jobCoordinator.beginJob();
|
|
189
|
+
|
|
190
|
+
const logger = createLogger('txe:session');
|
|
191
|
+
const contractSyncService = new ContractSyncService(stateMachine.node, contractStore, noteStore, logger);
|
|
171
192
|
|
|
172
193
|
const topLevelOracleHandler = new TXEOracleTopLevelContext(
|
|
173
194
|
stateMachine,
|
|
174
|
-
|
|
195
|
+
contractStore,
|
|
196
|
+
noteStore,
|
|
175
197
|
keyStore,
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
198
|
+
addressStore,
|
|
199
|
+
accountStore,
|
|
200
|
+
senderTaggingStore,
|
|
201
|
+
recipientTaggingStore,
|
|
202
|
+
senderAddressBookStore,
|
|
203
|
+
capsuleStore,
|
|
204
|
+
privateEventStore,
|
|
179
205
|
nextBlockTimestamp,
|
|
180
206
|
version,
|
|
181
207
|
chainId,
|
|
182
208
|
new Map(),
|
|
209
|
+
contractSyncService,
|
|
183
210
|
);
|
|
184
|
-
await topLevelOracleHandler.
|
|
211
|
+
await topLevelOracleHandler.advanceBlocksBy(1);
|
|
185
212
|
|
|
186
213
|
return new TXESession(
|
|
187
|
-
|
|
214
|
+
logger,
|
|
188
215
|
stateMachine,
|
|
189
216
|
topLevelOracleHandler,
|
|
190
|
-
|
|
217
|
+
contractStore,
|
|
218
|
+
noteStore,
|
|
191
219
|
keyStore,
|
|
192
|
-
|
|
193
|
-
|
|
220
|
+
addressStore,
|
|
221
|
+
accountStore,
|
|
222
|
+
senderTaggingStore,
|
|
223
|
+
recipientTaggingStore,
|
|
224
|
+
senderAddressBookStore,
|
|
225
|
+
capsuleStore,
|
|
226
|
+
privateEventStore,
|
|
227
|
+
jobCoordinator,
|
|
228
|
+
initialJobId,
|
|
194
229
|
version,
|
|
195
230
|
chainId,
|
|
196
231
|
nextBlockTimestamp,
|
|
197
|
-
|
|
232
|
+
contractSyncService,
|
|
198
233
|
);
|
|
199
234
|
}
|
|
200
235
|
|
|
@@ -229,6 +264,17 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
229
264
|
}
|
|
230
265
|
}
|
|
231
266
|
|
|
267
|
+
getCurrentJob(): string {
|
|
268
|
+
return this.currentJobId;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/** Commits the current job and begins a new one. Returns the new job ID. */
|
|
272
|
+
async cycleJob(): Promise<string> {
|
|
273
|
+
await this.jobCoordinator.commitJob(this.currentJobId);
|
|
274
|
+
this.currentJobId = this.jobCoordinator.beginJob();
|
|
275
|
+
return this.currentJobId;
|
|
276
|
+
}
|
|
277
|
+
|
|
232
278
|
async enterTopLevelState() {
|
|
233
279
|
switch (this.state.name) {
|
|
234
280
|
case 'PRIVATE': {
|
|
@@ -251,17 +297,26 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
251
297
|
}
|
|
252
298
|
}
|
|
253
299
|
|
|
300
|
+
// Commit all staged stores from the job that was just completed, then begin a new job
|
|
301
|
+
await this.cycleJob();
|
|
302
|
+
|
|
254
303
|
this.oracleHandler = new TXEOracleTopLevelContext(
|
|
255
304
|
this.stateMachine,
|
|
256
|
-
this.
|
|
305
|
+
this.contractStore,
|
|
306
|
+
this.noteStore,
|
|
257
307
|
this.keyStore,
|
|
258
|
-
this.
|
|
259
|
-
this.
|
|
260
|
-
this.
|
|
308
|
+
this.addressStore,
|
|
309
|
+
this.accountStore,
|
|
310
|
+
this.senderTaggingStore,
|
|
311
|
+
this.recipientTaggingStore,
|
|
312
|
+
this.senderAddressBookStore,
|
|
313
|
+
this.capsuleStore,
|
|
314
|
+
this.privateEventStore,
|
|
261
315
|
this.nextBlockTimestamp,
|
|
262
316
|
this.version,
|
|
263
317
|
this.chainId,
|
|
264
318
|
this.authwits,
|
|
319
|
+
this.contractSyncService,
|
|
265
320
|
);
|
|
266
321
|
|
|
267
322
|
this.state = { name: 'TOP_LEVEL' };
|
|
@@ -270,53 +325,67 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
270
325
|
|
|
271
326
|
async enterPrivateState(
|
|
272
327
|
contractAddress: AztecAddress = DEFAULT_ADDRESS,
|
|
273
|
-
anchorBlockNumber?:
|
|
328
|
+
anchorBlockNumber?: BlockNumber,
|
|
274
329
|
): Promise<PrivateContextInputs> {
|
|
275
330
|
this.exitTopLevelState();
|
|
276
331
|
|
|
277
|
-
// There is no automatic message discovery and contract-driven syncing process in inlined private or utility
|
|
278
|
-
// contexts, which means that known nullifiers are also not searched for, since it is during the tagging sync that
|
|
279
|
-
// we perform this. We therefore search for known nullifiers now, as otherwise notes that were nullified would not
|
|
280
|
-
// be removed from the database.
|
|
281
|
-
// TODO(#12553): make the synchronizer sync here instead and remove this
|
|
282
|
-
await this.pxeOracleInterface.syncNoteNullifiers(contractAddress);
|
|
283
|
-
|
|
284
332
|
// Private execution has two associated block numbers: the anchor block (i.e. the historical block that is used to
|
|
285
333
|
// build the proof), and the *next* block, i.e. the one we'll create once the execution ends, and which will contain
|
|
286
334
|
// a single transaction with the effects of what was done in the test.
|
|
287
335
|
const anchorBlock = await this.stateMachine.node.getBlockHeader(anchorBlockNumber ?? 'latest');
|
|
336
|
+
|
|
337
|
+
await new NoteService(this.noteStore, this.stateMachine.node, anchorBlock!, this.currentJobId).syncNoteNullifiers(
|
|
338
|
+
contractAddress,
|
|
339
|
+
'ALL_SCOPES',
|
|
340
|
+
);
|
|
288
341
|
const latestBlock = await this.stateMachine.node.getBlockHeader('latest');
|
|
289
342
|
|
|
290
343
|
const nextBlockGlobalVariables = makeGlobalVariables(undefined, {
|
|
291
|
-
blockNumber: latestBlock!.globalVariables.blockNumber + 1,
|
|
344
|
+
blockNumber: BlockNumber(latestBlock!.globalVariables.blockNumber + 1),
|
|
292
345
|
timestamp: this.nextBlockTimestamp,
|
|
293
346
|
version: this.version,
|
|
294
347
|
chainId: this.chainId,
|
|
295
348
|
});
|
|
296
349
|
|
|
297
350
|
const txRequestHash = getSingleTxBlockRequestHash(nextBlockGlobalVariables.blockNumber);
|
|
298
|
-
const
|
|
351
|
+
const protocolNullifier = await computeProtocolNullifier(txRequestHash);
|
|
352
|
+
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
299
353
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
300
354
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
new
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
355
|
+
const utilityExecutor = this.utilityExecutorForContractSync(anchorBlock);
|
|
356
|
+
this.oracleHandler = new PrivateExecutionOracle({
|
|
357
|
+
argsHash: Fr.ZERO,
|
|
358
|
+
txContext: new TxContext(this.chainId, this.version, GasSettings.empty()),
|
|
359
|
+
callContext: new CallContext(AztecAddress.ZERO, contractAddress, FunctionSelector.empty(), false),
|
|
360
|
+
anchorBlockHeader: anchorBlock!,
|
|
361
|
+
utilityExecutor,
|
|
362
|
+
authWitnesses: [],
|
|
363
|
+
capsules: [],
|
|
364
|
+
executionCache: new HashedValuesCache(),
|
|
309
365
|
noteCache,
|
|
310
366
|
taggingIndexCache,
|
|
311
|
-
this.
|
|
312
|
-
|
|
367
|
+
contractStore: this.contractStore,
|
|
368
|
+
noteStore: this.noteStore,
|
|
369
|
+
keyStore: this.keyStore,
|
|
370
|
+
addressStore: this.addressStore,
|
|
371
|
+
aztecNode: this.stateMachine.node,
|
|
372
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
373
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
374
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
375
|
+
capsuleStore: this.capsuleStore,
|
|
376
|
+
privateEventStore: this.privateEventStore,
|
|
377
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
378
|
+
jobId: this.currentJobId,
|
|
379
|
+
scopes: 'ALL_SCOPES',
|
|
380
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
381
|
+
});
|
|
313
382
|
|
|
314
383
|
// We store the note and tagging index caches fed into the PrivateExecutionOracle (along with some other auxiliary
|
|
315
384
|
// data) in order to refer to it later, mimicking the way this object is used by the ContractFunctionSimulator. The
|
|
316
385
|
// difference resides in that the simulator has all information needed in order to run the simulation, while ours
|
|
317
386
|
// will be ongoing as the different oracles will be invoked from the Noir test, until eventually the private
|
|
318
387
|
// execution finishes.
|
|
319
|
-
this.state = { name: 'PRIVATE', nextBlockGlobalVariables,
|
|
388
|
+
this.state = { name: 'PRIVATE', nextBlockGlobalVariables, noteCache, taggingIndexCache };
|
|
320
389
|
this.logger.debug(`Entered state ${this.state.name}`);
|
|
321
390
|
|
|
322
391
|
return (this.oracleHandler as PrivateExecutionOracle).getPrivateContextInputs();
|
|
@@ -329,7 +398,7 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
329
398
|
// the test. The block therefore gets the *next* block number and timestamp.
|
|
330
399
|
const latestBlockNumber = (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.blockNumber;
|
|
331
400
|
const globalVariables = makeGlobalVariables(undefined, {
|
|
332
|
-
blockNumber: latestBlockNumber + 1,
|
|
401
|
+
blockNumber: BlockNumber(latestBlockNumber + 1),
|
|
333
402
|
timestamp: this.nextBlockTimestamp,
|
|
334
403
|
version: this.version,
|
|
335
404
|
chainId: this.chainId,
|
|
@@ -349,14 +418,39 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
349
418
|
async enterUtilityState(contractAddress: AztecAddress = DEFAULT_ADDRESS) {
|
|
350
419
|
this.exitTopLevelState();
|
|
351
420
|
|
|
421
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
422
|
+
|
|
352
423
|
// There is no automatic message discovery and contract-driven syncing process in inlined private or utility
|
|
353
424
|
// contexts, which means that known nullifiers are also not searched for, since it is during the tagging sync that
|
|
354
425
|
// we perform this. We therefore search for known nullifiers now, as otherwise notes that were nullified would not
|
|
355
426
|
// be removed from the database.
|
|
356
427
|
// TODO(#12553): make the synchronizer sync here instead and remove this
|
|
357
|
-
await
|
|
358
|
-
|
|
359
|
-
|
|
428
|
+
await new NoteService(
|
|
429
|
+
this.noteStore,
|
|
430
|
+
this.stateMachine.node,
|
|
431
|
+
anchorBlockHeader,
|
|
432
|
+
this.currentJobId,
|
|
433
|
+
).syncNoteNullifiers(contractAddress, 'ALL_SCOPES');
|
|
434
|
+
|
|
435
|
+
this.oracleHandler = new UtilityExecutionOracle({
|
|
436
|
+
contractAddress,
|
|
437
|
+
authWitnesses: [],
|
|
438
|
+
capsules: [],
|
|
439
|
+
anchorBlockHeader,
|
|
440
|
+
contractStore: this.contractStore,
|
|
441
|
+
noteStore: this.noteStore,
|
|
442
|
+
keyStore: this.keyStore,
|
|
443
|
+
addressStore: this.addressStore,
|
|
444
|
+
aztecNode: this.stateMachine.node,
|
|
445
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
446
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
447
|
+
capsuleStore: this.capsuleStore,
|
|
448
|
+
privateEventStore: this.privateEventStore,
|
|
449
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
450
|
+
contractSyncService: this.contractSyncService,
|
|
451
|
+
jobId: this.currentJobId,
|
|
452
|
+
scopes: 'ALL_SCOPES',
|
|
453
|
+
});
|
|
360
454
|
|
|
361
455
|
this.state = { name: 'UTILITY' };
|
|
362
456
|
this.logger.debug(`Entered state ${this.state.name}`);
|
|
@@ -369,8 +463,8 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
369
463
|
|
|
370
464
|
// Note that while all public and private contexts do is build a single block that we then process when exiting
|
|
371
465
|
// those, the top level context performs a large number of actions not captured in the following 'close' call. Among
|
|
372
|
-
// others, it will create empty blocks (via `
|
|
373
|
-
// `
|
|
466
|
+
// others, it will create empty blocks (via `advanceBlocksBy` and `deploy`), create blocks with transactions via
|
|
467
|
+
// `privateCallNewFlow` and `publicCallNewFlow`, add accounts to PXE via `addAccount`, etc. This is a
|
|
374
468
|
// slight inconsistency in the working model of this class, but is not too bad.
|
|
375
469
|
// TODO: it's quite unfortunate that we need to capture the authwits created to later pass them again when the top
|
|
376
470
|
// level context is re-created. This is because authwits create a temporary utility context that'd otherwise reset
|
|
@@ -390,21 +484,14 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
390
484
|
|
|
391
485
|
// We rely on the note cache to determine the effects of the transaction. This is incomplete as it doesn't private
|
|
392
486
|
// logs (other effects like enqueued public calls don't need to be considered since those are not allowed).
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
this.state.txRequestHash,
|
|
396
|
-
this.state.nextBlockGlobalVariables.blockNumber,
|
|
397
|
-
);
|
|
487
|
+
|
|
488
|
+
const txEffect = await makeTxEffect(this.state.noteCache, this.state.nextBlockGlobalVariables.blockNumber);
|
|
398
489
|
|
|
399
490
|
// We build a block holding just this transaction
|
|
400
491
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
401
492
|
await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
|
|
402
493
|
|
|
403
|
-
const block =
|
|
404
|
-
makeAppendOnlyTreeSnapshot(),
|
|
405
|
-
await makeTXEBlockHeader(forkedWorldTrees, this.state.nextBlockGlobalVariables),
|
|
406
|
-
new Body([txEffect]),
|
|
407
|
-
);
|
|
494
|
+
const block = await makeTXEBlock(forkedWorldTrees, this.state.nextBlockGlobalVariables, [txEffect]);
|
|
408
495
|
await this.stateMachine.handleL2Block(block);
|
|
409
496
|
|
|
410
497
|
await forkedWorldTrees.close();
|
|
@@ -429,4 +516,51 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
429
516
|
throw new Error(`Expected to be in state 'UTILITY', but got '${this.state.name}' instead`);
|
|
430
517
|
}
|
|
431
518
|
}
|
|
519
|
+
|
|
520
|
+
private utilityExecutorForContractSync(anchorBlock: any) {
|
|
521
|
+
return async (call: FunctionCall, scopes: AccessScopes) => {
|
|
522
|
+
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
523
|
+
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
524
|
+
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
try {
|
|
528
|
+
const oracle = new UtilityExecutionOracle({
|
|
529
|
+
contractAddress: call.to,
|
|
530
|
+
authWitnesses: [],
|
|
531
|
+
capsules: [],
|
|
532
|
+
anchorBlockHeader: anchorBlock!,
|
|
533
|
+
contractStore: this.contractStore,
|
|
534
|
+
noteStore: this.noteStore,
|
|
535
|
+
keyStore: this.keyStore,
|
|
536
|
+
addressStore: this.addressStore,
|
|
537
|
+
aztecNode: this.stateMachine.node,
|
|
538
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
539
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
540
|
+
capsuleStore: this.capsuleStore,
|
|
541
|
+
privateEventStore: this.privateEventStore,
|
|
542
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
543
|
+
contractSyncService: this.contractSyncService,
|
|
544
|
+
jobId: this.currentJobId,
|
|
545
|
+
scopes,
|
|
546
|
+
});
|
|
547
|
+
await new WASMSimulator()
|
|
548
|
+
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
549
|
+
.catch((err: Error) => {
|
|
550
|
+
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
551
|
+
throw new ExecutionError(
|
|
552
|
+
err.message,
|
|
553
|
+
{
|
|
554
|
+
contractAddress: call.to,
|
|
555
|
+
functionSelector: call.selector,
|
|
556
|
+
},
|
|
557
|
+
extractCallStack(err, entryPointArtifact.debug),
|
|
558
|
+
{ cause: err },
|
|
559
|
+
);
|
|
560
|
+
});
|
|
561
|
+
} catch (err) {
|
|
562
|
+
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error contract data sync'));
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
}
|
|
432
566
|
}
|
package/src/util/encoding.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
1
2
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
3
3
|
import { hexToBuffer } from '@aztec/foundation/string';
|
|
4
4
|
import { type ContractArtifact, ContractArtifactSchema } from '@aztec/stdlib/abi';
|
|
5
5
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
@@ -2,7 +2,7 @@ import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
|
2
2
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
3
3
|
import { CompleteAddress } from '@aztec/stdlib/contract';
|
|
4
4
|
|
|
5
|
-
export class
|
|
5
|
+
export class TXEAccountStore {
|
|
6
6
|
#accounts: AztecAsyncMap<string, Buffer>;
|
|
7
7
|
|
|
8
8
|
constructor(store: AztecAsyncKVStore) {
|
|
@@ -1,68 +1,43 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
|
+
import type { ContractStore } from '@aztec/pxe/server';
|
|
4
|
+
import { type ContractArtifact, FunctionSelector } from '@aztec/stdlib/abi';
|
|
4
5
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
5
|
-
import {
|
|
6
|
-
type ContractClassPublic,
|
|
7
|
-
type ContractDataSource,
|
|
8
|
-
type ContractInstanceWithAddress,
|
|
9
|
-
computePrivateFunctionsRoot,
|
|
10
|
-
computePublicBytecodeCommitment,
|
|
11
|
-
getContractClassPrivateFunctionFromArtifact,
|
|
12
|
-
} from '@aztec/stdlib/contract';
|
|
6
|
+
import type { ContractClassPublic, ContractDataSource, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
|
|
13
7
|
|
|
14
8
|
export class TXEPublicContractDataSource implements ContractDataSource {
|
|
15
|
-
#privateFunctionsRoot: Map<string, Buffer> = new Map();
|
|
16
9
|
constructor(
|
|
17
|
-
private blockNumber:
|
|
18
|
-
private
|
|
10
|
+
private blockNumber: BlockNumber,
|
|
11
|
+
private contractStore: ContractStore,
|
|
19
12
|
) {}
|
|
20
13
|
|
|
21
|
-
getBlockNumber(): Promise<
|
|
14
|
+
getBlockNumber(): Promise<BlockNumber> {
|
|
22
15
|
return Promise.resolve(this.blockNumber);
|
|
23
16
|
}
|
|
24
17
|
|
|
25
18
|
async getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
|
|
26
|
-
const contractClass = await this.
|
|
19
|
+
const contractClass = await this.contractStore.getContractClassWithPreimage(id);
|
|
27
20
|
if (!contractClass) {
|
|
28
21
|
return;
|
|
29
22
|
}
|
|
30
|
-
const artifact = await this.contractDataProvider.getContractArtifact(id);
|
|
31
|
-
if (!artifact) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
let privateFunctionsRoot;
|
|
36
|
-
if (!this.#privateFunctionsRoot.has(id.toString())) {
|
|
37
|
-
const privateFunctions = await Promise.all(
|
|
38
|
-
artifact.functions
|
|
39
|
-
.filter(fn => fn.functionType === FunctionType.PRIVATE)
|
|
40
|
-
.map(fn => getContractClassPrivateFunctionFromArtifact(fn)),
|
|
41
|
-
);
|
|
42
|
-
privateFunctionsRoot = await computePrivateFunctionsRoot(privateFunctions);
|
|
43
|
-
this.#privateFunctionsRoot.set(id.toString(), privateFunctionsRoot.toBuffer());
|
|
44
|
-
} else {
|
|
45
|
-
privateFunctionsRoot = Fr.fromBuffer(this.#privateFunctionsRoot.get(id.toString())!);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
23
|
return {
|
|
49
|
-
id,
|
|
50
|
-
artifactHash: contractClass
|
|
51
|
-
packedBytecode: contractClass
|
|
52
|
-
privateFunctionsRoot,
|
|
53
|
-
version: contractClass
|
|
24
|
+
id: contractClass.id,
|
|
25
|
+
artifactHash: contractClass.artifactHash,
|
|
26
|
+
packedBytecode: contractClass.packedBytecode,
|
|
27
|
+
privateFunctionsRoot: contractClass.privateFunctionsRoot,
|
|
28
|
+
version: contractClass.version,
|
|
54
29
|
privateFunctions: [],
|
|
55
30
|
utilityFunctions: [],
|
|
56
31
|
};
|
|
57
32
|
}
|
|
58
33
|
|
|
59
34
|
async getBytecodeCommitment(id: Fr): Promise<Fr | undefined> {
|
|
60
|
-
const contractClass = await this.
|
|
61
|
-
return contractClass
|
|
35
|
+
const contractClass = await this.contractStore.getContractClassWithPreimage(id);
|
|
36
|
+
return contractClass?.publicBytecodeCommitment;
|
|
62
37
|
}
|
|
63
38
|
|
|
64
39
|
async getContract(address: AztecAddress): Promise<ContractInstanceWithAddress | undefined> {
|
|
65
|
-
const instance = await this.
|
|
40
|
+
const instance = await this.contractStore.getContractInstance(address);
|
|
66
41
|
return instance && { ...instance, address };
|
|
67
42
|
}
|
|
68
43
|
|
|
@@ -71,12 +46,12 @@ export class TXEPublicContractDataSource implements ContractDataSource {
|
|
|
71
46
|
}
|
|
72
47
|
|
|
73
48
|
async getContractArtifact(address: AztecAddress): Promise<ContractArtifact | undefined> {
|
|
74
|
-
const instance = await this.
|
|
75
|
-
return instance && this.
|
|
49
|
+
const instance = await this.contractStore.getContractInstance(address);
|
|
50
|
+
return instance && this.contractStore.getContractArtifact(instance.currentContractClassId);
|
|
76
51
|
}
|
|
77
52
|
|
|
78
53
|
async getDebugFunctionName(address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
|
|
79
|
-
return await this.
|
|
54
|
+
return await this.contractStore.getDebugFunctionName(address, selector);
|
|
80
55
|
}
|
|
81
56
|
|
|
82
57
|
registerContractFunctionSignatures(_signatures: []): Promise<void> {
|