Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Cleanup after e2e tests #10748

Merged
merged 8 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions yarn-project/end-to-end/src/fixtures/snapshot_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { deployInstance, registerContractClass } from '@aztec/aztec.js/deploymen
import { type DeployL1ContractsArgs, createL1Clients, getL1ContractsConfigEnvVars, l1Artifacts } from '@aztec/ethereum';
import { startAnvil } from '@aztec/ethereum/test';
import { asyncMap } from '@aztec/foundation/async-map';
import { randomBytes } from '@aztec/foundation/crypto';
import { createLogger } from '@aztec/foundation/log';
import { resolver, reviver } from '@aztec/foundation/serialize';
import { TestDateProvider } from '@aztec/foundation/timer';
Expand All @@ -28,7 +29,9 @@ import { createAndStartTelemetryClient, getConfigEnvVars as getTelemetryConfig }
import { type Anvil } from '@viem/anvil';
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
import { copySync, removeSync } from 'fs-extra/esm';
import { join } from 'path';
import fs from 'fs/promises';
import { tmpdir } from 'os';
import path, { join } from 'path';
import { type Hex, getContract } from 'viem';
import { mnemonicToAccount } from 'viem/accounts';

Expand All @@ -51,6 +54,7 @@ export type SubsystemsContext = {
watcher: AnvilTestWatcher;
cheatCodes: CheatCodes;
dateProvider: TestDateProvider;
directoryToCleanup?: string;
};

type SnapshotEntry = {
Expand Down Expand Up @@ -248,8 +252,12 @@ async function teardown(context: SubsystemsContext | undefined) {
await context.proverNode?.stop();
await context.aztecNode.stop();
await context.acvmConfig?.cleanup();
await context.bbConfig?.cleanup();
await context.anvil.stop();
await context.watcher.stop();
if (context.directoryToCleanup) {
await fs.rm(context.directoryToCleanup, { recursive: true, force: true });
}
} catch (err) {
getLogger().error('Error during teardown', err);
}
Expand All @@ -274,7 +282,15 @@ async function setupFromFresh(
// Fetch the AztecNode config.
// TODO: For some reason this is currently the union of a bunch of subsystems. That needs fixing.
const aztecNodeConfig: AztecNodeConfig & SetupOptions = { ...getConfigEnvVars(), ...opts };
aztecNodeConfig.dataDirectory = statePath;

// Create a temp directory for all ephemeral state and cleanup afterwards
const directoryToCleanup = path.join(tmpdir(), randomBytes(8).toString('hex'));
await fs.mkdir(directoryToCleanup, { recursive: true });
if (statePath === undefined) {
aztecNodeConfig.dataDirectory = directoryToCleanup;
} else {
aztecNodeConfig.dataDirectory = statePath;
}

// Start anvil. We go via a wrapper script to ensure if the parent dies, anvil dies.
logger.verbose('Starting anvil...');
Expand Down Expand Up @@ -364,12 +380,13 @@ async function setupFromFresh(
`0x${proverNodePrivateKey!.toString('hex')}`,
aztecNodeConfig,
aztecNode,
path.join(directoryToCleanup, randomBytes(8).toString('hex')),
);
}

logger.verbose('Creating pxe...');
const pxeConfig = getPXEServiceConfig();
pxeConfig.dataDirectory = statePath;
pxeConfig.dataDirectory = statePath ?? path.join(directoryToCleanup, randomBytes(8).toString('hex'));
const pxe = await createPXEService(aztecNode, pxeConfig);

const cheatCodes = await CheatCodes.create(aztecNodeConfig.l1RpcUrl, pxe);
Expand All @@ -390,6 +407,7 @@ async function setupFromFresh(
watcher,
cheatCodes,
dateProvider,
directoryToCleanup,
};
}

Expand All @@ -399,6 +417,9 @@ async function setupFromFresh(
async function setupFromState(statePath: string, logger: Logger): Promise<SubsystemsContext> {
logger.verbose(`Initializing with saved state at ${statePath}...`);

const directoryToCleanup = path.join(tmpdir(), randomBytes(8).toString('hex'));
await fs.mkdir(directoryToCleanup, { recursive: true });

// TODO: For some reason this is currently the union of a bunch of subsystems. That needs fixing.
const aztecNodeConfig: AztecNodeConfig & SetupOptions = JSON.parse(
readFileSync(`${statePath}/aztec_node_config.json`, 'utf-8'),
Expand Down Expand Up @@ -447,7 +468,12 @@ async function setupFromState(statePath: string, logger: Logger): Promise<Subsys
logger.verbose('Creating and syncing a simulated prover node...');
const proverNodePrivateKey = getPrivateKeyFromIndex(2);
const proverNodePrivateKeyHex: Hex = `0x${proverNodePrivateKey!.toString('hex')}`;
proverNode = await createAndSyncProverNode(proverNodePrivateKeyHex, aztecNodeConfig, aztecNode);
proverNode = await createAndSyncProverNode(
proverNodePrivateKeyHex,
aztecNodeConfig,
aztecNode,
path.join(directoryToCleanup, randomBytes(8).toString('hex')),
);
}

logger.verbose('Creating pxe...');
Expand All @@ -473,6 +499,7 @@ async function setupFromState(statePath: string, logger: Logger): Promise<Subsys
watcher,
cheatCodes,
dateProvider,
directoryToCleanup,
};
}

Expand Down
48 changes: 44 additions & 4 deletions yarn-project/end-to-end/src/fixtures/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
l1Artifacts,
} from '@aztec/ethereum';
import { startAnvil } from '@aztec/ethereum/test';
import { randomBytes } from '@aztec/foundation/crypto';
import { retryUntil } from '@aztec/foundation/retry';
import { TestDateProvider } from '@aztec/foundation/timer';
import { FeeJuiceContract } from '@aztec/noir-contracts.js/FeeJuice';
Expand All @@ -49,6 +50,8 @@ import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
import { createAndStartTelemetryClient, getConfigEnvVars as getTelemetryConfig } from '@aztec/telemetry-client/start';

import { type Anvil } from '@viem/anvil';
import fs from 'fs/promises';
import { tmpdir } from 'os';
import * as path from 'path';
import {
type Account,
Expand Down Expand Up @@ -145,9 +148,20 @@ export async function setupPXEService(
teardown: () => Promise<void>;
}> {
const pxeServiceConfig = { ...getPXEServiceConfig(), ...opts };

// If no data directory provided, create a temp directory and clean up afterwards
const configuredDataDirectory = pxeServiceConfig.dataDirectory;
if (!configuredDataDirectory) {
pxeServiceConfig.dataDirectory = path.join(tmpdir(), randomBytes(8).toString('hex'));
}

const pxe = await createPXEService(aztecNode, pxeServiceConfig, useLogSuffix, proofCreator);

const teardown = async () => {};
const teardown = async () => {
if (!configuredDataDirectory) {
await fs.rm(pxeServiceConfig.dataDirectory!, { recursive: true, force: true });
}
};

return {
pxe,
Expand Down Expand Up @@ -304,6 +318,13 @@ export async function setup(
const config = { ...getConfigEnvVars(), ...opts };
const logger = getLogger();

// Create a temp directory for any services that need it and cleanup later
const directoryToCleanup = path.join(tmpdir(), randomBytes(8).toString('hex'));
await fs.mkdir(directoryToCleanup, { recursive: true });
if (!config.dataDirectory) {
config.dataDirectory = directoryToCleanup;
}

let anvil: Anvil | undefined;

if (!config.l1RpcUrl) {
Expand Down Expand Up @@ -428,11 +449,16 @@ export async function setup(
logger.verbose('Creating and syncing a simulated prover node...');
const proverNodePrivateKey = getPrivateKeyFromIndex(2);
const proverNodePrivateKeyHex: Hex = `0x${proverNodePrivateKey!.toString('hex')}`;
proverNode = await createAndSyncProverNode(proverNodePrivateKeyHex, config, aztecNode);
proverNode = await createAndSyncProverNode(
proverNodePrivateKeyHex,
config,
aztecNode,
path.join(directoryToCleanup, randomBytes(8).toString('hex')),
);
}

logger.verbose('Creating a pxe...');
const { pxe } = await setupPXEService(aztecNode!, pxeOpts, logger);
const { pxe, teardown: pxeTeardown } = await setupPXEService(aztecNode!, pxeOpts, logger);

if (!config.skipProtocolContracts) {
logger.verbose('Setting up Fee Juice...');
Expand All @@ -445,6 +471,8 @@ export async function setup(
const cheatCodes = await CheatCodes.create(config.l1RpcUrl, pxe!);

const teardown = async () => {
await pxeTeardown();

if (aztecNode instanceof AztecNodeService) {
await aztecNode?.stop();
}
Expand All @@ -455,8 +483,19 @@ export async function setup(
await acvmConfig.cleanup();
}

if (bbConfig?.cleanup) {
// remove the temp directory created for the acvm
logger.verbose(`Cleaning up BB state`);
await bbConfig.cleanup();
}

await anvil?.stop();
await watcher.stop();

if (directoryToCleanup) {
logger.verbose(`Cleaning up data directory at ${directoryToCleanup}`);
await fs.rm(directoryToCleanup, { recursive: true, force: true });
}
};

return {
Expand Down Expand Up @@ -660,6 +699,7 @@ export async function createAndSyncProverNode(
proverNodePrivateKey: `0x${string}`,
aztecNodeConfig: AztecNodeConfig,
aztecNode: AztecNode,
dataDirectory: string,
) {
// Disable stopping the aztec node as the prover coordination test will kill it otherwise
// This is only required when stopping the prover node for testing
Expand All @@ -670,7 +710,7 @@ export async function createAndSyncProverNode(
};

// Creating temp store and archiver for simulated prover node
const archiverConfig = { ...aztecNodeConfig, dataDirectory: undefined };
const archiverConfig = { ...aztecNodeConfig, dataDirectory };
const archiver = await createArchiver(archiverConfig, new NoopTelemetryClient(), { blockUntilSync: true });

// Prover node config is for simulated proofs
Expand Down
10 changes: 5 additions & 5 deletions yarn-project/kv-store/src/lmdb/store.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { randomBytes } from '@aztec/foundation/crypto';
import { createLogger } from '@aztec/foundation/log';

import { promises as fs, mkdirSync } from 'fs';
Expand Down Expand Up @@ -64,13 +65,12 @@ export class AztecLmdbStore implements AztecKVStore, AztecAsyncKVStore {
ephemeral: boolean = false,
log = createLogger('kv-store:lmdb'),
): AztecLmdbStore {
if (path) {
mkdirSync(path, { recursive: true });
}
const dbPath = path ?? join(tmpdir(), randomBytes(8).toString('hex'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could make path required in order to catch any places that ask for a tmp location?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a place in the node server.ts that requests a tmp store. I don't see that this needs to provide a location, it calls delete on the stores once it's finished. With this change, that call is now actually cleaning up the directory which is what would be expected.

mkdirSync(dbPath, { recursive: true });
const mapSize = 1024 * mapSizeKb;
log.debug(`Opening LMDB database at ${path || 'temporary location'} with map size ${mapSize}`);
const rootDb = open({ path, noSync: ephemeral, mapSize });
return new AztecLmdbStore(rootDb, ephemeral, path);
const rootDb = open({ path: dbPath, noSync: ephemeral, mapSize });
return new AztecLmdbStore(rootDb, ephemeral, dbPath);
}

/**
Expand Down
Loading