|
| 1 | +import type { LogFn } from '@aztec/foundation/log'; |
| 2 | + |
| 3 | +import { Command } from 'commander'; |
| 4 | + |
| 5 | +import { parseAztecAddress, parseEthereumAddress, parseHex, parseOptionalInteger } from '../../utils/commands.js'; |
| 6 | + |
| 7 | +export function injectCommands(program: Command, log: LogFn) { |
| 8 | + const group = program |
| 9 | + .command('validator-keys') |
| 10 | + .aliases(['valKeys']) |
| 11 | + .description('Manage validator keystores for node operators'); |
| 12 | + |
| 13 | + group |
| 14 | + .command('new') |
| 15 | + .summary('Generate a new validator keystore JSON') |
| 16 | + .description('Generates a new validator keystore with ETH secp256k1 accounts and optional BLS accounts') |
| 17 | + .option('--data-dir <path>', 'Directory to store keystore(s). Defaults to ~/.aztec/keystore') |
| 18 | + .option('--file <name>', 'Keystore file name. Defaults to key1.json (or keyN.json if key1.json exists)') |
| 19 | + .option('--count <N>', 'Number of validators to generate', parseOptionalInteger) |
| 20 | + .option('--publisher-count <N>', 'Number of publisher accounts per validator (default 1)', value => |
| 21 | + parseOptionalInteger(value, 0), |
| 22 | + ) |
| 23 | + .option('--mnemonic <mnemonic>', 'Mnemonic for ETH/BLS derivation') |
| 24 | + .option('--passphrase <str>', 'Optional passphrase for mnemonic') |
| 25 | + .option('--account-index <N>', 'Base account index for ETH derivation', parseOptionalInteger) |
| 26 | + .option('--address-index <N>', 'Base address index for ETH derivation', parseOptionalInteger) |
| 27 | + .option('--coinbase <address>', 'Coinbase ETH address to use when proposing', parseEthereumAddress) |
| 28 | + .option('--funding-account <address>', 'ETH account to fund publishers', parseEthereumAddress) |
| 29 | + .option('--remote-signer <url>', 'Default remote signer URL for accounts in this file') |
| 30 | + .option('--ikm <hex>', 'Initial keying material for BLS (alternative to mnemonic)', value => parseHex(value, 32)) |
| 31 | + .option('--bls-path <path>', 'EIP-2334 path (default m/12381/3600/0/0/0)') |
| 32 | + .option('--bls-only', 'Generate only BLS keys') |
| 33 | + .option( |
| 34 | + '--password <str>', |
| 35 | + 'Password for writing keystore files (ETH JSON V3 and BLS EIP-2335). Empty string allowed', |
| 36 | + ) |
| 37 | + .option('--out-dir <dir>', 'Output directory for generated keystore file(s)') |
| 38 | + .option('--json', 'Echo resulting JSON to stdout') |
| 39 | + .requiredOption('--fee-recipient <address>', 'Aztec address that will receive fees', parseAztecAddress) |
| 40 | + .action(async options => { |
| 41 | + const { newValidatorKeystore } = await import('./new.js'); |
| 42 | + await newValidatorKeystore(options, log); |
| 43 | + }); |
| 44 | + |
| 45 | + group |
| 46 | + .command('add') |
| 47 | + .summary('Augment an existing validator keystore JSON') |
| 48 | + .description('Adds attester/publisher/BLS entries to an existing keystore using the same flags as new') |
| 49 | + .argument('<existing>', 'Path to existing keystore JSON') |
| 50 | + .option('--data-dir <path>', 'Directory where keystore(s) live') |
| 51 | + .option('--file <name>', 'Override output file name') |
| 52 | + .option('--count <N>', 'Number of validators to add', parseOptionalInteger) |
| 53 | + .option('--publisher-count <N>', 'Number of publisher accounts per validator (default 1)', value => |
| 54 | + parseOptionalInteger(value, 0), |
| 55 | + ) |
| 56 | + .option('--mnemonic <mnemonic>', 'Mnemonic for ETH/BLS derivation') |
| 57 | + .option('--passphrase <str>', 'Optional passphrase for mnemonic') |
| 58 | + .option('--account-index <N>', 'Base account index for ETH derivation', parseOptionalInteger) |
| 59 | + .option('--address-index <N>', 'Base address index for ETH derivation', parseOptionalInteger) |
| 60 | + .option('--coinbase <address>', 'Coinbase ETH address to use when proposing', parseEthereumAddress) |
| 61 | + .option('--funding-account <address>', 'ETH account to fund publishers', parseEthereumAddress) |
| 62 | + .option('--remote-signer <url>', 'Default remote signer URL for accounts in this file') |
| 63 | + .option('--ikm <hex>', 'Initial keying material for BLS (alternative to mnemonic)', value => parseHex(value, 32)) |
| 64 | + .option('--bls-path <path>', 'EIP-2334 path (default m/12381/3600/0/0/0)') |
| 65 | + .option('--bls-only', 'Generate only BLS keys') |
| 66 | + .option('--empty', 'Generate an empty skeleton without keys') |
| 67 | + .option( |
| 68 | + '--password <str>', |
| 69 | + 'Password for writing keystore files (ETH JSON V3 and BLS EIP-2335). Empty string allowed', |
| 70 | + ) |
| 71 | + .option('--out-dir <dir>', 'Output directory for generated keystore file(s)') |
| 72 | + .option('--json', 'Echo resulting JSON to stdout') |
| 73 | + .requiredOption('--fee-recipient <address>', 'Aztec address that will receive fees', parseAztecAddress) |
| 74 | + .action(async (existing: string, options) => { |
| 75 | + const { addValidatorKeys } = await import('./add.js'); |
| 76 | + await addValidatorKeys(existing, options, log); |
| 77 | + }); |
| 78 | + |
| 79 | + // top-level convenience: aztec generate-bls-keypair |
| 80 | + program |
| 81 | + .command('generate-bls-keypair') |
| 82 | + .description('Generate a BLS keypair with convenience flags') |
| 83 | + .option('--mnemonic <mnemonic>', 'Mnemonic for BLS derivation') |
| 84 | + .option('--ikm <hex>', 'Initial keying material for BLS (alternative to mnemonic)', value => parseHex(value, 32)) |
| 85 | + .option('--bls-path <path>', 'EIP-2334 path (default m/12381/3600/0/0/0)') |
| 86 | + .option('--g2', 'Derive on G2 subgroup') |
| 87 | + .option('--compressed', 'Output compressed public key') |
| 88 | + .option('--json', 'Print JSON output to stdout') |
| 89 | + .option('--out <file>', 'Write output to file') |
| 90 | + .action(async options => { |
| 91 | + const { generateBlsKeypair } = await import('./generate_bls_keypair.js'); |
| 92 | + await generateBlsKeypair(options, log); |
| 93 | + }); |
| 94 | + |
| 95 | + return program; |
| 96 | +} |
0 commit comments