@aztec/end-to-end 0.0.1-commit.ffe5b04ea → 0.0.1-commit.fff30aa
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/README.md +27 -0
- 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 +3 -4
- package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +3 -2
- 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 +1 -1
- 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.js +1 -1
- 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 +1 -1
- package/dest/e2e_p2p/p2p_network.js +1 -1
- package/dest/e2e_p2p/shared.d.ts +19 -1
- package/dest/e2e_p2p/shared.d.ts.map +1 -1
- package/dest/e2e_p2p/shared.js +31 -0
- package/dest/fixtures/authwit_proxy.d.ts +1 -1
- package/dest/fixtures/authwit_proxy.d.ts.map +1 -1
- package/dest/fixtures/authwit_proxy.js +4 -0
- package/dest/fixtures/setup.d.ts +9 -5
- package/dest/fixtures/setup.d.ts.map +1 -1
- package/dest/fixtures/setup.js +13 -9
- package/dest/forward-compatibility/wallet_rpc_client.d.ts +7 -0
- package/dest/forward-compatibility/wallet_rpc_client.d.ts.map +1 -0
- package/dest/forward-compatibility/wallet_rpc_client.js +15 -0
- package/dest/forward-compatibility/wallet_service.d.ts +3 -0
- package/dest/forward-compatibility/wallet_service.d.ts.map +1 -0
- package/dest/forward-compatibility/wallet_service.js +109 -0
- package/dest/install_legacy_contracts.d.cts +10 -0
- package/dest/install_legacy_contracts.d.cts.map +1 -0
- package/dest/legacy-jest-resolver.d.cts +3 -0
- package/dest/legacy-jest-resolver.d.cts.map +1 -0
- package/dest/shared/jest_setup.js +1 -41
- package/dest/shared/submit-transactions.d.ts +1 -1
- package/dest/shared/submit-transactions.d.ts.map +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 +9 -12
- 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 +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 +24 -12
- package/dest/spartan/tx_metrics.js +1 -1
- package/dest/spartan/utils/config.d.ts +1 -4
- package/dest/spartan/utils/config.d.ts.map +1 -1
- package/dest/spartan/utils/config.js +1 -2
- package/dest/spartan/utils/nodes.d.ts +5 -4
- package/dest/spartan/utils/nodes.d.ts.map +1 -1
- package/dest/spartan/utils/nodes.js +9 -9
- package/dest/test-wallet/test_wallet.d.ts +24 -23
- package/dest/test-wallet/test_wallet.d.ts.map +1 -1
- package/dest/test-wallet/test_wallet.js +115 -80
- 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_schema.d.ts +3 -3
- package/package.json +45 -43
- package/src/bench/client_flows/client_flows_benchmark.ts +3 -3
- package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +3 -6
- package/src/e2e_epochs/epochs_test.ts +14 -2
- package/src/e2e_fees/fees_test.ts +1 -1
- package/src/e2e_p2p/inactivity_slash_test.ts +1 -0
- package/src/e2e_p2p/p2p_network.ts +1 -1
- package/src/e2e_p2p/shared.ts +52 -0
- package/src/fixtures/authwit_proxy.ts +4 -0
- package/src/fixtures/dumps/epoch_proof_result.json +1 -1
- package/src/fixtures/setup.ts +20 -12
- package/src/forward-compatibility/wallet_rpc_client.ts +14 -0
- package/src/forward-compatibility/wallet_service.ts +104 -0
- package/src/install_legacy_contracts.cjs +75 -0
- package/src/legacy-jest-resolver.cjs +101 -0
- package/src/shared/jest_setup.ts +1 -51
- package/src/shared/submit-transactions.ts +4 -1
- package/src/shared/uniswap_l1_l2.ts +29 -24
- package/src/simulators/lending_simulator.ts +4 -2
- package/src/spartan/setup_test_wallets.ts +48 -9
- package/src/spartan/tx_metrics.ts +1 -1
- package/src/spartan/utils/config.ts +0 -1
- package/src/spartan/utils/nodes.ts +10 -15
- package/src/test-wallet/test_wallet.ts +144 -99
- package/src/test-wallet/worker_wallet.ts +3 -2
- package/dest/fixtures/elu_monitor.d.ts +0 -21
- package/dest/fixtures/elu_monitor.d.ts.map +0 -1
- package/dest/fixtures/elu_monitor.js +0 -102
- package/src/fixtures/elu_monitor.ts +0 -126
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env -S node --no-warnings
|
|
2
|
+
/**
|
|
3
|
+
* Standalone entrypoint that spins up a local Aztec network (L1 + node) and exposes a {@link NodeEmbeddedWallet} over
|
|
4
|
+
* JSON-RPC.
|
|
5
|
+
*
|
|
6
|
+
* Intended for forward-compatibility testing: an **old** release image runs this script so that **new** tests can send
|
|
7
|
+
* new artifacts to old runtime code (loadContractArtifact, ACIR simulator, class-ID computation, entrypoint encoding,
|
|
8
|
+
* etc.).
|
|
9
|
+
*/
|
|
10
|
+
import { getSchnorrAccountContractAddress } from '@aztec/accounts/schnorr';
|
|
11
|
+
import { getInitialTestAccountsData } from '@aztec/accounts/testing';
|
|
12
|
+
import { createLocalNetwork } from '@aztec/aztec';
|
|
13
|
+
import { Fr } from '@aztec/aztec.js/fields';
|
|
14
|
+
import { WalletSchema } from '@aztec/aztec.js/wallet';
|
|
15
|
+
import { GrumpkinScalar } from '@aztec/foundation/curves/grumpkin';
|
|
16
|
+
import { createNamespacedSafeJsonRpcServer, startHttpRpcServer } from '@aztec/foundation/json-rpc/server';
|
|
17
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
18
|
+
import { AztecNodeApiSchema } from '@aztec/stdlib/interfaces/client';
|
|
19
|
+
import { EmbeddedWallet } from '@aztec/wallets/embedded';
|
|
20
|
+
|
|
21
|
+
const logger = createLogger('wallet-service');
|
|
22
|
+
|
|
23
|
+
const { ETHEREUM_HOSTS = 'http://localhost:8545', NODE_PORT = '8080', WALLET_PORT = '8081' } = process.env;
|
|
24
|
+
|
|
25
|
+
async function main() {
|
|
26
|
+
const l1RpcUrls = ETHEREUM_HOSTS.split(',').map(url => url.trim());
|
|
27
|
+
|
|
28
|
+
// Some tests (e.g. AMM) need 4 accounts but only 3 are funded via genesis. Generate deterministic keys for a 4th
|
|
29
|
+
// account so we can compute its address before network startup and include it in genesis funding. We cannot do this
|
|
30
|
+
// in the test because Wallet interface does not expose account creation functionality (only TestWallet exposes that
|
|
31
|
+
// but that's not used in forward compatibility testing).
|
|
32
|
+
const extraAccountSecret = Fr.fromHexString('0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef');
|
|
33
|
+
const extraAccountSalt = Fr.ZERO;
|
|
34
|
+
const extraAccountSigningKey = GrumpkinScalar.random();
|
|
35
|
+
const extraAccountAddress = await getSchnorrAccountContractAddress(
|
|
36
|
+
extraAccountSecret,
|
|
37
|
+
extraAccountSalt,
|
|
38
|
+
extraAccountSigningKey,
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
logger.info('Starting wallet service...', { l1RpcUrls });
|
|
42
|
+
|
|
43
|
+
// createLocalNetwork deploys L1 contracts, starts the node, and optionally deploys funded test accounts (when
|
|
44
|
+
// TEST_ACCOUNTS=true via env). We are not proving anything just like is done when local network is started by
|
|
45
|
+
// the `aztecStart` function. The extra account address is passed via prefundAddresses so it gets fee juice at genesis.
|
|
46
|
+
const { node, stop: stopNetwork } = await createLocalNetwork(
|
|
47
|
+
{ l1RpcUrls, realProofs: false, prefundAddresses: [extraAccountAddress.toString()] },
|
|
48
|
+
logger.info,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
// Create an ephemeral embedded wallet backed by the local node.
|
|
52
|
+
const wallet = await EmbeddedWallet.create(node, { ephemeral: true });
|
|
53
|
+
|
|
54
|
+
// Re-register the initial test accounts so they are available via wallet.getAccounts(). createLocalNetwork deploys
|
|
55
|
+
// them onchain but uses a temporary wallet that is then stopped.
|
|
56
|
+
//
|
|
57
|
+
// We use the non-lazy import path (@aztec/accounts/testing, not /lazy) to avoid the dynamic JSON import that is
|
|
58
|
+
// incompatible with Node.js import attribute enforcement.
|
|
59
|
+
const testAccountsData = await getInitialTestAccountsData();
|
|
60
|
+
const accounts = await Promise.all(
|
|
61
|
+
testAccountsData.map(({ secret, salt, signingKey }) => wallet.createSchnorrAccount(secret, salt, signingKey)),
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
// Register and deploy the 4th account.
|
|
65
|
+
const extraAccount = await wallet.createSchnorrAccount(extraAccountSecret, extraAccountSalt, extraAccountSigningKey);
|
|
66
|
+
const deployMethod = await extraAccount.getDeployMethod();
|
|
67
|
+
await deployMethod.send({ from: accounts[0].address });
|
|
68
|
+
|
|
69
|
+
logger.info('Embedded wallet created', {
|
|
70
|
+
accounts: [...accounts, extraAccount].map(a => a.address.toString()),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Contract artifacts are large, so allow generous body sizes for RPC requests.
|
|
74
|
+
const rpcOptions = { maxBodySizeBytes: '50mb' };
|
|
75
|
+
|
|
76
|
+
// Serve node RPC
|
|
77
|
+
const nodeRpcServer = createNamespacedSafeJsonRpcServer({ node: [node, AztecNodeApiSchema] }, rpcOptions);
|
|
78
|
+
const nodeHttpServer = await startHttpRpcServer(nodeRpcServer, { port: NODE_PORT });
|
|
79
|
+
logger.info(`Node JSON-RPC server listening on port ${nodeHttpServer.port}`);
|
|
80
|
+
|
|
81
|
+
// Serve wallet RPC
|
|
82
|
+
const walletRpcServer = createNamespacedSafeJsonRpcServer({ wallet: [wallet, WalletSchema] }, rpcOptions);
|
|
83
|
+
const walletHttpServer = await startHttpRpcServer(walletRpcServer, { port: WALLET_PORT });
|
|
84
|
+
logger.info(`Wallet JSON-RPC server listening on port ${walletHttpServer.port}`);
|
|
85
|
+
|
|
86
|
+
const shutdown = async () => {
|
|
87
|
+
logger.info('Shutting down...');
|
|
88
|
+
nodeHttpServer.close();
|
|
89
|
+
walletHttpServer.close();
|
|
90
|
+
await wallet.stop();
|
|
91
|
+
await stopNetwork();
|
|
92
|
+
process.exit(0);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
96
|
+
process.once('SIGINT', shutdown);
|
|
97
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
98
|
+
process.once('SIGTERM', shutdown);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
main().catch(err => {
|
|
102
|
+
logger.error('Wallet service failed to start', err);
|
|
103
|
+
process.exit(1);
|
|
104
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Installs pinned legacy @aztec/* contract-artifact packages into .legacy-contracts/<version>/.
|
|
3
|
+
//
|
|
4
|
+
// Called from two places:
|
|
5
|
+
// - bootstrap.sh ci-compat-e2e: pre-populates the cache on the host before hermetic test
|
|
6
|
+
// containers launch. The containers run with --net=none (see ci3/docker_isolate), so on-demand
|
|
7
|
+
// installs from inside them fail with EAI_AGAIN.
|
|
8
|
+
// - legacy-jest-resolver.cjs: on-demand install for local dev, where jest runs with network.
|
|
9
|
+
//
|
|
10
|
+
// Idempotent: no-op when all packages are already present.
|
|
11
|
+
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
12
|
+
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const { execFileSync } = require('child_process');
|
|
16
|
+
|
|
17
|
+
const REDIRECTED = ['@aztec/noir-contracts.js', '@aztec/noir-test-contracts.js', '@aztec/accounts'];
|
|
18
|
+
|
|
19
|
+
const e2eRoot = path.resolve(__dirname, '..');
|
|
20
|
+
|
|
21
|
+
function cacheRoot(version) {
|
|
22
|
+
return path.join(e2eRoot, '.legacy-contracts', version);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function pkgJsonPath(version, pkg) {
|
|
26
|
+
return path.join(cacheRoot(version), 'node_modules', pkg, 'package.json');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function installLegacyContracts(version) {
|
|
30
|
+
if (!version) {
|
|
31
|
+
throw new Error('installLegacyContracts: version is required');
|
|
32
|
+
}
|
|
33
|
+
if (REDIRECTED.every(pkg => fs.existsSync(pkgJsonPath(version, pkg)))) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const cacheDir = cacheRoot(version);
|
|
38
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
39
|
+
|
|
40
|
+
// Seed a standalone package.json so `npm install --prefix` treats cacheRoot as its own project. Without this, npm
|
|
41
|
+
// walks up and finds the yarn-project workspace root, which breaks on `workspace:` protocol deps and risks
|
|
42
|
+
// clobbering the monorepo's node_modules.
|
|
43
|
+
const seed = path.join(cacheDir, 'package.json');
|
|
44
|
+
if (!fs.existsSync(seed)) {
|
|
45
|
+
fs.writeFileSync(seed, JSON.stringify({ name: 'legacy-contracts-cache', private: true }));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const specs = REDIRECTED.map(pkg => `${pkg}@${version}`);
|
|
49
|
+
process.stderr.write(`[legacy-contracts] installing ${specs.join(' ')} into ${cacheDir}\n`);
|
|
50
|
+
// --prefix: install into cacheRoot instead of cwd, so the cache is isolated from the monorepo.
|
|
51
|
+
// --no-save: don't write the installed packages back to the seeded package.json.
|
|
52
|
+
// --ignore-scripts: skip lifecycle scripts (preinstall/postinstall) of the legacy packages and their transitive
|
|
53
|
+
// deps; we only want the files on disk, not to run any build steps.
|
|
54
|
+
// --legacy-peer-deps: tolerate peer-dependency mismatches between the pinned legacy @aztec/* graph and whatever
|
|
55
|
+
// current versions npm would otherwise try to reconcile.
|
|
56
|
+
execFileSync(
|
|
57
|
+
'npm',
|
|
58
|
+
['install', '--prefix', cacheDir, '--no-save', '--ignore-scripts', '--legacy-peer-deps', ...specs],
|
|
59
|
+
{ stdio: 'inherit' },
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
// Verify versions on disk match the requested version.
|
|
63
|
+
for (const pkg of REDIRECTED) {
|
|
64
|
+
const onDisk = JSON.parse(fs.readFileSync(pkgJsonPath(version, pkg), 'utf8')).version;
|
|
65
|
+
if (onDisk !== version) {
|
|
66
|
+
throw new Error(`[legacy-contracts] ${pkg} on disk is ${onDisk}, expected ${version}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = { installLegacyContracts, REDIRECTED, cacheRoot };
|
|
72
|
+
|
|
73
|
+
if (require.main === module) {
|
|
74
|
+
installLegacyContracts(process.argv[2]);
|
|
75
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// Custom Jest resolver. When CONTRACT_ARTIFACTS_VERSION is set, redirects *only* JSON artifact files under
|
|
2
|
+
// @aztec/noir-contracts.js/artifacts/, @aztec/noir-test-contracts.js/artifacts/, and @aztec/accounts/artifacts/ to a local cache of the pinned
|
|
3
|
+
// legacy versions. TypeScript wrapper classes (e.g. Token.ts) continue to load from the current workspace and use the
|
|
4
|
+
// current @aztec/aztec.js — only the artifact JSON (the deployed-contract ABI / bytecode / notes surface) is swapped.
|
|
5
|
+
//
|
|
6
|
+
// Why JSON-only: the JSON artifact is the actual interchange surface a "deployed contract" exposes. The TS wrapper is
|
|
7
|
+
// generated client-side ergonomics that's tightly coupled to the current @aztec/aztec.js API. Redirecting the wrapper
|
|
8
|
+
// would couple this test to a moving aztec.js surface and break at import time on unrelated breaking changes; we want
|
|
9
|
+
// to fail only on actual artifact-compat regressions.
|
|
10
|
+
//
|
|
11
|
+
// Cache population lives in install_legacy_contracts.cjs — invoked lazily here for local dev, and eagerly
|
|
12
|
+
// by bootstrap.sh ci-compat-e2e before hermetic test containers (which run with --net=none) launch.
|
|
13
|
+
//
|
|
14
|
+
// Activated by env var; passthrough otherwise.
|
|
15
|
+
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
16
|
+
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const { installLegacyContracts, REDIRECTED, cacheRoot } = require('./install_legacy_contracts.cjs');
|
|
20
|
+
|
|
21
|
+
const version = process.env.CONTRACT_ARTIFACTS_VERSION;
|
|
22
|
+
const cacheDir = version ? cacheRoot(version) : null;
|
|
23
|
+
|
|
24
|
+
function pkgJsonPath(name) {
|
|
25
|
+
return path.join(cacheDir, 'node_modules', name, 'package.json');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Kept in a separate module (not inlined) because bootstrap.sh ci-compat-e2e also calls it directly
|
|
29
|
+
// via `node .../install_legacy_contracts.cjs <version>` to pre-populate the cache on the host before
|
|
30
|
+
// hermetic --net=none test containers launch. Inlining here would force us to duplicate the logic
|
|
31
|
+
// in bash or re-run jest just to trigger the install.
|
|
32
|
+
if (version) {
|
|
33
|
+
installLegacyContracts(version);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let bannerPrinted = false;
|
|
37
|
+
const seen = new Set();
|
|
38
|
+
|
|
39
|
+
function printBannerOnce() {
|
|
40
|
+
if (bannerPrinted || !version) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
bannerPrinted = true;
|
|
44
|
+
const lines = ['='.repeat(60), `[legacy-contracts][jest] CONTRACT_ARTIFACTS_VERSION=${version}`];
|
|
45
|
+
for (const p of REDIRECTED) {
|
|
46
|
+
const v = JSON.parse(fs.readFileSync(pkgJsonPath(p), 'utf8')).version;
|
|
47
|
+
if (v !== version) {
|
|
48
|
+
throw new Error(`[legacy-contracts] ${p} on disk is ${v}, expected ${version}`);
|
|
49
|
+
}
|
|
50
|
+
lines.push(`[legacy-contracts][jest] redirecting ${p}/artifacts/*.json -> .legacy-contracts/${version}/...`);
|
|
51
|
+
}
|
|
52
|
+
lines.push('='.repeat(60));
|
|
53
|
+
process.stderr.write(lines.join('\n') + '\n');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Match a resolved absolute path against the workspace artifacts dirs and return the legacy cache equivalent, or null
|
|
57
|
+
// if it's not an artifact path we should redirect.
|
|
58
|
+
function legacyArtifactPath(resolved) {
|
|
59
|
+
if (!resolved.endsWith('.json')) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
for (const pkg of REDIRECTED) {
|
|
63
|
+
// pkg = '@aztec/noir-contracts.js' -> match '/noir-contracts.js/artifacts/'
|
|
64
|
+
const dirName = pkg.split('/')[1];
|
|
65
|
+
const marker = `/${dirName}/artifacts/`;
|
|
66
|
+
const idx = resolved.indexOf(marker);
|
|
67
|
+
if (idx === -1) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const basename = resolved.slice(idx + marker.length);
|
|
71
|
+
return path.join(cacheDir, 'node_modules', pkg, 'artifacts', basename);
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = function legacyResolver(request, options) {
|
|
77
|
+
// Always run the default resolver first. We only inspect (and possibly rewrite) the *result*; this catches both
|
|
78
|
+
// bare-specifier imports of `@aztec/noir-contracts.js/artifacts/foo.json` and the relative `../artifacts/foo.json`
|
|
79
|
+
// imports inside the workspace TS wrapper classes — both resolve to the same workspace artifact path that we then
|
|
80
|
+
// redirect.
|
|
81
|
+
const resolved = options.defaultResolver(request, options);
|
|
82
|
+
if (!version) {
|
|
83
|
+
return resolved;
|
|
84
|
+
}
|
|
85
|
+
printBannerOnce();
|
|
86
|
+
const legacy = legacyArtifactPath(resolved);
|
|
87
|
+
if (!legacy) {
|
|
88
|
+
return resolved;
|
|
89
|
+
}
|
|
90
|
+
if (!fs.existsSync(legacy)) {
|
|
91
|
+
throw new Error(
|
|
92
|
+
`[legacy-contracts] artifact ${path.basename(legacy)} not present in legacy cache @${version}; ` +
|
|
93
|
+
`the contract may have been added after that release. Pin a newer CONTRACT_ARTIFACTS_VERSION or skip this test.`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
if (!seen.has(resolved)) {
|
|
97
|
+
seen.add(resolved);
|
|
98
|
+
process.stderr.write(`[legacy-contracts][jest] redirected ${path.basename(legacy)} -> ${legacy}\n`);
|
|
99
|
+
}
|
|
100
|
+
return legacy;
|
|
101
|
+
};
|
package/src/shared/jest_setup.ts
CHANGED
|
@@ -1,19 +1,8 @@
|
|
|
1
1
|
import { createLogger } from '@aztec/aztec.js/log';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { readlinkSync } from 'fs';
|
|
3
|
+
import { beforeEach, expect } from '@jest/globals';
|
|
5
4
|
import { basename } from 'path';
|
|
6
5
|
|
|
7
|
-
import { EluMonitor } from '../fixtures/elu_monitor.js';
|
|
8
|
-
|
|
9
|
-
const eluMonitor = process.env.ELU_MONITOR_FILE
|
|
10
|
-
? new EluMonitor(process.env.ELU_MONITOR_FILE, Number(process.env.ELU_MONITOR_INTERVAL_MS) || undefined)
|
|
11
|
-
: undefined;
|
|
12
|
-
|
|
13
|
-
if (eluMonitor) {
|
|
14
|
-
process.on('exit', () => eluMonitor.stop());
|
|
15
|
-
}
|
|
16
|
-
|
|
17
6
|
beforeEach(() => {
|
|
18
7
|
const { testPath, currentTestName } = expect.getState();
|
|
19
8
|
if (!testPath || !currentTestName) {
|
|
@@ -21,43 +10,4 @@ beforeEach(() => {
|
|
|
21
10
|
}
|
|
22
11
|
const logger = createLogger(`e2e:${basename(testPath).replace('.test.ts', '')}`);
|
|
23
12
|
logger.info(`Running test: ${currentTestName}`);
|
|
24
|
-
eluMonitor?.startTest(currentTestName);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
afterEach(() => {
|
|
28
|
-
eluMonitor?.stopTest();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
// Log leaked handles after all tests complete. This runs after test-level afterAll hooks,
|
|
32
|
-
// so any handles still alive at this point were not properly cleaned up during teardown.
|
|
33
|
-
// This diagnostic helps identify the source of exit hangs without masking them.
|
|
34
|
-
afterAll(() => {
|
|
35
|
-
const handles = (process as any)._getActiveHandles();
|
|
36
|
-
if (handles.length > 0) {
|
|
37
|
-
const details = handles.map((h: any) => {
|
|
38
|
-
const type = h?.constructor?.name ?? typeof h;
|
|
39
|
-
const fd = h?.fd ?? h?._handle?.fd ?? '?';
|
|
40
|
-
const destroyed = h?.destroyed ?? '?';
|
|
41
|
-
const hasRef = typeof h?.hasRef === 'function' ? h.hasRef() : '?';
|
|
42
|
-
const localAddr = h?.localAddress ?? '';
|
|
43
|
-
const remoteAddr = h?.remoteAddress ?? '';
|
|
44
|
-
const localPort = h?.localPort ?? '';
|
|
45
|
-
const remotePort = h?.remotePort ?? '';
|
|
46
|
-
const proto = Object.getPrototypeOf(h)?.constructor?.name ?? '?';
|
|
47
|
-
const keys = Object.keys(h).slice(0, 10).join(',');
|
|
48
|
-
let fdTarget = '';
|
|
49
|
-
if (typeof fd === 'number') {
|
|
50
|
-
try {
|
|
51
|
-
fdTarget = ` -> ${readlinkSync(`/proc/self/fd/${fd}`)}`;
|
|
52
|
-
} catch {
|
|
53
|
-
// ignore
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return ` ${type}(fd=${fd}, destroyed=${destroyed}, hasRef=${hasRef}${fdTarget}) proto=${proto} addr=${localAddr}:${localPort}->${remoteAddr}:${remotePort} keys=[${keys}]`;
|
|
57
|
-
});
|
|
58
|
-
process.stderr.write(
|
|
59
|
-
`\n[jest_setup] WARNING: ${handles.length} handle(s) still active after teardown:\n${details.join('\n')}\n` +
|
|
60
|
-
`These may prevent Jest from exiting. Investigate and fix the leak.\n\n`,
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
13
|
});
|
|
@@ -19,7 +19,10 @@ export const submitTxsTo = async (
|
|
|
19
19
|
times(numTxs, async () => {
|
|
20
20
|
const accountManager = await wallet.createSchnorrAccount(Fr.random(), Fr.random(), GrumpkinScalar.random());
|
|
21
21
|
const deployMethod = await accountManager.getDeployMethod();
|
|
22
|
-
const { txHash } = await deployMethod.send({
|
|
22
|
+
const { txHash } = await deployMethod.send({
|
|
23
|
+
from: submitter,
|
|
24
|
+
wait: NO_WAIT,
|
|
25
|
+
});
|
|
23
26
|
|
|
24
27
|
logger.info(`Tx sent with hash ${txHash}`);
|
|
25
28
|
const receipt: TxReceipt = await wallet.getTxReceipt(txHash);
|
|
@@ -252,8 +252,12 @@ export const uniswapL1L2TestSuite = (
|
|
|
252
252
|
await wethCrossChainHarness.expectPublicBalanceOnL2(uniswapL2Contract.address, 0n);
|
|
253
253
|
|
|
254
254
|
// Since the outbox is only consumable when the epoch is proven, we need to advance to the next epoch.
|
|
255
|
-
const
|
|
256
|
-
|
|
255
|
+
const swapResult = (await computeL2ToL1MembershipWitness(
|
|
256
|
+
aztecNode,
|
|
257
|
+
swapPrivateLeaf,
|
|
258
|
+
l2UniswapInteractionReceipt.txHash,
|
|
259
|
+
))!;
|
|
260
|
+
const { epochNumber: epoch } = swapResult;
|
|
257
261
|
await cheatCodes.rollup.advanceToEpoch(EpochNumber(epoch + 1));
|
|
258
262
|
await waitForProven(aztecNode, l2UniswapInteractionReceipt, { provenTimeout: 300 });
|
|
259
263
|
|
|
@@ -262,14 +266,17 @@ export const uniswapL1L2TestSuite = (
|
|
|
262
266
|
const daiL1BalanceOfPortalBeforeSwap = await daiCrossChainHarness.getL1BalanceOf(
|
|
263
267
|
daiCrossChainHarness.tokenPortalAddress,
|
|
264
268
|
);
|
|
265
|
-
const
|
|
266
|
-
|
|
269
|
+
const withdrawResult = (await computeL2ToL1MembershipWitness(
|
|
270
|
+
aztecNode,
|
|
271
|
+
withdrawLeaf,
|
|
272
|
+
l2UniswapInteractionReceipt.txHash,
|
|
273
|
+
))!;
|
|
267
274
|
|
|
268
|
-
const swapPrivateL2MessageIndex = swapResult
|
|
269
|
-
const swapPrivateSiblingPath = swapResult
|
|
275
|
+
const swapPrivateL2MessageIndex = swapResult.leafIndex;
|
|
276
|
+
const swapPrivateSiblingPath = swapResult.siblingPath;
|
|
270
277
|
|
|
271
|
-
const withdrawL2MessageIndex = withdrawResult
|
|
272
|
-
const withdrawSiblingPath = withdrawResult
|
|
278
|
+
const withdrawL2MessageIndex = withdrawResult.leafIndex;
|
|
279
|
+
const withdrawSiblingPath = withdrawResult.siblingPath;
|
|
273
280
|
|
|
274
281
|
const withdrawMessageMetadata = {
|
|
275
282
|
_epoch: BigInt(epoch),
|
|
@@ -840,16 +847,15 @@ export const uniswapL1L2TestSuite = (
|
|
|
840
847
|
chainId: new Fr(l1Client.chain.id),
|
|
841
848
|
});
|
|
842
849
|
|
|
843
|
-
const
|
|
844
|
-
const epoch =
|
|
845
|
-
const
|
|
846
|
-
const withdrawResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, withdrawLeaf);
|
|
850
|
+
const swapResult = (await computeL2ToL1MembershipWitness(aztecNode, swapPrivateLeaf, withdrawReceipt.txHash))!;
|
|
851
|
+
const { epochNumber: epoch } = swapResult;
|
|
852
|
+
const withdrawResult = (await computeL2ToL1MembershipWitness(aztecNode, withdrawLeaf, withdrawReceipt.txHash))!;
|
|
847
853
|
|
|
848
|
-
const swapPrivateL2MessageIndex = swapResult
|
|
849
|
-
const swapPrivateSiblingPath = swapResult
|
|
854
|
+
const swapPrivateL2MessageIndex = swapResult.leafIndex;
|
|
855
|
+
const swapPrivateSiblingPath = swapResult.siblingPath;
|
|
850
856
|
|
|
851
|
-
const withdrawL2MessageIndex = withdrawResult
|
|
852
|
-
const withdrawSiblingPath = withdrawResult
|
|
857
|
+
const withdrawL2MessageIndex = withdrawResult.leafIndex;
|
|
858
|
+
const withdrawSiblingPath = withdrawResult.siblingPath;
|
|
853
859
|
|
|
854
860
|
const withdrawMessageMetadata = {
|
|
855
861
|
_epoch: BigInt(epoch),
|
|
@@ -973,16 +979,15 @@ export const uniswapL1L2TestSuite = (
|
|
|
973
979
|
chainId: new Fr(l1Client.chain.id),
|
|
974
980
|
});
|
|
975
981
|
|
|
976
|
-
const
|
|
977
|
-
const epoch =
|
|
978
|
-
const
|
|
979
|
-
const withdrawResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, withdrawLeaf);
|
|
982
|
+
const swapResult = (await computeL2ToL1MembershipWitness(aztecNode, swapPublicLeaf, withdrawReceipt.txHash))!;
|
|
983
|
+
const { epochNumber: epoch } = swapResult;
|
|
984
|
+
const withdrawResult = (await computeL2ToL1MembershipWitness(aztecNode, withdrawLeaf, withdrawReceipt.txHash))!;
|
|
980
985
|
|
|
981
|
-
const swapPublicL2MessageIndex = swapResult
|
|
982
|
-
const swapPublicSiblingPath = swapResult
|
|
986
|
+
const swapPublicL2MessageIndex = swapResult.leafIndex;
|
|
987
|
+
const swapPublicSiblingPath = swapResult.siblingPath;
|
|
983
988
|
|
|
984
|
-
const withdrawL2MessageIndex = withdrawResult
|
|
985
|
-
const withdrawSiblingPath = withdrawResult
|
|
989
|
+
const withdrawL2MessageIndex = withdrawResult.leafIndex;
|
|
990
|
+
const withdrawSiblingPath = withdrawResult.siblingPath;
|
|
986
991
|
|
|
987
992
|
const withdrawMessageMetadata = {
|
|
988
993
|
_epoch: BigInt(epoch),
|
|
@@ -94,7 +94,9 @@ export class LendingSimulator {
|
|
|
94
94
|
|
|
95
95
|
async prepare() {
|
|
96
96
|
this.accumulator = BASE;
|
|
97
|
-
const slot = await this.rollup.getSlotAt(
|
|
97
|
+
const slot = await this.rollup.getSlotAt(
|
|
98
|
+
BigInt(await this.cc.eth.lastBlockTimestamp()) + BigInt(this.ethereumSlotDuration),
|
|
99
|
+
);
|
|
98
100
|
this.time = Number(await this.rollup.getTimestampForSlot(slot));
|
|
99
101
|
}
|
|
100
102
|
|
|
@@ -103,7 +105,7 @@ export class LendingSimulator {
|
|
|
103
105
|
return;
|
|
104
106
|
}
|
|
105
107
|
|
|
106
|
-
const slot = await this.rollup.getSlotAt(BigInt(await this.cc.eth.
|
|
108
|
+
const slot = await this.rollup.getSlotAt(BigInt(await this.cc.eth.lastBlockTimestamp()));
|
|
107
109
|
const targetSlot = SlotNumber(slot + diff);
|
|
108
110
|
const ts = Number(await this.rollup.getTimestampForSlot(targetSlot));
|
|
109
111
|
const timeDiff = ts - this.time;
|
|
@@ -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';
|
|
@@ -89,7 +90,7 @@ export async function deploySponsoredTestAccountsWithTokens(
|
|
|
89
90
|
const paymentMethod = new SponsoredFeePaymentMethod(await getSponsoredFPCAddress());
|
|
90
91
|
const recipientDeployMethod = await recipientAccount.getDeployMethod();
|
|
91
92
|
await recipientDeployMethod.send({
|
|
92
|
-
from:
|
|
93
|
+
from: NO_FROM,
|
|
93
94
|
fee: { paymentMethod },
|
|
94
95
|
wait: { timeout: 2400 },
|
|
95
96
|
});
|
|
@@ -97,7 +98,7 @@ export async function deploySponsoredTestAccountsWithTokens(
|
|
|
97
98
|
fundedAccounts.map(async a => {
|
|
98
99
|
const deployMethod = await a.getDeployMethod();
|
|
99
100
|
await deployMethod.send({
|
|
100
|
-
from:
|
|
101
|
+
from: NO_FROM,
|
|
101
102
|
fee: { paymentMethod },
|
|
102
103
|
wait: { timeout: 2400 },
|
|
103
104
|
}); // increase timeout on purpose in order to account for two empty epochs
|
|
@@ -129,16 +130,27 @@ export async function deploySponsoredTestAccountsWithTokens(
|
|
|
129
130
|
}
|
|
130
131
|
|
|
131
132
|
async function deployAccountWithDiagnostics(
|
|
132
|
-
account: { getDeployMethod: () => Promise<{ send: (opts: any) => any }>; address: any },
|
|
133
|
+
account: { getDeployMethod: () => Promise<{ simulate: (opts: any) => any; send: (opts: any) => any }>; address: any },
|
|
133
134
|
paymentMethod: SponsoredFeePaymentMethod,
|
|
134
135
|
aztecNode: AztecNode,
|
|
135
136
|
logger: Logger,
|
|
136
137
|
accountLabel: string,
|
|
138
|
+
estimateGas?: boolean,
|
|
137
139
|
): Promise<void> {
|
|
138
140
|
const deployMethod = await account.getDeployMethod();
|
|
139
141
|
let txHash;
|
|
140
142
|
try {
|
|
141
|
-
|
|
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
|
+
});
|
|
142
154
|
txHash = deployResult.txHash;
|
|
143
155
|
await waitForTx(aztecNode, txHash, { timeout: 2400 });
|
|
144
156
|
logger.info(`${accountLabel} deployed at ${account.address}`);
|
|
@@ -161,18 +173,29 @@ async function deployAccountWithDiagnostics(
|
|
|
161
173
|
}
|
|
162
174
|
|
|
163
175
|
async function deployAccountsInBatches(
|
|
164
|
-
accounts: {
|
|
176
|
+
accounts: {
|
|
177
|
+
getDeployMethod: () => Promise<{ simulate: (opts: any) => any; send: (opts: any) => any }>;
|
|
178
|
+
address: any;
|
|
179
|
+
}[],
|
|
165
180
|
paymentMethod: SponsoredFeePaymentMethod,
|
|
166
181
|
aztecNode: AztecNode,
|
|
167
182
|
logger: Logger,
|
|
168
183
|
labelPrefix: string,
|
|
169
184
|
batchSize = 2,
|
|
185
|
+
estimateGas?: boolean,
|
|
170
186
|
): Promise<void> {
|
|
171
187
|
for (let i = 0; i < accounts.length; i += batchSize) {
|
|
172
188
|
const batch = accounts.slice(i, i + batchSize);
|
|
173
189
|
await Promise.all(
|
|
174
190
|
batch.map((account, idx) =>
|
|
175
|
-
deployAccountWithDiagnostics(
|
|
191
|
+
deployAccountWithDiagnostics(
|
|
192
|
+
account,
|
|
193
|
+
paymentMethod,
|
|
194
|
+
aztecNode,
|
|
195
|
+
logger,
|
|
196
|
+
`${labelPrefix}${i + idx + 1}`,
|
|
197
|
+
estimateGas,
|
|
198
|
+
),
|
|
176
199
|
),
|
|
177
200
|
);
|
|
178
201
|
}
|
|
@@ -183,6 +206,7 @@ export async function deploySponsoredTestAccounts(
|
|
|
183
206
|
aztecNode: AztecNode,
|
|
184
207
|
logger: Logger,
|
|
185
208
|
numberOfFundedWallets = 1,
|
|
209
|
+
opts?: { estimateGas?: boolean },
|
|
186
210
|
): Promise<TestAccountsWithoutTokens> {
|
|
187
211
|
const [recipient, ...funded] = await generateSchnorrAccounts(numberOfFundedWallets + 1);
|
|
188
212
|
const recipientAccount = await wallet.createSchnorrAccount(recipient.secret, recipient.salt);
|
|
@@ -192,8 +216,23 @@ export async function deploySponsoredTestAccounts(
|
|
|
192
216
|
|
|
193
217
|
const paymentMethod = new SponsoredFeePaymentMethod(await getSponsoredFPCAddress());
|
|
194
218
|
|
|
195
|
-
await deployAccountWithDiagnostics(
|
|
196
|
-
|
|
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
|
+
);
|
|
197
236
|
|
|
198
237
|
return {
|
|
199
238
|
aztecNode,
|
|
@@ -231,7 +270,7 @@ export async function deployTestAccountsWithTokens(
|
|
|
231
270
|
fundedAccounts.map(async (a, i) => {
|
|
232
271
|
const paymentMethod = new FeeJuicePaymentMethodWithClaim(a.address, claims[i]);
|
|
233
272
|
const deployMethod = await a.getDeployMethod();
|
|
234
|
-
await deployMethod.send({ from:
|
|
273
|
+
await deployMethod.send({ from: NO_FROM, fee: { paymentMethod } });
|
|
235
274
|
logger.info(`Account deployed at ${a.address}`);
|
|
236
275
|
}),
|
|
237
276
|
);
|
|
@@ -16,7 +16,6 @@ const testConfigSchema = z.object({
|
|
|
16
16
|
AZTEC_PROOF_SUBMISSION_WINDOW: z.coerce.number().optional().default(5),
|
|
17
17
|
AZTEC_LAG_IN_EPOCHS_FOR_VALIDATOR_SET: z.coerce.number().optional().default(2),
|
|
18
18
|
FUNDING_PRIVATE_KEY: z.string().optional(),
|
|
19
|
-
AZTEC_ADMIN_API_KEY: z.string().optional(),
|
|
20
19
|
});
|
|
21
20
|
|
|
22
21
|
export type TestConfig = z.infer<typeof testConfigSchema>;
|