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

feat(config): add fallbacks #12593

Merged
merged 3 commits into from
Mar 10, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
25 changes: 18 additions & 7 deletions yarn-project/aztec/src/cli/cmds/start_node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,17 @@ export async function startNode(
): Promise<{ config: AztecNodeConfig }> {
// options specifically namespaced with --node.<option>
const nodeSpecificOptions = extractNamespacedOptions(options, 'node');

// All options set from environment variables
const configFromEnvVars = getConfigEnvVars();

// Extract relevant options from command line arguments
const relevantOptions = extractRelevantOptions(options, aztecNodeConfigMappings, 'node');

// All options that are relevant to the Aztec Node
let nodeConfig: AztecNodeConfig = {
...getConfigEnvVars(),
...extractRelevantOptions(options, aztecNodeConfigMappings, 'node'),
...configFromEnvVars,
...relevantOptions,
};

if (options.proverNode) {
Expand Down Expand Up @@ -96,22 +103,26 @@ export async function startNode(
if (!options.sequencer) {
nodeConfig.disableValidator = true;
} else {
const sequencerConfig = extractNamespacedOptions(options, 'sequencer');
const sequencerConfig = {
...configFromEnvVars,
...extractNamespacedOptions(options, 'sequencer'),
};
let account;
if (!sequencerConfig.publisherPrivateKey || sequencerConfig.publisherPrivateKey === NULL_KEY) {
if (!options.l1Mnemonic) {
if (sequencerConfig.validatorPrivateKey) {
sequencerConfig.publisherPrivateKey = sequencerConfig.validatorPrivateKey as `0x${string}`;
} else if (!options.l1Mnemonic) {
userLog(
'--sequencer.publisherPrivateKey or --l1-mnemonic is required to start Aztec Node with --sequencer option',
);
throw new Error('Private key or Mnemonic is required to start Aztec Node with --sequencer option');
} else {
account = mnemonicToAccount(options.l1Mnemonic);
const privKey = account.getHdKey().privateKey;
nodeConfig.publisherPrivateKey = `0x${Buffer.from(privKey!).toString('hex')}`;
sequencerConfig.publisherPrivateKey = `0x${Buffer.from(privKey!).toString('hex')}`;
}
} else {
nodeConfig.publisherPrivateKey = sequencerConfig.publisherPrivateKey;
}
nodeConfig.publisherPrivateKey = sequencerConfig.publisherPrivateKey;
}

if (nodeConfig.p2pEnabled) {
Expand Down
13 changes: 7 additions & 6 deletions yarn-project/end-to-end/scripts/native-network/validator.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ exec > >(tee -a "$(dirname $0)/logs/${SCRIPT_NAME}.log") 2> >(tee -a "$(dirname
PORT="$1"
P2P_PORT="$2"
ADDRESS="${3:-${ADDRESS:-}}"
export VALIDATOR_PRIVATE_KEY="${4:-${VALIDATOR_PRIVATE_KEY:-}}"
validator_private_key="${4:-${VALIDATOR_PRIVATE_KEY:-}}"

# Starts the Validator Node
REPO=$(git rev-parse --show-toplevel)
Expand Down Expand Up @@ -47,15 +47,16 @@ export BOOTSTRAP_NODES=$(echo "$output" | grep -oP 'Node ENR: \K.*')
echo "BOOTSTRAP_NODES: $BOOTSTRAP_NODES"

# Generate a private key for the validator only if not already set
if [ -z "${VALIDATOR_PRIVATE_KEY:-}" ] || [ -z "${ADDRESS:-}" ]; then
if [ -z "${validator_private_key:-}" ] || [ -z "${ADDRESS:-}" ]; then
echo "Generating new L1 Validator account..."
json_account=$(node --no-warnings "$REPO"/yarn-project/aztec/dest/bin/index.js generate-l1-account)
export ADDRESS=$(echo $json_account | jq -r '.address')
export VALIDATOR_PRIVATE_KEY=$(echo $json_account | jq -r '.privateKey')
validator_private_key=$(echo $json_account | jq -r '.privateKey')
fi

export L1_PRIVATE_KEY=$VALIDATOR_PRIVATE_KEY
export SEQ_PUBLISHER_PRIVATE_KEY=$VALIDATOR_PRIVATE_KEY
## We want to use the private key from the cli
unset VALIDATOR_PRIVATE_KEY

export DEBUG=${DEBUG:-""}
export LOG_LEVEL=${LOG_LEVEL:-"verbose"}
export L1_CONSENSUS_HOST_URL=${L1_CONSENSUS_HOST_URL:-}
Expand Down Expand Up @@ -90,4 +91,4 @@ else
fi

# Start the Validator Node with the sequencer and archiver
node --no-warnings "$REPO"/yarn-project/aztec/dest/bin/index.js start --port="$PORT" --node --archiver --sequencer
node --no-warnings "$REPO"/yarn-project/aztec/dest/bin/index.js start --port="$PORT" --node --archiver --sequencer --sequencer.validatorPrivateKey="$validator_private_key"
Copy link
Member Author

Choose a reason for hiding this comment

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

Adding it this way such that we are testing this flow, as this is what we expect users to do

54 changes: 47 additions & 7 deletions yarn-project/foundation/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface ConfigMapping {
description: string;
isBoolean?: boolean;
nested?: Record<string, ConfigMapping>;
fallback?: EnvVar[];
}

export function isBooleanConfigValue<T>(obj: T, key: keyof T): boolean {
Expand All @@ -18,20 +19,59 @@ export function isBooleanConfigValue<T>(obj: T, key: keyof T): boolean {

export type ConfigMappingsType<T> = Record<keyof T, ConfigMapping>;

/**
* Shared utility function to get a value from environment variables with fallback support.
* This can be used by both getConfigFromMappings and CLI utilities.
*
* @param env - The primary environment variable name
* @param fallback - Optional array of fallback environment variable names
* @param parseFunc - Optional function to parse the environment variable value
* @param defaultValue - Optional default value to use if no environment variable is set
* @returns The parsed value from environment variables or the default value
*/
export function getValueFromEnvWithFallback<T>(
env: EnvVar | undefined,
parseFunc: ((val: string) => T) | undefined,
defaultValue: T | undefined,
fallback?: EnvVar[],
): T | undefined {
let value: string | undefined;

// Try primary env var
if (env) {
value = process.env[env];
}

// If primary not found, try fallbacks
if (value === undefined && fallback && fallback.length > 0) {
for (const fallbackEnv of fallback) {
const fallbackVal = process.env[fallbackEnv];
if (fallbackVal !== undefined) {
value = fallbackVal;
break;
}
}
}

// Parse the value if needed
if (value !== undefined) {
return parseFunc ? parseFunc(value) : (value as unknown as T);
}

// Return default if no env var found
return defaultValue;
}

export function getConfigFromMappings<T>(configMappings: ConfigMappingsType<T>): T {
const config = {} as T;

for (const key in configMappings) {
const { env, parseEnv, defaultValue: def, nested } = configMappings[key];
const { env, parseEnv, defaultValue, nested, fallback } = configMappings[key];
if (nested) {
(config as any)[key] = getConfigFromMappings(nested);
} else {
const val = env ? process.env[env] : undefined;
if (val !== undefined) {
(config as any)[key] = parseEnv ? parseEnv(val) : val;
} else if (def !== undefined) {
(config as any)[key] = def;
}
// Use the shared utility function
(config as any)[key] = getValueFromEnvWithFallback(env, parseEnv, defaultValue, fallback);
}
}

Expand Down
3 changes: 3 additions & 0 deletions yarn-project/sequencer-client/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Fr } from '@aztec/foundation/fields';
import { FunctionSelector } from '@aztec/stdlib/abi';
import { AztecAddress } from '@aztec/stdlib/aztec-address';
import { type AllowedElement, type ChainConfig, type SequencerConfig, chainConfigMappings } from '@aztec/stdlib/config';
import { type ValidatorClientConfig, validatorClientConfigMappings } from '@aztec/validator-client';

import {
type PublisherConfig,
Expand All @@ -31,6 +32,7 @@ export type { SequencerConfig };
* Configuration settings for the SequencerClient.
*/
export type SequencerClientConfig = PublisherConfig &
ValidatorClientConfig &
TxSenderConfig &
SequencerConfig &
L1ReaderConfig &
Expand Down Expand Up @@ -113,6 +115,7 @@ export const sequencerConfigMappings: ConfigMappingsType<SequencerConfig> = {
};

export const sequencerClientConfigMappings: ConfigMappingsType<SequencerClientConfig> = {
...validatorClientConfigMappings,
...sequencerConfigMappings,
...l1ReaderConfigMappings,
...getTxSenderConfigMappings('SEQ'),
Expand Down
1 change: 1 addition & 0 deletions yarn-project/sequencer-client/src/publisher/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export const getTxSenderConfigMappings: (
description: 'The private key to be used by the publisher.',
parseEnv: (val: string) => (val ? `0x${val.replace('0x', '')}` : NULL_KEY),
defaultValue: NULL_KEY,
fallback: ['VALIDATOR_PRIVATE_KEY'],
},
});

Expand Down