@chainsafe/lodestar 1.35.0-dev.fcf8d024ea → 1.35.0-dev.feed916580

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/.git-data.json +1 -1
  2. package/lib/cmds/beacon/handler.d.ts +1 -1
  3. package/lib/cmds/beacon/handler.js +1 -1
  4. package/lib/cmds/beacon/handler.js.map +1 -1
  5. package/lib/cmds/validator/handler.js +1 -1
  6. package/lib/cmds/validator/handler.js.map +1 -1
  7. package/lib/cmds/validator/slashingProtection/utils.js +1 -1
  8. package/lib/cmds/validator/slashingProtection/utils.js.map +1 -1
  9. package/lib/util/file.js.map +1 -1
  10. package/package.json +18 -19
  11. package/bin/lodestar.js +0 -3
  12. package/bin/lodestar.ts +0 -3
  13. package/lib/applyPreset.d.ts.map +0 -1
  14. package/lib/cli.d.ts.map +0 -1
  15. package/lib/cmds/beacon/handler.d.ts.map +0 -1
  16. package/lib/cmds/beacon/index.d.ts.map +0 -1
  17. package/lib/cmds/beacon/initBeaconState.d.ts.map +0 -1
  18. package/lib/cmds/beacon/initPeerIdAndEnr.d.ts.map +0 -1
  19. package/lib/cmds/beacon/options.d.ts.map +0 -1
  20. package/lib/cmds/beacon/paths.d.ts.map +0 -1
  21. package/lib/cmds/bootnode/handler.d.ts.map +0 -1
  22. package/lib/cmds/bootnode/index.d.ts.map +0 -1
  23. package/lib/cmds/bootnode/options.d.ts.map +0 -1
  24. package/lib/cmds/dev/files.d.ts.map +0 -1
  25. package/lib/cmds/dev/handler.d.ts.map +0 -1
  26. package/lib/cmds/dev/index.d.ts.map +0 -1
  27. package/lib/cmds/dev/options.d.ts.map +0 -1
  28. package/lib/cmds/index.d.ts.map +0 -1
  29. package/lib/cmds/lightclient/handler.d.ts.map +0 -1
  30. package/lib/cmds/lightclient/index.d.ts.map +0 -1
  31. package/lib/cmds/lightclient/options.d.ts.map +0 -1
  32. package/lib/cmds/validator/blsToExecutionChange.d.ts.map +0 -1
  33. package/lib/cmds/validator/handler.d.ts.map +0 -1
  34. package/lib/cmds/validator/import.d.ts.map +0 -1
  35. package/lib/cmds/validator/index.d.ts.map +0 -1
  36. package/lib/cmds/validator/keymanager/decryptKeystoreDefinitions.d.ts.map +0 -1
  37. package/lib/cmds/validator/keymanager/decryptKeystores/index.d.ts.map +0 -1
  38. package/lib/cmds/validator/keymanager/decryptKeystores/poolSize.d.ts.map +0 -1
  39. package/lib/cmds/validator/keymanager/decryptKeystores/threadPool.d.ts.map +0 -1
  40. package/lib/cmds/validator/keymanager/decryptKeystores/types.d.ts.map +0 -1
  41. package/lib/cmds/validator/keymanager/decryptKeystores/worker.d.ts.map +0 -1
  42. package/lib/cmds/validator/keymanager/impl.d.ts.map +0 -1
  43. package/lib/cmds/validator/keymanager/interface.d.ts.map +0 -1
  44. package/lib/cmds/validator/keymanager/keystoreCache.d.ts.map +0 -1
  45. package/lib/cmds/validator/keymanager/persistedKeys.d.ts.map +0 -1
  46. package/lib/cmds/validator/keymanager/server.d.ts.map +0 -1
  47. package/lib/cmds/validator/list.d.ts.map +0 -1
  48. package/lib/cmds/validator/options.d.ts.map +0 -1
  49. package/lib/cmds/validator/paths.d.ts.map +0 -1
  50. package/lib/cmds/validator/signers/importExternalKeystores.d.ts.map +0 -1
  51. package/lib/cmds/validator/signers/index.d.ts.map +0 -1
  52. package/lib/cmds/validator/signers/logSigners.d.ts.map +0 -1
  53. package/lib/cmds/validator/slashingProtection/export.d.ts.map +0 -1
  54. package/lib/cmds/validator/slashingProtection/import.d.ts.map +0 -1
  55. package/lib/cmds/validator/slashingProtection/index.d.ts.map +0 -1
  56. package/lib/cmds/validator/slashingProtection/options.d.ts.map +0 -1
  57. package/lib/cmds/validator/slashingProtection/utils.d.ts.map +0 -1
  58. package/lib/cmds/validator/voluntaryExit.d.ts.map +0 -1
  59. package/lib/config/beaconNodeOptions.d.ts.map +0 -1
  60. package/lib/config/beaconParams.d.ts.map +0 -1
  61. package/lib/config/index.d.ts.map +0 -1
  62. package/lib/config/peerId.d.ts.map +0 -1
  63. package/lib/config/types.d.ts.map +0 -1
  64. package/lib/index.d.ts.map +0 -1
  65. package/lib/migrations/index.d.ts.map +0 -1
  66. package/lib/networks/chiado.d.ts.map +0 -1
  67. package/lib/networks/dev.d.ts.map +0 -1
  68. package/lib/networks/ephemery.d.ts.map +0 -1
  69. package/lib/networks/gnosis.d.ts.map +0 -1
  70. package/lib/networks/holesky.d.ts.map +0 -1
  71. package/lib/networks/hoodi.d.ts.map +0 -1
  72. package/lib/networks/index.d.ts.map +0 -1
  73. package/lib/networks/mainnet.d.ts.map +0 -1
  74. package/lib/networks/sepolia.d.ts.map +0 -1
  75. package/lib/options/beaconNodeOptions/api.d.ts.map +0 -1
  76. package/lib/options/beaconNodeOptions/builder.d.ts.map +0 -1
  77. package/lib/options/beaconNodeOptions/chain.d.ts.map +0 -1
  78. package/lib/options/beaconNodeOptions/eth1.d.ts.map +0 -1
  79. package/lib/options/beaconNodeOptions/execution.d.ts.map +0 -1
  80. package/lib/options/beaconNodeOptions/index.d.ts.map +0 -1
  81. package/lib/options/beaconNodeOptions/metrics.d.ts.map +0 -1
  82. package/lib/options/beaconNodeOptions/monitoring.d.ts.map +0 -1
  83. package/lib/options/beaconNodeOptions/network.d.ts.map +0 -1
  84. package/lib/options/beaconNodeOptions/sync.d.ts.map +0 -1
  85. package/lib/options/globalOptions.d.ts.map +0 -1
  86. package/lib/options/index.d.ts.map +0 -1
  87. package/lib/options/logOptions.d.ts.map +0 -1
  88. package/lib/options/paramsOptions.d.ts.map +0 -1
  89. package/lib/paths/global.d.ts.map +0 -1
  90. package/lib/paths/rootDir.d.ts.map +0 -1
  91. package/lib/util/errors.d.ts.map +0 -1
  92. package/lib/util/ethers.d.ts.map +0 -1
  93. package/lib/util/feeRecipient.d.ts.map +0 -1
  94. package/lib/util/file.d.ts.map +0 -1
  95. package/lib/util/format.d.ts.map +0 -1
  96. package/lib/util/fs.d.ts.map +0 -1
  97. package/lib/util/gitData/gitDataPath.d.ts.map +0 -1
  98. package/lib/util/gitData/index.d.ts.map +0 -1
  99. package/lib/util/gitData/writeGitData.d.ts.map +0 -1
  100. package/lib/util/index.d.ts.map +0 -1
  101. package/lib/util/jwt.d.ts.map +0 -1
  102. package/lib/util/lockfile.d.ts.map +0 -1
  103. package/lib/util/logger.d.ts.map +0 -1
  104. package/lib/util/object.d.ts.map +0 -1
  105. package/lib/util/passphrase.d.ts.map +0 -1
  106. package/lib/util/process.d.ts.map +0 -1
  107. package/lib/util/progress.d.ts.map +0 -1
  108. package/lib/util/proposerConfig.d.ts.map +0 -1
  109. package/lib/util/pruneOldFilesInDir.d.ts.map +0 -1
  110. package/lib/util/sleep.d.ts.map +0 -1
  111. package/lib/util/stripOffNewlines.d.ts.map +0 -1
  112. package/lib/util/types.d.ts.map +0 -1
  113. package/lib/util/version.d.ts.map +0 -1
  114. package/src/applyPreset.ts +0 -91
  115. package/src/cli.ts +0 -56
  116. package/src/cmds/beacon/handler.ts +0 -267
  117. package/src/cmds/beacon/index.ts +0 -18
  118. package/src/cmds/beacon/initBeaconState.ts +0 -275
  119. package/src/cmds/beacon/initPeerIdAndEnr.ts +0 -199
  120. package/src/cmds/beacon/options.ts +0 -214
  121. package/src/cmds/beacon/paths.ts +0 -62
  122. package/src/cmds/bootnode/handler.ts +0 -203
  123. package/src/cmds/bootnode/index.ts +0 -13
  124. package/src/cmds/bootnode/options.ts +0 -109
  125. package/src/cmds/dev/files.ts +0 -52
  126. package/src/cmds/dev/handler.ts +0 -86
  127. package/src/cmds/dev/index.ts +0 -18
  128. package/src/cmds/dev/options.ts +0 -110
  129. package/src/cmds/index.ts +0 -15
  130. package/src/cmds/lightclient/handler.ts +0 -36
  131. package/src/cmds/lightclient/index.ts +0 -18
  132. package/src/cmds/lightclient/options.ts +0 -21
  133. package/src/cmds/validator/blsToExecutionChange.ts +0 -91
  134. package/src/cmds/validator/handler.ts +0 -300
  135. package/src/cmds/validator/import.ts +0 -111
  136. package/src/cmds/validator/index.ts +0 -28
  137. package/src/cmds/validator/keymanager/decryptKeystoreDefinitions.ts +0 -189
  138. package/src/cmds/validator/keymanager/decryptKeystores/index.ts +0 -1
  139. package/src/cmds/validator/keymanager/decryptKeystores/poolSize.ts +0 -16
  140. package/src/cmds/validator/keymanager/decryptKeystores/threadPool.ts +0 -75
  141. package/src/cmds/validator/keymanager/decryptKeystores/types.ts +0 -12
  142. package/src/cmds/validator/keymanager/decryptKeystores/worker.ts +0 -24
  143. package/src/cmds/validator/keymanager/impl.ts +0 -425
  144. package/src/cmds/validator/keymanager/interface.ts +0 -35
  145. package/src/cmds/validator/keymanager/keystoreCache.ts +0 -91
  146. package/src/cmds/validator/keymanager/persistedKeys.ts +0 -268
  147. package/src/cmds/validator/keymanager/server.ts +0 -86
  148. package/src/cmds/validator/list.ts +0 -35
  149. package/src/cmds/validator/options.ts +0 -461
  150. package/src/cmds/validator/paths.ts +0 -95
  151. package/src/cmds/validator/signers/importExternalKeystores.ts +0 -69
  152. package/src/cmds/validator/signers/index.ts +0 -176
  153. package/src/cmds/validator/signers/logSigners.ts +0 -81
  154. package/src/cmds/validator/slashingProtection/export.ts +0 -110
  155. package/src/cmds/validator/slashingProtection/import.ts +0 -70
  156. package/src/cmds/validator/slashingProtection/index.ts +0 -12
  157. package/src/cmds/validator/slashingProtection/options.ts +0 -15
  158. package/src/cmds/validator/slashingProtection/utils.ts +0 -56
  159. package/src/cmds/validator/voluntaryExit.ts +0 -232
  160. package/src/config/beaconNodeOptions.ts +0 -68
  161. package/src/config/beaconParams.ts +0 -87
  162. package/src/config/index.ts +0 -3
  163. package/src/config/peerId.ts +0 -50
  164. package/src/config/types.ts +0 -3
  165. package/src/index.ts +0 -28
  166. package/src/migrations/index.ts +0 -0
  167. package/src/networks/chiado.ts +0 -20
  168. package/src/networks/dev.ts +0 -27
  169. package/src/networks/ephemery.ts +0 -9
  170. package/src/networks/gnosis.ts +0 -18
  171. package/src/networks/holesky.ts +0 -17
  172. package/src/networks/hoodi.ts +0 -16
  173. package/src/networks/index.ts +0 -236
  174. package/src/networks/mainnet.ts +0 -34
  175. package/src/networks/sepolia.ts +0 -17
  176. package/src/options/beaconNodeOptions/api.ts +0 -110
  177. package/src/options/beaconNodeOptions/builder.ts +0 -63
  178. package/src/options/beaconNodeOptions/chain.ts +0 -326
  179. package/src/options/beaconNodeOptions/eth1.ts +0 -95
  180. package/src/options/beaconNodeOptions/execution.ts +0 -92
  181. package/src/options/beaconNodeOptions/index.ts +0 -50
  182. package/src/options/beaconNodeOptions/metrics.ts +0 -39
  183. package/src/options/beaconNodeOptions/monitoring.ts +0 -61
  184. package/src/options/beaconNodeOptions/network.ts +0 -401
  185. package/src/options/beaconNodeOptions/sync.ts +0 -65
  186. package/src/options/globalOptions.ts +0 -72
  187. package/src/options/index.ts +0 -3
  188. package/src/options/logOptions.ts +0 -70
  189. package/src/options/paramsOptions.ts +0 -72
  190. package/src/paths/global.ts +0 -24
  191. package/src/paths/rootDir.ts +0 -11
  192. package/src/util/errors.ts +0 -20
  193. package/src/util/ethers.ts +0 -44
  194. package/src/util/feeRecipient.ts +0 -6
  195. package/src/util/file.ts +0 -167
  196. package/src/util/format.ts +0 -76
  197. package/src/util/fs.ts +0 -59
  198. package/src/util/gitData/gitDataPath.ts +0 -48
  199. package/src/util/gitData/index.ts +0 -70
  200. package/src/util/gitData/writeGitData.ts +0 -10
  201. package/src/util/index.ts +0 -17
  202. package/src/util/jwt.ts +0 -10
  203. package/src/util/lockfile.ts +0 -45
  204. package/src/util/logger.ts +0 -105
  205. package/src/util/object.ts +0 -15
  206. package/src/util/passphrase.ts +0 -25
  207. package/src/util/process.ts +0 -25
  208. package/src/util/progress.ts +0 -58
  209. package/src/util/proposerConfig.ts +0 -136
  210. package/src/util/pruneOldFilesInDir.ts +0 -27
  211. package/src/util/sleep.ts +0 -3
  212. package/src/util/stripOffNewlines.ts +0 -6
  213. package/src/util/types.ts +0 -8
  214. package/src/util/version.ts +0 -74
@@ -1,176 +0,0 @@
1
- import path from "node:path";
2
- import {deriveEth2ValidatorKeys, deriveKeyFromMnemonic} from "@chainsafe/bls-keygen";
3
- import {SecretKey} from "@chainsafe/blst";
4
- import {interopSecretKey} from "@lodestar/state-transition";
5
- import {LogLevel, Logger, isValidHttpUrl} from "@lodestar/utils";
6
- import {Signer, SignerType, externalSignerGetKeys} from "@lodestar/validator";
7
- import {GlobalArgs, defaultNetwork} from "../../../options/index.js";
8
- import {YargsError, assertValidPubkeysHex, parseRange} from "../../../util/index.js";
9
- import {showProgress} from "../../../util/progress.js";
10
- import {decryptKeystoreDefinitions} from "../keymanager/decryptKeystoreDefinitions.js";
11
- import {PersistedKeysBackend} from "../keymanager/persistedKeys.js";
12
- import {IValidatorCliArgs} from "../options.js";
13
- import {getAccountPaths} from "../paths.js";
14
- import {importKeystoreDefinitionsFromExternalDir, readPassphraseOrPrompt} from "./importExternalKeystores.js";
15
-
16
- const KEYSTORE_IMPORT_PROGRESS_MS = 10000;
17
-
18
- /**
19
- * Options processing hierarchy
20
- * --interopIndexes
21
- * --fromMnemonic, then requires --mnemonicIndexes
22
- * --importKeystores, then requires --importKeystoresPassword
23
- * --externalSigner.fetch, then requires --externalSigner.url
24
- * --externalSigner.pubkeys, then requires --externalSigner.url
25
- * else load from persisted
26
- * - both remote keys and local keystores
27
- *
28
- * @returns Signers = an item capable of producing signatures. Two types exist:
29
- * - Local: a secret key capable of signing
30
- * - Remote: a URL that supports EIP-3030 (BLS Remote Signer HTTP API)
31
- *
32
- * Local secret keys can be gathered from:
33
- * - Local keystores existent on disk
34
- * - Local keystores imported via keymanager api
35
- * - Derived from a mnemonic (TESTING ONLY)
36
- * - Derived from interop keys (TESTING ONLY)
37
- *
38
- * Remote signers need to pre-declare the list of pubkeys to validate with
39
- * - Via CLI argument
40
- * - Fetched directly from remote signer API
41
- * - Remote signer definition imported from keymanager api
42
- */
43
- export async function getSignersFromArgs(
44
- args: IValidatorCliArgs & GlobalArgs,
45
- network: string,
46
- {logger, signal}: {logger: Pick<Logger, LogLevel.info | LogLevel.warn | LogLevel.debug>; signal: AbortSignal}
47
- ): Promise<Signer[]> {
48
- const accountPaths = getAccountPaths(args, network);
49
-
50
- // ONLY USE FOR TESTNETS - Derive interop keys
51
- if (args.interopIndexes) {
52
- const indexes = parseRange(args.interopIndexes);
53
- // Using a remote signer with TESTNETS
54
- if (args["externalSigner.pubkeys"] || args["externalSigner.fetch"]) {
55
- return getRemoteSigners(args);
56
- }
57
- return indexes.map((index) => ({type: SignerType.Local, secretKey: interopSecretKey(index)}));
58
- }
59
-
60
- // UNSAFE, ONLY USE FOR TESTNETS - Derive keys directly from a mnemonic
61
- if (args.fromMnemonic) {
62
- if (network === defaultNetwork) {
63
- throw new YargsError("fromMnemonic must only be used in testnets");
64
- }
65
- if (!args.mnemonicIndexes) {
66
- throw new YargsError("Must specify mnemonicIndexes with fromMnemonic");
67
- }
68
-
69
- const masterSK = deriveKeyFromMnemonic(args.fromMnemonic);
70
- const indexes = parseRange(args.mnemonicIndexes);
71
- return indexes.map((index) => ({
72
- type: SignerType.Local,
73
- secretKey: SecretKey.fromBytes(deriveEth2ValidatorKeys(masterSK, index).signing),
74
- }));
75
- }
76
-
77
- // Import JSON keystores and run
78
- if (args.importKeystores) {
79
- const keystoreDefinitions = importKeystoreDefinitionsFromExternalDir({
80
- keystoresPath: args.importKeystores,
81
- password: await readPassphraseOrPrompt(args),
82
- });
83
-
84
- const needle = showProgress({
85
- total: keystoreDefinitions.length,
86
- frequencyMs: KEYSTORE_IMPORT_PROGRESS_MS,
87
- signal,
88
- progress: ({ratePerSec, percentage, current, total}) => {
89
- logger.info(
90
- `${percentage.toFixed(0)}% of keystores imported. current=${current} total=${total} rate=${(
91
- ratePerSec * 60
92
- ).toFixed(2)}keys/m`
93
- );
94
- },
95
- });
96
- return decryptKeystoreDefinitions(keystoreDefinitions, {
97
- ignoreLockFile: args.force,
98
- onDecrypt: needle,
99
- cacheFilePath: path.join(accountPaths.cacheDir, "imported_keystores.cache"),
100
- disableThreadPool: args.disableKeystoresThreadPool,
101
- logger,
102
- signal,
103
- });
104
- }
105
-
106
- // Remote keys are declared manually or will be fetched from external signer
107
- if (args["externalSigner.pubkeys"] || args["externalSigner.fetch"]) {
108
- return getRemoteSigners(args);
109
- }
110
-
111
- // Read keys from local account manager
112
- const persistedKeysBackend = new PersistedKeysBackend(accountPaths);
113
-
114
- // Read and decrypt local keystores, imported via keymanager api or import cmd
115
- const keystoreDefinitions = persistedKeysBackend.readAllKeystores();
116
-
117
- const needle = showProgress({
118
- total: keystoreDefinitions.length,
119
- frequencyMs: KEYSTORE_IMPORT_PROGRESS_MS,
120
- signal,
121
- progress: ({ratePerSec, percentage, current, total}) => {
122
- logger.info(
123
- `${percentage.toFixed(0)}% of local keystores imported. current=${current} total=${total} rate=${(
124
- ratePerSec * 60
125
- ).toFixed(2)}keys/m`
126
- );
127
- },
128
- });
129
-
130
- const keystoreSigners = await decryptKeystoreDefinitions(keystoreDefinitions, {
131
- ignoreLockFile: args.force,
132
- onDecrypt: needle,
133
- cacheFilePath: path.join(accountPaths.cacheDir, "local_keystores.cache"),
134
- disableThreadPool: args.disableKeystoresThreadPool,
135
- logger,
136
- signal,
137
- });
138
-
139
- // Read local remote keys, imported via keymanager api
140
- const signerDefinitions = persistedKeysBackend.readAllRemoteKeys();
141
- const remoteSigners = signerDefinitions.map(({url, pubkey}): Signer => ({type: SignerType.Remote, url, pubkey}));
142
-
143
- return [...keystoreSigners, ...remoteSigners];
144
- }
145
-
146
- export function getSignerPubkeyHex(signer: Signer): string {
147
- switch (signer.type) {
148
- case SignerType.Local:
149
- return signer.secretKey.toPublicKey().toHex();
150
-
151
- case SignerType.Remote:
152
- return signer.pubkey;
153
- }
154
- }
155
-
156
- async function getRemoteSigners(args: IValidatorCliArgs & GlobalArgs): Promise<Signer[]> {
157
- const externalSignerUrl = args["externalSigner.url"];
158
- if (!externalSignerUrl) {
159
- throw new YargsError(
160
- `Must set externalSigner.url with ${
161
- args["externalSigner.pubkeys"] ? "externalSigner.pubkeys" : "externalSigner.fetch"
162
- }`
163
- );
164
- }
165
- if (!isValidHttpUrl(externalSignerUrl)) {
166
- throw new YargsError(`Invalid external signer URL: ${externalSignerUrl}`);
167
- }
168
- if (args["externalSigner.pubkeys"] && args["externalSigner.pubkeys"].length === 0) {
169
- throw new YargsError("externalSigner.pubkeys is set to an empty list");
170
- }
171
-
172
- const pubkeys = args["externalSigner.pubkeys"] ?? (await externalSignerGetKeys(externalSignerUrl));
173
- assertValidPubkeysHex(pubkeys);
174
-
175
- return pubkeys.map((pubkey) => ({type: SignerType.Remote, pubkey, url: externalSignerUrl}));
176
- }
@@ -1,81 +0,0 @@
1
- import {LogLevel, Logger, toPrintableUrl} from "@lodestar/utils";
2
- import {Signer, SignerLocal, SignerRemote, SignerType} from "@lodestar/validator";
3
- import {YargsError} from "../../../util/errors.js";
4
- import {IValidatorCliArgs} from "../options.js";
5
-
6
- /**
7
- * Log each pubkeys for auditing out keys are loaded from the logs
8
- */
9
- export function logSigners(logger: Pick<Logger, LogLevel.info>, signers: Signer[]): void {
10
- const localSigners: SignerLocal[] = [];
11
- const remoteSigners: SignerRemote[] = [];
12
-
13
- for (const signer of signers) {
14
- switch (signer.type) {
15
- case SignerType.Local:
16
- localSigners.push(signer);
17
- break;
18
- case SignerType.Remote:
19
- remoteSigners.push(signer);
20
- break;
21
- }
22
- }
23
-
24
- if (localSigners.length > 0) {
25
- logger.info(`${localSigners.length} local keystores`);
26
- for (const signer of localSigners) {
27
- logger.info(signer.secretKey.toPublicKey().toHex());
28
- }
29
- }
30
-
31
- for (const {url, pubkeys} of groupRemoteSignersByUrl(remoteSigners)) {
32
- logger.info(`Remote signers on URL: ${toPrintableUrl(url)}`);
33
- for (const pubkey of pubkeys) {
34
- logger.info(pubkey);
35
- }
36
- }
37
- }
38
-
39
- /**
40
- * Only used for logging remote signers grouped by URL
41
- */
42
- function groupRemoteSignersByUrl(remoteSigners: SignerRemote[]): {url: string; pubkeys: string[]}[] {
43
- const byUrl = new Map<string, {url: string; pubkeys: string[]}>();
44
-
45
- for (const remoteSigner of remoteSigners) {
46
- let x = byUrl.get(remoteSigner.url);
47
- if (!x) {
48
- x = {url: remoteSigner.url, pubkeys: []};
49
- byUrl.set(remoteSigner.url, x);
50
- }
51
- x.pubkeys.push(remoteSigner.pubkey);
52
- }
53
-
54
- return Array.from(byUrl.values());
55
- }
56
-
57
- /**
58
- * Notify user if there are no signers at startup, this might be intended but could also be due to
59
- * misconfiguration. It is possible that signers are added later via keymanager or if an external signer
60
- * is connected with fetching enabled, but otherwise exit the process and suggest a different configuration.
61
- */
62
- export function warnOrExitNoSigners(args: IValidatorCliArgs, logger: Pick<Logger, LogLevel.warn>): void {
63
- if (args.keymanager && !args["externalSigner.fetch"]) {
64
- logger.warn("No local keystores or remote keys found with current args, expecting to be added via keymanager");
65
- } else if (!args.keymanager && args["externalSigner.fetch"]) {
66
- logger.warn("No remote keys found with current args, expecting to be added to external signer and fetched later");
67
- } else if (args.keymanager && args["externalSigner.fetch"]) {
68
- logger.warn(
69
- "No local keystores or remote keys found with current args, expecting to be added via keymanager or fetched from external signer later"
70
- );
71
- } else {
72
- if (args["externalSigner.url"]) {
73
- throw new YargsError(
74
- "No remote keys found with current args, start with --externalSigner.fetch to automatically fetch from external signer"
75
- );
76
- }
77
- throw new YargsError(
78
- "No local keystores or remote keys found with current args, start with --keymanager if intending to add them later via keymanager"
79
- );
80
- }
81
- }
@@ -1,110 +0,0 @@
1
- import path from "node:path";
2
- import {getNodeLogger} from "@lodestar/logger/node";
3
- import {CliCommand, toPubkeyHex} from "@lodestar/utils";
4
- import {InterchangeFormatVersion} from "@lodestar/validator";
5
- import {getBeaconConfigFromArgs} from "../../../config/index.js";
6
- import {GlobalArgs} from "../../../options/index.js";
7
- import {LogArgs} from "../../../options/logOptions.js";
8
- import {YargsError, ensure0xPrefix, isValidatePubkeyHex, writeFile600Perm} from "../../../util/index.js";
9
- import {parseLoggerArgs} from "../../../util/logger.js";
10
- import {AccountValidatorArgs} from "../options.js";
11
- import {getValidatorPaths} from "../paths.js";
12
- import {ISlashingProtectionArgs} from "./options.js";
13
- import {getGenesisValidatorsRoot, getSlashingProtection} from "./utils.js";
14
-
15
- type ExportArgs = {
16
- file: string;
17
- pubkeys?: string[];
18
- };
19
-
20
- export const exportCmd: CliCommand<ExportArgs, ISlashingProtectionArgs & AccountValidatorArgs & GlobalArgs & LogArgs> =
21
- {
22
- command: "export",
23
-
24
- describe: "Export an interchange file.",
25
-
26
- examples: [
27
- {
28
- command: "validator slashing-protection export --network hoodi --file interchange.json",
29
- description: "Export an interchange JSON file for all validators in the slashing protection DB",
30
- },
31
- ],
32
-
33
- options: {
34
- file: {
35
- description: "The slashing protection interchange file to export to (.json).",
36
- demandOption: true,
37
- type: "string",
38
- },
39
- pubkeys: {
40
- description: "Export slashing protection data only for a given subset of public keys",
41
- type: "array",
42
- string: true, // Ensures the pubkey string is not automatically converted to numbers
43
- coerce: (pubkeys: string[]): string[] =>
44
- // Parse ["0x11,0x22"] to ["0x11", "0x22"]
45
- pubkeys
46
- .flatMap((item) => item.split(","))
47
- .map(ensure0xPrefix),
48
- },
49
- },
50
-
51
- handler: async (args) => {
52
- const {file} = args;
53
-
54
- const {config, network} = getBeaconConfigFromArgs(args);
55
- const validatorPaths = getValidatorPaths(args, network);
56
- // slashingProtection commands are fast so do not require logFile feature
57
- const logger = getNodeLogger(
58
- parseLoggerArgs(args, {defaultLogFilepath: path.join(validatorPaths.dataDir, "validator.log")}, config)
59
- );
60
-
61
- const {validatorsDbDir: dbPath} = getValidatorPaths(args, network);
62
-
63
- const formatVersion: InterchangeFormatVersion = {version: "5"};
64
- logger.info("Exporting slashing protection data", {...formatVersion, dbPath});
65
-
66
- const {slashingProtection, metadata} = await getSlashingProtection(args, network, logger);
67
-
68
- // When exporting validator DB should already have genesisValidatorsRoot persisted.
69
- // For legacy node and general fallback, fetch from:
70
- // - known genesis data from existing network
71
- // - else fetch from beacon node
72
- const genesisValidatorsRoot =
73
- (await metadata.getGenesisValidatorsRoot()) ?? (await getGenesisValidatorsRoot(args));
74
-
75
- logger.verbose("Fetching pubkeys from slashing protection db");
76
- const allPubkeys = await slashingProtection.listPubkeys();
77
- let pubkeysToExport = allPubkeys;
78
-
79
- if (args.pubkeys) {
80
- logger.verbose("Filtering by pubkeys from args", {count: args.pubkeys.length});
81
- const filteredPubkeys = [];
82
-
83
- for (const pubkeyHex of args.pubkeys) {
84
- if (!isValidatePubkeyHex(pubkeyHex)) {
85
- throw new YargsError(`Invalid pubkey ${pubkeyHex}`);
86
- }
87
- const existingPubkey = allPubkeys.find((pubkey) => toPubkeyHex(pubkey) === pubkeyHex);
88
- if (!existingPubkey) {
89
- logger.warn("Pubkey not found in slashing protection db", {pubkey: pubkeyHex});
90
- } else {
91
- filteredPubkeys.push(existingPubkey);
92
- }
93
- }
94
-
95
- pubkeysToExport = filteredPubkeys;
96
- }
97
-
98
- logger.info("Starting export for pubkeys found", {count: pubkeysToExport.length});
99
- const interchange = await slashingProtection.exportInterchange(
100
- genesisValidatorsRoot,
101
- pubkeysToExport,
102
- formatVersion,
103
- logger
104
- );
105
-
106
- logger.info("Writing slashing protection data", {file});
107
- writeFile600Perm(file, interchange);
108
- logger.info("Export completed successfully");
109
- },
110
- };
@@ -1,70 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import {getNodeLogger} from "@lodestar/logger/node";
4
- import {CliCommand} from "@lodestar/utils";
5
- import {Interchange} from "@lodestar/validator";
6
- import {getBeaconConfigFromArgs} from "../../../config/index.js";
7
- import {GlobalArgs} from "../../../options/index.js";
8
- import {LogArgs} from "../../../options/logOptions.js";
9
- import {parseLoggerArgs} from "../../../util/logger.js";
10
- import {AccountValidatorArgs} from "../options.js";
11
- import {getValidatorPaths} from "../paths.js";
12
- import {ISlashingProtectionArgs} from "./options.js";
13
- import {getGenesisValidatorsRoot, getSlashingProtection} from "./utils.js";
14
-
15
- type ImportArgs = {
16
- file: string;
17
- };
18
-
19
- export const importCmd: CliCommand<ImportArgs, ISlashingProtectionArgs & AccountValidatorArgs & GlobalArgs & LogArgs> =
20
- {
21
- command: "import",
22
-
23
- describe: "Import an interchange file.",
24
-
25
- examples: [
26
- {
27
- command: "validator slashing-protection import --network hoodi --file interchange.json",
28
- description: "Import an interchange file to the slashing protection DB",
29
- },
30
- ],
31
-
32
- options: {
33
- file: {
34
- description: "The slashing protection interchange file to import (.json).",
35
- demandOption: true,
36
- type: "string",
37
- },
38
- },
39
-
40
- handler: async (args) => {
41
- const {file} = args;
42
-
43
- const {config, network} = getBeaconConfigFromArgs(args);
44
- const validatorPaths = getValidatorPaths(args, network);
45
- // slashingProtection commands are fast so do not require logFile feature
46
- const logger = getNodeLogger(
47
- parseLoggerArgs(args, {defaultLogFilepath: path.join(validatorPaths.dataDir, "validator.log")}, config)
48
- );
49
-
50
- const {validatorsDbDir: dbPath} = getValidatorPaths(args, network);
51
-
52
- logger.info("Importing slashing protection data", {dbPath});
53
-
54
- const {slashingProtection, metadata} = await getSlashingProtection(args, network, logger);
55
-
56
- // Fetch genesisValidatorsRoot from:
57
- // - existing cached in validator DB
58
- // - known genesis data from existing network
59
- // - else fetch from beacon node
60
- const genesisValidatorsRoot =
61
- (await metadata.getGenesisValidatorsRoot()) ?? (await getGenesisValidatorsRoot(args));
62
-
63
- logger.verbose("Reading slashing protection data", {file});
64
- const interchangeStr = await fs.promises.readFile(file, "utf8");
65
- const interchangeJson = JSON.parse(interchangeStr) as Interchange;
66
-
67
- await slashingProtection.importInterchange(interchangeJson, genesisValidatorsRoot, logger);
68
- logger.info("Import completed successfully");
69
- },
70
- };
@@ -1,12 +0,0 @@
1
- import {CliCommand} from "@lodestar/utils";
2
- import {AccountValidatorArgs} from "../options.js";
3
- import {exportCmd} from "./export.js";
4
- import {importCmd} from "./import.js";
5
- import {ISlashingProtectionArgs, slashingProtectionOptions} from "./options.js";
6
-
7
- export const slashingProtection: CliCommand<ISlashingProtectionArgs, AccountValidatorArgs> = {
8
- command: "slashing-protection <command>",
9
- describe: "Import or export slashing protection data to or from another client.",
10
- options: slashingProtectionOptions,
11
- subcommands: [importCmd, exportCmd],
12
- };
@@ -1,15 +0,0 @@
1
- import {CliCommandOptions} from "@lodestar/utils";
2
- import {IValidatorCliArgs, validatorOptions} from "../options.js";
3
-
4
- export type ISlashingProtectionArgs = Pick<IValidatorCliArgs, "beaconNodes"> & {
5
- force?: boolean;
6
- };
7
-
8
- export const slashingProtectionOptions: CliCommandOptions<ISlashingProtectionArgs> = {
9
- beaconNodes: validatorOptions.beaconNodes,
10
-
11
- force: {
12
- description: "If `genesisValidatorsRoot` can't be fetched from the Beacon node, use a zero hash",
13
- type: "boolean",
14
- },
15
- };
@@ -1,56 +0,0 @@
1
- import {getClient} from "@lodestar/api";
2
- import {NetworkName, genesisData} from "@lodestar/config/networks";
3
- import {LevelDbController} from "@lodestar/db/controller/level";
4
- import {Root} from "@lodestar/types";
5
- import {Logger, fromHex} from "@lodestar/utils";
6
- import {MetaDataRepository, SlashingProtection} from "@lodestar/validator";
7
- import {getBeaconConfigFromArgs} from "../../../config/index.js";
8
- import {GlobalArgs} from "../../../options/index.js";
9
- import {getValidatorPaths} from "../paths.js";
10
- import {ISlashingProtectionArgs} from "./options.js";
11
-
12
- /**
13
- * Returns a new SlashingProtection object instance based on global args.
14
- */
15
- export async function getSlashingProtection(
16
- args: GlobalArgs,
17
- network: string,
18
- logger: Logger
19
- ): Promise<{slashingProtection: SlashingProtection; metadata: MetaDataRepository}> {
20
- const validatorPaths = getValidatorPaths(args, network);
21
- const dbPath = validatorPaths.validatorsDbDir;
22
-
23
- const db = await LevelDbController.create({name: dbPath}, {logger});
24
-
25
- return {
26
- slashingProtection: new SlashingProtection(db),
27
- metadata: new MetaDataRepository(db),
28
- };
29
- }
30
-
31
- /**
32
- * Returns genesisValidatorsRoot from validator API client.
33
- */
34
- export async function getGenesisValidatorsRoot(args: GlobalArgs & ISlashingProtectionArgs): Promise<Root> {
35
- const server = args.beaconNodes[0];
36
-
37
- const networkGenesis = genesisData[args.network as NetworkName];
38
- if (networkGenesis !== undefined) {
39
- return fromHex(networkGenesis.genesisValidatorsRoot);
40
- }
41
-
42
- const {config} = getBeaconConfigFromArgs(args);
43
- const api = getClient({baseUrl: server}, {config});
44
- const genesis = await api.beacon.getGenesis();
45
-
46
- try {
47
- genesis.assertOk();
48
- } catch (e) {
49
- if (args.force) {
50
- return Buffer.alloc(32, 0);
51
- }
52
- throw e;
53
- }
54
-
55
- return genesis.value().genesisValidatorsRoot;
56
- }