Skip to content

Commit

Permalink
chore: Granular CLI imports to reduce start time (#10778)
Browse files Browse the repository at this point in the history
Breaks down imports from CLI to reduce start time to under a second:

```
$ time node ./dest/bin/index.js --help > /dev/null

real	0m0.979s
user	0m1.286s
sys	0m0.152s
```

Builds on #10765
  • Loading branch information
spalladino authored Dec 17, 2024
1 parent 1516d7f commit e2fd046
Show file tree
Hide file tree
Showing 41 changed files with 264 additions and 251 deletions.
5 changes: 3 additions & 2 deletions yarn-project/archiver/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
".": "./dest/index.js",
"./data-retrieval": "./dest/archiver/data_retrieval.js",
"./epoch": "./dest/archiver/epoch_helpers.js",
"./test": "./dest/test/index.js"
"./test": "./dest/test/index.js",
"./config": "./dest/archiver/config.js"
},
"typedocOptions": {
"entryPoints": [
Expand Down Expand Up @@ -109,4 +110,4 @@
"engines": {
"node": ">=18"
}
}
}
5 changes: 3 additions & 2 deletions yarn-project/aztec-faucet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"type": "module",
"bin": "./dest/bin/index.js",
"exports": {
".": "./dest/index.js"
".": "./dest/index.js",
"./config": "./dest/config.js"
},
"typedocOptions": {
"entryPoints": [
Expand Down Expand Up @@ -93,4 +94,4 @@
"engines": {
"node": ">=18"
}
}
}
7 changes: 5 additions & 2 deletions yarn-project/aztec-node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
"version": "0.1.0",
"main": "dest/index.js",
"type": "module",
"exports": "./dest/index.js",
"exports": {
".": "./dest/index.js",
"./config": "./dest/aztec-node/config.js"
},
"bin": "./dest/bin/index.js",
"typedocOptions": {
"entryPoints": [
Expand Down Expand Up @@ -103,4 +106,4 @@
"engines": {
"node": ">=18"
}
}
}
12 changes: 6 additions & 6 deletions yarn-project/aztec-node/src/aztec-node/config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { type ArchiverConfig, archiverConfigMappings } from '@aztec/archiver';
import { type ArchiverConfig, archiverConfigMappings } from '@aztec/archiver/config';
import { type ConfigMappingsType, booleanConfigHelper, getConfigFromMappings } from '@aztec/foundation/config';
import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config';
import { type P2PConfig, p2pConfigMappings } from '@aztec/p2p';
import { type ProverClientConfig, proverClientConfigMappings } from '@aztec/prover-client';
import { type SequencerClientConfig, sequencerClientConfigMappings } from '@aztec/sequencer-client';
import { type ValidatorClientConfig, validatorClientConfigMappings } from '@aztec/validator-client';
import { type WorldStateConfig, worldStateConfigMappings } from '@aztec/world-state';
import { type P2PConfig, p2pConfigMappings } from '@aztec/p2p/config';
import { type ProverClientConfig, proverClientConfigMappings } from '@aztec/prover-client/config';
import { type SequencerClientConfig, sequencerClientConfigMappings } from '@aztec/sequencer-client/config';
import { type ValidatorClientConfig, validatorClientConfigMappings } from '@aztec/validator-client/config';
import { type WorldStateConfig, worldStateConfigMappings } from '@aztec/world-state/config';

import { readFileSync } from 'fs';
import { dirname, resolve } from 'path';
Expand Down
3 changes: 2 additions & 1 deletion yarn-project/aztec.js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"./fields": "./dest/api/fields.js",
"./init": "./dest/api/init.js",
"./log_id": "./dest/api/log_id.js",
"./rpc": "./dest/rpc_clients/index.js",
"./tx_hash": "./dest/api/tx_hash.js",
"./wallet": "./dest/api/wallet.js"
},
Expand Down Expand Up @@ -118,4 +119,4 @@
"engines": {
"node": ">=18"
}
}
}
2 changes: 1 addition & 1 deletion yarn-project/aztec.js/src/rpc_clients/pxe_client.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type PXE, PXESchema } from '@aztec/circuit-types';
import { type PXE, PXESchema } from '@aztec/circuit-types/interfaces';
import { createSafeJsonRpcClient, makeFetch } from '@aztec/foundation/json-rpc/client';

/**
Expand Down
101 changes: 101 additions & 0 deletions yarn-project/aztec/src/cli/aztec_start_action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { deployInitialTestAccounts } from '@aztec/accounts/testing';
import { AztecNodeApiSchema, PXESchema } from '@aztec/circuit-types';
import {
type NamespacedApiHandlers,
createNamespacedSafeJsonRpcServer,
startHttpRpcServer,
} from '@aztec/foundation/json-rpc/server';
import { type LogFn, type Logger } from '@aztec/foundation/log';

import { createSandbox } from '../sandbox.js';
import { github, splash } from '../splash.js';
import { createAccountLogs, extractNamespacedOptions, installSignalHandlers } from './util.js';

export async function aztecStart(options: any, userLog: LogFn, debugLogger: Logger) {
// list of 'stop' functions to call when process ends
const signalHandlers: Array<() => Promise<void>> = [];
const services: NamespacedApiHandlers = {};

if (options.sandbox) {
const sandboxOptions = extractNamespacedOptions(options, 'sandbox');
userLog(`${splash}\n${github}\n\n`);
userLog(`Setting up Aztec Sandbox, please stand by...`);
const { aztecNodeConfig, node, pxe, stop } = await createSandbox({
enableGas: sandboxOptions.enableGas,
l1Mnemonic: options.l1Mnemonic,
l1RpcUrl: options.l1RpcUrl,
});

// Deploy test accounts by default
if (sandboxOptions.testAccounts) {
if (aztecNodeConfig.p2pEnabled) {
userLog(`Not setting up test accounts as we are connecting to a network`);
} else if (sandboxOptions.noPXE) {
userLog(`Not setting up test accounts as we are not exposing a PXE`);
} else {
userLog('Setting up test accounts...');
const accounts = await deployInitialTestAccounts(pxe);
const accLogs = await createAccountLogs(accounts, pxe);
userLog(accLogs.join(''));
}
}

// Start Node and PXE JSON-RPC server
signalHandlers.push(stop);
services.node = [node, AztecNodeApiSchema];
if (!sandboxOptions.noPXE) {
services.pxe = [pxe, PXESchema];
} else {
userLog(`Not exposing PXE API through JSON-RPC server`);
}
} else {
if (options.node) {
const { startNode } = await import('./cmds/start_node.js');
await startNode(options, signalHandlers, services, userLog);
} else if (options.proofVerifier) {
const { startProofVerifier } = await import('./cmds/start_proof_verifier.js');
await startProofVerifier(options, signalHandlers, userLog);
} else if (options.bot) {
const { startBot } = await import('./cmds/start_bot.js');
await startBot(options, signalHandlers, services, userLog);
} else if (options.proverNode) {
const { startProverNode } = await import('./cmds/start_prover_node.js');
await startProverNode(options, signalHandlers, services, userLog);
} else if (options.pxe) {
const { startPXE } = await import('./cmds/start_pxe.js');
await startPXE(options, signalHandlers, services, userLog);
} else if (options.archiver) {
const { startArchiver } = await import('./cmds/start_archiver.js');
await startArchiver(options, signalHandlers, services);
} else if (options.p2pBootstrap) {
const { startP2PBootstrap } = await import('./cmds/start_p2p_bootstrap.js');
await startP2PBootstrap(options, signalHandlers, services, userLog);
} else if (options.proverAgent) {
const { startProverAgent } = await import('./cmds/start_prover_agent.js');
await startProverAgent(options, signalHandlers, services, userLog);
} else if (options.proverBroker) {
const { startProverBroker } = await import('./cmds/start_prover_broker.js');
await startProverBroker(options, signalHandlers, services, userLog);
} else if (options.txe) {
const { startTXE } = await import('./cmds/start_txe.js');
await startTXE(options, debugLogger);
} else if (options.sequencer) {
userLog(`Cannot run a standalone sequencer without a node`);
process.exit(1);
} else if (options.faucet) {
const { startFaucet } = await import('./cmds/start_faucet.js');
await startFaucet(options, signalHandlers, services, userLog);
} else {
userLog(`No module specified to start`);
process.exit(1);
}
}

installSignalHandlers(debugLogger.info, signalHandlers);

if (Object.entries(services).length > 0) {
const rpcServer = createNamespacedSafeJsonRpcServer(services, debugLogger);
const { port } = await startHttpRpcServer(rpcServer, { port: options.port });
debugLogger.info(`Aztec Server listening on port ${port}`);
}
}
22 changes: 11 additions & 11 deletions yarn-project/aztec/src/cli/aztec_start_options.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import { type ArchiverConfig, archiverConfigMappings } from '@aztec/archiver';
import { faucetConfigMapping } from '@aztec/aztec-faucet';
import { sequencerClientConfigMappings } from '@aztec/aztec-node';
import { botConfigMappings } from '@aztec/bot';
import { type ArchiverConfig, archiverConfigMappings } from '@aztec/archiver/config';
import { faucetConfigMapping } from '@aztec/aztec-faucet/config';
import { sequencerClientConfigMappings } from '@aztec/aztec-node/config';
import { botConfigMappings } from '@aztec/bot/config';
import {
type ProverAgentConfig,
type ProverBrokerConfig,
proverAgentConfigMappings,
proverBrokerConfigMappings,
} from '@aztec/circuit-types';
} from '@aztec/circuit-types/config';
import {
type ConfigMapping,
type EnvVar,
booleanConfigHelper,
isBooleanConfigValue,
omitConfigMappings,
} from '@aztec/foundation/config';
import { bootnodeConfigMappings, p2pConfigMappings } from '@aztec/p2p';
import { proofVerifierConfigMappings } from '@aztec/proof-verifier';
import { proverNodeConfigMappings } from '@aztec/prover-node';
import { allPxeConfigMappings } from '@aztec/pxe';
import { bootnodeConfigMappings, p2pConfigMappings } from '@aztec/p2p/config';
import { proofVerifierConfigMappings } from '@aztec/proof-verifier/config';
import { proverNodeConfigMappings } from '@aztec/prover-node/config';
import { allPxeConfigMappings } from '@aztec/pxe/config';
import { telemetryClientConfigMappings } from '@aztec/telemetry-client/start';

import { defaultMnemonic } from '../sandbox.js';
import { DefaultMnemonic } from '../mnemonic.js';

// Define an interface for options
export interface AztecStartOption {
Expand Down Expand Up @@ -115,7 +115,7 @@ export const aztecStartOptions: { [key: string]: AztecStartOption[] } = {
{
flag: '--l1-mnemonic <value>',
description: 'Mnemonic for L1 accounts. Will be used if no publisher private keys are provided',
defaultValue: defaultMnemonic,
defaultValue: DefaultMnemonic,
envVar: 'MNEMONIC',
},
],
Expand Down
105 changes: 3 additions & 102 deletions yarn-project/aztec/src/cli/cli.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,9 @@
import { deployInitialTestAccounts } from '@aztec/accounts/testing';
import { AztecNodeApiSchema, PXESchema } from '@aztec/circuit-types';
import {
type NamespacedApiHandlers,
createNamespacedSafeJsonRpcServer,
startHttpRpcServer,
} from '@aztec/foundation/json-rpc/server';
import { type LogFn, type Logger } from '@aztec/foundation/log';

import { Command } from 'commander';

import { createSandbox } from '../sandbox.js';
import { github, splash } from '../splash.js';
import { aztecStartOptions } from './aztec_start_options.js';
import {
addOptions,
createAccountLogs,
extractNamespacedOptions,
installSignalHandlers,
printAztecStartHelpText,
} from './util.js';
import { addOptions, printAztecStartHelpText } from './util.js';

/**
* Returns commander program that defines the 'aztec' command line interface.
Expand All @@ -38,92 +23,8 @@ export function injectAztecCommands(program: Command, userLog: LogFn, debugLogge
startCmd.helpInformation = printAztecStartHelpText;

startCmd.action(async options => {
// list of 'stop' functions to call when process ends
const signalHandlers: Array<() => Promise<void>> = [];
const services: NamespacedApiHandlers = {};

if (options.sandbox) {
const sandboxOptions = extractNamespacedOptions(options, 'sandbox');
userLog(`${splash}\n${github}\n\n`);
userLog(`Setting up Aztec Sandbox, please stand by...`);
const { aztecNodeConfig, node, pxe, stop } = await createSandbox({
enableGas: sandboxOptions.enableGas,
l1Mnemonic: options.l1Mnemonic,
l1RpcUrl: options.l1RpcUrl,
});

// Deploy test accounts by default
if (sandboxOptions.testAccounts) {
if (aztecNodeConfig.p2pEnabled) {
userLog(`Not setting up test accounts as we are connecting to a network`);
} else if (sandboxOptions.noPXE) {
userLog(`Not setting up test accounts as we are not exposing a PXE`);
} else {
userLog('Setting up test accounts...');
const accounts = await deployInitialTestAccounts(pxe);
const accLogs = await createAccountLogs(accounts, pxe);
userLog(accLogs.join(''));
}
}

// Start Node and PXE JSON-RPC server
signalHandlers.push(stop);
services.node = [node, AztecNodeApiSchema];
if (!sandboxOptions.noPXE) {
services.pxe = [pxe, PXESchema];
} else {
userLog(`Not exposing PXE API through JSON-RPC server`);
}
} else {
if (options.node) {
const { startNode } = await import('./cmds/start_node.js');
await startNode(options, signalHandlers, services, userLog);
} else if (options.proofVerifier) {
const { startProofVerifier } = await import('./cmds/start_proof_verifier.js');
await startProofVerifier(options, signalHandlers, userLog);
} else if (options.bot) {
const { startBot } = await import('./cmds/start_bot.js');
await startBot(options, signalHandlers, services, userLog);
} else if (options.proverNode) {
const { startProverNode } = await import('./cmds/start_prover_node.js');
await startProverNode(options, signalHandlers, services, userLog);
} else if (options.pxe) {
const { startPXE } = await import('./cmds/start_pxe.js');
await startPXE(options, signalHandlers, services, userLog);
} else if (options.archiver) {
const { startArchiver } = await import('./cmds/start_archiver.js');
await startArchiver(options, signalHandlers, services);
} else if (options.p2pBootstrap) {
const { startP2PBootstrap } = await import('./cmds/start_p2p_bootstrap.js');
await startP2PBootstrap(options, signalHandlers, services, userLog);
} else if (options.proverAgent) {
const { startProverAgent } = await import('./cmds/start_prover_agent.js');
await startProverAgent(options, signalHandlers, services, userLog);
} else if (options.proverBroker) {
const { startProverBroker } = await import('./cmds/start_prover_broker.js');
await startProverBroker(options, signalHandlers, services, userLog);
} else if (options.txe) {
const { startTXE } = await import('./cmds/start_txe.js');
await startTXE(options, debugLogger);
} else if (options.sequencer) {
userLog(`Cannot run a standalone sequencer without a node`);
process.exit(1);
} else if (options.faucet) {
const { startFaucet } = await import('./cmds/start_faucet.js');
await startFaucet(options, signalHandlers, services, userLog);
} else {
userLog(`No module specified to start`);
process.exit(1);
}
}

installSignalHandlers(debugLogger.info, signalHandlers);

if (Object.entries(services).length > 0) {
const rpcServer = createNamespacedSafeJsonRpcServer(services, debugLogger);
const { port } = await startHttpRpcServer(rpcServer, { port: options.port });
debugLogger.info(`Aztec Server listening on port ${port}`);
}
const { aztecStart } = await import('./aztec_start_action.js');
return await aztecStart(options, userLog, debugLogger);
});

program.addCommand(startCmd);
Expand Down
1 change: 1 addition & 0 deletions yarn-project/aztec/src/mnemonic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const DefaultMnemonic = 'test test test test test test test test test test test junk';
6 changes: 3 additions & 3 deletions yarn-project/aztec/src/sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec
import { AnvilTestWatcher, EthCheatCodes, SignerlessWallet, retryUntil } from '@aztec/aztec.js';
import { DefaultMultiCallEntrypoint } from '@aztec/aztec.js/entrypoint';
import { type AztecNode } from '@aztec/circuit-types';
import { setupCanonicalL2FeeJuice } from '@aztec/cli/misc';
import { setupCanonicalL2FeeJuice } from '@aztec/cli/setup-contracts';
import {
type DeployL1Contracts,
NULL_KEY,
Expand All @@ -25,7 +25,7 @@ import { type HDAccount, type PrivateKeyAccount, createPublicClient, http as htt
import { mnemonicToAccount } from 'viem/accounts';
import { foundry } from 'viem/chains';

export const defaultMnemonic = 'test test test test test test test test test test test junk';
import { DefaultMnemonic } from './mnemonic.js';

const logger = createLogger('sandbox');

Expand Down Expand Up @@ -110,7 +110,7 @@ export type SandboxConfig = AztecNodeConfig & {
*/
export async function createSandbox(config: Partial<SandboxConfig> = {}) {
const aztecNodeConfig: AztecNodeConfig = { ...getConfigEnvVars(), ...config };
const hdAccount = mnemonicToAccount(config.l1Mnemonic || defaultMnemonic);
const hdAccount = mnemonicToAccount(config.l1Mnemonic || DefaultMnemonic);
if (!aztecNodeConfig.publisherPrivateKey || aztecNodeConfig.publisherPrivateKey === NULL_KEY) {
const privKey = hdAccount.getHdKey().privateKey;
aztecNodeConfig.publisherPrivateKey = `0x${Buffer.from(privKey!).toString('hex')}`;
Expand Down
Loading

0 comments on commit e2fd046

Please sign in to comment.