@aztec/end-to-end 4.0.0-devnet.2-patch.4 → 4.0.0-devnet.3-patch.0
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/bench/client_flows/client_flows_benchmark.d.ts +1 -1
- package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
- package/dest/bench/client_flows/client_flows_benchmark.js +17 -10
- package/dest/bench/utils.d.ts +1 -1
- package/dest/bench/utils.d.ts.map +1 -1
- package/dest/bench/utils.js +6 -3
- package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +1 -1
- package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -1
- package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +14 -14
- package/dest/e2e_epochs/epochs_test.d.ts +3 -1
- package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
- package/dest/e2e_epochs/epochs_test.js +5 -2
- package/dest/e2e_fees/fees_test.d.ts +1 -1
- package/dest/e2e_fees/fees_test.d.ts.map +1 -1
- package/dest/e2e_fees/fees_test.js +13 -6
- package/dest/e2e_nested_contract/nested_contract_test.d.ts +1 -1
- package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
- package/dest/e2e_nested_contract/nested_contract_test.js +4 -6
- package/dest/e2e_p2p/inactivity_slash_test.d.ts +1 -1
- package/dest/e2e_p2p/inactivity_slash_test.d.ts.map +1 -1
- package/dest/e2e_p2p/inactivity_slash_test.js +1 -0
- package/dest/e2e_p2p/p2p_network.d.ts +3 -2
- package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
- package/dest/e2e_p2p/p2p_network.js +21 -4
- package/dest/e2e_p2p/shared.d.ts +15 -1
- package/dest/e2e_p2p/shared.d.ts.map +1 -1
- package/dest/e2e_p2p/shared.js +25 -2
- package/dest/e2e_token_contract/token_contract_test.d.ts +1 -1
- package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
- package/dest/e2e_token_contract/token_contract_test.js +11 -11
- package/dest/fixtures/authwit_proxy.d.ts +3 -3
- package/dest/fixtures/authwit_proxy.d.ts.map +1 -1
- package/dest/fixtures/e2e_prover_test.d.ts +1 -1
- package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
- package/dest/fixtures/e2e_prover_test.js +6 -6
- package/dest/fixtures/setup.d.ts +8 -5
- package/dest/fixtures/setup.d.ts.map +1 -1
- package/dest/fixtures/setup.js +16 -12
- package/dest/fixtures/token_utils.d.ts +2 -2
- package/dest/fixtures/token_utils.d.ts.map +1 -1
- package/dest/fixtures/token_utils.js +5 -4
- package/dest/shared/cross_chain_test_harness.d.ts +1 -1
- package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
- package/dest/shared/cross_chain_test_harness.js +13 -13
- package/dest/shared/gas_portal_test_harness.js +2 -2
- package/dest/shared/submit-transactions.d.ts +1 -1
- package/dest/shared/submit-transactions.d.ts.map +1 -1
- package/dest/shared/submit-transactions.js +1 -1
- package/dest/shared/uniswap_l1_l2.d.ts +1 -1
- package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
- package/dest/shared/uniswap_l1_l2.js +14 -17
- package/dest/simulators/lending_simulator.d.ts +1 -1
- package/dest/simulators/lending_simulator.d.ts.map +1 -1
- package/dest/simulators/lending_simulator.js +4 -4
- package/dest/simulators/token_simulator.d.ts +1 -1
- package/dest/simulators/token_simulator.d.ts.map +1 -1
- package/dest/simulators/token_simulator.js +2 -2
- package/dest/spartan/setup_test_wallets.d.ts +4 -2
- package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
- package/dest/spartan/setup_test_wallets.js +28 -15
- package/dest/spartan/utils/index.d.ts +2 -1
- package/dest/spartan/utils/index.d.ts.map +1 -1
- package/dest/spartan/utils/index.js +2 -0
- package/dest/test-wallet/test_wallet.d.ts +10 -17
- package/dest/test-wallet/test_wallet.d.ts.map +1 -1
- package/dest/test-wallet/test_wallet.js +48 -49
- package/dest/test-wallet/wallet_worker_script.js +41 -33
- package/dest/test-wallet/worker_wallet.d.ts +4 -4
- package/dest/test-wallet/worker_wallet.d.ts.map +1 -1
- package/dest/test-wallet/worker_wallet.js +53 -5
- package/dest/test-wallet/worker_wallet_schema.d.ts +8 -5
- package/dest/test-wallet/worker_wallet_schema.d.ts.map +1 -1
- package/package.json +40 -40
- package/src/bench/client_flows/client_flows_benchmark.ts +39 -31
- package/src/bench/utils.ts +7 -2
- package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +18 -14
- package/src/e2e_epochs/epochs_test.ts +14 -2
- package/src/e2e_fees/fees_test.ts +13 -6
- package/src/e2e_nested_contract/nested_contract_test.ts +6 -4
- package/src/e2e_p2p/inactivity_slash_test.ts +1 -0
- package/src/e2e_p2p/p2p_network.ts +28 -2
- package/src/e2e_p2p/shared.ts +45 -2
- package/src/e2e_token_contract/token_contract_test.ts +16 -8
- package/src/fixtures/e2e_prover_test.ts +11 -5
- package/src/fixtures/setup.ts +25 -16
- package/src/fixtures/token_utils.ts +6 -3
- package/src/shared/cross_chain_test_harness.ts +13 -9
- package/src/shared/gas_portal_test_harness.ts +1 -1
- package/src/shared/submit-transactions.ts +4 -1
- package/src/shared/uniswap_l1_l2.ts +35 -28
- package/src/simulators/lending_simulator.ts +8 -4
- package/src/simulators/token_simulator.ts +6 -2
- package/src/spartan/setup_test_wallets.ts +61 -17
- package/src/spartan/utils/index.ts +3 -0
- package/src/test-wallet/test_wallet.ts +61 -66
- package/src/test-wallet/wallet_worker_script.ts +47 -30
- package/src/test-wallet/worker_wallet.ts +55 -7
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { generateSchnorrAccounts } from '@aztec/accounts/testing';
|
|
2
|
+
import { NO_FROM } from '@aztec/aztec.js/account';
|
|
2
3
|
import { AztecAddress } from '@aztec/aztec.js/addresses';
|
|
3
4
|
import { NO_WAIT } from '@aztec/aztec.js/contracts';
|
|
4
5
|
import { L1FeeJuicePortalManager } from '@aztec/aztec.js/ethereum';
|
|
@@ -88,11 +89,19 @@ export async function deploySponsoredTestAccountsWithTokens(
|
|
|
88
89
|
|
|
89
90
|
const paymentMethod = new SponsoredFeePaymentMethod(await getSponsoredFPCAddress());
|
|
90
91
|
const recipientDeployMethod = await recipientAccount.getDeployMethod();
|
|
91
|
-
await recipientDeployMethod.send({
|
|
92
|
+
await recipientDeployMethod.send({
|
|
93
|
+
from: NO_FROM,
|
|
94
|
+
fee: { paymentMethod },
|
|
95
|
+
wait: { timeout: 2400 },
|
|
96
|
+
});
|
|
92
97
|
await Promise.all(
|
|
93
98
|
fundedAccounts.map(async a => {
|
|
94
99
|
const deployMethod = await a.getDeployMethod();
|
|
95
|
-
await deployMethod.send({
|
|
100
|
+
await deployMethod.send({
|
|
101
|
+
from: NO_FROM,
|
|
102
|
+
fee: { paymentMethod },
|
|
103
|
+
wait: { timeout: 2400 },
|
|
104
|
+
}); // increase timeout on purpose in order to account for two empty epochs
|
|
96
105
|
logger.info(`Account deployed at ${a.address}`);
|
|
97
106
|
}),
|
|
98
107
|
);
|
|
@@ -121,16 +130,28 @@ export async function deploySponsoredTestAccountsWithTokens(
|
|
|
121
130
|
}
|
|
122
131
|
|
|
123
132
|
async function deployAccountWithDiagnostics(
|
|
124
|
-
account: { getDeployMethod: () => Promise<{ send: (opts: any) => any }>; address: any },
|
|
133
|
+
account: { getDeployMethod: () => Promise<{ simulate: (opts: any) => any; send: (opts: any) => any }>; address: any },
|
|
125
134
|
paymentMethod: SponsoredFeePaymentMethod,
|
|
126
135
|
aztecNode: AztecNode,
|
|
127
136
|
logger: Logger,
|
|
128
137
|
accountLabel: string,
|
|
138
|
+
estimateGas?: boolean,
|
|
129
139
|
): Promise<void> {
|
|
130
140
|
const deployMethod = await account.getDeployMethod();
|
|
131
141
|
let txHash;
|
|
132
142
|
try {
|
|
133
|
-
|
|
143
|
+
let gasSettings;
|
|
144
|
+
if (estimateGas) {
|
|
145
|
+
const sim = await deployMethod.simulate({ from: NO_FROM, fee: { paymentMethod } });
|
|
146
|
+
gasSettings = sim.estimatedGas;
|
|
147
|
+
logger.info(`${accountLabel} estimated gas: DA=${gasSettings.gasLimits.daGas} L2=${gasSettings.gasLimits.l2Gas}`);
|
|
148
|
+
}
|
|
149
|
+
const deployResult = await deployMethod.send({
|
|
150
|
+
from: NO_FROM,
|
|
151
|
+
fee: { paymentMethod, gasSettings },
|
|
152
|
+
wait: NO_WAIT,
|
|
153
|
+
});
|
|
154
|
+
txHash = deployResult.txHash;
|
|
134
155
|
await waitForTx(aztecNode, txHash, { timeout: 2400 });
|
|
135
156
|
logger.info(`${accountLabel} deployed at ${account.address}`);
|
|
136
157
|
} catch (error) {
|
|
@@ -152,18 +173,29 @@ async function deployAccountWithDiagnostics(
|
|
|
152
173
|
}
|
|
153
174
|
|
|
154
175
|
async function deployAccountsInBatches(
|
|
155
|
-
accounts: {
|
|
176
|
+
accounts: {
|
|
177
|
+
getDeployMethod: () => Promise<{ simulate: (opts: any) => any; send: (opts: any) => any }>;
|
|
178
|
+
address: any;
|
|
179
|
+
}[],
|
|
156
180
|
paymentMethod: SponsoredFeePaymentMethod,
|
|
157
181
|
aztecNode: AztecNode,
|
|
158
182
|
logger: Logger,
|
|
159
183
|
labelPrefix: string,
|
|
160
184
|
batchSize = 2,
|
|
185
|
+
estimateGas?: boolean,
|
|
161
186
|
): Promise<void> {
|
|
162
187
|
for (let i = 0; i < accounts.length; i += batchSize) {
|
|
163
188
|
const batch = accounts.slice(i, i + batchSize);
|
|
164
189
|
await Promise.all(
|
|
165
190
|
batch.map((account, idx) =>
|
|
166
|
-
deployAccountWithDiagnostics(
|
|
191
|
+
deployAccountWithDiagnostics(
|
|
192
|
+
account,
|
|
193
|
+
paymentMethod,
|
|
194
|
+
aztecNode,
|
|
195
|
+
logger,
|
|
196
|
+
`${labelPrefix}${i + idx + 1}`,
|
|
197
|
+
estimateGas,
|
|
198
|
+
),
|
|
167
199
|
),
|
|
168
200
|
);
|
|
169
201
|
}
|
|
@@ -174,6 +206,7 @@ export async function deploySponsoredTestAccounts(
|
|
|
174
206
|
aztecNode: AztecNode,
|
|
175
207
|
logger: Logger,
|
|
176
208
|
numberOfFundedWallets = 1,
|
|
209
|
+
opts?: { estimateGas?: boolean },
|
|
177
210
|
): Promise<TestAccountsWithoutTokens> {
|
|
178
211
|
const [recipient, ...funded] = await generateSchnorrAccounts(numberOfFundedWallets + 1);
|
|
179
212
|
const recipientAccount = await wallet.createSchnorrAccount(recipient.secret, recipient.salt);
|
|
@@ -183,8 +216,23 @@ export async function deploySponsoredTestAccounts(
|
|
|
183
216
|
|
|
184
217
|
const paymentMethod = new SponsoredFeePaymentMethod(await getSponsoredFPCAddress());
|
|
185
218
|
|
|
186
|
-
await deployAccountWithDiagnostics(
|
|
187
|
-
|
|
219
|
+
await deployAccountWithDiagnostics(
|
|
220
|
+
recipientAccount,
|
|
221
|
+
paymentMethod,
|
|
222
|
+
aztecNode,
|
|
223
|
+
logger,
|
|
224
|
+
'Recipient account',
|
|
225
|
+
opts?.estimateGas,
|
|
226
|
+
);
|
|
227
|
+
await deployAccountsInBatches(
|
|
228
|
+
fundedAccounts,
|
|
229
|
+
paymentMethod,
|
|
230
|
+
aztecNode,
|
|
231
|
+
logger,
|
|
232
|
+
'Funded account ',
|
|
233
|
+
2,
|
|
234
|
+
opts?.estimateGas,
|
|
235
|
+
);
|
|
188
236
|
|
|
189
237
|
return {
|
|
190
238
|
aztecNode,
|
|
@@ -222,7 +270,7 @@ export async function deployTestAccountsWithTokens(
|
|
|
222
270
|
fundedAccounts.map(async (a, i) => {
|
|
223
271
|
const paymentMethod = new FeeJuicePaymentMethodWithClaim(a.address, claims[i]);
|
|
224
272
|
const deployMethod = await a.getDeployMethod();
|
|
225
|
-
await deployMethod.send({ from:
|
|
273
|
+
await deployMethod.send({ from: NO_FROM, fee: { paymentMethod } });
|
|
226
274
|
logger.info(`Account deployed at ${a.address}`);
|
|
227
275
|
}),
|
|
228
276
|
);
|
|
@@ -266,7 +314,7 @@ async function bridgeL1FeeJuice(
|
|
|
266
314
|
const claim = await portal.bridgeTokensPublic(recipient, amount, true /* mint */);
|
|
267
315
|
|
|
268
316
|
const isSynced = async () =>
|
|
269
|
-
(await aztecNode.
|
|
317
|
+
(await aztecNode.getL1ToL2MessageCheckpoint(Fr.fromHexString(claim.messageHash))) !== undefined;
|
|
270
318
|
await retryUntil(isSynced, `message ${claim.messageHash} sync`, 24, 0.5);
|
|
271
319
|
|
|
272
320
|
log.info(`Created a claim for ${amount} L1 fee juice to ${recipient}.`, claim);
|
|
@@ -298,13 +346,9 @@ async function deployTokenAndMint(
|
|
|
298
346
|
logger: Logger,
|
|
299
347
|
) {
|
|
300
348
|
logger.verbose(`Deploying TokenContract...`);
|
|
301
|
-
const {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
TOKEN_NAME,
|
|
305
|
-
TOKEN_SYMBOL,
|
|
306
|
-
TOKEN_DECIMALS,
|
|
307
|
-
).send({
|
|
349
|
+
const {
|
|
350
|
+
receipt: { contract: tokenContract },
|
|
351
|
+
} = await TokenContract.deploy(wallet, admin, TOKEN_NAME, TOKEN_SYMBOL, TOKEN_DECIMALS).send({
|
|
308
352
|
from: admin,
|
|
309
353
|
fee: {
|
|
310
354
|
paymentMethod,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EcdsaKAccountContract, EcdsaRAccountContract } from '@aztec/accounts/ecdsa';
|
|
2
2
|
import { SchnorrAccountContract } from '@aztec/accounts/schnorr';
|
|
3
3
|
import { StubAccountContractArtifact, createStubAccount } from '@aztec/accounts/stub';
|
|
4
|
-
import { type Account, type AccountContract,
|
|
4
|
+
import { type Account, type AccountContract, NO_FROM } from '@aztec/aztec.js/account';
|
|
5
5
|
import {
|
|
6
6
|
type CallIntent,
|
|
7
7
|
type ContractFunctionInteractionCallIntent,
|
|
@@ -14,9 +14,10 @@ import {
|
|
|
14
14
|
import type { AztecNode } from '@aztec/aztec.js/node';
|
|
15
15
|
import { AccountManager, type SendOptions } from '@aztec/aztec.js/wallet';
|
|
16
16
|
import type { DefaultAccountEntrypointOptions } from '@aztec/entrypoints/account';
|
|
17
|
+
import { DefaultEntrypoint } from '@aztec/entrypoints/default';
|
|
17
18
|
import { Fq, Fr } from '@aztec/foundation/curves/bn254';
|
|
18
19
|
import { GrumpkinScalar } from '@aztec/foundation/curves/grumpkin';
|
|
19
|
-
import type {
|
|
20
|
+
import type { NotesFilter } from '@aztec/pxe/client/lazy';
|
|
20
21
|
import { type PXEConfig, getPXEConfig } from '@aztec/pxe/config';
|
|
21
22
|
import { PXE, type PXECreationOptions, createPXE } from '@aztec/pxe/server';
|
|
22
23
|
import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
@@ -24,9 +25,16 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
|
24
25
|
import { getContractInstanceFromInstantiationParams } from '@aztec/stdlib/contract';
|
|
25
26
|
import { deriveSigningKey } from '@aztec/stdlib/keys';
|
|
26
27
|
import type { NoteDao } from '@aztec/stdlib/note';
|
|
27
|
-
import type {
|
|
28
|
+
import type {
|
|
29
|
+
BlockHeader,
|
|
30
|
+
SimulationOverrides,
|
|
31
|
+
TxExecutionRequest,
|
|
32
|
+
TxHash,
|
|
33
|
+
TxReceipt,
|
|
34
|
+
TxSimulationResult,
|
|
35
|
+
} from '@aztec/stdlib/tx';
|
|
28
36
|
import { ExecutionPayload, mergeExecutionPayloads } from '@aztec/stdlib/tx';
|
|
29
|
-
import { BaseWallet, type
|
|
37
|
+
import { BaseWallet, type SimulateViaEntrypointOptions } from '@aztec/wallet-sdk/base-wallet';
|
|
30
38
|
|
|
31
39
|
import { AztecNodeProxy, ProvenTx } from './utils.js';
|
|
32
40
|
|
|
@@ -104,10 +112,7 @@ export class TestWallet extends BaseWallet {
|
|
|
104
112
|
|
|
105
113
|
async getFakeAccountDataFor(address: AztecAddress) {
|
|
106
114
|
const originalAccount = await this.getAccountFromAddress(address);
|
|
107
|
-
|
|
108
|
-
throw new Error(`Cannot create fake account data for SignerlessAccount at address: ${address}`);
|
|
109
|
-
}
|
|
110
|
-
const originalAddress = (originalAccount as Account).getCompleteAddress();
|
|
115
|
+
const originalAddress = originalAccount.getCompleteAddress();
|
|
111
116
|
const contractInstance = await this.pxe.getContractInstance(originalAddress.address);
|
|
112
117
|
if (!contractInstance) {
|
|
113
118
|
throw new Error(`No contract instance found for address: ${originalAddress.address}`);
|
|
@@ -125,21 +130,15 @@ export class TestWallet extends BaseWallet {
|
|
|
125
130
|
protected accounts: Map<string, Account> = new Map();
|
|
126
131
|
|
|
127
132
|
/**
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* generating kernel witnesses. When false, simulateViaEntrypoint defers to the standard
|
|
133
|
-
* simulation path via the real account entrypoint.
|
|
133
|
+
* Controls how the test wallet simulates transactions:
|
|
134
|
+
* - `kernelless`: Skips kernel circuits but uses the real account contract. Default.
|
|
135
|
+
* - `kernelless-override`: Skips kernels and replaces the account with a stub that doesn't do authwit validation.
|
|
136
|
+
* - `full`: Uses real kernel circuits and real account contracts. Slow!
|
|
134
137
|
*/
|
|
135
|
-
private
|
|
136
|
-
|
|
137
|
-
enableSimulatedSimulations() {
|
|
138
|
-
this.simulatedSimulations = true;
|
|
139
|
-
}
|
|
138
|
+
private simulationMode: 'kernelless' | 'kernelless-override' | 'full' = 'kernelless';
|
|
140
139
|
|
|
141
|
-
|
|
142
|
-
this.
|
|
140
|
+
setSimulationMode(mode: 'kernelless' | 'kernelless-override' | 'full') {
|
|
141
|
+
this.simulationMode = mode;
|
|
143
142
|
}
|
|
144
143
|
|
|
145
144
|
setMinFeePadding(value?: number) {
|
|
@@ -147,12 +146,7 @@ export class TestWallet extends BaseWallet {
|
|
|
147
146
|
}
|
|
148
147
|
|
|
149
148
|
protected getAccountFromAddress(address: AztecAddress): Promise<Account> {
|
|
150
|
-
|
|
151
|
-
if (address.equals(AztecAddress.ZERO)) {
|
|
152
|
-
account = new SignerlessAccount();
|
|
153
|
-
} else {
|
|
154
|
-
account = this.accounts.get(address?.toString() ?? '');
|
|
155
|
-
}
|
|
149
|
+
const account = this.accounts.get(address?.toString() ?? '');
|
|
156
150
|
|
|
157
151
|
if (!account) {
|
|
158
152
|
throw new Error(`Account not found in wallet for address: ${address}`);
|
|
@@ -220,54 +214,55 @@ export class TestWallet extends BaseWallet {
|
|
|
220
214
|
return account.createAuthWit(intentInnerHash, chainInfo);
|
|
221
215
|
}
|
|
222
216
|
|
|
223
|
-
/**
|
|
224
|
-
* Override simulateViaEntrypoint to use fake accounts for kernelless simulation
|
|
225
|
-
* when simulatedSimulations is enabled. Otherwise falls through to the real entrypoint path.
|
|
226
|
-
*/
|
|
227
217
|
protected override async simulateViaEntrypoint(
|
|
228
218
|
executionPayload: ExecutionPayload,
|
|
229
|
-
|
|
230
|
-
feeOptions: FeeOptions,
|
|
231
|
-
scopes: AccessScopes,
|
|
232
|
-
skipTxValidation?: boolean,
|
|
233
|
-
skipFeeEnforcement?: boolean,
|
|
219
|
+
opts: SimulateViaEntrypointOptions,
|
|
234
220
|
): Promise<TxSimulationResult> {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
executionPayload,
|
|
238
|
-
from,
|
|
239
|
-
feeOptions,
|
|
240
|
-
scopes,
|
|
241
|
-
skipTxValidation,
|
|
242
|
-
skipFeeEnforcement,
|
|
243
|
-
);
|
|
244
|
-
}
|
|
245
|
-
|
|
221
|
+
const { from, feeOptions, scopes, skipTxValidation, skipFeeEnforcement } = opts;
|
|
222
|
+
const skipKernels = this.simulationMode !== 'full';
|
|
246
223
|
const feeExecutionPayload = await feeOptions.walletFeePaymentMethod?.getExecutionPayload();
|
|
247
|
-
const executionOptions: DefaultAccountEntrypointOptions = {
|
|
248
|
-
txNonce: Fr.random(),
|
|
249
|
-
cancellable: this.cancellableTransactions,
|
|
250
|
-
feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions,
|
|
251
|
-
};
|
|
252
224
|
const finalExecutionPayload = feeExecutionPayload
|
|
253
225
|
? mergeExecutionPayloads([feeExecutionPayload, executionPayload])
|
|
254
226
|
: executionPayload;
|
|
255
|
-
const { account: fromAccount, instance, artifact } = await this.getFakeAccountDataFor(from);
|
|
256
227
|
const chainInfo = await this.getChainInfo();
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
228
|
+
|
|
229
|
+
let overrides: SimulationOverrides | undefined;
|
|
230
|
+
let txRequest: TxExecutionRequest;
|
|
231
|
+
if (from === NO_FROM) {
|
|
232
|
+
const entrypoint = new DefaultEntrypoint();
|
|
233
|
+
txRequest = await entrypoint.createTxExecutionRequest(finalExecutionPayload, feeOptions.gasSettings, chainInfo);
|
|
234
|
+
} else {
|
|
235
|
+
const useOverride = this.simulationMode === 'kernelless-override';
|
|
236
|
+
let fromAccount: Account;
|
|
237
|
+
if (useOverride) {
|
|
238
|
+
const { account, instance, artifact } = await this.getFakeAccountDataFor(from);
|
|
239
|
+
fromAccount = account;
|
|
240
|
+
overrides = {
|
|
241
|
+
contracts: { [from.toString()]: { instance, artifact } },
|
|
242
|
+
};
|
|
243
|
+
} else {
|
|
244
|
+
fromAccount = await this.getAccountFromAddress(from);
|
|
245
|
+
}
|
|
246
|
+
const executionOptions: DefaultAccountEntrypointOptions = {
|
|
247
|
+
txNonce: Fr.random(),
|
|
248
|
+
cancellable: this.cancellableTransactions,
|
|
249
|
+
// If from is an address, feeOptions include the way the account contract should handle the fee payment
|
|
250
|
+
feePaymentMethodOptions: feeOptions.accountFeePaymentMethodOptions!,
|
|
251
|
+
};
|
|
252
|
+
txRequest = await fromAccount.createTxExecutionRequest(
|
|
253
|
+
finalExecutionPayload,
|
|
254
|
+
feeOptions.gasSettings,
|
|
255
|
+
chainInfo,
|
|
256
|
+
executionOptions,
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
266
260
|
return this.pxe.simulateTx(txRequest, {
|
|
267
261
|
simulatePublic: true,
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
262
|
+
skipKernels,
|
|
263
|
+
skipFeeEnforcement,
|
|
264
|
+
skipTxValidation,
|
|
265
|
+
overrides,
|
|
271
266
|
scopes,
|
|
272
267
|
});
|
|
273
268
|
}
|
|
@@ -275,7 +270,7 @@ export class TestWallet extends BaseWallet {
|
|
|
275
270
|
async proveTx(exec: ExecutionPayload, opts: Omit<SendOptions, 'wait'>): Promise<ProvenTx> {
|
|
276
271
|
const fee = await this.completeFeeOptions(opts.from, exec.feePayer, opts.fee?.gasSettings);
|
|
277
272
|
const txRequest = await this.createTxExecutionRequestFromPayloadAndFee(exec, opts.from, fee);
|
|
278
|
-
const txProvingResult = await this.pxe.proveTx(txRequest, this.
|
|
273
|
+
const txProvingResult = await this.pxe.proveTx(txRequest, this.scopesFrom(opts.from, opts.additionalScopes));
|
|
279
274
|
return new ProvenTx(
|
|
280
275
|
this.aztecNode,
|
|
281
276
|
await txProvingResult.toTx(),
|
|
@@ -1,43 +1,60 @@
|
|
|
1
1
|
import { createAztecNodeClient } from '@aztec/aztec.js/node';
|
|
2
|
+
import type { SendOptions } from '@aztec/aztec.js/wallet';
|
|
2
3
|
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
3
|
-
import
|
|
4
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
5
|
+
import type { ApiSchema, Fr } from '@aztec/foundation/schemas';
|
|
4
6
|
import { parseWithOptionals, schemaHasMethod } from '@aztec/foundation/schemas';
|
|
5
7
|
import { NodeListener, TransportServer } from '@aztec/foundation/transport';
|
|
8
|
+
import { ExecutionPayload, Tx } from '@aztec/stdlib/tx';
|
|
6
9
|
|
|
7
10
|
import { workerData } from 'worker_threads';
|
|
8
11
|
|
|
9
12
|
import { TestWallet } from './test_wallet.js';
|
|
10
13
|
import { WorkerWalletSchema } from './worker_wallet_schema.js';
|
|
11
14
|
|
|
12
|
-
const
|
|
15
|
+
const logger = createLogger('e2e:test-wallet:worker');
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
const
|
|
17
|
+
try {
|
|
18
|
+
const { nodeUrl, pxeConfig } = workerData as { nodeUrl: string; pxeConfig?: Record<string, unknown> };
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
// ProvenTx has non-serializable fields (node proxy, etc.) — extract only Tx-compatible fields
|
|
22
|
-
const { data, chonkProof, contractClassLogFields, publicFunctionCalldata } = provenTx;
|
|
23
|
-
return { data, chonkProof, contractClassLogFields, publicFunctionCalldata };
|
|
24
|
-
},
|
|
25
|
-
registerAccount: async (secret, salt) => {
|
|
26
|
-
const manager = await wallet.createSchnorrAccount(secret, salt);
|
|
27
|
-
return manager.address;
|
|
28
|
-
},
|
|
29
|
-
};
|
|
20
|
+
logger.info('Initializing worker wallet', { nodeUrl });
|
|
21
|
+
const node = createAztecNodeClient(nodeUrl);
|
|
22
|
+
const wallet = await TestWallet.create(node, pxeConfig);
|
|
23
|
+
logger.info('Worker wallet initialized');
|
|
30
24
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
25
|
+
const customMethods = {
|
|
26
|
+
proveTx: async (exec: ExecutionPayload, opts: Omit<SendOptions, 'wait'>) => {
|
|
27
|
+
const provenTx = await wallet.proveTx(exec, opts);
|
|
28
|
+
return new Tx(
|
|
29
|
+
provenTx.getTxHash(),
|
|
30
|
+
provenTx.data,
|
|
31
|
+
provenTx.chonkProof,
|
|
32
|
+
provenTx.contractClassLogFields,
|
|
33
|
+
provenTx.publicFunctionCalldata,
|
|
34
|
+
);
|
|
35
|
+
},
|
|
36
|
+
registerAccount: async (secret: Fr, salt: Fr) => {
|
|
37
|
+
const manager = await wallet.createSchnorrAccount(secret, salt);
|
|
38
|
+
return manager.address;
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const schema = WorkerWalletSchema as ApiSchema;
|
|
43
|
+
const listener = new NodeListener();
|
|
44
|
+
const server = new TransportServer<{ fn: string; args: string }>(listener, async msg => {
|
|
45
|
+
if (!schemaHasMethod(schema, msg.fn)) {
|
|
46
|
+
throw new Error(`Unknown method: ${msg.fn}`);
|
|
47
|
+
}
|
|
48
|
+
const jsonParams = JSON.parse(msg.args) as unknown[];
|
|
49
|
+
const args: any[] = await parseWithOptionals(jsonParams, schema[msg.fn].parameters());
|
|
50
|
+
// we have to erase the fn type in order to be able to spread ...args
|
|
51
|
+
const handler: ((...args: any[]) => Promise<any>) | undefined =
|
|
52
|
+
msg.fn in customMethods ? customMethods[msg.fn as keyof typeof customMethods] : undefined;
|
|
53
|
+
const result = handler ? await handler(...args) : await (wallet as any)[msg.fn](...args);
|
|
54
|
+
return jsonStringify(result);
|
|
55
|
+
});
|
|
56
|
+
server.start();
|
|
57
|
+
} catch (err: unknown) {
|
|
58
|
+
logger.error('Worker wallet initialization failed', { error: err instanceof Error ? err.stack : String(err) });
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
@@ -7,26 +7,29 @@ import type {
|
|
|
7
7
|
BatchedMethod,
|
|
8
8
|
ContractClassMetadata,
|
|
9
9
|
ContractMetadata,
|
|
10
|
+
ExecuteUtilityOptions,
|
|
10
11
|
PrivateEvent,
|
|
11
12
|
PrivateEventFilter,
|
|
12
13
|
ProfileOptions,
|
|
13
14
|
SendOptions,
|
|
14
15
|
SimulateOptions,
|
|
15
|
-
SimulateUtilityOptions,
|
|
16
16
|
Wallet,
|
|
17
17
|
WalletCapabilities,
|
|
18
18
|
} from '@aztec/aztec.js/wallet';
|
|
19
19
|
import type { ChainInfo } from '@aztec/entrypoints/interfaces';
|
|
20
20
|
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
21
21
|
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
22
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
23
|
+
import { promiseWithResolvers } from '@aztec/foundation/promise';
|
|
22
24
|
import type { ApiSchema } from '@aztec/foundation/schemas';
|
|
25
|
+
import { sleep } from '@aztec/foundation/sleep';
|
|
23
26
|
import { NodeConnector, TransportClient } from '@aztec/foundation/transport';
|
|
24
27
|
import type { PXEConfig } from '@aztec/pxe/config';
|
|
25
28
|
import type { ContractArtifact, EventMetadataDefinition, FunctionCall } from '@aztec/stdlib/abi';
|
|
26
29
|
import type { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
27
30
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
28
31
|
import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
|
|
29
|
-
import type { ExecutionPayload, TxProfileResult, TxSimulationResult,
|
|
32
|
+
import type { ExecutionPayload, TxProfileResult, TxSimulationResult, UtilityExecutionResult } from '@aztec/stdlib/tx';
|
|
30
33
|
import { Tx } from '@aztec/stdlib/tx';
|
|
31
34
|
|
|
32
35
|
import { Worker } from 'worker_threads';
|
|
@@ -35,6 +38,10 @@ import { WorkerWalletSchema } from './worker_wallet_schema.js';
|
|
|
35
38
|
|
|
36
39
|
type WorkerMsg = { fn: string; args: string };
|
|
37
40
|
|
|
41
|
+
const log = createLogger('e2e:test-wallet:worker-wallet');
|
|
42
|
+
|
|
43
|
+
const WORKER_READY_TIMEOUT_MS = 120_000;
|
|
44
|
+
|
|
38
45
|
/**
|
|
39
46
|
* Wallet implementation that offloads all work to a worker thread.
|
|
40
47
|
* Implements the Wallet interface by proxying calls over a transport layer
|
|
@@ -53,8 +60,18 @@ export class WorkerWallet implements Wallet {
|
|
|
53
60
|
* @returns A WorkerWallet ready to use.
|
|
54
61
|
*/
|
|
55
62
|
static async create(nodeUrl: string, pxeConfig?: Partial<PXEConfig>): Promise<WorkerWallet> {
|
|
56
|
-
|
|
63
|
+
// replace stc/ with dest/ so the wallet works in Jest tests
|
|
64
|
+
const workerUrl = new URL('./wallet_worker_script.js', import.meta.url);
|
|
65
|
+
workerUrl.pathname = workerUrl.pathname.replace('/src/', '/dest/');
|
|
66
|
+
// remove JEST_WORKER_ID so the worker uses pino-pretty transport instead of Jest's raw output.
|
|
67
|
+
const { JEST_WORKER_ID: _, ...parentEnv } = process.env;
|
|
68
|
+
const worker = new Worker(workerUrl, {
|
|
57
69
|
workerData: { nodeUrl, pxeConfig },
|
|
70
|
+
env: {
|
|
71
|
+
...parentEnv,
|
|
72
|
+
...(process.stderr.isTTY || process.env.FORCE_COLOR ? { FORCE_COLOR: '1' } : {}),
|
|
73
|
+
LOG_LEVEL: process.env.WORKER_LOG_LEVEL ?? 'warn',
|
|
74
|
+
},
|
|
58
75
|
});
|
|
59
76
|
|
|
60
77
|
const connector = new NodeConnector(worker);
|
|
@@ -62,8 +79,39 @@ export class WorkerWallet implements Wallet {
|
|
|
62
79
|
await client.open();
|
|
63
80
|
|
|
64
81
|
const wallet = new WorkerWallet(worker, client);
|
|
65
|
-
|
|
66
|
-
|
|
82
|
+
|
|
83
|
+
const { promise: workerDied, reject: rejectWorkerDied } = promiseWithResolvers<void>();
|
|
84
|
+
// reject if the worker exits or errors before the warmup completes.
|
|
85
|
+
const onError = (err: Error): void => {
|
|
86
|
+
worker.off('exit', onExit!);
|
|
87
|
+
rejectWorkerDied(new Error(`Worker wallet thread error: ${err.message}`));
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const onExit = (code: number): void => {
|
|
91
|
+
worker.off('error', onError!);
|
|
92
|
+
rejectWorkerDied(new Error(`Worker wallet thread exited with code ${code} before becoming ready`));
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
worker.once('error', onError);
|
|
96
|
+
worker.once('exit', onExit);
|
|
97
|
+
|
|
98
|
+
const timeout = sleep(WORKER_READY_TIMEOUT_MS).then(() => {
|
|
99
|
+
throw new Error(`Worker wallet creation timed out after ${WORKER_READY_TIMEOUT_MS / 1000}s`);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
// wait for worker wallet to start
|
|
104
|
+
await Promise.race([wallet.getChainInfo(), workerDied, timeout]);
|
|
105
|
+
} catch (err) {
|
|
106
|
+
log.error('Worker wallet creation failed, cleaning up', { error: String(err) });
|
|
107
|
+
client.close();
|
|
108
|
+
await worker.terminate();
|
|
109
|
+
throw err;
|
|
110
|
+
} finally {
|
|
111
|
+
worker.off('error', onError);
|
|
112
|
+
worker.off('exit', onExit);
|
|
113
|
+
}
|
|
114
|
+
|
|
67
115
|
return wallet;
|
|
68
116
|
}
|
|
69
117
|
|
|
@@ -121,8 +169,8 @@ export class WorkerWallet implements Wallet {
|
|
|
121
169
|
return this.call('simulateTx', exec, opts);
|
|
122
170
|
}
|
|
123
171
|
|
|
124
|
-
|
|
125
|
-
return this.call('
|
|
172
|
+
executeUtility(call: FunctionCall, opts: ExecuteUtilityOptions): Promise<UtilityExecutionResult> {
|
|
173
|
+
return this.call('executeUtility', call, opts);
|
|
126
174
|
}
|
|
127
175
|
|
|
128
176
|
profileTx(exec: ExecutionPayload, opts: ProfileOptions): Promise<TxProfileResult> {
|