-
-
Notifications
You must be signed in to change notification settings - Fork 457
Expand file tree
/
Copy pathimport.ts
More file actions
118 lines (98 loc) · 4.23 KB
/
import.ts
File metadata and controls
118 lines (98 loc) · 4.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import fs from "node:fs";
import {Keystore} from "@chainsafe/bls-keystore";
import {CliCommand} from "@lodestar/utils";
import {getBeaconConfigFromArgs} from "../../config/beaconParams.js";
import {GlobalArgs} from "../../options/index.js";
import {YargsError, getPubkeyHexFromKeystore} from "../../util/index.js";
import {PersistedKeysBackend} from "./keymanager/persistedKeys.js";
import {IValidatorCliArgs, validatorOptions} from "./options.js";
import {getAccountPaths} from "./paths.js";
import {readKeystoreDefinitionsFromArgs} from "./signers/importExternalKeystores.js";
type ValidatorImportArgs = Pick<
IValidatorCliArgs,
"importKeystores" | "importKeystoresPassword" | "importKeystoresPasswords"
>;
const {importKeystores, importKeystoresPassword, importKeystoresPasswords} = validatorOptions;
export const importCmd: CliCommand<ValidatorImportArgs, IValidatorCliArgs & GlobalArgs> = {
command: "import",
describe:
"Imports one or more EIP-2335 keystores into a Lodestar validator client directory, \
using either a shared password or per-keystore password files. The directory flag provides a convenient \
method for importing a directory of keys generated by the eth2-deposit-cli \
Ethereum Foundation utility.",
examples: [
{
command: "validator import --network hoodi --importKeystores $HOME/staking-deposit-cli/validator_keys",
description: "Import validator keystores generated with the Ethereum Foundation Staking Launchpad",
},
{
command:
"validator import --network hoodi --importKeystores $HOME/staking-deposit-cli/validator_keys --importKeystoresPasswords $HOME/staking-deposit-cli/passwords",
description: "Import validator keystores with one password file per validator public key",
},
],
// Note: re-uses `--importKeystores`, `--importKeystoresPassword`, and `--importKeystoresPasswords` from root validator command options
options: {
importKeystores: {
...importKeystores,
requiresArg: true,
},
importKeystoresPassword,
importKeystoresPasswords,
},
handler: async (args) => {
const {network} = getBeaconConfigFromArgs(args);
// This command takes: importKeystores, importKeystoresPassword, importKeystoresPasswords
//
// - recursively finds keystores in importKeystores
// - validates keystores can decrypt
// - writes them in persisted form - do not lock
if (!args.importKeystores) {
throw new YargsError("Must set importKeystores");
}
const keystoreDefinitions = await readKeystoreDefinitionsFromArgs({
keystoresPath: args.importKeystores,
importKeystoresPassword: args.importKeystoresPassword,
importKeystoresPasswords: args.importKeystoresPasswords,
});
if (keystoreDefinitions.length === 0) {
throw new YargsError("No keystores found");
}
console.log(
`Importing ${keystoreDefinitions.length} keystores:\n ${keystoreDefinitions
.map((def) => def.keystorePath)
.join("\n")}`
);
const accountPaths = getAccountPaths(args, network);
const persistedKeystoresBackend = new PersistedKeysBackend(accountPaths);
let importedCount = 0;
for (const {keystorePath, password} of keystoreDefinitions) {
const keystoreStr = fs.readFileSync(keystorePath, "utf8");
const keystore = Keystore.parse(keystoreStr);
const pubkeyHex = getPubkeyHexFromKeystore(keystore);
// Check if keystore can decrypt
if (!(await keystore.verifyPassword(password))) {
throw Error(`Invalid password for keystore ${keystorePath}`);
}
const didImportKey = persistedKeystoresBackend.writeKeystore({
keystoreStr,
password,
// Not used immediately
lockBeforeWrite: false,
// Return duplicate status if already found
persistIfDuplicate: false,
});
if (didImportKey) {
console.log(`Imported keystore ${pubkeyHex} ${keystorePath}`);
importedCount++;
} else {
console.log(`Duplicate keystore ${pubkeyHex} ${keystorePath}`);
}
}
console.log(`\nSuccessfully imported ${importedCount}/${keystoreDefinitions.length} keystores`);
console.log(`
DO NOT USE THE ORIGINAL KEYSTORES TO VALIDATE WITH
ANOTHER CLIENT, OR YOU WILL GET SLASHED.
`);
},
};