@aztec/end-to-end 0.0.1-commit.2ed92850 → 0.0.1-commit.3d8f95d
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/config.d.ts +2 -2
- package/dest/bench/client_flows/config.d.ts.map +1 -1
- package/dest/bench/client_flows/config.js +18 -0
- package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +1 -1
- package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts.map +1 -1
- package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.js +3 -2
- package/dest/e2e_epochs/epochs_test.d.ts +7 -1
- package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
- package/dest/e2e_epochs/epochs_test.js +37 -12
- package/dest/e2e_l1_publisher/write_json.d.ts +3 -2
- package/dest/e2e_l1_publisher/write_json.d.ts.map +1 -1
- package/dest/e2e_l1_publisher/write_json.js +1 -7
- package/dest/e2e_p2p/reqresp/utils.d.ts +22 -0
- package/dest/e2e_p2p/reqresp/utils.d.ts.map +1 -0
- package/dest/e2e_p2p/reqresp/utils.js +153 -0
- package/dest/e2e_p2p/shared.d.ts +1 -1
- package/dest/e2e_p2p/shared.d.ts.map +1 -1
- package/dest/e2e_p2p/shared.js +5 -2
- package/dest/e2e_storage_proof/fixtures/storage_proof_fetcher.d.ts +2 -0
- package/dest/e2e_storage_proof/fixtures/storage_proof_fetcher.d.ts.map +1 -0
- package/dest/e2e_storage_proof/fixtures/storage_proof_fetcher.js +184 -0
- package/dest/e2e_storage_proof/fixtures/storage_proof_fixture.d.ts +18 -0
- package/dest/e2e_storage_proof/fixtures/storage_proof_fixture.d.ts.map +1 -0
- package/dest/e2e_storage_proof/fixtures/storage_proof_fixture.js +120 -0
- package/dest/fixtures/e2e_prover_test.js +1 -1
- package/dest/fixtures/ha_setup.d.ts +71 -0
- package/dest/fixtures/ha_setup.d.ts.map +1 -0
- package/dest/fixtures/ha_setup.js +114 -0
- package/dest/fixtures/index.d.ts +2 -1
- package/dest/fixtures/index.d.ts.map +1 -1
- package/dest/fixtures/index.js +1 -0
- package/dest/fixtures/setup.d.ts +15 -15
- package/dest/fixtures/setup.d.ts.map +1 -1
- package/dest/fixtures/setup.js +30 -90
- package/dest/fixtures/setup_p2p_test.d.ts +12 -8
- package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
- package/dest/fixtures/setup_p2p_test.js +29 -21
- 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 +8 -6
- package/dest/spartan/tx_metrics.d.ts +35 -1
- package/dest/spartan/tx_metrics.d.ts.map +1 -1
- package/dest/spartan/tx_metrics.js +150 -0
- package/dest/spartan/utils/config.d.ts +4 -1
- package/dest/spartan/utils/config.d.ts.map +1 -1
- package/dest/spartan/utils/config.js +2 -1
- package/dest/spartan/utils/index.d.ts +4 -4
- package/dest/spartan/utils/index.d.ts.map +1 -1
- package/dest/spartan/utils/index.js +2 -2
- package/dest/spartan/utils/k8s.d.ts +29 -1
- package/dest/spartan/utils/k8s.d.ts.map +1 -1
- package/dest/spartan/utils/k8s.js +118 -0
- package/dest/spartan/utils/nodes.d.ts +11 -1
- package/dest/spartan/utils/nodes.d.ts.map +1 -1
- package/dest/spartan/utils/nodes.js +198 -27
- package/dest/spartan/utils/scripts.d.ts +18 -4
- package/dest/spartan/utils/scripts.d.ts.map +1 -1
- package/dest/spartan/utils/scripts.js +19 -4
- package/package.json +42 -39
- package/src/bench/client_flows/client_flows_benchmark.ts +5 -5
- package/src/bench/client_flows/config.ts +9 -1
- package/src/bench/utils.ts +1 -1
- package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +1 -1
- package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +6 -7
- package/src/e2e_deploy_contract/deploy_test.ts +2 -2
- package/src/e2e_epochs/epochs_test.ts +44 -13
- package/src/e2e_fees/fees_test.ts +6 -6
- package/src/e2e_l1_publisher/write_json.ts +1 -6
- package/src/e2e_nested_contract/nested_contract_test.ts +1 -1
- package/src/e2e_p2p/inactivity_slash_test.ts +4 -4
- package/src/e2e_p2p/p2p_network.ts +4 -4
- package/src/e2e_p2p/reqresp/utils.ts +207 -0
- package/src/e2e_p2p/shared.ts +11 -2
- package/src/e2e_storage_proof/fixtures/storage_proof.json +915 -0
- package/src/e2e_storage_proof/fixtures/storage_proof_fetcher.ts +190 -0
- package/src/e2e_storage_proof/fixtures/storage_proof_fixture.ts +173 -0
- package/src/e2e_token_contract/token_contract_test.ts +1 -1
- package/src/fixtures/dumps/epoch_proof_result.json +1 -1
- package/src/fixtures/e2e_prover_test.ts +4 -4
- package/src/fixtures/ha_setup.ts +184 -0
- package/src/fixtures/index.ts +1 -0
- package/src/fixtures/setup.ts +33 -118
- package/src/fixtures/setup_p2p_test.ts +31 -27
- package/src/shared/uniswap_l1_l2.ts +8 -10
- package/src/spartan/tx_metrics.ts +126 -0
- package/src/spartan/utils/config.ts +1 -0
- package/src/spartan/utils/index.ts +3 -1
- package/src/spartan/utils/k8s.ts +152 -0
- package/src/spartan/utils/nodes.ts +239 -24
- package/src/spartan/utils/scripts.ts +43 -7
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { EthAddress } from '@aztec/aztec.js/addresses';
|
|
2
|
+
import { Fr } from '@aztec/aztec.js/fields';
|
|
3
|
+
import type { Logger } from '@aztec/aztec.js/log';
|
|
4
|
+
import { SecretValue } from '@aztec/foundation/config';
|
|
5
|
+
|
|
6
|
+
import { Pool } from 'pg';
|
|
7
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Configuration for HA database connection
|
|
11
|
+
*/
|
|
12
|
+
export interface HADatabaseConfig {
|
|
13
|
+
/** PostgreSQL connection URL */
|
|
14
|
+
databaseUrl: string;
|
|
15
|
+
/** Node ID for HA coordination */
|
|
16
|
+
nodeId: string;
|
|
17
|
+
/** Enable HA signing */
|
|
18
|
+
haSigningEnabled: boolean;
|
|
19
|
+
/** Polling interval in ms */
|
|
20
|
+
pollingIntervalMs: number;
|
|
21
|
+
/** Signing timeout in ms */
|
|
22
|
+
signingTimeoutMs: number;
|
|
23
|
+
/** Max stuck duties age in ms */
|
|
24
|
+
maxStuckDutiesAgeMs: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get database configuration from environment variables
|
|
29
|
+
*/
|
|
30
|
+
export function createHADatabaseConfig(nodeId: string): HADatabaseConfig {
|
|
31
|
+
const databaseUrl = process.env.DATABASE_URL || 'postgresql://aztec:aztec@localhost:5432/aztec_ha_test';
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
databaseUrl,
|
|
35
|
+
nodeId,
|
|
36
|
+
haSigningEnabled: true,
|
|
37
|
+
pollingIntervalMs: 100,
|
|
38
|
+
signingTimeoutMs: 3000,
|
|
39
|
+
maxStuckDutiesAgeMs: 72000,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Setup PostgreSQL database connection pool for HA tests
|
|
45
|
+
*
|
|
46
|
+
* Note: Database migrations should be run separately before starting tests,
|
|
47
|
+
* either via docker-compose entrypoint or manually with: aztec migrate-ha-db up
|
|
48
|
+
*/
|
|
49
|
+
export function setupHADatabase(databaseUrl: string, logger?: Logger): Pool {
|
|
50
|
+
try {
|
|
51
|
+
// Create connection pool for test usage
|
|
52
|
+
// Migrations are already run by docker-compose entrypoint before tests start
|
|
53
|
+
const pool = new Pool({ connectionString: databaseUrl });
|
|
54
|
+
|
|
55
|
+
logger?.info('Connected to HA database (migrations should already be applied)');
|
|
56
|
+
|
|
57
|
+
return pool;
|
|
58
|
+
} catch (error) {
|
|
59
|
+
logger?.error(`Failed to connect to HA database: ${error}`);
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Clean up HA database - drop all tables
|
|
66
|
+
* Use this between tests to ensure clean state
|
|
67
|
+
*/
|
|
68
|
+
export async function cleanupHADatabase(pool: Pool, logger?: Logger): Promise<void> {
|
|
69
|
+
try {
|
|
70
|
+
// Drop all HA tables
|
|
71
|
+
await pool.query('DROP TABLE IF EXISTS validator_duties CASCADE');
|
|
72
|
+
await pool.query('DROP TABLE IF EXISTS slashing_protection CASCADE');
|
|
73
|
+
await pool.query('DROP TABLE IF EXISTS schema_version CASCADE');
|
|
74
|
+
|
|
75
|
+
logger?.info('HA database cleaned up successfully');
|
|
76
|
+
} catch (error) {
|
|
77
|
+
logger?.error(`Failed to cleanup HA database: ${error}`);
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Query validator duties from the database
|
|
84
|
+
*/
|
|
85
|
+
export async function getValidatorDuties(
|
|
86
|
+
pool: Pool,
|
|
87
|
+
slot: bigint,
|
|
88
|
+
dutyType?: 'ATTESTATION' | 'BLOCK_PROPOSAL' | 'GOVERNANCE_VOTE' | 'SLASHING_VOTE',
|
|
89
|
+
): Promise<
|
|
90
|
+
Array<{
|
|
91
|
+
slot: string;
|
|
92
|
+
dutyType: string;
|
|
93
|
+
validatorAddress: string;
|
|
94
|
+
nodeId: string;
|
|
95
|
+
startedAt: Date;
|
|
96
|
+
completedAt: Date | undefined;
|
|
97
|
+
}>
|
|
98
|
+
> {
|
|
99
|
+
const query = dutyType
|
|
100
|
+
? 'SELECT slot, duty_type, validator_address, node_id, started_at, completed_at FROM validator_duties WHERE slot = $1 AND duty_type = $2 ORDER BY started_at'
|
|
101
|
+
: 'SELECT slot, duty_type, validator_address, node_id, started_at, completed_at FROM validator_duties WHERE slot = $1 ORDER BY started_at';
|
|
102
|
+
|
|
103
|
+
const params = dutyType ? [slot.toString(), dutyType] : [slot.toString()];
|
|
104
|
+
|
|
105
|
+
const result = await pool.query<{
|
|
106
|
+
slot: string;
|
|
107
|
+
duty_type: string;
|
|
108
|
+
validator_address: string;
|
|
109
|
+
node_id: string;
|
|
110
|
+
started_at: Date;
|
|
111
|
+
completed_at: Date | undefined;
|
|
112
|
+
}>(query, params);
|
|
113
|
+
|
|
114
|
+
return result.rows.map(row => ({
|
|
115
|
+
slot: row.slot,
|
|
116
|
+
dutyType: row.duty_type,
|
|
117
|
+
validatorAddress: row.validator_address,
|
|
118
|
+
nodeId: row.node_id,
|
|
119
|
+
startedAt: row.started_at,
|
|
120
|
+
completedAt: row.completed_at,
|
|
121
|
+
}));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Convert private keys to Ethereum addresses
|
|
126
|
+
*/
|
|
127
|
+
export function getAddressesFromPrivateKeys(privateKeys: `0x${string}`[]): string[] {
|
|
128
|
+
return privateKeys.map(pk => {
|
|
129
|
+
const account = privateKeyToAccount(pk);
|
|
130
|
+
return account.address;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Create initial validators from private keys for L1 contract deployment
|
|
136
|
+
*/
|
|
137
|
+
export function createInitialValidatorsFromPrivateKeys(attesterPrivateKeys: `0x${string}`[]): Array<{
|
|
138
|
+
attester: EthAddress;
|
|
139
|
+
withdrawer: EthAddress;
|
|
140
|
+
privateKey: `0x${string}`;
|
|
141
|
+
bn254SecretKey: SecretValue<bigint>;
|
|
142
|
+
}> {
|
|
143
|
+
return attesterPrivateKeys.map(pk => {
|
|
144
|
+
const account = privateKeyToAccount(pk);
|
|
145
|
+
return {
|
|
146
|
+
attester: EthAddress.fromString(account.address),
|
|
147
|
+
withdrawer: EthAddress.fromString(account.address),
|
|
148
|
+
privateKey: pk,
|
|
149
|
+
bn254SecretKey: new SecretValue(Fr.random().toBigInt()),
|
|
150
|
+
};
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Verify no duplicate attestations per validator (HA coordination check)
|
|
156
|
+
* Groups duties by validator address and verifies each validator attested exactly once
|
|
157
|
+
*/
|
|
158
|
+
export function verifyNoDuplicateAttestations(
|
|
159
|
+
attestationDuties: Array<{
|
|
160
|
+
validatorAddress: string;
|
|
161
|
+
nodeId: string;
|
|
162
|
+
completedAt: Date | undefined;
|
|
163
|
+
}>,
|
|
164
|
+
logger?: Logger,
|
|
165
|
+
): Map<string, typeof attestationDuties> {
|
|
166
|
+
const dutiesByValidator = new Map<string, typeof attestationDuties>();
|
|
167
|
+
for (const duty of attestationDuties) {
|
|
168
|
+
const existing = dutiesByValidator.get(duty.validatorAddress) || [];
|
|
169
|
+
existing.push(duty);
|
|
170
|
+
dutiesByValidator.set(duty.validatorAddress, existing);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
for (const [validatorAddress, validatorDuties] of dutiesByValidator.entries()) {
|
|
174
|
+
if (validatorDuties.length !== 1) {
|
|
175
|
+
throw new Error(`Validator ${validatorAddress} attested ${validatorDuties.length} times (expected exactly once)`);
|
|
176
|
+
}
|
|
177
|
+
if (!validatorDuties[0].completedAt) {
|
|
178
|
+
throw new Error(`Validator ${validatorAddress} attestation duty not completed`);
|
|
179
|
+
}
|
|
180
|
+
logger?.info(`Validator ${validatorAddress} attested once via node ${validatorDuties[0].nodeId}`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return dutiesByValidator;
|
|
184
|
+
}
|
package/src/fixtures/index.ts
CHANGED
package/src/fixtures/setup.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SchnorrAccountContractArtifact } from '@aztec/accounts/schnorr';
|
|
2
|
-
import { type InitialAccountData, generateSchnorrAccounts
|
|
2
|
+
import { type InitialAccountData, generateSchnorrAccounts } from '@aztec/accounts/testing';
|
|
3
3
|
import { type Archiver, createArchiver } from '@aztec/archiver';
|
|
4
4
|
import { type AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/aztec-node';
|
|
5
5
|
import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses';
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import { publishContractClass, publishInstance } from '@aztec/aztec.js/deployment';
|
|
14
14
|
import { Fr } from '@aztec/aztec.js/fields';
|
|
15
15
|
import { type Logger, createLogger } from '@aztec/aztec.js/log';
|
|
16
|
-
import {
|
|
16
|
+
import type { AztecNode } from '@aztec/aztec.js/node';
|
|
17
17
|
import type { Wallet } from '@aztec/aztec.js/wallet';
|
|
18
18
|
import { AnvilTestWatcher, CheatCodes } from '@aztec/aztec/testing';
|
|
19
19
|
import { createBlobClientWithFileStores } from '@aztec/blob-client/client';
|
|
@@ -41,7 +41,7 @@ import { BlockNumber, EpochNumber } from '@aztec/foundation/branded-types';
|
|
|
41
41
|
import { SecretValue } from '@aztec/foundation/config';
|
|
42
42
|
import { randomBytes } from '@aztec/foundation/crypto/random';
|
|
43
43
|
import { tryRmDir } from '@aztec/foundation/fs';
|
|
44
|
-
import {
|
|
44
|
+
import { withLoggerBindings } from '@aztec/foundation/log/server';
|
|
45
45
|
import { retryUntil } from '@aztec/foundation/retry';
|
|
46
46
|
import { sleep } from '@aztec/foundation/sleep';
|
|
47
47
|
import { DateProvider, TestDateProvider } from '@aztec/foundation/timer';
|
|
@@ -92,9 +92,6 @@ import { getEndToEndTestTelemetryClient } from './with_telemetry_utils.js';
|
|
|
92
92
|
|
|
93
93
|
export { startAnvil };
|
|
94
94
|
|
|
95
|
-
const { AZTEC_NODE_URL = '' } = process.env;
|
|
96
|
-
const getAztecUrl = () => AZTEC_NODE_URL;
|
|
97
|
-
|
|
98
95
|
let telemetry: TelemetryClient | undefined = undefined;
|
|
99
96
|
async function getTelemetryClient(partialConfig: Partial<TelemetryClientConfig> & { benchmark?: boolean } = {}) {
|
|
100
97
|
if (!telemetry) {
|
|
@@ -125,14 +122,14 @@ export async function setupSharedBlobStorage(config: { dataDirectory?: string }
|
|
|
125
122
|
* @param aztecNode - An instance of Aztec Node.
|
|
126
123
|
* @param opts - Partial configuration for the PXE.
|
|
127
124
|
* @param logger - The logger to be used.
|
|
128
|
-
* @param
|
|
125
|
+
* @param actor - Actor label to include in log output (e.g., 'pxe-test').
|
|
129
126
|
* @returns A test wallet, logger and teardown function.
|
|
130
127
|
*/
|
|
131
128
|
export async function setupPXEAndGetWallet(
|
|
132
129
|
aztecNode: AztecNode,
|
|
133
130
|
opts: Partial<PXEConfig> = {},
|
|
134
131
|
logger = getLogger(),
|
|
135
|
-
|
|
132
|
+
actor?: string,
|
|
136
133
|
): Promise<{
|
|
137
134
|
wallet: TestWallet;
|
|
138
135
|
logger: Logger;
|
|
@@ -150,9 +147,7 @@ export async function setupPXEAndGetWallet(
|
|
|
150
147
|
|
|
151
148
|
const teardown = configuredDataDirectory ? () => Promise.resolve() : () => tryRmDir(PXEConfig.dataDirectory!);
|
|
152
149
|
|
|
153
|
-
const wallet = await TestWallet.create(aztecNode, PXEConfig, {
|
|
154
|
-
useLogSuffix,
|
|
155
|
-
});
|
|
150
|
+
const wallet = await TestWallet.create(aztecNode, PXEConfig, { loggerActorLabel: actor });
|
|
156
151
|
|
|
157
152
|
return {
|
|
158
153
|
wallet,
|
|
@@ -219,13 +214,13 @@ export type EndToEndContext = {
|
|
|
219
214
|
anvil: Anvil | undefined;
|
|
220
215
|
/** The Aztec Node service or client a connected to it. */
|
|
221
216
|
aztecNode: AztecNode;
|
|
222
|
-
/** The Aztec Node as a service
|
|
223
|
-
aztecNodeService: AztecNodeService
|
|
224
|
-
/** Client to the Aztec Node admin interface
|
|
225
|
-
aztecNodeAdmin: AztecNodeAdmin
|
|
217
|
+
/** The Aztec Node as a service. */
|
|
218
|
+
aztecNodeService: AztecNodeService;
|
|
219
|
+
/** Client to the Aztec Node admin interface. */
|
|
220
|
+
aztecNodeAdmin: AztecNodeAdmin;
|
|
226
221
|
/** The prover node service (only set if startProverNode is true) */
|
|
227
222
|
proverNode: ProverNode | undefined;
|
|
228
|
-
/** A client to the sequencer service
|
|
223
|
+
/** A client to the sequencer service. */
|
|
229
224
|
sequencer: SequencerClient | undefined;
|
|
230
225
|
/** Return values from deployAztecL1Contracts function. */
|
|
231
226
|
deployL1ContractsValues: DeployAztecL1ContractsReturnType;
|
|
@@ -245,12 +240,12 @@ export type EndToEndContext = {
|
|
|
245
240
|
cheatCodes: CheatCodes;
|
|
246
241
|
/** The cheat codes for L1 */
|
|
247
242
|
ethCheatCodes: EthCheatCodes;
|
|
248
|
-
/** The anvil test watcher
|
|
249
|
-
watcher: AnvilTestWatcher
|
|
250
|
-
/** Allows tweaking current system time, used by the epoch cache only
|
|
251
|
-
dateProvider: TestDateProvider
|
|
243
|
+
/** The anvil test watcher. */
|
|
244
|
+
watcher: AnvilTestWatcher;
|
|
245
|
+
/** Allows tweaking current system time, used by the epoch cache only. */
|
|
246
|
+
dateProvider: TestDateProvider;
|
|
252
247
|
/** Telemetry client */
|
|
253
|
-
telemetryClient: TelemetryClient
|
|
248
|
+
telemetryClient: TelemetryClient;
|
|
254
249
|
/** Mock gossip sub network used for gossipping messages (only if mockGossipSubNetwork was set to true in opts) */
|
|
255
250
|
mockGossipSubNetwork: MockGossipSubNetwork | undefined;
|
|
256
251
|
/** Prefilled public data used for setting up nodes. */
|
|
@@ -260,87 +255,11 @@ export type EndToEndContext = {
|
|
|
260
255
|
/** BB config (only set if running locally). */
|
|
261
256
|
bbConfig: Awaited<ReturnType<typeof getBBConfig>>;
|
|
262
257
|
/** Directory to cleanup on teardown. */
|
|
263
|
-
directoryToCleanup: string
|
|
258
|
+
directoryToCleanup: string;
|
|
264
259
|
/** Function to stop the started services. */
|
|
265
260
|
teardown: () => Promise<void>;
|
|
266
261
|
};
|
|
267
262
|
|
|
268
|
-
/**
|
|
269
|
-
* Function to setup the test against a remote deployment. It is assumed that L1 contract are already deployed
|
|
270
|
-
*/
|
|
271
|
-
async function setupWithRemoteEnvironment(
|
|
272
|
-
account: HDAccount | PrivateKeyAccount,
|
|
273
|
-
config: AztecNodeConfig & SetupOptions,
|
|
274
|
-
logger: Logger,
|
|
275
|
-
numberOfAccounts: number,
|
|
276
|
-
): Promise<EndToEndContext> {
|
|
277
|
-
const aztecNodeUrl = getAztecUrl();
|
|
278
|
-
logger.verbose(`Creating Aztec Node client to remote host ${aztecNodeUrl}`);
|
|
279
|
-
const aztecNode = createAztecNodeClient(aztecNodeUrl);
|
|
280
|
-
await waitForNode(aztecNode, logger);
|
|
281
|
-
logger.verbose('JSON RPC client connected to Aztec Node');
|
|
282
|
-
logger.verbose(`Retrieving contract addresses from ${aztecNodeUrl}`);
|
|
283
|
-
const { l1ContractAddresses, rollupVersion } = await aztecNode.getNodeInfo();
|
|
284
|
-
|
|
285
|
-
const l1Client = createExtendedL1Client(config.l1RpcUrls, account, foundry);
|
|
286
|
-
|
|
287
|
-
const deployL1ContractsValues: DeployAztecL1ContractsReturnType = {
|
|
288
|
-
l1ContractAddresses,
|
|
289
|
-
l1Client,
|
|
290
|
-
rollupVersion,
|
|
291
|
-
};
|
|
292
|
-
const ethCheatCodes = new EthCheatCodes(config.l1RpcUrls, new DateProvider());
|
|
293
|
-
const wallet = await TestWallet.create(aztecNode);
|
|
294
|
-
|
|
295
|
-
if (config.walletMinFeePadding !== undefined) {
|
|
296
|
-
wallet.setMinFeePadding(config.walletMinFeePadding);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
const cheatCodes = await CheatCodes.create(config.l1RpcUrls, aztecNode, new DateProvider());
|
|
300
|
-
const teardown = () => Promise.resolve();
|
|
301
|
-
|
|
302
|
-
logger.verbose('Populating wallet from already registered accounts...');
|
|
303
|
-
const initialFundedAccounts = await getInitialTestAccountsData();
|
|
304
|
-
|
|
305
|
-
if (initialFundedAccounts.length < numberOfAccounts) {
|
|
306
|
-
throw new Error(`Required ${numberOfAccounts} accounts. Found ${initialFundedAccounts.length}.`);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const testAccounts = await Promise.all(
|
|
310
|
-
initialFundedAccounts.slice(0, numberOfAccounts).map(async account => {
|
|
311
|
-
const accountManager = await wallet.createSchnorrAccount(account.secret, account.salt, account.signingKey);
|
|
312
|
-
return accountManager.address;
|
|
313
|
-
}),
|
|
314
|
-
);
|
|
315
|
-
|
|
316
|
-
return {
|
|
317
|
-
anvil: undefined,
|
|
318
|
-
aztecNode,
|
|
319
|
-
aztecNodeService: undefined,
|
|
320
|
-
aztecNodeAdmin: undefined,
|
|
321
|
-
sequencer: undefined,
|
|
322
|
-
proverNode: undefined,
|
|
323
|
-
deployL1ContractsValues,
|
|
324
|
-
config,
|
|
325
|
-
aztecNodeConfig: config,
|
|
326
|
-
initialFundedAccounts,
|
|
327
|
-
wallet,
|
|
328
|
-
accounts: testAccounts,
|
|
329
|
-
logger,
|
|
330
|
-
cheatCodes,
|
|
331
|
-
ethCheatCodes,
|
|
332
|
-
prefilledPublicData: undefined,
|
|
333
|
-
mockGossipSubNetwork: undefined,
|
|
334
|
-
watcher: undefined,
|
|
335
|
-
dateProvider: undefined,
|
|
336
|
-
telemetryClient: undefined,
|
|
337
|
-
acvmConfig: undefined,
|
|
338
|
-
bbConfig: undefined,
|
|
339
|
-
directoryToCleanup: undefined,
|
|
340
|
-
teardown,
|
|
341
|
-
};
|
|
342
|
-
}
|
|
343
|
-
|
|
344
263
|
/**
|
|
345
264
|
* Sets up the environment for the end-to-end tests.
|
|
346
265
|
* @param numberOfAccounts - The number of new accounts to be created once the PXE is initiated.
|
|
@@ -383,16 +302,10 @@ export async function setup(
|
|
|
383
302
|
if (!isAnvilTestChain(chain.id)) {
|
|
384
303
|
throw new Error(`No ETHEREUM_HOSTS set but non anvil chain requested`);
|
|
385
304
|
}
|
|
386
|
-
if (AZTEC_NODE_URL) {
|
|
387
|
-
throw new Error(
|
|
388
|
-
`AZTEC_NODE_URL provided but no ETHEREUM_HOSTS set. Refusing to run, please set both variables so tests can deploy L1 contracts to the same Anvil instance`,
|
|
389
|
-
);
|
|
390
|
-
}
|
|
391
|
-
|
|
392
305
|
const res = await startAnvil({
|
|
393
306
|
l1BlockTime: opts.ethereumSlotDuration,
|
|
394
307
|
accounts: opts.anvilAccounts,
|
|
395
|
-
port: opts.anvilPort,
|
|
308
|
+
port: opts.anvilPort ?? (process.env.ANVIL_PORT ? parseInt(process.env.ANVIL_PORT) : undefined),
|
|
396
309
|
});
|
|
397
310
|
anvil = res.anvil;
|
|
398
311
|
config.l1RpcUrls = [res.rpcUrl];
|
|
@@ -443,11 +356,6 @@ export async function setup(
|
|
|
443
356
|
config.coinbase = EthAddress.fromString(publisherHdAccount.address);
|
|
444
357
|
}
|
|
445
358
|
|
|
446
|
-
if (AZTEC_NODE_URL) {
|
|
447
|
-
// we are setting up against a remote environment, l1 contracts are assumed to already be deployed
|
|
448
|
-
return await setupWithRemoteEnvironment(publisherHdAccount!, config, logger, numberOfAccounts);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
359
|
// Determine which addresses to fund in genesis
|
|
452
360
|
const initialFundedAccounts =
|
|
453
361
|
opts.initialFundedAccounts ??
|
|
@@ -574,10 +482,12 @@ export async function setup(
|
|
|
574
482
|
}
|
|
575
483
|
}
|
|
576
484
|
|
|
577
|
-
const aztecNodeService = await
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
485
|
+
const aztecNodeService = await withLoggerBindings({ actor: 'node-0' }, () =>
|
|
486
|
+
AztecNodeService.createAndSync(
|
|
487
|
+
config,
|
|
488
|
+
{ dateProvider, telemetry: telemetryClient, p2pClientDeps },
|
|
489
|
+
{ prefilledPublicData },
|
|
490
|
+
),
|
|
581
491
|
);
|
|
582
492
|
const sequencerClient = aztecNodeService.getSequencer();
|
|
583
493
|
|
|
@@ -595,7 +505,7 @@ export async function setup(
|
|
|
595
505
|
const proverNodeConfig = {
|
|
596
506
|
...config.proverNodeConfig,
|
|
597
507
|
dataDirectory: proverNodeDataDirectory,
|
|
598
|
-
p2pEnabled:
|
|
508
|
+
p2pEnabled: !!mockGossipSubNetwork,
|
|
599
509
|
};
|
|
600
510
|
proverNode = await createAndSyncProverNode(
|
|
601
511
|
proverNodePrivateKeyHex,
|
|
@@ -603,6 +513,11 @@ export async function setup(
|
|
|
603
513
|
proverNodeConfig,
|
|
604
514
|
aztecNodeService,
|
|
605
515
|
prefilledPublicData,
|
|
516
|
+
{
|
|
517
|
+
p2pClientDeps: mockGossipSubNetwork
|
|
518
|
+
? { p2pServiceFactory: getMockPubSubP2PServiceFactory(mockGossipSubNetwork) }
|
|
519
|
+
: undefined,
|
|
520
|
+
},
|
|
606
521
|
);
|
|
607
522
|
}
|
|
608
523
|
|
|
@@ -611,7 +526,7 @@ export async function setup(
|
|
|
611
526
|
pxeConfig.dataDirectory = path.join(directoryToCleanup, randomBytes(8).toString('hex'));
|
|
612
527
|
// For tests we only want proving enabled if specifically requested
|
|
613
528
|
pxeConfig.proverEnabled = !!pxeOpts.proverEnabled;
|
|
614
|
-
const wallet = await TestWallet.create(aztecNodeService, pxeConfig);
|
|
529
|
+
const wallet = await TestWallet.create(aztecNodeService, pxeConfig, { loggerActorLabel: 'pxe-0' });
|
|
615
530
|
|
|
616
531
|
if (opts.walletMinFeePadding !== undefined) {
|
|
617
532
|
wallet.setMinFeePadding(opts.walletMinFeePadding);
|
|
@@ -683,7 +598,7 @@ export async function setup(
|
|
|
683
598
|
logger.error(`Error during e2e test teardown`, err);
|
|
684
599
|
} finally {
|
|
685
600
|
try {
|
|
686
|
-
await telemetryClient
|
|
601
|
+
await telemetryClient.stop();
|
|
687
602
|
} catch (err) {
|
|
688
603
|
logger.error(`Error during telemetry client stop`, err);
|
|
689
604
|
}
|
|
@@ -797,7 +712,7 @@ export function createAndSyncProverNode(
|
|
|
797
712
|
prefilledPublicData: PublicDataTreeLeaf[] = [],
|
|
798
713
|
proverNodeDeps: ProverNodeDeps = {},
|
|
799
714
|
) {
|
|
800
|
-
return
|
|
715
|
+
return withLoggerBindings({ actor: 'prover-0' }, async () => {
|
|
801
716
|
const aztecNodeTxProvider = aztecNode && {
|
|
802
717
|
getTxByHash: aztecNode.getTxByHash.bind(aztecNode),
|
|
803
718
|
getTxsByHash: aztecNode.getTxsByHash.bind(aztecNode),
|
|
@@ -4,14 +4,13 @@
|
|
|
4
4
|
import { type AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node';
|
|
5
5
|
import { range } from '@aztec/foundation/array';
|
|
6
6
|
import { SecretValue } from '@aztec/foundation/config';
|
|
7
|
-
import {
|
|
7
|
+
import { withLoggerBindings } from '@aztec/foundation/log/server';
|
|
8
8
|
import { bufferToHex } from '@aztec/foundation/string';
|
|
9
9
|
import type { DateProvider } from '@aztec/foundation/timer';
|
|
10
10
|
import type { ProverNodeConfig, ProverNodeDeps } from '@aztec/prover-node';
|
|
11
11
|
import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
|
|
12
12
|
|
|
13
13
|
import getPort from 'get-port';
|
|
14
|
-
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
15
14
|
|
|
16
15
|
import { TEST_PEER_CHECK_INTERVAL_MS } from './fixtures.js';
|
|
17
16
|
import { createAndSyncProverNode, getPrivateKeyFromIndex } from './utils.js';
|
|
@@ -22,6 +21,11 @@ import { getEndToEndTestTelemetryClient } from './with_telemetry_utils.js';
|
|
|
22
21
|
// to avoid running validators with the same key
|
|
23
22
|
export const ATTESTER_PRIVATE_KEYS_START_INDEX = 3;
|
|
24
23
|
|
|
24
|
+
// Global counters for actor naming (start at 1)
|
|
25
|
+
let validatorCounter = 1;
|
|
26
|
+
let nodeCounter = 1;
|
|
27
|
+
let proverCounter = 1;
|
|
28
|
+
|
|
25
29
|
export function generatePrivateKeys(startIndex: number, numberOfKeys: number): `0x${string}`[] {
|
|
26
30
|
const privateKeys: `0x${string}`[] = [];
|
|
27
31
|
// Do not start from 0 as it is used during setup
|
|
@@ -44,10 +48,6 @@ export async function createNodes(
|
|
|
44
48
|
validatorsPerNode = 1,
|
|
45
49
|
): Promise<AztecNodeService[]> {
|
|
46
50
|
const nodePromises: Promise<AztecNodeService>[] = [];
|
|
47
|
-
const loggerIdStorage = new AsyncLocalStorage<string>();
|
|
48
|
-
const logNameHandler = (module: string) =>
|
|
49
|
-
loggerIdStorage.getStore() ? `${module}:${loggerIdStorage.getStore()}` : module;
|
|
50
|
-
addLogNameHandler(logNameHandler);
|
|
51
51
|
|
|
52
52
|
for (let i = 0; i < numNodes; i++) {
|
|
53
53
|
const index = indexOffset + i;
|
|
@@ -69,7 +69,6 @@ export async function createNodes(
|
|
|
69
69
|
prefilledPublicData,
|
|
70
70
|
dataDir,
|
|
71
71
|
metricsPort,
|
|
72
|
-
loggerIdStorage,
|
|
73
72
|
);
|
|
74
73
|
nodePromises.push(nodePromise);
|
|
75
74
|
}
|
|
@@ -81,13 +80,20 @@ export async function createNodes(
|
|
|
81
80
|
throw new Error('Sequencer not found');
|
|
82
81
|
}
|
|
83
82
|
|
|
84
|
-
removeLogNameHandler(logNameHandler);
|
|
85
83
|
return nodes;
|
|
86
84
|
}
|
|
87
85
|
|
|
88
|
-
/**
|
|
86
|
+
/** Extended config type for createNode with test-specific overrides. */
|
|
87
|
+
export type CreateNodeConfig = AztecNodeConfig & {
|
|
88
|
+
/** Whether to skip starting the sequencer. */
|
|
89
|
+
dontStartSequencer?: boolean;
|
|
90
|
+
/** Override the private key (instead of deriving from addressIndex). */
|
|
91
|
+
validatorPrivateKey?: `0x${string}`;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/** Creates a P2P enabled instance of Aztec Node Service with a validator. */
|
|
89
95
|
export async function createNode(
|
|
90
|
-
config:
|
|
96
|
+
config: CreateNodeConfig,
|
|
91
97
|
dateProvider: DateProvider,
|
|
92
98
|
tcpPort: number,
|
|
93
99
|
bootstrapNode: string | undefined,
|
|
@@ -95,9 +101,9 @@ export async function createNode(
|
|
|
95
101
|
prefilledPublicData?: PublicDataTreeLeaf[],
|
|
96
102
|
dataDirectory?: string,
|
|
97
103
|
metricsPort?: number,
|
|
98
|
-
loggerIdStorage?: AsyncLocalStorage<string>,
|
|
99
104
|
) {
|
|
100
|
-
const
|
|
105
|
+
const actorIndex = validatorCounter++;
|
|
106
|
+
return await withLoggerBindings({ actor: `validator-${actorIndex}` }, async () => {
|
|
101
107
|
const validatorConfig = await createValidatorConfig(config, bootstrapNode, tcpPort, addressIndex, dataDirectory);
|
|
102
108
|
const telemetry = await getEndToEndTestTelemetryClient(metricsPort);
|
|
103
109
|
return await AztecNodeService.createAndSync(
|
|
@@ -105,8 +111,7 @@ export async function createNode(
|
|
|
105
111
|
{ telemetry, dateProvider },
|
|
106
112
|
{ prefilledPublicData, dontStartSequencer: config.dontStartSequencer },
|
|
107
113
|
);
|
|
108
|
-
};
|
|
109
|
-
return loggerIdStorage ? await loggerIdStorage.run(tcpPort.toString(), createNode) : createNode();
|
|
114
|
+
});
|
|
110
115
|
}
|
|
111
116
|
|
|
112
117
|
/** Creates a P2P enabled instance of Aztec Node Service without a validator */
|
|
@@ -118,9 +123,9 @@ export async function createNonValidatorNode(
|
|
|
118
123
|
prefilledPublicData?: PublicDataTreeLeaf[],
|
|
119
124
|
dataDirectory?: string,
|
|
120
125
|
metricsPort?: number,
|
|
121
|
-
loggerIdStorage?: AsyncLocalStorage<string>,
|
|
122
126
|
) {
|
|
123
|
-
const
|
|
127
|
+
const actorIndex = nodeCounter++;
|
|
128
|
+
return await withLoggerBindings({ actor: `node-${actorIndex}` }, async () => {
|
|
124
129
|
const p2pConfig = await createP2PConfig(baseConfig, bootstrapNode, tcpPort, dataDirectory);
|
|
125
130
|
const config: AztecNodeConfig = {
|
|
126
131
|
...p2pConfig,
|
|
@@ -130,8 +135,7 @@ export async function createNonValidatorNode(
|
|
|
130
135
|
};
|
|
131
136
|
const telemetry = await getEndToEndTestTelemetryClient(metricsPort);
|
|
132
137
|
return await AztecNodeService.createAndSync(config, { telemetry, dateProvider }, { prefilledPublicData });
|
|
133
|
-
};
|
|
134
|
-
return loggerIdStorage ? await loggerIdStorage.run(tcpPort.toString(), createNode) : createNode();
|
|
138
|
+
});
|
|
135
139
|
}
|
|
136
140
|
|
|
137
141
|
export async function createProverNode(
|
|
@@ -143,9 +147,9 @@ export async function createProverNode(
|
|
|
143
147
|
prefilledPublicData?: PublicDataTreeLeaf[],
|
|
144
148
|
dataDirectory?: string,
|
|
145
149
|
metricsPort?: number,
|
|
146
|
-
loggerIdStorage?: AsyncLocalStorage<string>,
|
|
147
150
|
) {
|
|
148
|
-
const
|
|
151
|
+
const actorIndex = proverCounter++;
|
|
152
|
+
return await withLoggerBindings({ actor: `prover-${actorIndex}` }, async () => {
|
|
149
153
|
const proverNodePrivateKey = getPrivateKeyFromIndex(ATTESTER_PRIVATE_KEYS_START_INDEX + addressIndex)!;
|
|
150
154
|
const telemetry = await getEndToEndTestTelemetryClient(metricsPort);
|
|
151
155
|
|
|
@@ -165,8 +169,7 @@ export async function createProverNode(
|
|
|
165
169
|
prefilledPublicData,
|
|
166
170
|
{ ...proverNodeDeps, telemetry },
|
|
167
171
|
);
|
|
168
|
-
};
|
|
169
|
-
return loggerIdStorage ? await loggerIdStorage.run(tcpPort.toString(), createProverNode) : createProverNode();
|
|
172
|
+
});
|
|
170
173
|
}
|
|
171
174
|
|
|
172
175
|
export async function createP2PConfig(
|
|
@@ -192,20 +195,21 @@ export async function createP2PConfig(
|
|
|
192
195
|
}
|
|
193
196
|
|
|
194
197
|
export async function createValidatorConfig(
|
|
195
|
-
config:
|
|
198
|
+
config: CreateNodeConfig,
|
|
196
199
|
bootstrapNodeEnr?: string,
|
|
197
200
|
port?: number,
|
|
198
201
|
addressIndex: number | number[] = 1,
|
|
199
202
|
dataDirectory?: string,
|
|
200
203
|
) {
|
|
201
204
|
const addressIndices = Array.isArray(addressIndex) ? addressIndex : [addressIndex];
|
|
202
|
-
if (addressIndices.length === 0) {
|
|
205
|
+
if (addressIndices.length === 0 && !config.validatorPrivateKey) {
|
|
203
206
|
throw new Error('At least one address index must be provided to create a validator config');
|
|
204
207
|
}
|
|
205
208
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
+
// Use override private key if provided, otherwise derive from address indices
|
|
210
|
+
const attesterPrivateKeys = config.validatorPrivateKey
|
|
211
|
+
? [config.validatorPrivateKey]
|
|
212
|
+
: addressIndices.map(index => bufferToHex(getPrivateKeyFromIndex(ATTESTER_PRIVATE_KEYS_START_INDEX + index)!));
|
|
209
213
|
const p2pConfig = await createP2PConfig(config, bootstrapNodeEnr, port, dataDirectory);
|
|
210
214
|
const nodeConfig: AztecNodeConfig = {
|
|
211
215
|
...config,
|
|
@@ -11,7 +11,7 @@ import type { DeployAztecL1ContractsReturnType } from '@aztec/ethereum/deploy-az
|
|
|
11
11
|
import { deployL1Contract } from '@aztec/ethereum/deploy-l1-contract';
|
|
12
12
|
import type { ExtendedViemWalletClient } from '@aztec/ethereum/types';
|
|
13
13
|
import { extractEvent } from '@aztec/ethereum/utils';
|
|
14
|
-
import {
|
|
14
|
+
import { EpochNumber } from '@aztec/foundation/branded-types';
|
|
15
15
|
import { sha256ToField } from '@aztec/foundation/crypto/sha256';
|
|
16
16
|
import { InboxAbi, UniswapPortalAbi, UniswapPortalBytecode } from '@aztec/l1-artifacts';
|
|
17
17
|
import { UniswapContract } from '@aztec/noir-contracts.js/Uniswap';
|
|
@@ -84,7 +84,7 @@ export const uniswapL1L2TestSuite = (
|
|
|
84
84
|
|
|
85
85
|
l1Client = deployL1ContractsValues.l1Client;
|
|
86
86
|
|
|
87
|
-
t.watcher
|
|
87
|
+
t.watcher.setIsMarkingAsProven(false);
|
|
88
88
|
|
|
89
89
|
if (Number(await l1Client.getBlockNumber()) < expectedForkBlockNumber) {
|
|
90
90
|
throw new Error('This test must be run on a fork of mainnet with the expected fork block');
|
|
@@ -250,8 +250,8 @@ export const uniswapL1L2TestSuite = (
|
|
|
250
250
|
await wethCrossChainHarness.expectPublicBalanceOnL2(uniswapL2Contract.address, 0n);
|
|
251
251
|
|
|
252
252
|
// Since the outbox is only consumable when the epoch is proven, we need to advance to the next epoch.
|
|
253
|
-
const
|
|
254
|
-
const epoch = await rollup.getEpochNumberForCheckpoint(checkpointNumber);
|
|
253
|
+
const block = await aztecNode.getBlock(l2UniswapInteractionReceipt.blockNumber!);
|
|
254
|
+
const epoch = await rollup.getEpochNumberForCheckpoint(block!.checkpointNumber);
|
|
255
255
|
await cheatCodes.rollup.advanceToEpoch(EpochNumber(epoch + 1));
|
|
256
256
|
await waitForProven(aztecNode, l2UniswapInteractionReceipt, { provenTimeout: 300 });
|
|
257
257
|
|
|
@@ -838,9 +838,8 @@ export const uniswapL1L2TestSuite = (
|
|
|
838
838
|
chainId: new Fr(l1Client.chain.id),
|
|
839
839
|
});
|
|
840
840
|
|
|
841
|
-
const
|
|
842
|
-
|
|
843
|
-
);
|
|
841
|
+
const block = await aztecNode.getBlock(withdrawReceipt.blockNumber!);
|
|
842
|
+
const epoch = await rollup.getEpochNumberForCheckpoint(block!.checkpointNumber);
|
|
844
843
|
const swapResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, swapPrivateLeaf);
|
|
845
844
|
const withdrawResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, withdrawLeaf);
|
|
846
845
|
|
|
@@ -972,9 +971,8 @@ export const uniswapL1L2TestSuite = (
|
|
|
972
971
|
chainId: new Fr(l1Client.chain.id),
|
|
973
972
|
});
|
|
974
973
|
|
|
975
|
-
const
|
|
976
|
-
|
|
977
|
-
);
|
|
974
|
+
const block = await aztecNode.getBlock(withdrawReceipt.blockNumber!);
|
|
975
|
+
const epoch = await rollup.getEpochNumberForCheckpoint(block!.checkpointNumber);
|
|
978
976
|
const swapResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, swapPublicLeaf);
|
|
979
977
|
const withdrawResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, withdrawLeaf);
|
|
980
978
|
|