@aztec/txe 0.0.1-commit.8f9871590 → 0.0.1-commit.9117c5f5a
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/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +82 -50
- package/dest/oracle/interfaces.d.ts +4 -3
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.d.ts +6 -7
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +27 -17
- package/dest/rpc_translator.d.ts +2 -2
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +16 -4
- package/dest/state_machine/dummy_p2p_client.d.ts +6 -5
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +7 -4
- package/dest/state_machine/index.d.ts +1 -1
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +1 -1
- package/dest/txe_session.d.ts +9 -6
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +12 -12
- package/dest/util/txe_public_contract_data_source.d.ts +2 -3
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +5 -22
- package/package.json +15 -15
- package/src/index.ts +83 -49
- package/src/oracle/interfaces.ts +6 -1
- package/src/oracle/txe_oracle_top_level_context.ts +36 -16
- package/src/rpc_translator.ts +18 -3
- package/src/state_machine/dummy_p2p_client.ts +11 -7
- package/src/state_machine/index.ts +1 -0
- package/src/txe_session.ts +19 -15
- package/src/util/txe_public_contract_data_source.ts +10 -36
- package/dest/util/txe_contract_store.d.ts +0 -12
- package/dest/util/txe_contract_store.d.ts.map +0 -1
- package/dest/util/txe_contract_store.js +0 -22
- package/src/util/txe_contract_store.ts +0 -36
package/src/index.ts
CHANGED
|
@@ -9,9 +9,12 @@ import { Fr } from '@aztec/aztec.js/fields';
|
|
|
9
9
|
import { PublicKeys, deriveKeys } from '@aztec/aztec.js/keys';
|
|
10
10
|
import { createSafeJsonRpcServer } from '@aztec/foundation/json-rpc/server';
|
|
11
11
|
import type { Logger } from '@aztec/foundation/log';
|
|
12
|
-
import {
|
|
12
|
+
import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
|
|
13
|
+
import { protocolContractNames } from '@aztec/protocol-contracts';
|
|
13
14
|
import { BundledProtocolContractsProvider } from '@aztec/protocol-contracts/providers/bundle';
|
|
15
|
+
import { ContractStore } from '@aztec/pxe/server';
|
|
14
16
|
import { computeArtifactHash } from '@aztec/stdlib/contract';
|
|
17
|
+
import type { ContractArtifactWithHash } from '@aztec/stdlib/contract';
|
|
15
18
|
import type { ApiSchemaFor } from '@aztec/stdlib/schemas';
|
|
16
19
|
import { zodFor } from '@aztec/stdlib/schemas';
|
|
17
20
|
|
|
@@ -33,18 +36,24 @@ import {
|
|
|
33
36
|
fromSingle,
|
|
34
37
|
toSingle,
|
|
35
38
|
} from './util/encoding.js';
|
|
36
|
-
import type { ContractArtifactWithHash } from './util/txe_contract_store.js';
|
|
37
39
|
|
|
38
40
|
const sessions = new Map<number, TXESession>();
|
|
39
41
|
|
|
40
42
|
/*
|
|
41
43
|
* TXE typically has to load the same contract artifacts over and over again for multiple tests,
|
|
42
|
-
* so we cache them here to avoid
|
|
44
|
+
* so we cache them here to avoid loading from disk repeatedly.
|
|
45
|
+
*
|
|
46
|
+
* The in-flight map coalesces concurrent requests for the same cache key so that
|
|
47
|
+
* computeArtifactHash (very expensive) is only run once even under parallelism.
|
|
43
48
|
*/
|
|
44
49
|
const TXEArtifactsCache = new Map<
|
|
45
50
|
string,
|
|
46
51
|
{ artifact: ContractArtifactWithHash; instance: ContractInstanceWithAddress }
|
|
47
52
|
>();
|
|
53
|
+
const TXEArtifactsCacheInFlight = new Map<
|
|
54
|
+
string,
|
|
55
|
+
Promise<{ artifact: ContractArtifactWithHash; instance: ContractInstanceWithAddress }>
|
|
56
|
+
>();
|
|
48
57
|
|
|
49
58
|
type TXEForeignCallInput = {
|
|
50
59
|
session_id: number;
|
|
@@ -68,7 +77,7 @@ const TXEForeignCallInputSchema = zodFor<TXEForeignCallInput>()(
|
|
|
68
77
|
);
|
|
69
78
|
|
|
70
79
|
class TXEDispatcher {
|
|
71
|
-
private
|
|
80
|
+
private contractStore!: ContractStore;
|
|
72
81
|
|
|
73
82
|
constructor(private logger: Logger) {}
|
|
74
83
|
|
|
@@ -135,29 +144,36 @@ class TXEDispatcher {
|
|
|
135
144
|
this.logger.debug(`Using cached artifact for ${cacheKey}`);
|
|
136
145
|
({ artifact, instance } = TXEArtifactsCache.get(cacheKey)!);
|
|
137
146
|
} else {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
147
|
+
if (!TXEArtifactsCacheInFlight.has(cacheKey)) {
|
|
148
|
+
this.logger.debug(`Loading compiled artifact ${artifactPath}`);
|
|
149
|
+
const compute = async () => {
|
|
150
|
+
const artifactJSON = JSON.parse(await readFile(artifactPath, 'utf-8')) as NoirCompiledContract;
|
|
151
|
+
const artifactWithoutHash = loadContractArtifact(artifactJSON);
|
|
152
|
+
const computedArtifact: ContractArtifactWithHash = {
|
|
153
|
+
...artifactWithoutHash,
|
|
154
|
+
// Artifact hash is *very* expensive to compute, so we do it here once
|
|
155
|
+
// and the TXE contract data provider can cache it
|
|
156
|
+
artifactHash: await computeArtifactHash(artifactWithoutHash),
|
|
157
|
+
};
|
|
158
|
+
this.logger.debug(
|
|
159
|
+
`Deploy ${computedArtifact.name} with initializer ${initializer}(${decodedArgs}) and public keys hash ${publicKeysHash.toString()}`,
|
|
160
|
+
);
|
|
161
|
+
const computedInstance = await getContractInstanceFromInstantiationParams(computedArtifact, {
|
|
162
|
+
constructorArgs: decodedArgs,
|
|
163
|
+
skipArgsDecoding: true,
|
|
164
|
+
salt: Fr.ONE,
|
|
165
|
+
publicKeys,
|
|
166
|
+
constructorArtifact: initializer ? initializer : undefined,
|
|
167
|
+
deployer: AztecAddress.ZERO,
|
|
168
|
+
});
|
|
169
|
+
const result = { artifact: computedArtifact, instance: computedInstance };
|
|
170
|
+
TXEArtifactsCache.set(cacheKey, result);
|
|
171
|
+
TXEArtifactsCacheInFlight.delete(cacheKey);
|
|
172
|
+
return result;
|
|
173
|
+
};
|
|
174
|
+
TXEArtifactsCacheInFlight.set(cacheKey, compute());
|
|
175
|
+
}
|
|
176
|
+
({ artifact, instance } = await TXEArtifactsCacheInFlight.get(cacheKey)!);
|
|
161
177
|
}
|
|
162
178
|
|
|
163
179
|
inputs.splice(0, 1, artifact, instance, toSingle(secret));
|
|
@@ -175,23 +191,35 @@ class TXEDispatcher {
|
|
|
175
191
|
this.logger.debug(`Using cached artifact for ${cacheKey}`);
|
|
176
192
|
({ artifact, instance } = TXEArtifactsCache.get(cacheKey)!);
|
|
177
193
|
} else {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
194
|
+
if (!TXEArtifactsCacheInFlight.has(cacheKey)) {
|
|
195
|
+
const compute = async () => {
|
|
196
|
+
const keys = await deriveKeys(secret);
|
|
197
|
+
const args = [
|
|
198
|
+
keys.publicKeys.masterIncomingViewingPublicKey.x,
|
|
199
|
+
keys.publicKeys.masterIncomingViewingPublicKey.y,
|
|
200
|
+
];
|
|
201
|
+
const computedArtifact: ContractArtifactWithHash = {
|
|
202
|
+
...SchnorrAccountContractArtifact,
|
|
203
|
+
// Artifact hash is *very* expensive to compute, so we do it here once
|
|
204
|
+
// and the TXE contract data provider can cache it
|
|
205
|
+
artifactHash: await computeArtifactHash(SchnorrAccountContractArtifact),
|
|
206
|
+
};
|
|
207
|
+
const computedInstance = await getContractInstanceFromInstantiationParams(computedArtifact, {
|
|
208
|
+
constructorArgs: args,
|
|
209
|
+
skipArgsDecoding: true,
|
|
210
|
+
salt: Fr.ONE,
|
|
211
|
+
publicKeys: keys.publicKeys,
|
|
212
|
+
constructorArtifact: 'constructor',
|
|
213
|
+
deployer: AztecAddress.ZERO,
|
|
214
|
+
});
|
|
215
|
+
const result = { artifact: computedArtifact, instance: computedInstance };
|
|
216
|
+
TXEArtifactsCache.set(cacheKey, result);
|
|
217
|
+
TXEArtifactsCacheInFlight.delete(cacheKey);
|
|
218
|
+
return result;
|
|
219
|
+
};
|
|
220
|
+
TXEArtifactsCacheInFlight.set(cacheKey, compute());
|
|
221
|
+
}
|
|
222
|
+
({ artifact, instance } = await TXEArtifactsCacheInFlight.get(cacheKey)!);
|
|
195
223
|
}
|
|
196
224
|
|
|
197
225
|
inputs.splice(0, 0, artifact, instance);
|
|
@@ -204,12 +232,18 @@ class TXEDispatcher {
|
|
|
204
232
|
|
|
205
233
|
if (!sessions.has(sessionId)) {
|
|
206
234
|
this.logger.debug(`Creating new session ${sessionId}`);
|
|
207
|
-
if (!this.
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
);
|
|
235
|
+
if (!this.contractStore) {
|
|
236
|
+
const kvStore = await openTmpStore('txe-contracts');
|
|
237
|
+
this.contractStore = new ContractStore(kvStore);
|
|
238
|
+
const provider = new BundledProtocolContractsProvider();
|
|
239
|
+
for (const name of protocolContractNames) {
|
|
240
|
+
const { instance, artifact } = await provider.getProtocolContractArtifact(name);
|
|
241
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
242
|
+
await this.contractStore.addContractInstance(instance);
|
|
243
|
+
}
|
|
244
|
+
this.logger.debug('Registered protocol contracts in shared contract store');
|
|
211
245
|
}
|
|
212
|
-
sessions.set(sessionId, await TXESession.init(this.
|
|
246
|
+
sessions.set(sessionId, await TXESession.init(this.contractStore));
|
|
213
247
|
}
|
|
214
248
|
|
|
215
249
|
switch (functionName) {
|
package/src/oracle/interfaces.ts
CHANGED
|
@@ -71,11 +71,13 @@ export interface ITxeExecutionOracle {
|
|
|
71
71
|
args: Fr[],
|
|
72
72
|
argsHash: Fr,
|
|
73
73
|
isStaticCall: boolean,
|
|
74
|
+
jobId: string,
|
|
74
75
|
): Promise<Fr[]>;
|
|
75
|
-
|
|
76
|
+
txeExecuteUtilityFunction(
|
|
76
77
|
targetContractAddress: AztecAddress,
|
|
77
78
|
functionSelector: FunctionSelector,
|
|
78
79
|
args: Fr[],
|
|
80
|
+
jobId: string,
|
|
79
81
|
): Promise<Fr[]>;
|
|
80
82
|
txePublicCallNewFlow(
|
|
81
83
|
from: AztecAddress,
|
|
@@ -83,4 +85,7 @@ export interface ITxeExecutionOracle {
|
|
|
83
85
|
calldata: Fr[],
|
|
84
86
|
isStaticCall: boolean,
|
|
85
87
|
): Promise<Fr[]>;
|
|
88
|
+
// TODO(F-335): Drop this from here as it's not a real oracle handler - it's only called from
|
|
89
|
+
// RPCTranslator::txeGetPrivateEvents and never from Noir.
|
|
90
|
+
syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string): Promise<void>;
|
|
86
91
|
}
|
|
@@ -16,6 +16,7 @@ import type { AccessScopes } from '@aztec/pxe/client/lazy';
|
|
|
16
16
|
import {
|
|
17
17
|
AddressStore,
|
|
18
18
|
CapsuleStore,
|
|
19
|
+
type ContractStore,
|
|
19
20
|
NoteStore,
|
|
20
21
|
ORACLE_VERSION,
|
|
21
22
|
PrivateEventStore,
|
|
@@ -84,7 +85,6 @@ import { ForkCheckpoint } from '@aztec/world-state';
|
|
|
84
85
|
import { DEFAULT_ADDRESS } from '../constants.js';
|
|
85
86
|
import type { TXEStateMachine } from '../state_machine/index.js';
|
|
86
87
|
import type { TXEAccountStore } from '../util/txe_account_store.js';
|
|
87
|
-
import type { TXEContractStore } from '../util/txe_contract_store.js';
|
|
88
88
|
import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
|
|
89
89
|
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
90
90
|
import type { ITxeExecutionOracle } from './interfaces.js';
|
|
@@ -97,7 +97,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
97
97
|
|
|
98
98
|
constructor(
|
|
99
99
|
private stateMachine: TXEStateMachine,
|
|
100
|
-
private contractStore:
|
|
100
|
+
private contractStore: ContractStore,
|
|
101
101
|
private noteStore: NoteStore,
|
|
102
102
|
private keyStore: KeyStore,
|
|
103
103
|
private addressStore: AddressStore,
|
|
@@ -107,7 +107,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
107
107
|
private senderAddressBookStore: SenderAddressBookStore,
|
|
108
108
|
private capsuleStore: CapsuleStore,
|
|
109
109
|
private privateEventStore: PrivateEventStore,
|
|
110
|
-
private jobId: string,
|
|
111
110
|
private nextBlockTimestamp: bigint,
|
|
112
111
|
private version: Fr,
|
|
113
112
|
private chainId: Fr,
|
|
@@ -172,6 +171,25 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
172
171
|
return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
|
|
173
172
|
}
|
|
174
173
|
|
|
174
|
+
async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
|
|
175
|
+
if (contractAddress.equals(DEFAULT_ADDRESS)) {
|
|
176
|
+
this.logger.debug(`Skipping sync in txeGetPrivateEvents because the events correspond to the default address.`);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
181
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
182
|
+
contractAddress,
|
|
183
|
+
null,
|
|
184
|
+
async (call, execScopes) => {
|
|
185
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
186
|
+
},
|
|
187
|
+
blockHeader,
|
|
188
|
+
jobId,
|
|
189
|
+
[scope],
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
175
193
|
async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
|
|
176
194
|
return (
|
|
177
195
|
await this.privateEventStore.getPrivateEvents(selector, {
|
|
@@ -211,7 +229,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
211
229
|
await this.txeAddAccount(artifact, instance, secret);
|
|
212
230
|
} else {
|
|
213
231
|
await this.contractStore.addContractInstance(instance);
|
|
214
|
-
await this.contractStore.addContractArtifact(
|
|
232
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
215
233
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
216
234
|
}
|
|
217
235
|
}
|
|
@@ -221,7 +239,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
221
239
|
|
|
222
240
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
223
241
|
await this.contractStore.addContractInstance(instance);
|
|
224
|
-
await this.contractStore.addContractArtifact(
|
|
242
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
225
243
|
|
|
226
244
|
const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
|
|
227
245
|
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
@@ -285,6 +303,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
285
303
|
args: Fr[],
|
|
286
304
|
argsHash: Fr = Fr.zero(),
|
|
287
305
|
isStaticCall: boolean = false,
|
|
306
|
+
jobId: string,
|
|
288
307
|
) {
|
|
289
308
|
this.logger.verbose(
|
|
290
309
|
`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
@@ -304,7 +323,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
304
323
|
|
|
305
324
|
// Sync notes before executing private function to discover notes from previous transactions
|
|
306
325
|
const utilityExecutor = async (call: FunctionCall, execScopes: AccessScopes) => {
|
|
307
|
-
await this.executeUtilityCall(call, execScopes);
|
|
326
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
308
327
|
};
|
|
309
328
|
|
|
310
329
|
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
@@ -313,7 +332,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
313
332
|
functionSelector,
|
|
314
333
|
utilityExecutor,
|
|
315
334
|
blockHeader,
|
|
316
|
-
|
|
335
|
+
jobId,
|
|
317
336
|
effectiveScopes,
|
|
318
337
|
);
|
|
319
338
|
|
|
@@ -360,7 +379,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
360
379
|
capsuleStore: this.capsuleStore,
|
|
361
380
|
privateEventStore: this.privateEventStore,
|
|
362
381
|
contractSyncService: this.stateMachine.contractSyncService,
|
|
363
|
-
jobId
|
|
382
|
+
jobId,
|
|
364
383
|
totalPublicCalldataCount: 0,
|
|
365
384
|
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
366
385
|
scopes: effectiveScopes,
|
|
@@ -659,10 +678,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
659
678
|
return returnValues ?? [];
|
|
660
679
|
}
|
|
661
680
|
|
|
662
|
-
async
|
|
681
|
+
async txeExecuteUtilityFunction(
|
|
663
682
|
targetContractAddress: AztecAddress,
|
|
664
683
|
functionSelector: FunctionSelector,
|
|
665
684
|
args: Fr[],
|
|
685
|
+
jobId: string,
|
|
666
686
|
) {
|
|
667
687
|
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
668
688
|
if (!artifact) {
|
|
@@ -675,10 +695,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
675
695
|
targetContractAddress,
|
|
676
696
|
functionSelector,
|
|
677
697
|
async (call, execScopes) => {
|
|
678
|
-
await this.executeUtilityCall(call, execScopes);
|
|
698
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
679
699
|
},
|
|
680
700
|
blockHeader,
|
|
681
|
-
|
|
701
|
+
jobId,
|
|
682
702
|
'ALL_SCOPES',
|
|
683
703
|
);
|
|
684
704
|
|
|
@@ -693,10 +713,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
693
713
|
returnTypes: [],
|
|
694
714
|
});
|
|
695
715
|
|
|
696
|
-
return this.executeUtilityCall(call, 'ALL_SCOPES');
|
|
716
|
+
return this.executeUtilityCall(call, 'ALL_SCOPES', jobId);
|
|
697
717
|
}
|
|
698
718
|
|
|
699
|
-
private async executeUtilityCall(call: FunctionCall, scopes: AccessScopes): Promise<Fr[]> {
|
|
719
|
+
private async executeUtilityCall(call: FunctionCall, scopes: AccessScopes, jobId: string): Promise<Fr[]> {
|
|
700
720
|
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
701
721
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
702
722
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
@@ -723,7 +743,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
723
743
|
senderAddressBookStore: this.senderAddressBookStore,
|
|
724
744
|
capsuleStore: this.capsuleStore,
|
|
725
745
|
privateEventStore: this.privateEventStore,
|
|
726
|
-
jobId
|
|
746
|
+
jobId,
|
|
727
747
|
scopes,
|
|
728
748
|
});
|
|
729
749
|
const acirExecutionResult = await new WASMSimulator()
|
|
@@ -741,10 +761,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
741
761
|
);
|
|
742
762
|
});
|
|
743
763
|
|
|
744
|
-
this.logger.verbose(`Utility
|
|
764
|
+
this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
|
|
745
765
|
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
746
766
|
} catch (err) {
|
|
747
|
-
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility
|
|
767
|
+
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
|
|
748
768
|
}
|
|
749
769
|
}
|
|
750
770
|
|
package/src/rpc_translator.ts
CHANGED
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
toSingle,
|
|
31
31
|
} from './util/encoding.js';
|
|
32
32
|
|
|
33
|
-
const MAX_EVENT_LEN =
|
|
33
|
+
const MAX_EVENT_LEN = 10; // This is MAX_MESSAGE_CONTENT_LEN - PRIVATE_EVENT_MSG_PLAINTEXT_RESERVED_FIELDS_LEN
|
|
34
34
|
const MAX_PRIVATE_EVENTS_PER_TXE_QUERY = 5;
|
|
35
35
|
|
|
36
36
|
export class UnavailableOracleError extends Error {
|
|
@@ -285,6 +285,13 @@ export class RPCTranslator {
|
|
|
285
285
|
const contractAddress = addressFromSingle(foreignContractAddress);
|
|
286
286
|
const scope = addressFromSingle(foreignScope);
|
|
287
287
|
|
|
288
|
+
// TODO(F-335): Avoid doing the following 2 calls here.
|
|
289
|
+
{
|
|
290
|
+
await this.handlerAsTxe().syncContractNonOracleMethod(contractAddress, scope, this.stateHandler.getCurrentJob());
|
|
291
|
+
// We cycle job to commit the stores after the contract sync.
|
|
292
|
+
await this.stateHandler.cycleJob();
|
|
293
|
+
}
|
|
294
|
+
|
|
288
295
|
const events = await this.handlerAsTxe().txeGetPrivateEvents(selector, contractAddress, scope);
|
|
289
296
|
|
|
290
297
|
if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
|
|
@@ -1038,12 +1045,15 @@ export class RPCTranslator {
|
|
|
1038
1045
|
args,
|
|
1039
1046
|
argsHash,
|
|
1040
1047
|
isStaticCall,
|
|
1048
|
+
this.stateHandler.getCurrentJob(),
|
|
1041
1049
|
);
|
|
1042
1050
|
|
|
1051
|
+
// TODO(F-335): Avoid doing the following call here.
|
|
1052
|
+
await this.stateHandler.cycleJob();
|
|
1043
1053
|
return toForeignCallResult([toArray(returnValues)]);
|
|
1044
1054
|
}
|
|
1045
1055
|
|
|
1046
|
-
async
|
|
1056
|
+
async txeExecuteUtilityFunction(
|
|
1047
1057
|
foreignTargetContractAddress: ForeignCallSingle,
|
|
1048
1058
|
foreignFunctionSelector: ForeignCallSingle,
|
|
1049
1059
|
foreignArgs: ForeignCallArray,
|
|
@@ -1052,12 +1062,15 @@ export class RPCTranslator {
|
|
|
1052
1062
|
const functionSelector = FunctionSelector.fromField(fromSingle(foreignFunctionSelector));
|
|
1053
1063
|
const args = fromArray(foreignArgs);
|
|
1054
1064
|
|
|
1055
|
-
const returnValues = await this.handlerAsTxe().
|
|
1065
|
+
const returnValues = await this.handlerAsTxe().txeExecuteUtilityFunction(
|
|
1056
1066
|
targetContractAddress,
|
|
1057
1067
|
functionSelector,
|
|
1058
1068
|
args,
|
|
1069
|
+
this.stateHandler.getCurrentJob(),
|
|
1059
1070
|
);
|
|
1060
1071
|
|
|
1072
|
+
// TODO(F-335): Avoid doing the following call here.
|
|
1073
|
+
await this.stateHandler.cycleJob();
|
|
1061
1074
|
return toForeignCallResult([toArray(returnValues)]);
|
|
1062
1075
|
}
|
|
1063
1076
|
|
|
@@ -1074,6 +1087,8 @@ export class RPCTranslator {
|
|
|
1074
1087
|
|
|
1075
1088
|
const returnValues = await this.handlerAsTxe().txePublicCallNewFlow(from, address, calldata, isStaticCall);
|
|
1076
1089
|
|
|
1090
|
+
// TODO(F-335): Avoid doing the following call here.
|
|
1091
|
+
await this.stateHandler.cycleJob();
|
|
1077
1092
|
return toForeignCallResult([toArray(returnValues)]);
|
|
1078
1093
|
}
|
|
1079
1094
|
|
|
@@ -16,12 +16,12 @@ import type {
|
|
|
16
16
|
StatusMessage,
|
|
17
17
|
} from '@aztec/p2p';
|
|
18
18
|
import type { EthAddress, L2BlockStreamEvent, L2Tips } from '@aztec/stdlib/block';
|
|
19
|
-
import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
|
|
20
|
-
import type { BlockProposal, CheckpointAttestation, CheckpointProposal } from '@aztec/stdlib/p2p';
|
|
19
|
+
import type { ITxProvider, PeerInfo } from '@aztec/stdlib/interfaces/server';
|
|
20
|
+
import type { BlockProposal, CheckpointAttestation, CheckpointProposal, TopicType } from '@aztec/stdlib/p2p';
|
|
21
21
|
import type { BlockHeader, Tx, TxHash } from '@aztec/stdlib/tx';
|
|
22
22
|
|
|
23
23
|
export class DummyP2P implements P2P {
|
|
24
|
-
public
|
|
24
|
+
public validateTxsReceivedInBlockProposal(_txs: Tx[]): Promise<void> {
|
|
25
25
|
return Promise.resolve();
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -41,6 +41,10 @@ export class DummyP2P implements P2P {
|
|
|
41
41
|
throw new Error('DummyP2P does not implement "getPeers"');
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
public getGossipMeshPeerCount(_topicType: TopicType): Promise<number> {
|
|
45
|
+
return Promise.resolve(0);
|
|
46
|
+
}
|
|
47
|
+
|
|
44
48
|
public broadcastProposal(_proposal: BlockProposal): Promise<void> {
|
|
45
49
|
throw new Error('DummyP2P does not implement "broadcastProposal"');
|
|
46
50
|
}
|
|
@@ -131,6 +135,10 @@ export class DummyP2P implements P2P {
|
|
|
131
135
|
throw new Error('DummyP2P does not implement "isP2PClient"');
|
|
132
136
|
}
|
|
133
137
|
|
|
138
|
+
public getTxProvider(): ITxProvider {
|
|
139
|
+
throw new Error('DummyP2P does not implement "getTxProvider"');
|
|
140
|
+
}
|
|
141
|
+
|
|
134
142
|
public getTxsByHash(_txHashes: TxHash[]): Promise<Tx[]> {
|
|
135
143
|
throw new Error('DummyP2P does not implement "getTxsByHash"');
|
|
136
144
|
}
|
|
@@ -171,10 +179,6 @@ export class DummyP2P implements P2P {
|
|
|
171
179
|
throw new Error('DummyP2P does not implement "hasTxsInPool"');
|
|
172
180
|
}
|
|
173
181
|
|
|
174
|
-
public addTxsToPool(_txs: Tx[]): Promise<number> {
|
|
175
|
-
throw new Error('DummyP2P does not implement "addTxs"');
|
|
176
|
-
}
|
|
177
|
-
|
|
178
182
|
public getSyncedLatestBlockNum(): Promise<number> {
|
|
179
183
|
throw new Error('DummyP2P does not implement "getSyncedLatestBlockNum"');
|
|
180
184
|
}
|
package/src/txe_session.ts
CHANGED
|
@@ -3,12 +3,12 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
3
3
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import { KeyStore } from '@aztec/key-store';
|
|
5
5
|
import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
|
|
6
|
-
import type { ProtocolContract } from '@aztec/protocol-contracts';
|
|
7
6
|
import type { AccessScopes } from '@aztec/pxe/client/lazy';
|
|
8
7
|
import {
|
|
9
8
|
AddressStore,
|
|
10
9
|
AnchorBlockStore,
|
|
11
10
|
CapsuleStore,
|
|
11
|
+
ContractStore,
|
|
12
12
|
JobCoordinator,
|
|
13
13
|
NoteService,
|
|
14
14
|
NoteStore,
|
|
@@ -55,7 +55,6 @@ import { TXEArchiver } from './state_machine/archiver.js';
|
|
|
55
55
|
import { TXEStateMachine } from './state_machine/index.js';
|
|
56
56
|
import type { ForeignCallArgs, ForeignCallResult } from './util/encoding.js';
|
|
57
57
|
import { TXEAccountStore } from './util/txe_account_store.js';
|
|
58
|
-
import { TXEContractStore } from './util/txe_contract_store.js';
|
|
59
58
|
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from './utils/block_creation.js';
|
|
60
59
|
import { makeTxEffect } from './utils/tx_effect_creation.js';
|
|
61
60
|
|
|
@@ -114,6 +113,10 @@ export interface TXESessionStateHandler {
|
|
|
114
113
|
enterPublicState(contractAddress?: AztecAddress): Promise<void>;
|
|
115
114
|
enterPrivateState(contractAddress?: AztecAddress, anchorBlockNumber?: BlockNumber): Promise<PrivateContextInputs>;
|
|
116
115
|
enterUtilityState(contractAddress?: AztecAddress): Promise<void>;
|
|
116
|
+
|
|
117
|
+
// TODO(F-335): Exposing the job info is abstraction breakage - drop the following 2 functions.
|
|
118
|
+
cycleJob(): Promise<string>;
|
|
119
|
+
getCurrentJob(): string;
|
|
117
120
|
}
|
|
118
121
|
|
|
119
122
|
/**
|
|
@@ -132,7 +135,7 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
132
135
|
| IPrivateExecutionOracle
|
|
133
136
|
| IAvmExecutionOracle
|
|
134
137
|
| ITxeExecutionOracle,
|
|
135
|
-
private contractStore:
|
|
138
|
+
private contractStore: ContractStore,
|
|
136
139
|
private noteStore: NoteStore,
|
|
137
140
|
private keyStore: KeyStore,
|
|
138
141
|
private addressStore: AddressStore,
|
|
@@ -149,12 +152,11 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
149
152
|
private nextBlockTimestamp: bigint,
|
|
150
153
|
) {}
|
|
151
154
|
|
|
152
|
-
static async init(
|
|
155
|
+
static async init(contractStore: ContractStore) {
|
|
153
156
|
const store = await openTmpStore('txe-session');
|
|
154
157
|
|
|
155
158
|
const addressStore = new AddressStore(store);
|
|
156
159
|
const privateEventStore = new PrivateEventStore(store);
|
|
157
|
-
const contractStore = new TXEContractStore(store);
|
|
158
160
|
const noteStore = new NoteStore(store);
|
|
159
161
|
const senderTaggingStore = new SenderTaggingStore(store);
|
|
160
162
|
const recipientTaggingStore = new RecipientTaggingStore(store);
|
|
@@ -173,12 +175,6 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
173
175
|
noteStore,
|
|
174
176
|
]);
|
|
175
177
|
|
|
176
|
-
// Register protocol contracts.
|
|
177
|
-
for (const { contractClass, instance, artifact } of protocolContracts) {
|
|
178
|
-
await contractStore.addContractArtifact(contractClass.id, artifact);
|
|
179
|
-
await contractStore.addContractInstance(instance);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
178
|
const archiver = new TXEArchiver(store);
|
|
183
179
|
const anchorBlockStore = new AnchorBlockStore(store);
|
|
184
180
|
const stateMachine = await TXEStateMachine.create(archiver, anchorBlockStore, contractStore, noteStore);
|
|
@@ -201,7 +197,6 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
201
197
|
senderAddressBookStore,
|
|
202
198
|
capsuleStore,
|
|
203
199
|
privateEventStore,
|
|
204
|
-
initialJobId,
|
|
205
200
|
nextBlockTimestamp,
|
|
206
201
|
version,
|
|
207
202
|
chainId,
|
|
@@ -262,6 +257,17 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
262
257
|
}
|
|
263
258
|
}
|
|
264
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
|
+
|
|
265
271
|
async enterTopLevelState() {
|
|
266
272
|
switch (this.state.name) {
|
|
267
273
|
case 'PRIVATE': {
|
|
@@ -285,8 +291,7 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
285
291
|
}
|
|
286
292
|
|
|
287
293
|
// Commit all staged stores from the job that was just completed, then begin a new job
|
|
288
|
-
await this.
|
|
289
|
-
this.currentJobId = this.jobCoordinator.beginJob();
|
|
294
|
+
await this.cycleJob();
|
|
290
295
|
|
|
291
296
|
this.oracleHandler = new TXEOracleTopLevelContext(
|
|
292
297
|
this.stateMachine,
|
|
@@ -300,7 +305,6 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
300
305
|
this.senderAddressBookStore,
|
|
301
306
|
this.capsuleStore,
|
|
302
307
|
this.privateEventStore,
|
|
303
|
-
this.currentJobId,
|
|
304
308
|
this.nextBlockTimestamp,
|
|
305
309
|
this.version,
|
|
306
310
|
this.chainId,
|