mirror of
https://github.com/AtHeartEngineering/lodestar.git
synced 2026-01-09 21:38:03 -05:00
Lock keystores in validator cli (#3498)
This commit is contained in:
@@ -29,7 +29,7 @@ export async function validatorHandler(args: IValidatorCliArgs & IGlobalArgs): P
|
||||
const version = getVersion();
|
||||
logger.info("Lodestar", {version: version, network: args.network});
|
||||
|
||||
const secretKeys = await getSecretKeys(args);
|
||||
const {secretKeys, unlockSecretKeys: unlockSecretKeys} = await getSecretKeys(args);
|
||||
if (secretKeys.length === 0) {
|
||||
throw new YargsError("No validator keystores found");
|
||||
}
|
||||
@@ -46,6 +46,7 @@ export async function validatorHandler(args: IValidatorCliArgs & IGlobalArgs): P
|
||||
const onGracefulShutdownCbs: (() => Promise<void>)[] = [];
|
||||
onGracefulShutdown(async () => {
|
||||
for (const cb of onGracefulShutdownCbs) await cb();
|
||||
unlockSecretKeys?.();
|
||||
}, logger.info.bind(logger));
|
||||
|
||||
// This AbortController interrupts the sleep() calls when waiting for genesis
|
||||
|
||||
@@ -6,11 +6,16 @@ import {deriveEth2ValidatorKeys, deriveKeyFromMnemonic} from "@chainsafe/bls-key
|
||||
import {interopSecretKey} from "@chainsafe/lodestar-beacon-state-transition";
|
||||
import {defaultNetwork, IGlobalArgs} from "../../options";
|
||||
import {parseRange, stripOffNewlines, YargsError} from "../../util";
|
||||
import {getLockFile} from "../../util/lockfile";
|
||||
import {ValidatorDirManager} from "../../validatorDir";
|
||||
import {getAccountPaths} from "../account/paths";
|
||||
import {IValidatorCliArgs} from "./options";
|
||||
|
||||
export async function getSecretKeys(args: IValidatorCliArgs & IGlobalArgs): Promise<SecretKey[]> {
|
||||
const LOCK_FILE_EXT = ".lock";
|
||||
|
||||
export async function getSecretKeys(
|
||||
args: IValidatorCliArgs & IGlobalArgs
|
||||
): Promise<{secretKeys: SecretKey[]; unlockSecretKeys?: () => void}> {
|
||||
// UNSAFE - ONLY USE FOR TESTNETS. Derive keys directly from a mnemonic
|
||||
if (args.fromMnemonic) {
|
||||
if (args.network === defaultNetwork) {
|
||||
@@ -22,16 +27,18 @@ export async function getSecretKeys(args: IValidatorCliArgs & IGlobalArgs): Prom
|
||||
|
||||
const masterSK = deriveKeyFromMnemonic(args.fromMnemonic);
|
||||
const indexes = parseRange(args.mnemonicIndexes);
|
||||
return indexes.map((index) => {
|
||||
const {signing} = deriveEth2ValidatorKeys(masterSK, index);
|
||||
return SecretKey.fromBytes(signing);
|
||||
});
|
||||
return {
|
||||
secretKeys: indexes.map((index) => {
|
||||
const {signing} = deriveEth2ValidatorKeys(masterSK, index);
|
||||
return SecretKey.fromBytes(signing);
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
// Derive interop keys
|
||||
else if (args.interopIndexes) {
|
||||
const indexes = parseRange(args.interopIndexes);
|
||||
return indexes.map((index) => interopSecretKey(index));
|
||||
return {secretKeys: indexes.map((index) => interopSecretKey(index))};
|
||||
}
|
||||
|
||||
// Import JSON keystores and run
|
||||
@@ -44,18 +51,36 @@ export async function getSecretKeys(args: IValidatorCliArgs & IGlobalArgs): Prom
|
||||
|
||||
const keystorePaths = args.importKeystoresPath.map((filepath) => resolveKeystorePaths(filepath)).flat(1);
|
||||
|
||||
return await Promise.all(
|
||||
// Create lock files for all keystores
|
||||
const lockFile = getLockFile();
|
||||
const lockFilePaths = keystorePaths.map((keystorePath) => keystorePath + LOCK_FILE_EXT);
|
||||
|
||||
// Lock all keystores first
|
||||
for (const lockFilePath of lockFilePaths) {
|
||||
lockFile.lockSync(lockFilePath);
|
||||
}
|
||||
|
||||
const secretKeys = await Promise.all(
|
||||
keystorePaths.map(async (keystorePath) =>
|
||||
SecretKey.fromBytes(await Keystore.parse(fs.readFileSync(keystorePath, "utf8")).decrypt(passphrase))
|
||||
)
|
||||
);
|
||||
|
||||
return {
|
||||
secretKeys,
|
||||
unlockSecretKeys: () => {
|
||||
for (const lockFilePath of lockFilePaths) {
|
||||
lockFile.unlockSync(lockFilePath);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Read keys from local account manager
|
||||
else {
|
||||
const accountPaths = getAccountPaths(args);
|
||||
const validatorDirManager = new ValidatorDirManager(accountPaths);
|
||||
return await validatorDirManager.decryptAllValidators({force: args.force});
|
||||
return {secretKeys: await validatorDirManager.decryptAllValidators({force: args.force})};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user