@aztec/txe 0.0.1-commit.b655e406 → 0.0.1-commit.c0b82b2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/bin/index.d.ts +1 -1
- package/dest/constants.d.ts +3 -0
- package/dest/constants.d.ts.map +1 -0
- package/dest/constants.js +2 -0
- package/dest/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +85 -52
- package/dest/oracle/interfaces.d.ts +14 -10
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.d.ts +7 -7
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +10 -12
- package/dest/oracle/txe_oracle_top_level_context.d.ts +24 -15
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +205 -88
- package/dest/rpc_translator.d.ts +35 -20
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +151 -65
- package/dest/state_machine/archiver.d.ts +21 -51
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +63 -94
- package/dest/state_machine/dummy_p2p_client.d.ts +21 -14
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +42 -22
- package/dest/state_machine/global_variable_builder.d.ts +6 -4
- package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
- package/dest/state_machine/global_variable_builder.js +13 -1
- package/dest/state_machine/index.d.ts +7 -7
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +40 -23
- package/dest/state_machine/mock_epoch_cache.d.ts +14 -10
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +21 -13
- package/dest/state_machine/synchronizer.d.ts +3 -2
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/state_machine/synchronizer.js +5 -4
- package/dest/txe_session.d.ts +26 -15
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +161 -53
- package/dest/util/encoding.d.ts +615 -16
- package/dest/util/encoding.d.ts.map +1 -1
- package/dest/util/encoding.js +1 -1
- package/dest/util/expected_failure_error.d.ts +1 -1
- package/dest/util/expected_failure_error.d.ts.map +1 -1
- package/dest/util/txe_account_store.d.ts +10 -0
- package/dest/util/txe_account_store.d.ts.map +1 -0
- package/dest/util/{txe_account_data_provider.js → txe_account_store.js} +1 -1
- package/dest/util/txe_public_contract_data_source.d.ts +8 -8
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +12 -29
- package/dest/utils/block_creation.d.ts +21 -6
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +38 -4
- package/dest/utils/tx_effect_creation.d.ts +3 -3
- package/dest/utils/tx_effect_creation.d.ts.map +1 -1
- package/dest/utils/tx_effect_creation.js +4 -7
- package/package.json +18 -17
- package/src/constants.ts +3 -0
- package/src/index.ts +97 -60
- package/src/oracle/interfaces.ts +16 -8
- package/src/oracle/txe_oracle_public_context.ts +12 -19
- package/src/oracle/txe_oracle_top_level_context.ts +249 -127
- package/src/rpc_translator.ts +179 -68
- package/src/state_machine/archiver.ts +63 -117
- package/src/state_machine/dummy_p2p_client.ts +59 -29
- package/src/state_machine/global_variable_builder.ts +22 -4
- package/src/state_machine/index.ts +60 -21
- package/src/state_machine/mock_epoch_cache.ts +25 -20
- package/src/state_machine/synchronizer.ts +6 -5
- package/src/txe_session.ts +222 -101
- package/src/util/encoding.ts +1 -1
- package/src/util/{txe_account_data_provider.ts → txe_account_store.ts} +1 -1
- package/src/util/txe_public_contract_data_source.ts +20 -45
- package/src/utils/block_creation.ts +49 -14
- package/src/utils/tx_effect_creation.ts +5 -12
- package/dest/util/txe_account_data_provider.d.ts +0 -10
- package/dest/util/txe_account_data_provider.d.ts.map +0 -1
- package/dest/util/txe_contract_data_provider.d.ts +0 -12
- package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
- package/dest/util/txe_contract_data_provider.js +0 -22
- package/src/util/txe_contract_data_provider.ts +0 -36
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
|
|
2
|
-
import {
|
|
2
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
4
|
import type { L2Block } from '@aztec/stdlib/block';
|
|
4
5
|
import type {
|
|
5
6
|
MerkleTreeReadOperations,
|
|
@@ -12,7 +13,7 @@ import { NativeWorldStateService } from '@aztec/world-state/native';
|
|
|
12
13
|
|
|
13
14
|
export class TXESynchronizer implements WorldStateSynchronizer {
|
|
14
15
|
// This works when set to 1 as well.
|
|
15
|
-
private blockNumber =
|
|
16
|
+
private blockNumber = BlockNumber.ZERO;
|
|
16
17
|
|
|
17
18
|
constructor(public nativeWorldStateService: NativeWorldStateService) {}
|
|
18
19
|
|
|
@@ -37,7 +38,7 @@ export class TXESynchronizer implements WorldStateSynchronizer {
|
|
|
37
38
|
* @param skipThrowIfTargetNotReached - Whether to skip throwing if the target block number is not reached.
|
|
38
39
|
* @returns A promise that resolves with the block number the world state was synced to
|
|
39
40
|
*/
|
|
40
|
-
public syncImmediate(_minBlockNumber?:
|
|
41
|
+
public syncImmediate(_minBlockNumber?: BlockNumber, _skipThrowIfTargetNotReached?: boolean): Promise<BlockNumber> {
|
|
41
42
|
return Promise.resolve(this.blockNumber);
|
|
42
43
|
}
|
|
43
44
|
|
|
@@ -48,12 +49,12 @@ export class TXESynchronizer implements WorldStateSynchronizer {
|
|
|
48
49
|
|
|
49
50
|
/** Forks the world state at the given block number, defaulting to the latest one. */
|
|
50
51
|
public fork(block?: number): Promise<MerkleTreeWriteOperations> {
|
|
51
|
-
return this.nativeWorldStateService.fork(block);
|
|
52
|
+
return this.nativeWorldStateService.fork(block ? BlockNumber(block) : undefined);
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
/** Gets a handle that allows reading the state as it was at the given block number. */
|
|
55
56
|
public getSnapshot(blockNumber: number): MerkleTreeReadOperations {
|
|
56
|
-
return this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
57
|
+
return this.nativeWorldStateService.getSnapshot(BlockNumber(blockNumber));
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
/** Backups the db to the target path. */
|
package/src/txe_session.ts
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
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
|
+
JobCoordinator,
|
|
13
|
+
NoteService,
|
|
14
|
+
NoteStore,
|
|
15
|
+
PrivateEventStore,
|
|
16
|
+
RecipientTaggingStore,
|
|
17
|
+
SenderAddressBookStore,
|
|
18
|
+
SenderTaggingStore,
|
|
13
19
|
} from '@aztec/pxe/server';
|
|
14
20
|
import {
|
|
15
21
|
ExecutionNoteCache,
|
|
@@ -17,34 +23,39 @@ import {
|
|
|
17
23
|
HashedValuesCache,
|
|
18
24
|
type IPrivateExecutionOracle,
|
|
19
25
|
type IUtilityExecutionOracle,
|
|
26
|
+
Oracle,
|
|
20
27
|
PrivateExecutionOracle,
|
|
21
28
|
UtilityExecutionOracle,
|
|
22
29
|
} from '@aztec/pxe/simulator';
|
|
23
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
ExecutionError,
|
|
32
|
+
WASMSimulator,
|
|
33
|
+
createSimulationError,
|
|
34
|
+
extractCallStack,
|
|
35
|
+
resolveAssertionMessageFromError,
|
|
36
|
+
toACVMWitness,
|
|
37
|
+
} from '@aztec/simulator/client';
|
|
38
|
+
import { FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
24
39
|
import type { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
25
40
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
26
|
-
import { Body, L2Block } from '@aztec/stdlib/block';
|
|
27
41
|
import { GasSettings } from '@aztec/stdlib/gas';
|
|
42
|
+
import { computeProtocolNullifier } from '@aztec/stdlib/hash';
|
|
28
43
|
import { PrivateContextInputs } from '@aztec/stdlib/kernel';
|
|
29
|
-
import {
|
|
44
|
+
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
30
45
|
import { CallContext, GlobalVariables, TxContext } from '@aztec/stdlib/tx';
|
|
31
|
-
import type { UInt32 } from '@aztec/stdlib/types';
|
|
32
46
|
|
|
33
47
|
import { z } from 'zod';
|
|
34
48
|
|
|
49
|
+
import { DEFAULT_ADDRESS } from './constants.js';
|
|
35
50
|
import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
|
|
36
51
|
import { TXEOraclePublicContext } from './oracle/txe_oracle_public_context.js';
|
|
37
52
|
import { TXEOracleTopLevelContext } from './oracle/txe_oracle_top_level_context.js';
|
|
38
53
|
import { RPCTranslator } from './rpc_translator.js';
|
|
54
|
+
import { TXEArchiver } from './state_machine/archiver.js';
|
|
39
55
|
import { TXEStateMachine } from './state_machine/index.js';
|
|
40
56
|
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';
|
|
57
|
+
import { TXEAccountStore } from './util/txe_account_store.js';
|
|
58
|
+
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from './utils/block_creation.js';
|
|
48
59
|
import { makeTxEffect } from './utils/tx_effect_creation.js';
|
|
49
60
|
|
|
50
61
|
/**
|
|
@@ -66,7 +77,6 @@ type SessionState =
|
|
|
66
77
|
| {
|
|
67
78
|
name: 'PRIVATE';
|
|
68
79
|
nextBlockGlobalVariables: GlobalVariables;
|
|
69
|
-
txRequestHash: Fr;
|
|
70
80
|
noteCache: ExecutionNoteCache;
|
|
71
81
|
taggingIndexCache: ExecutionTaggingIndexCache;
|
|
72
82
|
}
|
|
@@ -101,11 +111,13 @@ export type TXEOracleFunctionName = Exclude<
|
|
|
101
111
|
export interface TXESessionStateHandler {
|
|
102
112
|
enterTopLevelState(): Promise<void>;
|
|
103
113
|
enterPublicState(contractAddress?: AztecAddress): Promise<void>;
|
|
104
|
-
enterPrivateState(contractAddress?: AztecAddress, anchorBlockNumber?:
|
|
114
|
+
enterPrivateState(contractAddress?: AztecAddress, anchorBlockNumber?: BlockNumber): Promise<PrivateContextInputs>;
|
|
105
115
|
enterUtilityState(contractAddress?: AztecAddress): Promise<void>;
|
|
106
|
-
}
|
|
107
116
|
|
|
108
|
-
|
|
117
|
+
// TODO(F-335): Exposing the job info is abstraction breakage - drop the following 2 functions.
|
|
118
|
+
cycleJob(): Promise<string>;
|
|
119
|
+
getCurrentJob(): string;
|
|
120
|
+
}
|
|
109
121
|
|
|
110
122
|
/**
|
|
111
123
|
* A `TXESession` corresponds to a Noir `#[test]` function, and handles all of its oracle calls, stores test-specific
|
|
@@ -123,59 +135,68 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
123
135
|
| IPrivateExecutionOracle
|
|
124
136
|
| IAvmExecutionOracle
|
|
125
137
|
| ITxeExecutionOracle,
|
|
126
|
-
private
|
|
138
|
+
private contractStore: ContractStore,
|
|
139
|
+
private noteStore: NoteStore,
|
|
127
140
|
private keyStore: KeyStore,
|
|
128
|
-
private
|
|
129
|
-
private
|
|
141
|
+
private addressStore: AddressStore,
|
|
142
|
+
private accountStore: TXEAccountStore,
|
|
143
|
+
private senderTaggingStore: SenderTaggingStore,
|
|
144
|
+
private recipientTaggingStore: RecipientTaggingStore,
|
|
145
|
+
private senderAddressBookStore: SenderAddressBookStore,
|
|
146
|
+
private capsuleStore: CapsuleStore,
|
|
147
|
+
private privateEventStore: PrivateEventStore,
|
|
148
|
+
private jobCoordinator: JobCoordinator,
|
|
149
|
+
private currentJobId: string,
|
|
130
150
|
private chainId: Fr,
|
|
131
151
|
private version: Fr,
|
|
132
152
|
private nextBlockTimestamp: bigint,
|
|
133
|
-
private pxeOracleInterface: PXEOracleInterface,
|
|
134
153
|
) {}
|
|
135
154
|
|
|
136
|
-
static async init(
|
|
155
|
+
static async init(contractStore: ContractStore) {
|
|
137
156
|
const store = await openTmpStore('txe-session');
|
|
138
157
|
|
|
139
|
-
const
|
|
140
|
-
const
|
|
141
|
-
const
|
|
142
|
-
const
|
|
143
|
-
const
|
|
144
|
-
const
|
|
158
|
+
const addressStore = new AddressStore(store);
|
|
159
|
+
const privateEventStore = new PrivateEventStore(store);
|
|
160
|
+
const noteStore = new NoteStore(store);
|
|
161
|
+
const senderTaggingStore = new SenderTaggingStore(store);
|
|
162
|
+
const recipientTaggingStore = new RecipientTaggingStore(store);
|
|
163
|
+
const senderAddressBookStore = new SenderAddressBookStore(store);
|
|
164
|
+
const capsuleStore = new CapsuleStore(store);
|
|
145
165
|
const keyStore = new KeyStore(store);
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
//
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
166
|
+
const accountStore = new TXEAccountStore(store);
|
|
167
|
+
|
|
168
|
+
// Create job coordinator and register staged stores
|
|
169
|
+
const jobCoordinator = new JobCoordinator(store);
|
|
170
|
+
jobCoordinator.registerStores([
|
|
171
|
+
capsuleStore,
|
|
172
|
+
senderTaggingStore,
|
|
173
|
+
recipientTaggingStore,
|
|
174
|
+
privateEventStore,
|
|
175
|
+
noteStore,
|
|
176
|
+
]);
|
|
177
|
+
|
|
178
|
+
const archiver = new TXEArchiver(store);
|
|
179
|
+
const anchorBlockStore = new AnchorBlockStore(store);
|
|
180
|
+
const stateMachine = await TXEStateMachine.create(archiver, anchorBlockStore, contractStore, noteStore);
|
|
155
181
|
|
|
156
182
|
const nextBlockTimestamp = BigInt(Math.floor(new Date().getTime() / 1000));
|
|
157
183
|
const version = new Fr(await stateMachine.node.getVersion());
|
|
158
184
|
const chainId = new Fr(await stateMachine.node.getChainId());
|
|
159
185
|
|
|
160
|
-
const
|
|
161
|
-
stateMachine.node,
|
|
162
|
-
keyStore,
|
|
163
|
-
contractDataProvider,
|
|
164
|
-
noteDataProvider,
|
|
165
|
-
capsuleDataProvider,
|
|
166
|
-
stateMachine.syncDataProvider,
|
|
167
|
-
taggingDataProvider,
|
|
168
|
-
addressDataProvider,
|
|
169
|
-
privateEventDataProvider,
|
|
170
|
-
);
|
|
186
|
+
const initialJobId = jobCoordinator.beginJob();
|
|
171
187
|
|
|
172
188
|
const topLevelOracleHandler = new TXEOracleTopLevelContext(
|
|
173
189
|
stateMachine,
|
|
174
|
-
|
|
190
|
+
contractStore,
|
|
191
|
+
noteStore,
|
|
175
192
|
keyStore,
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
193
|
+
addressStore,
|
|
194
|
+
accountStore,
|
|
195
|
+
senderTaggingStore,
|
|
196
|
+
recipientTaggingStore,
|
|
197
|
+
senderAddressBookStore,
|
|
198
|
+
capsuleStore,
|
|
199
|
+
privateEventStore,
|
|
179
200
|
nextBlockTimestamp,
|
|
180
201
|
version,
|
|
181
202
|
chainId,
|
|
@@ -187,14 +208,21 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
187
208
|
createLogger('txe:session'),
|
|
188
209
|
stateMachine,
|
|
189
210
|
topLevelOracleHandler,
|
|
190
|
-
|
|
211
|
+
contractStore,
|
|
212
|
+
noteStore,
|
|
191
213
|
keyStore,
|
|
192
|
-
|
|
193
|
-
|
|
214
|
+
addressStore,
|
|
215
|
+
accountStore,
|
|
216
|
+
senderTaggingStore,
|
|
217
|
+
recipientTaggingStore,
|
|
218
|
+
senderAddressBookStore,
|
|
219
|
+
capsuleStore,
|
|
220
|
+
privateEventStore,
|
|
221
|
+
jobCoordinator,
|
|
222
|
+
initialJobId,
|
|
194
223
|
version,
|
|
195
224
|
chainId,
|
|
196
225
|
nextBlockTimestamp,
|
|
197
|
-
pxeOracleInterface,
|
|
198
226
|
);
|
|
199
227
|
}
|
|
200
228
|
|
|
@@ -229,6 +257,17 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
229
257
|
}
|
|
230
258
|
}
|
|
231
259
|
|
|
260
|
+
getCurrentJob(): string {
|
|
261
|
+
return this.currentJobId;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/** Commits the current job and begins a new one. Returns the new job ID. */
|
|
265
|
+
async cycleJob(): Promise<string> {
|
|
266
|
+
await this.jobCoordinator.commitJob(this.currentJobId);
|
|
267
|
+
this.currentJobId = this.jobCoordinator.beginJob();
|
|
268
|
+
return this.currentJobId;
|
|
269
|
+
}
|
|
270
|
+
|
|
232
271
|
async enterTopLevelState() {
|
|
233
272
|
switch (this.state.name) {
|
|
234
273
|
case 'PRIVATE': {
|
|
@@ -251,13 +290,21 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
251
290
|
}
|
|
252
291
|
}
|
|
253
292
|
|
|
293
|
+
// Commit all staged stores from the job that was just completed, then begin a new job
|
|
294
|
+
await this.cycleJob();
|
|
295
|
+
|
|
254
296
|
this.oracleHandler = new TXEOracleTopLevelContext(
|
|
255
297
|
this.stateMachine,
|
|
256
|
-
this.
|
|
298
|
+
this.contractStore,
|
|
299
|
+
this.noteStore,
|
|
257
300
|
this.keyStore,
|
|
258
|
-
this.
|
|
259
|
-
this.
|
|
260
|
-
this.
|
|
301
|
+
this.addressStore,
|
|
302
|
+
this.accountStore,
|
|
303
|
+
this.senderTaggingStore,
|
|
304
|
+
this.recipientTaggingStore,
|
|
305
|
+
this.senderAddressBookStore,
|
|
306
|
+
this.capsuleStore,
|
|
307
|
+
this.privateEventStore,
|
|
261
308
|
this.nextBlockTimestamp,
|
|
262
309
|
this.version,
|
|
263
310
|
this.chainId,
|
|
@@ -270,53 +317,66 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
270
317
|
|
|
271
318
|
async enterPrivateState(
|
|
272
319
|
contractAddress: AztecAddress = DEFAULT_ADDRESS,
|
|
273
|
-
anchorBlockNumber?:
|
|
320
|
+
anchorBlockNumber?: BlockNumber,
|
|
274
321
|
): Promise<PrivateContextInputs> {
|
|
275
322
|
this.exitTopLevelState();
|
|
276
323
|
|
|
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
324
|
// Private execution has two associated block numbers: the anchor block (i.e. the historical block that is used to
|
|
285
325
|
// build the proof), and the *next* block, i.e. the one we'll create once the execution ends, and which will contain
|
|
286
326
|
// a single transaction with the effects of what was done in the test.
|
|
287
327
|
const anchorBlock = await this.stateMachine.node.getBlockHeader(anchorBlockNumber ?? 'latest');
|
|
328
|
+
|
|
329
|
+
await new NoteService(this.noteStore, this.stateMachine.node, anchorBlock!, this.currentJobId).syncNoteNullifiers(
|
|
330
|
+
contractAddress,
|
|
331
|
+
'ALL_SCOPES',
|
|
332
|
+
);
|
|
288
333
|
const latestBlock = await this.stateMachine.node.getBlockHeader('latest');
|
|
289
334
|
|
|
290
335
|
const nextBlockGlobalVariables = makeGlobalVariables(undefined, {
|
|
291
|
-
blockNumber: latestBlock!.globalVariables.blockNumber + 1,
|
|
336
|
+
blockNumber: BlockNumber(latestBlock!.globalVariables.blockNumber + 1),
|
|
292
337
|
timestamp: this.nextBlockTimestamp,
|
|
293
338
|
version: this.version,
|
|
294
339
|
chainId: this.chainId,
|
|
295
340
|
});
|
|
296
341
|
|
|
297
342
|
const txRequestHash = getSingleTxBlockRequestHash(nextBlockGlobalVariables.blockNumber);
|
|
298
|
-
const
|
|
343
|
+
const protocolNullifier = await computeProtocolNullifier(txRequestHash);
|
|
344
|
+
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
299
345
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
300
346
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
new
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
347
|
+
const utilityExecutor = this.utilityExecutorForContractSync(anchorBlock);
|
|
348
|
+
this.oracleHandler = new PrivateExecutionOracle({
|
|
349
|
+
argsHash: Fr.ZERO,
|
|
350
|
+
txContext: new TxContext(this.chainId, this.version, GasSettings.empty()),
|
|
351
|
+
callContext: new CallContext(AztecAddress.ZERO, contractAddress, FunctionSelector.empty(), false),
|
|
352
|
+
anchorBlockHeader: anchorBlock!,
|
|
353
|
+
utilityExecutor,
|
|
354
|
+
authWitnesses: [],
|
|
355
|
+
capsules: [],
|
|
356
|
+
executionCache: new HashedValuesCache(),
|
|
309
357
|
noteCache,
|
|
310
358
|
taggingIndexCache,
|
|
311
|
-
this.
|
|
312
|
-
|
|
359
|
+
contractStore: this.contractStore,
|
|
360
|
+
noteStore: this.noteStore,
|
|
361
|
+
keyStore: this.keyStore,
|
|
362
|
+
addressStore: this.addressStore,
|
|
363
|
+
aztecNode: this.stateMachine.node,
|
|
364
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
365
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
366
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
367
|
+
capsuleStore: this.capsuleStore,
|
|
368
|
+
privateEventStore: this.privateEventStore,
|
|
369
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
370
|
+
jobId: this.currentJobId,
|
|
371
|
+
scopes: 'ALL_SCOPES',
|
|
372
|
+
});
|
|
313
373
|
|
|
314
374
|
// We store the note and tagging index caches fed into the PrivateExecutionOracle (along with some other auxiliary
|
|
315
375
|
// data) in order to refer to it later, mimicking the way this object is used by the ContractFunctionSimulator. The
|
|
316
376
|
// difference resides in that the simulator has all information needed in order to run the simulation, while ours
|
|
317
377
|
// will be ongoing as the different oracles will be invoked from the Noir test, until eventually the private
|
|
318
378
|
// execution finishes.
|
|
319
|
-
this.state = { name: 'PRIVATE', nextBlockGlobalVariables,
|
|
379
|
+
this.state = { name: 'PRIVATE', nextBlockGlobalVariables, noteCache, taggingIndexCache };
|
|
320
380
|
this.logger.debug(`Entered state ${this.state.name}`);
|
|
321
381
|
|
|
322
382
|
return (this.oracleHandler as PrivateExecutionOracle).getPrivateContextInputs();
|
|
@@ -329,7 +389,7 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
329
389
|
// the test. The block therefore gets the *next* block number and timestamp.
|
|
330
390
|
const latestBlockNumber = (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.blockNumber;
|
|
331
391
|
const globalVariables = makeGlobalVariables(undefined, {
|
|
332
|
-
blockNumber: latestBlockNumber + 1,
|
|
392
|
+
blockNumber: BlockNumber(latestBlockNumber + 1),
|
|
333
393
|
timestamp: this.nextBlockTimestamp,
|
|
334
394
|
version: this.version,
|
|
335
395
|
chainId: this.chainId,
|
|
@@ -349,14 +409,37 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
349
409
|
async enterUtilityState(contractAddress: AztecAddress = DEFAULT_ADDRESS) {
|
|
350
410
|
this.exitTopLevelState();
|
|
351
411
|
|
|
412
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
413
|
+
|
|
352
414
|
// There is no automatic message discovery and contract-driven syncing process in inlined private or utility
|
|
353
415
|
// contexts, which means that known nullifiers are also not searched for, since it is during the tagging sync that
|
|
354
416
|
// we perform this. We therefore search for known nullifiers now, as otherwise notes that were nullified would not
|
|
355
417
|
// be removed from the database.
|
|
356
418
|
// TODO(#12553): make the synchronizer sync here instead and remove this
|
|
357
|
-
await
|
|
358
|
-
|
|
359
|
-
|
|
419
|
+
await new NoteService(
|
|
420
|
+
this.noteStore,
|
|
421
|
+
this.stateMachine.node,
|
|
422
|
+
anchorBlockHeader,
|
|
423
|
+
this.currentJobId,
|
|
424
|
+
).syncNoteNullifiers(contractAddress, 'ALL_SCOPES');
|
|
425
|
+
|
|
426
|
+
this.oracleHandler = new UtilityExecutionOracle({
|
|
427
|
+
contractAddress,
|
|
428
|
+
authWitnesses: [],
|
|
429
|
+
capsules: [],
|
|
430
|
+
anchorBlockHeader,
|
|
431
|
+
contractStore: this.contractStore,
|
|
432
|
+
noteStore: this.noteStore,
|
|
433
|
+
keyStore: this.keyStore,
|
|
434
|
+
addressStore: this.addressStore,
|
|
435
|
+
aztecNode: this.stateMachine.node,
|
|
436
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
437
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
438
|
+
capsuleStore: this.capsuleStore,
|
|
439
|
+
privateEventStore: this.privateEventStore,
|
|
440
|
+
jobId: this.currentJobId,
|
|
441
|
+
scopes: 'ALL_SCOPES',
|
|
442
|
+
});
|
|
360
443
|
|
|
361
444
|
this.state = { name: 'UTILITY' };
|
|
362
445
|
this.logger.debug(`Entered state ${this.state.name}`);
|
|
@@ -390,21 +473,14 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
390
473
|
|
|
391
474
|
// We rely on the note cache to determine the effects of the transaction. This is incomplete as it doesn't private
|
|
392
475
|
// 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
|
-
);
|
|
476
|
+
|
|
477
|
+
const txEffect = await makeTxEffect(this.state.noteCache, this.state.nextBlockGlobalVariables.blockNumber);
|
|
398
478
|
|
|
399
479
|
// We build a block holding just this transaction
|
|
400
480
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
401
481
|
await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
|
|
402
482
|
|
|
403
|
-
const block =
|
|
404
|
-
makeAppendOnlyTreeSnapshot(),
|
|
405
|
-
await makeTXEBlockHeader(forkedWorldTrees, this.state.nextBlockGlobalVariables),
|
|
406
|
-
new Body([txEffect]),
|
|
407
|
-
);
|
|
483
|
+
const block = await makeTXEBlock(forkedWorldTrees, this.state.nextBlockGlobalVariables, [txEffect]);
|
|
408
484
|
await this.stateMachine.handleL2Block(block);
|
|
409
485
|
|
|
410
486
|
await forkedWorldTrees.close();
|
|
@@ -429,4 +505,49 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
429
505
|
throw new Error(`Expected to be in state 'UTILITY', but got '${this.state.name}' instead`);
|
|
430
506
|
}
|
|
431
507
|
}
|
|
508
|
+
|
|
509
|
+
private utilityExecutorForContractSync(anchorBlock: any) {
|
|
510
|
+
return async (call: FunctionCall, scopes: AccessScopes) => {
|
|
511
|
+
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
512
|
+
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
513
|
+
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
try {
|
|
517
|
+
const oracle = new UtilityExecutionOracle({
|
|
518
|
+
contractAddress: call.to,
|
|
519
|
+
authWitnesses: [],
|
|
520
|
+
capsules: [],
|
|
521
|
+
anchorBlockHeader: anchorBlock!,
|
|
522
|
+
contractStore: this.contractStore,
|
|
523
|
+
noteStore: this.noteStore,
|
|
524
|
+
keyStore: this.keyStore,
|
|
525
|
+
addressStore: this.addressStore,
|
|
526
|
+
aztecNode: this.stateMachine.node,
|
|
527
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
528
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
529
|
+
capsuleStore: this.capsuleStore,
|
|
530
|
+
privateEventStore: this.privateEventStore,
|
|
531
|
+
jobId: this.currentJobId,
|
|
532
|
+
scopes,
|
|
533
|
+
});
|
|
534
|
+
await new WASMSimulator()
|
|
535
|
+
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
536
|
+
.catch((err: Error) => {
|
|
537
|
+
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
538
|
+
throw new ExecutionError(
|
|
539
|
+
err.message,
|
|
540
|
+
{
|
|
541
|
+
contractAddress: call.to,
|
|
542
|
+
functionSelector: call.selector,
|
|
543
|
+
},
|
|
544
|
+
extractCallStack(err, entryPointArtifact.debug),
|
|
545
|
+
{ cause: err },
|
|
546
|
+
);
|
|
547
|
+
});
|
|
548
|
+
} catch (err) {
|
|
549
|
+
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error contract data sync'));
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
}
|
|
432
553
|
}
|
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> {
|